console

Eric Pouech eric.pouech at wanadoo.fr
Sun Jul 21 03:34:01 CDT 2002


this patch mainly allows, when wrapping is allowed, to extend the
edition on several lines.
it also implements a few more commands in emacs mode (alt-t and ctrl-l)
see the changelog for all the details

A+
-------------- next part --------------
Name:          conedit
ChangeLog:     
	multi-line edit is now enabled
	fixed a buffer allocation error
	yank buffer is no longer destroyed after the first copy
	implemented the transpose word (alt-t) and redraw (ctrl-l) emacs-commands
License:       X11
GenDate:       2002/07/21 08:25:04 UTC
ModifiedFiles: win32/console.c win32/editline.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/win32/console.c,v
retrieving revision 1.96
diff -u -u -r1.96 console.c
--- win32/console.c	10 Jul 2002 20:31:46 -0000	1.96
+++ win32/console.c	20 Jul 2002 16:00:48 -0000
@@ -33,7 +33,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
-#include <assert.h>
 
 #include "winbase.h"
 #include "winnls.h"
@@ -234,7 +233,7 @@
     DWORD	ncr = 0;
     BOOL	ret;
 
-    if ((ret = ReadConsoleW(hConsoleInput, ptr, nNumberOfCharsToRead, &ncr, 0)))
+    if ((ret = ReadConsoleW(hConsoleInput, ptr, nNumberOfCharsToRead, &ncr, NULL)))
 	ncr = WideCharToMultiByte(CP_ACP, 0, ptr, ncr, lpBuffer, nNumberOfCharsToRead, NULL, NULL);
 
     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = ncr;
@@ -1238,12 +1237,12 @@
 }
 
 /******************************************************************
- *		fill_line_uniform
+ *		CONSOLE_FillLineUniform
  *
  * Helper function for ScrollConsoleScreenBufferW
  * Fills a part of a line with a constant character info
  */
-static void fill_line_uniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill)
+void CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill)
 {
     SERVER_START_REQ( fill_console_output )
     {
@@ -1340,7 +1339,7 @@
 
     /* step 4: clean out the exposed part */
 
-    /* have to write celll [i,j] if it is not in dst rect (because it has already
+    /* have to write cell [i,j] if it is not in dst rect (because it has already
      * been written to by the scroll) and is in clip (we shall not write
      * outside of clip)
      */
@@ -1354,7 +1353,7 @@
 	    {
 		if (start != -1)
 		{
-		    fill_line_uniform(hConsoleOutput, start, j, i - start, lpFill);
+		    CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
 		    start = -1;
 		}
 	    }
@@ -1364,7 +1363,7 @@
 	    }
 	}
 	if (start != -1)
-	    fill_line_uniform(hConsoleOutput, start, j, i - start, lpFill);
+	    CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
     }
 
     return TRUE;
Index: win32/editline.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/win32/editline.c,v
retrieving revision 1.10
diff -u -u -r1.10 editline.c
--- win32/editline.c	2 Jun 2002 21:19:28 -0000	1.10
+++ win32/editline.c	20 Jul 2002 17:06:23 -0000
@@ -36,6 +36,7 @@
 extern int CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len);
 extern BOOL CONSOLE_AppendHistory(const WCHAR *p);
 extern unsigned int CONSOLE_GetNumHistoryEntries(void);
+extern void CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill);
 
 struct WCEL_Context;
 
@@ -63,7 +64,8 @@
     HANDLE			hConIn;
     HANDLE			hConOut;
     unsigned			done : 1,	/* to 1 when we're done with editing */
-	                        error : 1;	/* to 1 when an error occurred in the editing */
+	                        error : 1,	/* to 1 when an error occurred in the editing */
+                                can_wrap : 1;   /* to 1 when multi-line edition can take place */
     unsigned			histSize;
     unsigned			histPos;
     WCHAR*			histCurr;
@@ -72,12 +74,14 @@
 #if 0
 static void WCEL_Dump(WCEL_Context* ctx, const char* pfx)
 {
-    MESSAGE("%s: [line=%s[alloc=%u] ofs=%u len=%u start=(%d,%d) mask=%c%c\n"
-	    "\t\thist=(size=%u pos=%u curr=%s)\n",
+    MESSAGE("%s: [line=%s[alloc=%u] ofs=%u len=%u start=(%d,%d) mask=%c%c%c]\n"
+	    "\t\thist=(size=%u pos=%u curr=%s)\n"
+            "\t\tyanked=%s\n",
 	    pfx, debugstr_w(ctx->line), ctx->alloc, ctx->ofs, ctx->len,
 	    ctx->csbi.dwCursorPosition.X, ctx->csbi.dwCursorPosition.Y,
-	    ctx->done ? 'D' : 'd', ctx->error ? 'E' : 'e',
-	    ctx->histSize, ctx->histPos, debugstr_w(ctx->histCurr));
+	    ctx->done ? 'D' : 'd', ctx->error ? 'E' : 'e', ctx->can_wrap ? 'W' : 'w',
+	    ctx->histSize, ctx->histPos, debugstr_w(ctx->histCurr),
+            debugstr_w(ctx->yanked));
 }
 #endif
 
@@ -119,20 +123,31 @@
     Beep(400, 300);
 }
 
+static inline BOOL WCEL_IsSingleLine(WCEL_Context* ctx, size_t len)
+{
+    return ctx->csbi.dwCursorPosition.X + ctx->len + len <= ctx->csbi.dwSize.X;
+}
+
 static inline COORD WCEL_GetCoord(WCEL_Context* ctx, int ofs)
 {
-    COORD c;
-    c.X = ctx->csbi.dwCursorPosition.X + ofs;
+    COORD       c;
+    unsigned    len = ctx->csbi.dwSize.X - ctx->csbi.dwCursorPosition.X;
+
     c.Y = ctx->csbi.dwCursorPosition.Y;
+    if (ofs >= len)
+    {
+        ofs -= len;
+        c.X = ofs % ctx->csbi.dwSize.X;
+        c.Y += 1 + ofs / ctx->csbi.dwSize.X;
+    }
+    else c.X = ctx->csbi.dwCursorPosition.X + ofs;
     return c;
 }
 
-static inline void WCEL_GetRect(WCEL_Context* ctx, LPSMALL_RECT sr, int beg, int end)
+static inline void WCEL_Update(WCEL_Context* ctx, int beg, int len)
 {
-    sr->Left = ctx->csbi.dwCursorPosition.X + beg;
-    sr->Top = ctx->csbi.dwCursorPosition.Y;
-    sr->Right = ctx->csbi.dwCursorPosition.X + end;
-    sr->Bottom = ctx->csbi.dwCursorPosition.Y;
+    WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[beg], len, 
+                                 WCEL_GetCoord(ctx, beg), NULL);
 }
 
 /* ====================================================================
@@ -143,41 +158,61 @@
 
 static BOOL WCEL_Grow(WCEL_Context* ctx, size_t len)
 {
-    if (ctx->csbi.dwCursorPosition.X + ctx->len + len >= ctx->csbi.dwSize.X)
+    if (!WCEL_IsSingleLine(ctx, len) && !ctx->can_wrap)
     {
-	FIXME("Current implementation doesn't allow edition to spray across several lines\n");
-	return FALSE;
+        FIXME("Mode doesn't allow to wrap. However, we should allow to overwrite current string\n");
+        return FALSE;
     }
 
     if (ctx->len + len >= ctx->alloc)
     {
 	WCHAR*	newline;
-	newline = HeapReAlloc(GetProcessHeap(), 0, ctx->line, sizeof(WCHAR) * (ctx->alloc + 32));
+        size_t  newsize;
+
+        /* round up size to 32 byte-WCHAR boundary */
+        newsize = (ctx->len + len + 1 + 31) & ~31;
+	newline = HeapReAlloc(GetProcessHeap(), 0, ctx->line, sizeof(WCHAR) * newsize);
 	if (!newline) return FALSE;
 	ctx->line = newline;
-	ctx->alloc += 32;
+	ctx->alloc = newsize;
     }
     return TRUE;
 }
 
 static void WCEL_DeleteString(WCEL_Context* ctx, int beg, int end)
 {
-    SMALL_RECT	scl, clp;
-    CHAR_INFO	ci;
+    unsigned    str_len = end - beg;
+    COORD       cbeg = WCEL_GetCoord(ctx, ctx->len - str_len);
+    COORD       cend = WCEL_GetCoord(ctx, ctx->len);
+    CHAR_INFO   ci;
 
     if (end < ctx->len)
 	memmove(&ctx->line[beg], &ctx->line[end], (ctx->len - end) * sizeof(WCHAR));
-    /* make the source rect bigger than the actual rect to that the part outside the clip
-     * rect (before the scroll) will get redrawn after the scroll
-     */
-    WCEL_GetRect(ctx, &scl, end, ctx->len + end - beg);
-    WCEL_GetRect(ctx, &clp, beg, ctx->len);
+    /* we need to clean from ctx->len - str_len to ctx->len */
 
     ci.Char.UnicodeChar = ' ';
     ci.Attributes = ctx->csbi.wAttributes;
-    ScrollConsoleScreenBufferW(ctx->hConOut, &scl, &clp, WCEL_GetCoord(ctx, beg), &ci);
 
-    ctx->len -= end - beg;
+    if (cbeg.Y == cend.Y)
+    {
+        /* partial erase of sole line */
+        CONSOLE_FillLineUniform(ctx->hConOut, cbeg.X, cbeg.Y, 
+                                cend.X - cbeg.X, &ci);
+    }
+    else
+    {
+        int         i;
+        /* erase til eol on first line */
+        CONSOLE_FillLineUniform(ctx->hConOut, cbeg.X, cbeg.Y, 
+                                ctx->csbi.dwSize.X - cbeg.X, &ci);
+        /* completly erase all the others (full lines) */
+        for (i = cbeg.Y + 1; i < cend.Y; i++)
+            CONSOLE_FillLineUniform(ctx->hConOut, 0, i, ctx->csbi.dwSize.X, &ci);
+        /* erase from beg of line until last pos on last line */
+        CONSOLE_FillLineUniform(ctx->hConOut, 0, cend.Y, cend.X, &ci);
+    }
+    ctx->len -= str_len;
+    WCEL_Update(ctx, 0, ctx->len);
     ctx->line[ctx->len] = 0;
 }
 
@@ -191,8 +226,8 @@
     memcpy(&ctx->line[ctx->ofs], str, len * sizeof(WCHAR));
     ctx->len += len;
     ctx->line[ctx->len] = 0;
-    SetConsoleCursorPosition(ctx->hConOut, WCEL_GetCoord(ctx, ctx->ofs));
-    WriteConsoleW(ctx->hConOut, &ctx->line[ctx->ofs], ctx->len - ctx->ofs, NULL, NULL);
+    WCEL_Update(ctx, ctx->ofs, ctx->len - ctx->ofs);
+
     ctx->ofs += len;
 }
 
@@ -208,9 +243,21 @@
     WCEL_InsertString(ctx, buffer);
 }
 
+static void WCEL_FreeYank(WCEL_Context* ctx)
+{
+    if (ctx->yanked)
+    {
+        HeapFree(GetProcessHeap(), 0, ctx->yanked);
+        ctx->yanked = NULL;
+    }
+}
+
 static void WCEL_SaveYank(WCEL_Context* ctx, int beg, int end)
 {
     int len = end - beg;
+    if (len <= 0) return;
+
+    WCEL_FreeYank(ctx);
     ctx->yanked = HeapReAlloc(GetProcessHeap(), 0, ctx->yanked, (len + 1) * sizeof(WCHAR));
     if (!ctx->yanked) return;
     memcpy(ctx->yanked, &ctx->line[beg], len * sizeof(WCHAR));
@@ -265,7 +312,7 @@
 
 static void	WCEL_HistoryInit(WCEL_Context* ctx)
 {
-    ctx->histPos = CONSOLE_GetNumHistoryEntries();
+    ctx->histPos  = CONSOLE_GetNumHistoryEntries();
     ctx->histSize = ctx->histPos + 1;
     ctx->histCurr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
 }
@@ -342,10 +389,11 @@
 
 static void WCEL_Done(WCEL_Context* ctx)
 {
+    WCHAR       nl = '\n';
     if (!WCEL_Grow(ctx, 1)) return;
     ctx->line[ctx->len++] = '\n';
     ctx->line[ctx->len] = 0;
-    WriteConsoleA(ctx->hConOut, "\n", 1, NULL, NULL);
+    WriteConsoleW(ctx->hConOut, &nl, 1, NULL, NULL);
     ctx->done = 1;
 }
 
@@ -422,13 +470,30 @@
     ctx->line[ctx->ofs] = ctx->line[ctx->ofs - 1];
     ctx->line[ctx->ofs - 1] = c;
 
-    WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs - 1], 2, WCEL_GetCoord(ctx, ctx->ofs - 1), NULL);
+    WCEL_Update(ctx, ctx->ofs - 1, 2);
     ctx->ofs++;
 }
 
 static void WCEL_TransposeWords(WCEL_Context* ctx)
 {
-    FIXME("NIY\n");
+    int	left_ofs = WCEL_GetLeftWordTransition(ctx, ctx->ofs),
+        right_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
+    if (left_ofs < ctx->ofs && right_ofs > ctx->ofs)
+    {
+        unsigned len_r = right_ofs - ctx->ofs;
+        unsigned len_l = ctx->ofs - left_ofs;
+    
+        char*   tmp = HeapAlloc(GetProcessHeap(), 0, len_r * sizeof(WCHAR));
+        if (!tmp) return;
+
+        memcpy(tmp, &ctx->line[ctx->ofs], len_r * sizeof(WCHAR));
+        memmove(&ctx->line[left_ofs + len_r], &ctx->line[left_ofs], len_l * sizeof(WCHAR));
+        memcpy(&ctx->line[left_ofs], tmp, len_r * sizeof(WCHAR));
+        
+        HeapFree(GetProcessHeap(), 0, tmp);
+        WCEL_Update(ctx, left_ofs, len_l + len_r);
+        ctx->ofs = right_ofs;
+    }
 }
 
 static void WCEL_LowerCaseWord(WCEL_Context* ctx)
@@ -439,8 +504,7 @@
 	int	i;
 	for (i = ctx->ofs; i <= new_ofs; i++)
 	    ctx->line[i] = tolowerW(ctx->line[i]);
-	WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
-				     WCEL_GetCoord(ctx, ctx->ofs), NULL);
+        WCEL_Update(ctx, ctx->ofs, new_ofs - ctx->ofs + 1);
 	ctx->ofs = new_ofs;
     }
 }
@@ -453,8 +517,7 @@
 	int	i;
 	for (i = ctx->ofs; i <= new_ofs; i++)
 	    ctx->line[i] = toupperW(ctx->line[i]);
-	WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
-				     WCEL_GetCoord(ctx, ctx->ofs), NULL);
+	WCEL_Update(ctx, ctx->ofs, new_ofs - ctx->ofs + 1);
 	ctx->ofs = new_ofs;
     }
 }
@@ -469,8 +532,7 @@
 	ctx->line[ctx->ofs] = toupperW(ctx->line[ctx->ofs]);
 	for (i = ctx->ofs + 1; i <= new_ofs; i++)
 	    ctx->line[i] = tolowerW(ctx->line[i]);
-	WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
-				     WCEL_GetCoord(ctx, ctx->ofs), NULL);
+	WCEL_Update(ctx, ctx->ofs, new_ofs - ctx->ofs + 1);
 	ctx->ofs = new_ofs;
     }
 }
@@ -478,8 +540,6 @@
 static void WCEL_Yank(WCEL_Context* ctx)
 {
     WCEL_InsertString(ctx, ctx->yanked);
-    HeapFree(GetProcessHeap(), 0, ctx->yanked);
-    ctx->yanked = NULL;
 }
 
 static void WCEL_KillToEndOfLine(WCEL_Context* ctx)
@@ -560,6 +620,44 @@
     if (ctx->histPos != ctx->histSize - 1) WCEL_MoveToHist(ctx, ctx->histSize - 1);
 }
 
+static void WCEL_Redraw(WCEL_Context* ctx)
+{
+    COORD       c = WCEL_GetCoord(ctx, ctx->len);
+    CHAR_INFO   ci;
+
+    WCEL_Update(ctx, 0, ctx->len);
+
+    ci.Char.UnicodeChar = ' ';
+    ci.Attributes = ctx->csbi.wAttributes;
+
+    CONSOLE_FillLineUniform(ctx->hConOut, c.X, c.Y, ctx->csbi.dwSize.X - c.X, &ci);
+}
+
+static void WCEL_RepeatCount(WCEL_Context* ctx)
+{
+#if 0
+/* FIXME: wait untill all console code is in kernel32 */
+    INPUT_RECORD        ir;
+    unsigned            repeat = 0;
+
+    while (WCEL_Get(ctx, &ir, FALSE))
+    {
+        if (ir.EventType != KEY_EVENT) break;
+        if (ir.Event.KeyEvent.bKeyDown)
+        {
+            if ((ir.Event.KeyEvent.dwControlKeyState & ~(NUMLOCK_ON|SCROLLLOCK_ON|CAPSLOCK_ON)) != 0)
+                break;
+            if (ir.Event.KeyEvent.uChar.UnicodeChar < '0' ||
+                ir.Event.KeyEvent.uChar.UnicodeChar > '9')
+                break;
+            repeat = repeat * 10 + ir.Event.KeyEvent.uChar.UnicodeChar - '0';
+        }
+        WCEL_Get(ctx, &ir, TRUE);
+    }
+    FIXME("=> %u\n", repeat);
+#endif
+}
+
 /* ====================================================================
  *
  * 		Key Maps
@@ -587,7 +685,7 @@
     {	CTRL('@'),	WCEL_SetMark		},
     {	CTRL('A'),	WCEL_MoveToBeg		},
     {	CTRL('B'),	WCEL_MoveLeft		},
-    /* C */
+    /* C: done in server */
     {	CTRL('D'),	WCEL_DeleteCurrChar	},
     {	CTRL('E'),	WCEL_MoveToEnd		},
     {	CTRL('F'),	WCEL_MoveRight		},
@@ -596,7 +694,7 @@
     /* I: meaningless (or tab ???) */
     {	CTRL('J'),	WCEL_Done		},
     {	CTRL('K'),	WCEL_KillToEndOfLine	},
-    /* L: [NIY] redraw the whole stuff */
+    {   CTRL('L'),      WCEL_Redraw             },
     {	CTRL('M'),	WCEL_Done		},
     {	CTRL('N'),	WCEL_MoveToNextHist	},
     /* O; insert line... meaningless */
@@ -605,7 +703,7 @@
     /* R: [NIY] search backwards... */
     /* S: [NIY] search forwards... */
     {	CTRL('T'),	WCEL_TransposeChar	},
-    /* U: [NIY] set repeat count... */
+    {   CTRL('U'),      WCEL_RepeatCount        },
     /* V: paragraph down... meaningless */
     {	CTRL('W'),	WCEL_KillMarkedZone	},
     {	CTRL('X'),	WCEL_ExchangeMark	},
@@ -709,6 +807,8 @@
 				    OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE ||
 	!GetConsoleScreenBufferInfo(ctx.hConOut, &ctx.csbi))
 	return NULL;
+    ctx.can_wrap = (GetConsoleMode(ctx.hConOut, &ks) && (ks & ENABLE_WRAP_AT_EOL_OUTPUT)) ? 1 : 0;
+
     if (!WCEL_Grow(&ctx, 1))
     {
 	CloseHandle(ctx.hConOut);
@@ -726,7 +826,7 @@
 	      ir.Event.KeyEvent.wVirtualKeyCode, ir.Event.KeyEvent.wVirtualScanCode,
 	      ir.Event.KeyEvent.uChar.UnicodeChar, ir.Event.KeyEvent.dwControlKeyState);
 
-/* EPP 	WCEL_Dump(&ctx, "before func"); */
+/* EPP  	WCEL_Dump(&ctx, "before func"); */
 	ofs = ctx.ofs;
         /* mask out some bits which don't interest us */
         ks = ir.Event.KeyEvent.dwControlKeyState & ~(NUMLOCK_ON|SCROLLLOCK_ON|CAPSLOCK_ON);
@@ -760,7 +860,7 @@
 	    WCEL_InsertChar(&ctx, ir.Event.KeyEvent.uChar.UnicodeChar);
 	else TRACE("Dropped event\n");
 
-/* EPP 	WCEL_Dump(&ctx, "after func"); */
+/* EPP         WCEL_Dump(&ctx, "after func"); */
 	if (ctx.ofs != ofs)
 	    SetConsoleCursorPosition(ctx.hConOut, WCEL_GetCoord(&ctx, ctx.ofs));
     }
@@ -769,6 +869,7 @@
 	HeapFree(GetProcessHeap(), 0, ctx.line);
 	ctx.line = NULL;
     }
+    WCEL_FreeYank(&ctx);
     if (ctx.line)
 	CONSOLE_AppendHistory(ctx.line);
 


More information about the wine-patches mailing list