Eric Pouech : kernel32: In readline, now print control characters with ^ escape.
Alexandre Julliard
julliard at winehq.org
Mon Dec 13 10:43:20 CST 2010
Module: wine
Branch: master
Commit: 8aa3ec414d8ff4a5ebd7ca32fa171c267af2640e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=8aa3ec414d8ff4a5ebd7ca32fa171c267af2640e
Author: Eric Pouech <eric.pouech at orange.fr>
Date: Sun Dec 12 22:31:49 2010 +0100
kernel32: In readline, now print control characters with ^ escape.
---
dlls/kernel32/editline.c | 136 ++++++++++++++++++++++++++++++++++------------
1 files changed, 101 insertions(+), 35 deletions(-)
diff --git a/dlls/kernel32/editline.c b/dlls/kernel32/editline.c
index 4dff110..b33798b 100644
--- a/dlls/kernel32/editline.c
+++ b/dlls/kernel32/editline.c
@@ -57,7 +57,7 @@ typedef struct WCEL_Context {
(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 */
+ unsigned ofs; /* offset for cursor in current line */
WCHAR* yanked; /* yanked line */
unsigned mark; /* marked point (emacs mode only) */
CONSOLE_SCREEN_BUFFER_INFO csbi; /* current state (initial cursor, window size, attribute) */
@@ -111,10 +111,27 @@ 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)
+static inline int WCEL_CharWidth(WCHAR wch)
+{
+ return wch < ' ' ? 2 : 1;
+}
+
+static inline int WCEL_StringWidth(const WCHAR* str, int beg, int len)
+{
+ int i, ofs;
+
+ for (i = 0, ofs = 0; i < len; i++)
+ ofs += WCEL_CharWidth(str[beg + i]);
+ return ofs;
+}
+
+static inline COORD WCEL_GetCoord(WCEL_Context* ctx, int strofs)
{
COORD c;
int len = ctx->csbi.dwSize.X - ctx->csbi.dwCursorPosition.X;
+ int ofs;
+
+ ofs = WCEL_StringWidth(ctx->line, 0, strofs);
c.Y = ctx->csbi.dwCursorPosition.Y;
if (ofs >= len)
@@ -127,35 +144,79 @@ static inline COORD WCEL_GetCoord(WCEL_Context* ctx, int ofs)
return c;
}
+static DWORD WCEL_WriteConsole(WCEL_Context* ctx, DWORD beg, DWORD len)
+{
+ DWORD i, last, dw, ret = 0;
+ WCHAR tmp[2];
+
+ for (i = last = 0; i < len; i++)
+ {
+ if (ctx->line[beg + i] < ' ')
+ {
+ if (last != i)
+ {
+ WriteConsoleW(ctx->hConOut, &ctx->line[beg + last], i - last, &dw, NULL);
+ ret += dw;
+ }
+ tmp[0] = '^';
+ tmp[1] = '@' + ctx->line[beg + i];
+ WriteConsoleW(ctx->hConOut, tmp, 2, &dw, NULL);
+ last = i + 1;
+ ret += dw;
+ }
+ }
+ if (last != len)
+ {
+ WriteConsoleW(ctx->hConOut, &ctx->line[beg + last], len - last, &dw, NULL);
+ ret += dw;
+ }
+ return ret;
+}
+
+static inline void WCEL_WriteNChars(WCEL_Context* ctx, char ch, int count)
+{
+ DWORD dw;
+
+ if (count > 0)
+ {
+ while (count--) WriteFile(ctx->hConOut, &ch, 1, &dw, NULL);
+ }
+}
+
static inline void WCEL_Update(WCEL_Context* ctx, int beg, int len)
{
- if (!ctx->shall_echo) return;
- if (ctx->can_pos_cursor)
+ int i, last;
+ WCHAR tmp[2];
+
+ /* bare console case is handled in CONSOLE_ReadLine (we always reprint the whole string) */
+ if (!ctx->shall_echo || !ctx->can_pos_cursor) return;
+
+ for (i = last = beg; i < beg + len; i++)
{
- 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->line[i] < ' ')
+ {
+ if (last != i)
+ {
+ WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[last], i - last,
+ WCEL_GetCoord(ctx, last), NULL);
+ FillConsoleOutputAttribute(ctx->hConOut, ctx->csbi.wAttributes, i - last,
+ WCEL_GetCoord(ctx, last), NULL);
+ }
+ tmp[0] = '^';
+ tmp[1] = '@' + ctx->line[i];
+ WriteConsoleOutputCharacterW(ctx->hConOut, tmp, 2,
+ WCEL_GetCoord(ctx, i), NULL);
+ FillConsoleOutputAttribute(ctx->hConOut, ctx->csbi.wAttributes, 2,
+ WCEL_GetCoord(ctx, i), NULL);
+ last = i + 1;
+ }
}
- else
+ if (last != beg + len)
{
- 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);
+ WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[last], i - last,
+ WCEL_GetCoord(ctx, last), NULL);
+ FillConsoleOutputAttribute(ctx->hConOut, ctx->csbi.wAttributes, i - last,
+ WCEL_GetCoord(ctx, last), NULL);
}
}
@@ -887,18 +948,23 @@ WCHAR* CONSOLE_Readline(HANDLE hConsoleIn, BOOL can_pos_cursor)
}
else if (!ctx.done && !ctx.error)
{
- char ch;
- unsigned i;
- DWORD dw;
-
+ DWORD last;
/* erase previous chars */
- ch = '\b';
- for (i = 0; i < ctx.last_rub; i++)
- WriteFile(ctx.hConOut, &ch, 1, &dw, NULL);
+ WCEL_WriteNChars(&ctx, '\b', ctx.last_rub);
/* 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;
+ ctx.last_rub = WCEL_WriteConsole(&ctx, 0, ctx.ofs);
+ /* write chars past cursor */
+ last = ctx.last_rub + WCEL_WriteConsole(&ctx, ctx.ofs, ctx.len - ctx.ofs);
+ if (last < ctx.last_max) /* ctx.line has been shortened, erase */
+ {
+ WCEL_WriteNChars(&ctx, ' ', ctx.last_max - last);
+ WCEL_WriteNChars(&ctx, '\b', ctx.last_max - last);
+ ctx.last_max = last;
+ }
+ else ctx.last_max = last;
+ /* reposition at cursor */
+ WCEL_WriteNChars(&ctx, '\b', last - ctx.last_rub);
}
}
if (ctx.error)
More information about the wine-cvs
mailing list