Eric Pouech : kernel32: Modify editline logic so that it also work with bare consoles.

Alexandre Julliard julliard at winehq.org
Wed Sep 1 11:08:55 CDT 2010


Module: wine
Branch: master
Commit: efecd9c3377ec1e945ea967bfdb25fc8214f48cb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=efecd9c3377ec1e945ea967bfdb25fc8214f48cb

Author: Eric Pouech <eric.pouech at orange.fr>
Date:   Mon Aug 30 22:19:31 2010 +0200

kernel32: Modify editline logic so that it also work with bare consoles.

---

 dlls/kernel32/console.c         |    5 ++-
 dlls/kernel32/console_private.h |    2 +-
 dlls/kernel32/editline.c        |   63 ++++++++++++++++++++++++++++++++++-----
 3 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c
index 3b6dec0..cd2de5d 100644
--- a/dlls/kernel32/console.c
+++ b/dlls/kernel32/console.c
@@ -1523,11 +1523,12 @@ BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
     DWORD	charsread;
     LPWSTR	xbuf = lpBuffer;
     DWORD	mode;
+    BOOL        is_bare;
 
     TRACE("(%p,%p,%d,%p,%p)\n",
 	  hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved);
 
-    if (!GetConsoleMode(hConsoleInput, &mode))
+    if (!get_console_mode(hConsoleInput, &mode, &is_bare))
         return FALSE;
 
     if (mode & ENABLE_LINE_INPUT)
@@ -1535,7 +1536,7 @@ BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
 	if (!S_EditString || S_EditString[S_EditStrPos] == 0)
 	{
 	    HeapFree(GetProcessHeap(), 0, S_EditString);
-	    if (!(S_EditString = CONSOLE_Readline(hConsoleInput)))
+	    if (!(S_EditString = CONSOLE_Readline(hConsoleInput, !is_bare)))
 		return FALSE;
 	    S_EditStrPos = 0;
 	}
diff --git a/dlls/kernel32/console_private.h b/dlls/kernel32/console_private.h
index f8d5958..06a8bd6 100644
--- a/dlls/kernel32/console_private.h
+++ b/dlls/kernel32/console_private.h
@@ -31,6 +31,6 @@ extern void     CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int
 extern BOOL     CONSOLE_GetEditionMode(HANDLE, int*);
 
 /* editline.c */
-extern WCHAR*   CONSOLE_Readline(HANDLE);
+extern WCHAR*   CONSOLE_Readline(HANDLE, BOOL);
 
 #endif  /* __WINE_CONSOLE_PRIVATE_H */
diff --git a/dlls/kernel32/editline.c b/dlls/kernel32/editline.c
index ab70916..b79c5cb 100644
--- a/dlls/kernel32/editline.c
+++ b/dlls/kernel32/editline.c
@@ -53,6 +53,10 @@ typedef struct WCEL_Context {
     WCHAR*			line;		/* the line being edited */
     size_t			alloc;		/* number of WCHAR in line */
     unsigned    		len;		/* number of chars in line */
+    unsigned                    last_rub;       /* number of chars to rub to get to start
+                                                   (for consoles that can't change cursor pos) */
+    unsigned                    last_max;       /* max number of chars written
+                                                   (for consoles that can't change cursor pos) */
     unsigned			ofs;		/* offset for cursor in current line */
     WCHAR*			yanked;		/* yanked line */
     unsigned			mark;		/* marked point (emacs mode only) */
@@ -61,7 +65,8 @@ typedef struct WCEL_Context {
     HANDLE			hConOut;
     unsigned			done : 1,	/* to 1 when we're done with editing */
 	                        error : 1,	/* to 1 when an error occurred in the editing */
-                                can_wrap : 1;   /* to 1 when multi-line edition can take place */
+                                can_wrap : 1,   /* to 1 when multi-line edition can take place */
+                                can_pos_cursor : 1; /* to 1 when console can (re)position cursor */
     unsigned			histSize;
     unsigned			histPos;
     WCHAR*			histCurr;
@@ -123,10 +128,33 @@ static inline COORD WCEL_GetCoord(WCEL_Context* ctx, int ofs)
 
 static inline void WCEL_Update(WCEL_Context* ctx, int beg, int len)
 {
-    WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[beg], len,
-                                 WCEL_GetCoord(ctx, beg), NULL);
-    FillConsoleOutputAttribute(ctx->hConOut, ctx->csbi.wAttributes, len,
-                               WCEL_GetCoord(ctx, beg), NULL);
+    if (ctx->can_pos_cursor)
+    {
+        WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[beg], len,
+                                     WCEL_GetCoord(ctx, beg), NULL);
+        FillConsoleOutputAttribute(ctx->hConOut, ctx->csbi.wAttributes, len,
+                                   WCEL_GetCoord(ctx, beg), NULL);
+    }
+    else
+    {
+        char ch;
+        unsigned i;
+        DWORD dw;
+
+        /* erase previous chars */
+        ch = '\b';
+        for (i = beg; i < ctx->last_rub; i++)
+            WriteFile(ctx->hConOut, &ch, 1, &dw, NULL);
+        beg = min(beg, ctx->last_rub);
+
+        /* write new chars */
+        WriteConsoleW(ctx->hConOut, &ctx->line[beg], ctx->len - beg, &dw, NULL);
+        /* clean rest of line (if any) */
+        ch = ' ';
+        for (i = ctx->len; i < ctx->last_max; i++)
+            WriteFile(ctx->hConOut, &ch, 1, &dw, NULL);
+        ctx->last_rub = max(ctx->last_max, ctx->len);
+    }
 }
 
 /* ====================================================================
@@ -765,7 +793,7 @@ static const KeyMap Win32KeyMap[] =
  *
  * ====================================================================*/
 
-WCHAR* CONSOLE_Readline(HANDLE hConsoleIn)
+WCHAR* CONSOLE_Readline(HANDLE hConsoleIn, BOOL can_pos_cursor)
 {
     WCEL_Context	ctx;
     INPUT_RECORD	ir;
@@ -788,6 +816,7 @@ WCHAR* CONSOLE_Readline(HANDLE hConsoleIn)
 	!GetConsoleScreenBufferInfo(ctx.hConOut, &ctx.csbi))
 	return NULL;
     ctx.can_wrap = (GetConsoleMode(ctx.hConOut, &ks) && (ks & ENABLE_WRAP_AT_EOL_OUTPUT)) ? 1 : 0;
+    ctx.can_pos_cursor = can_pos_cursor;
 
     if (!WCEL_Grow(&ctx, 1))
     {
@@ -842,8 +871,26 @@ WCHAR* CONSOLE_Readline(HANDLE hConsoleIn)
 	else TRACE("Dropped event\n");
 
 /* EPP         WCEL_Dump(&ctx, "after func"); */
-	if (ctx.ofs != ofs)
-	    SetConsoleCursorPosition(ctx.hConOut, WCEL_GetCoord(&ctx, ctx.ofs));
+        if (ctx.can_pos_cursor)
+        {
+            if (ctx.ofs != ofs)
+                SetConsoleCursorPosition(ctx.hConOut, WCEL_GetCoord(&ctx, ctx.ofs));
+        }
+        else if (!ctx.done && !ctx.error)
+        {
+            char        ch;
+            unsigned    i;
+            DWORD       dw;
+
+            /* erase previous chars */
+            ch = '\b';
+            for (i = 0; i < ctx.last_rub; i++)
+                WriteFile(ctx.hConOut, &ch, 1, &dw, NULL);
+
+            /* write chars up to cursor */
+            WriteConsoleW(ctx.hConOut, ctx.line, ctx.ofs, &dw, NULL);
+            if ((ctx.last_rub = ctx.ofs) > ctx.last_max) ctx.last_max = ctx.ofs;
+        }
     }
     if (ctx.error)
     {




More information about the wine-cvs mailing list