Exemplo n.º 1
0
WCHAR* CONSOLE_Readline(HANDLE hConsoleIn)
{
    WCEL_Context	ctx;
    INPUT_RECORD	ir;
    const KeyMap*	km;
    const KeyEntry*	ke;
    unsigned		ofs;
    void		(*func)(struct WCEL_Context* ctx);
    DWORD               ks;
    int                 use_emacs;

    memset(&ctx, 0, sizeof(ctx));
    ctx.hConIn = hConsoleIn;
    WCEL_HistoryInit(&ctx);

    if (!CONSOLE_GetEditionMode(hConsoleIn, &use_emacs))
        use_emacs = 0;

    if ((ctx.hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
				    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);
	return NULL;
    }
    ctx.line[0] = 0;

/* EPP     WCEL_Dump(&ctx, "init"); */

    while (!ctx.done && !ctx.error && WCEL_Get(&ctx, &ir))
    {
	if (ir.EventType != KEY_EVENT) continue;
	TRACE("key%s repeatCount=%u, keyCode=%02x scanCode=%02x char=%02x keyState=%08x\n",
	      ir.Event.KeyEvent.bKeyDown ? "Down" : "Up  ", ir.Event.KeyEvent.wRepeatCount,
	      ir.Event.KeyEvent.wVirtualKeyCode, ir.Event.KeyEvent.wVirtualScanCode,
	      ir.Event.KeyEvent.uChar.UnicodeChar, ir.Event.KeyEvent.dwControlKeyState);
	if (!ir.Event.KeyEvent.bKeyDown) continue;

/* 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|ENHANCED_KEY);

	func = NULL;
	for (km = (use_emacs) ? EmacsKeyMap : Win32KeyMap; km->entries != NULL; km++)
	{
	    if (km->keyState != ks)
		continue;
	    if (km->chkChar)
	    {
		for (ke = &km->entries[0]; ke->func != 0; ke++)
		    if (ke->val == ir.Event.KeyEvent.uChar.UnicodeChar) break;
	    }
	    else
	    {
		for (ke = &km->entries[0]; ke->func != 0; ke++)
		    if (ke->val == ir.Event.KeyEvent.wVirtualKeyCode) break;

	    }
	    if (ke->func)
	    {
		func = ke->func;
		break;
	    }
	}

	if (func)
	    (func)(&ctx);
	else if (!(ir.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED))
	    WCEL_InsertChar(&ctx, ir.Event.KeyEvent.uChar.UnicodeChar);
	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.error)
    {
	HeapFree(GetProcessHeap(), 0, ctx.line);
	ctx.line = NULL;
    }
    WCEL_FreeYank(&ctx);
    if (ctx.line)
	CONSOLE_AppendHistory(ctx.line);

    CloseHandle(ctx.hConOut);
    HeapFree(GetProcessHeap(), 0, ctx.histCurr);
    return ctx.line;
}
Exemplo n.º 2
0
WCHAR* CONSOLE_Readline(HANDLE hConsoleIn, BOOL can_pos_cursor)
{
    WCEL_Context	ctx;
    INPUT_RECORD	ir;
    const KeyMap*	km;
    const KeyEntry*	ke;
    unsigned		ofs;
    void		(*func)(struct WCEL_Context* ctx);
    DWORD               mode, input_mode, ks;
    int                 use_emacs;

    memset(&ctx, 0, sizeof(ctx));
    ctx.hConIn = hConsoleIn;
    WCEL_HistoryInit(&ctx);

    if (!CONSOLE_GetEditionMode(hConsoleIn, &use_emacs))
        use_emacs = 0;

    if ((ctx.hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
				    OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE ||
	!GetConsoleScreenBufferInfo(ctx.hConOut, &ctx.csbi))
	return NULL;
    if (!GetConsoleMode(hConsoleIn, &mode)) mode = 0;
    input_mode = mode;
    ctx.shall_echo = (mode & ENABLE_ECHO_INPUT) ? 1 : 0;
    ctx.insert = (mode & (ENABLE_INSERT_MODE|ENABLE_EXTENDED_FLAGS)) == (ENABLE_INSERT_MODE|ENABLE_EXTENDED_FLAGS) ? 1 : 0;
    if (!GetConsoleMode(ctx.hConOut, &mode)) mode = 0;
    ctx.can_wrap = (mode & ENABLE_WRAP_AT_EOL_OUTPUT) ? 1 : 0;
    ctx.can_pos_cursor = can_pos_cursor;
    GetConsoleCursorInfo(ctx.hConOut, &ctx.cinfo);

    if (!WCEL_Grow(&ctx, 1))
    {
	CloseHandle(ctx.hConOut);
	return NULL;
    }
    ctx.line[0] = 0;

/* EPP     WCEL_Dump(&ctx, "init"); */

    while (!ctx.done && !ctx.error && WCEL_Get(&ctx, &ir))
    {
	if (ir.EventType != KEY_EVENT) continue;
	TRACE("key%s repeatCount=%u, keyCode=%02x scanCode=%02x char=%02x keyState=%08x\n",
	      ir.Event.KeyEvent.bKeyDown ? "Down" : "Up  ", ir.Event.KeyEvent.wRepeatCount,
	      ir.Event.KeyEvent.wVirtualKeyCode, ir.Event.KeyEvent.wVirtualScanCode,
	      ir.Event.KeyEvent.uChar.UnicodeChar, ir.Event.KeyEvent.dwControlKeyState);
	if (!ir.Event.KeyEvent.bKeyDown) continue;

/* 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|ENHANCED_KEY);

	func = NULL;
	for (km = (use_emacs) ? EmacsKeyMap : Win32KeyMap; km->entries != NULL; km++)
	{
	    if (km->keyState != ks)
		continue;
	    if (km->chkChar)
	    {
		for (ke = &km->entries[0]; ke->func != 0; ke++)
		    if (ke->val == ir.Event.KeyEvent.uChar.UnicodeChar) break;
	    }
	    else
	    {
		for (ke = &km->entries[0]; ke->func != 0; ke++)
		    if (ke->val == ir.Event.KeyEvent.wVirtualKeyCode) break;

	    }
	    if (ke->func)
	    {
		func = ke->func;
		break;
	    }
	}

        GetConsoleMode(hConsoleIn, &mode);
        if (input_mode != mode)
        {
            input_mode = mode;
            ctx.insertkey = 0;
        }
        ctx.insert = (mode & (ENABLE_INSERT_MODE|ENABLE_EXTENDED_FLAGS)) ==
                     (ENABLE_INSERT_MODE|ENABLE_EXTENDED_FLAGS);
        if (ctx.insertkey)
            ctx.insert = !ctx.insert;

	if (func)
	    (func)(&ctx);
	else if (!(ir.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED))
	    WCEL_InsertChar(&ctx, ir.Event.KeyEvent.uChar.UnicodeChar);
	else TRACE("Dropped event\n");

/* EPP         WCEL_Dump(&ctx, "after func"); */
        if (!ctx.shall_echo) continue;
        if (ctx.can_pos_cursor)
        {
            if (ctx.ofs != ofs)
                SetConsoleCursorPosition(ctx.hConOut, WCEL_GetCoord(&ctx, ctx.ofs));
        }
        else if (!ctx.done && !ctx.error)
        {
            DWORD last;
            /* erase previous chars */
            WCEL_WriteNChars(&ctx, '\b', ctx.last_rub);

            /* write chars up to cursor */
            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)
    {
	HeapFree(GetProcessHeap(), 0, ctx.line);
	ctx.line = NULL;
    }
    WCEL_FreeYank(&ctx);
    if (ctx.line)
	CONSOLE_AppendHistory(ctx.line);

    CloseHandle(ctx.hConOut);
    HeapFree(GetProcessHeap(), 0, ctx.histCurr);
    return ctx.line;
}