Пример #1
0
LRESULT CALLBACK EditBoxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_KEYDOWN:
		{
			if (LOWORD(wParam) == VK_RETURN)
			{
				if (serverConnection)
				{
					static char buf[50000];
					SendMessage(editBoxHwnd, WM_GETTEXT, sizeof buf, reinterpret_cast<LPARAM>(buf));
					buf[(sizeof buf) - 1] = '\0';

					commandHistory.push_back(buf);
					currentCommandHistoryPos = commandHistory.end();

					Words words;
					tokenize(buf, words);

					serverConnection->sendRequest(words);

					SendMessage(editBoxHwnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(""));
				}

				return TRUE;
			}
			else if (LOWORD(wParam) == VK_UP)
			{
				if (currentCommandHistoryPos != commandHistory.begin())
				{
					currentCommandHistoryPos--;
					const char* command = currentCommandHistoryPos->c_str();
					SendMessage(editBoxHwnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(command));
					size_t commandLength = strlen(command);
					SendMessage(editBoxHwnd, EM_SETSEL, commandLength, commandLength);
				}
				return TRUE;
			}
			else if (LOWORD(wParam) == VK_DOWN)
			{
				if (currentCommandHistoryPos != commandHistory.end())
				{
					currentCommandHistoryPos++;
					const char* command = (currentCommandHistoryPos != commandHistory.end()) ? currentCommandHistoryPos->c_str() : "";
					SendMessage(editBoxHwnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(command));
					size_t commandLength = strlen(command);
					SendMessage(editBoxHwnd, EM_SETSEL, commandLength, commandLength);
				}
				return TRUE;
			}
		}
		break;
	}

	return CallWindowProc(editBoxOriginalWndProc, hWnd, message, wParam, lParam);
}
Пример #2
0
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
    liquids_hist.load("liquids.history");
    commands.clear();
    commands.push_back(PluginCommand("liquids", "Place magma, water or obsidian.", df_liquids, true));
    return CR_OK;
}
Пример #3
0
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
    tiletypes_hist.load("tiletypes.history");
    commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true));
    commands.push_back(PluginCommand("tiletypes-command", "Run the given commands (seperated by ' ; '; an empty command is the same as run).", df_tiletypes_command));
    commands.push_back(PluginCommand("tiletypes-here", "Use the last settings from tiletypes, including brush, at cursor location.", df_tiletypes_here));
    commands.push_back(PluginCommand("tiletypes-here-point", "Use the last settings from tiletypes, not including brush, at cursor location.", df_tiletypes_here_point));
    return CR_OK;
}
Пример #4
0
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
    tiletypes_hist.load("tiletypes.history");
    commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true));
    commands.push_back(PluginCommand("tiletypes-command", "Run tiletypes commands (seperated by ' ; ')", df_tiletypes_command));
    commands.push_back(PluginCommand("tiletypes-here", "Repeat tiletypes command at cursor (with brush)", df_tiletypes_here));
    commands.push_back(PluginCommand("tiletypes-here-point", "Repeat tiletypes command at cursor (without brush)", df_tiletypes_here_point));
    return CR_OK;
}
Пример #5
0
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
    liquids_hist.load("liquids.history");
    commands.push_back(PluginCommand(
        "liquids", "Place magma, water or obsidian.",
        df_liquids, true)); // interactive, needs console for prompt
    commands.push_back(PluginCommand(
        "liquids-here", "Use settings from liquids at cursor position.",
        df_liquids_here, Gui::cursor_hotkey, // non-interactive, needs ingame cursor
        "  Identical to pressing enter in liquids, intended for use as keybinding.\n"
        "  Can (but doesn't need to) be called while liquids is running in the console."));
    return CR_OK;
}
Пример #6
0
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
    liquids_hist.load("liquids.history");
    commands.push_back(PluginCommand(
        "liquids", "Place magma, water or obsidian.",
        df_liquids, true,
        "This tool allows placing magma, water and other similar things.\n"
        "It is interactive and further help is available when you run it.\n"
        "The settings will be remembered until dfhack is closed and you can call\n"
        "'liquids-here' (mapped to a hotkey) to paint liquids at the cursor position\n"
        "without the need to go back to the dfhack console.\n")); // interactive, needs console for prompt
    commands.push_back(PluginCommand(
        "liquids-here", "Use settings from liquids at cursor position.",
        df_liquids_here, Gui::cursor_hotkey, // non-interactive, needs ingame cursor
        "  This command is intended to be mapped to a hotkey and is identical to pressing Enter in liquids with the current parameters.\n"));
    return CR_OK;
}
Пример #7
0
command_result df_liquids (color_ostream &out_, vector <string> & parameters)
{
    if(!out_.is_console())
        return CR_FAILURE;
    Console &out = static_cast<Console&>(out_);

    for(size_t i = 0; i < parameters.size();i++)
    {
        if(parameters[i] == "help" || parameters[i] == "?")
        {
            out.print(  "This tool allows placing magma, water and other similar things.\n"
                        "It is interactive and further help is available when you run it.\n"
                        "The settings will be remembered until dfhack is closed and you can call\n"
                        "'liquids-here' (mapped to a hotkey) to paint liquids at the cursor position\n"
                        "without the need to go back to the dfhack console.\n");
            return CR_OK;
        }
    }

    if (!Maps::IsValid())
    {
        out.printerr("Map is not available!\n");
        return CR_FAILURE;
    }

    bool end = false;

    out << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;

    while(!end)
    {
        string command = "";

        std::stringstream str;
        str <<"[" << mode << ":" << brushname;
        if (brushname == "range")
            str << "(w" << width << ":h" << height << ":z" << z_levels << ")";
        str << ":" << amount << ":" << flowmode << ":" << setmode << "]#";
        if(out.lineedit(str.str(),command,liquids_hist) == -1)
            return CR_FAILURE;
        liquids_hist.add(command);

        if(command=="help" || command == "?")
        {
            out << "Modes:" << endl
                 << "m             - switch to magma" << endl
                 << "w             - switch to water" << endl
                 << "o             - make obsidian wall instead" << endl
                 << "of            - make obsidian floors" << endl
                 << "rs            - make a river source" << endl
                 << "f             - flow bits only" << endl
                 << "wclean        - remove salt and stagnant flags from tiles" << endl
                 << "Set-Modes (only for magma/water):" << endl
                 << "s+            - only add" << endl
                 << "s.            - set" << endl
                 << "s-            - only remove" << endl
                 << "Properties (only for magma/water):" << endl
                 << "f+            - make the spawned liquid flow" << endl
                 << "f.            - don't change flow state (read state in flow mode)" << endl
                 << "f-            - make the spawned liquid static" << endl
                 << "0-7           - set liquid amount" << endl
                 << "Brush:" << endl
                 << "point         - single tile [p]" << endl
                 << "range         - block with cursor at bottom north-west [r]" << endl
                 << "                (any place, any size)" << endl
                 << "block         - DF map block with cursor in it" << endl
                 << "                (regular spaced 16x16x1 blocks)" << endl
                 << "column        - Column from cursor, up through free space" << endl
                 << "flood         - Flood-fill water tiles from cursor" << endl
                 << "                (only makes sense with wclean)" << endl
                 << "Other:" << endl
                 << "q             - quit" << endl
                 << "help or ?     - print this list of commands" << endl
                 << "empty line    - put liquid" << endl
                 << endl
                 << "Usage: point the DF cursor at a tile you want to modify" << endl
                 << "and use the commands available :)" << endl;
            out << endl << "Settings will be remembered until you quit DF. You can call liquids-here to execute the last configured action. Useful in combination with keybindings." << endl;
        }
        else if(command == "m")
        {
            mode = "magma";
        }
        else if(command == "o")
        {
            mode = "obsidian";
        }
        else if(command == "of")
        {
            mode = "obsidian_floor";
        }
        else if(command == "w")
        {
            mode = "water";
        }
        else if(command == "f")
        {
            mode = "flowbits";
        }
        else if(command == "rs")
        {
            mode = "riversource";
        }
        else if(command == "wclean")
        {
            mode = "wclean";
        }
        else if(command == "point" || command == "p")
        {
            brushname = "point";
        }
        else if(command == "range" || command == "r")
        {
            std::stringstream str;
            CommandHistory range_hist;
            str << " :set range width<" << width << "># ";
            out.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            width = command == "" ? width : atoi (command.c_str());
            if(width < 1) width = 1;

            str.str("");
            str << " :set range height<" << height << "># ";
            out.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            height = command == "" ? height : atoi (command.c_str());
            if(height < 1) height = 1;

            str.str("");
            str << " :set range z-levels<" << z_levels << "># ";
            out.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            z_levels = command == "" ? z_levels : atoi (command.c_str());
            if(z_levels < 1) z_levels = 1;
            if(width == 1 && height == 1 && z_levels == 1)
            {
                brushname = "point";
            }
            else
            {
                brushname = "range";
            }
        }
        else if(command == "block")
        {
            brushname = "block";
        }
        else if(command == "column")
        {
            brushname = "column";
        }
        else if(command == "flood")
        {
            brushname = "flood";
        }
        else if(command == "q")
        {
            end = true;
        }
        else if(command == "f+")
        {
            flowmode = "f+";
        }
        else if(command == "f-")
        {
            flowmode = "f-";
        }
        else if(command == "f.")
        {
            flowmode = "f.";
        }
        else if(command == "s+")
        {
            setmode = "s+";
        }
        else if(command == "s-")
        {
            setmode = "s-";
        }
        else if(command == "s.")
        {
            setmode = "s.";
        }
        // blah blah, bad code, bite me.
        else if(command == "0")
            amount = 0;
        else if(command == "1")
            amount = 1;
        else if(command == "2")
            amount = 2;
        else if(command == "3")
            amount = 3;
        else if(command == "4")
            amount = 4;
        else if(command == "5")
            amount = 5;
        else if(command == "6")
            amount = 6;
        else if(command == "7")
            amount = 7;
        else if(command.empty())
        {
            df_liquids_execute(out);
        }
        else
        {
            out << command << " : unknown command." << endl;
        }
    }
    return CR_OK;
}
Пример #8
0
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
    liquids_hist.save("liquids.history");
    return CR_OK;
}
Пример #9
0
command_result df_liquids (color_ostream &out_, vector <string> & parameters)
{
    if(!out_.is_console())
        return CR_FAILURE;
    Console &out = static_cast<Console&>(out_);

    for(size_t i = 0; i < parameters.size();i++)
    {
        if(parameters[i] == "help" || parameters[i] == "?")
            return CR_WRONG_USAGE;
    }

    if (!Maps::IsValid())
    {
        out.printerr("Map is not available!\n");
        return CR_FAILURE;
    }

    std::vector<std::string> commands;
    bool end = false;

    out << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;

    while(!end)
    {
        string input = "";

        std::stringstream str;
        print_prompt(str, cur_mode);
        str << "# ";
        if(out.lineedit(str.str(),input,liquids_hist) == -1)
            return CR_FAILURE;
        liquids_hist.add(input);

        commands.clear();
        Core::cheap_tokenise(input, commands);
        string command =  commands.empty() ? "" : commands[0];

        if(command=="help" || command == "?")
        {
            out << "Modes:" << endl
                 << "m             - switch to magma" << endl
                 << "w             - switch to water" << endl
                 << "o             - make obsidian wall instead" << endl
                 << "of            - make obsidian floors" << endl
                 << "rs            - make a river source" << endl
                 << "f             - flow bits only" << endl
                 << "wclean        - remove salt and stagnant flags from tiles" << endl
                 << "Set-Modes (only for magma/water):" << endl
                 << "s+            - only add" << endl
                 << "s.            - set" << endl
                 << "s-            - only remove" << endl
                 << "Properties (only for magma/water):" << endl
                 << "f+            - make the spawned liquid flow" << endl
                 << "f.            - don't change flow state (read state in flow mode)" << endl
                 << "f-            - make the spawned liquid static" << endl
                 << "Permaflow (only for water):" << endl
                 << "pf.           - don't change permaflow state" << endl
                 << "pf-           - make the spawned liquid static" << endl
                 << "pf[NS][EW]    - make the spawned liquid permanently flow" << endl
                 << "0-7           - set liquid amount" << endl
                 << "Brush:" << endl
                 << "point         - single tile [p]" << endl
                 << "range         - block with cursor at bottom north-west [r]" << endl
                 << "                (any place, any size)" << endl
                 << "block         - DF map block with cursor in it" << endl
                 << "                (regular spaced 16x16x1 blocks)" << endl
                 << "column        - Column from cursor, up through free space" << endl
                 << "flood         - Flood-fill water tiles from cursor" << endl
                 << "                (only makes sense with wclean)" << endl
                 << "Other:" << endl
                 << "q             - quit" << endl
                 << "help or ?     - print this list of commands" << endl
                 << "empty line    - put liquid" << endl
                 << endl
                 << "Usage: point the DF cursor at a tile you want to modify" << endl
                 << "and use the commands available :)" << endl;
            out << endl << "Settings will be remembered until you quit DF. You can call liquids-here to execute the last configured action. Useful in combination with keybindings." << endl;
        }
        else if(command == "m")
        {
            cur_mode.paint = P_MAGMA;
        }
        else if(command == "o")
        {
            cur_mode.paint = P_OBSIDIAN;
        }
        else if(command == "of")
        {
            cur_mode.paint = P_OBSIDIAN_FLOOR;
        }
        else if(command == "w")
        {
            cur_mode.paint = P_WATER;
        }
        else if(command == "f")
        {
            cur_mode.paint = P_FLOW_BITS;
        }
        else if(command == "rs")
        {
            cur_mode.paint = P_RIVER_SOURCE;
        }
        else if(command == "wclean")
        {
            cur_mode.paint = P_WCLEAN;
        }
        else if(command == "point" || command == "p")
        {
            cur_mode.brush = B_POINT;
        }
        else if(command == "range" || command == "r")
        {
            int width, height, z_levels;
            command_result res = parseRectangle(out, commands, 1, commands.size(),
                                                width, height, z_levels);
            if (res != CR_OK)
            {
                return res;
            }

            if (width == 1 && height == 1 && z_levels == 1)
            {
                cur_mode.brush = B_POINT;
                cur_mode.size = df::coord(1, 1, 1);
            }
            else
            {
                cur_mode.brush = B_RANGE;
                cur_mode.size = df::coord(width, height, z_levels);
            }
        }
        else if(command == "block")
        {
            cur_mode.brush = B_BLOCK;
        }
        else if(command == "column")
        {
            cur_mode.brush = B_COLUMN;
        }
        else if(command == "flood")
        {
            cur_mode.brush = B_FLOOD;
        }
        else if(command == "q")
        {
            end = true;
        }
        else if(command == "f+")
        {
            cur_mode.flowmode = M_INC;
        }
        else if(command == "f-")
        {
            cur_mode.flowmode = M_DEC;
        }
        else if(command == "f.")
        {
            cur_mode.flowmode = M_KEEP;
        }
        else if(command == "s+")
        {
            cur_mode.setmode = M_INC;
        }
        else if(command == "s-")
        {
            cur_mode.setmode = M_DEC;
        }
        else if(command == "s.")
        {
            cur_mode.setmode = M_KEEP;
        }
        else if (command.size() > 2 && memcmp(command.c_str(), "pf", 2) == 0)
        {
            auto *tail = command.c_str()+2;
            for (int pm = PF_KEEP; pm <= PF_SOUTHWEST; pm++)
            {
                if (strcmp(tail, permaflow_name[pm]) != 0)
                    continue;
                cur_mode.permaflow = PermaflowMode(pm);
                tail = NULL;
                break;
            }
            if (tail)
                out << command << " : invalid permaflow mode" << endl;
        }
        // blah blah, bad code, bite me.
        else if(command == "0")
            cur_mode.amount = 0;
        else if(command == "1")
            cur_mode.amount = 1;
        else if(command == "2")
            cur_mode.amount = 2;
        else if(command == "3")
            cur_mode.amount = 3;
        else if(command == "4")
            cur_mode.amount = 4;
        else if(command == "5")
            cur_mode.amount = 5;
        else if(command == "6")
            cur_mode.amount = 6;
        else if(command == "7")
            cur_mode.amount = 7;
        else if(command.empty())
        {
            df_liquids_execute(out);
        }
        else
        {
            out << command << " : unknown command." << endl;
        }
    }
    return CR_OK;
}
Пример #10
0
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
    tiletypes_hist.save("tiletypes.history");
    return CR_OK;
}
Пример #11
0
DFhackCExport command_result plugin_shutdown ( Core * c )
{
    liquids_hist.save("liquids.history");
    return CR_OK;
}
Пример #12
0
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
	currentCommandHistoryPos = commandHistory.end();

	static TCHAR szWindowClass[] = _T("win32app");
	static TCHAR szTitle[] = _T("RCON Console");

	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = szWindowClass;
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

	if (!RegisterClassEx(&wcex))
	{
		MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Error"), NULL);

		return 1;
	}

	::hInstance = hInstance; // Store instance handle in our global variable

	// The parameters to CreateWindow explained:
	// szWindowClass: the name of the application
	// szTitle: the text that appears in the title bar
	// WS_OVERLAPPEDWINDOW: the type of window to create
	// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
	// 500, 100: initial size (width, length)
	// NULL: the parent of this window
	// NULL: this application does not have a menu bar
	// hInstance: the first parameter from WinMain
	// NULL: not used in this application
	RECT windowRect = { 0, 0, InitialWindowWidth, InitialWindowHeight };
	AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);
	HWND hWnd = CreateWindow(
		szWindowClass,
		szTitle,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL
	);
	if (!hWnd)
	{
		MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Error"), NULL);

		return 1;
	}

	// The parameters to ShowWindow explained:
	// hWnd: the value returned from CreateWindow
	// nCmdShow: the fourth parameter from WinMain
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	serverConnection = new ServerConnectionThread(hWnd);

	// Main message loop:
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	serverConnection->requestQuit();

	delete serverConnection;

	return (int) msg.wParam;
}
Пример #13
0
        int prompt_loop(mutex * lock, CommandHistory & history)
        {
            int fd = STDIN_FILENO;
            size_t plen = prompt.size();
            int history_index = 0;
            raw_buffer.clear();
            raw_cursor = 0;
            /* The latest history entry is always our current buffer, that
             * initially is just an empty string. */
            const std::string empty;
            history.add(empty);
            if (::write(fd,prompt.c_str(),prompt.size()) == -1) return -1;
            while(1)
            {
                unsigned char c;
                int isok;
                unsigned char seq[2], seq2;
                lock->unlock();
                if(!read_char(c))
                {
                    lock->lock();
                    return -2;
                }
                lock->lock();
                /* Only autocomplete when the callback is set. It returns < 0 when
                 * there was an error reading from fd. Otherwise it will return the
                 * character that should be handled next. */
                if (c == 9)
                {
                    /*
                    if( completionCallback != NULL) {
                        c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols);
                        // Return on errors
                        if (c < 0) return len;
                        // Read next character when 0
                        if (c == 0) continue;
                    }
                    else
                    {
                        // ignore tab
                        continue;
                    }
                    */
                    // just ignore tabs
                    continue;
                }

                switch(c)
                {
                case 13:    // enter
                    history.remove();
                    return raw_buffer.size();
                case 3:     // ctrl-c
                    errno = EAGAIN;
                    return -1;
                case 127:   // backspace
                case 8:     // ctrl-h
                    if (raw_cursor > 0 && raw_buffer.size() > 0)
                    {
                        raw_buffer.erase(raw_cursor-1,1);
                        raw_cursor--;
                        prompt_refresh();
                    }
                    break;
                case 27:    // escape sequence
                    lock->unlock();
                    if(!read_char(seq[0]) || !read_char(seq[1]))
                    {
                        lock->lock();
                        return -2;
                    }
                    lock->lock();
                    if(seq[0] == '[')
                    {
                        if (seq[1] == 'D')
                        {
                            left_arrow:
                            if (raw_cursor > 0)
                            {
                                raw_cursor--;
                                prompt_refresh();
                            }
                        }
                        else if ( seq[1] == 'C')
                        {
                            right_arrow:
                            /* right arrow */
                            if (raw_cursor != raw_buffer.size())
                            {
                                raw_cursor++;
                                prompt_refresh();
                            }
                        }
                        else if (seq[1] == 'A' || seq[1] == 'B')
                        {
                            /* up and down arrow: history */
                            if (history.size() > 1)
                            {
                                /* Update the current history entry before to
                                 * overwrite it with tne next one. */
                                history[history_index] = raw_buffer;
                                /* Show the new entry */
                                history_index += (seq[1] == 'A') ? 1 : -1;
                                if (history_index < 0)
                                {
                                    history_index = 0;
                                    break;
                                }
                                else if (history_index >= history.size())
                                {
                                    history_index = history.size()-1;
                                    break;
                                }
                                raw_buffer = history[history_index];
                                raw_cursor = raw_buffer.size();
                                prompt_refresh();
                            }
                        }
                        else if(seq[1] == 'H')
                        {
                            // home
                            raw_cursor = 0;
                            prompt_refresh();
                        }
                        else if(seq[1] == 'F')
                        {
                            // end
                            raw_cursor = raw_buffer.size();
                            prompt_refresh();
                        }
                        else if (seq[1] > '0' && seq[1] < '7')
                        {
                            // extended escape
                            lock->unlock();
                            if(!read_char(seq2))
                            {
                                lock->lock();
                                return -2;
                            }
                            lock->lock();
                            if (seq[1] == '3' && seq2 == '~' )
                            {
                                // delete
                                if (raw_buffer.size() > 0 && raw_cursor < raw_buffer.size())
                                {
                                    raw_buffer.erase(raw_cursor,1);
                                    prompt_refresh();
                                }
                            }
                        }
                    }
                    break;
                default:
                    if (raw_buffer.size() == raw_cursor)
                    {
                        raw_buffer.append(1,c);
                        raw_cursor++;
                        if (plen+raw_buffer.size() < get_columns())
                        {
                            /* Avoid a full update of the line in the
                             * trivial case. */
                            if (::write(fd,&c,1) == -1) return -1;
                        }
                        else
                        {
                            prompt_refresh();
                        }
                    }
                    else
                    {
                        raw_buffer.insert(raw_cursor,1,c);
                        raw_cursor++;
                        prompt_refresh();
                    }
                    break;
                case 21: // Ctrl+u, delete the whole line.
                    raw_buffer.clear();
                    raw_cursor = 0;
                    prompt_refresh();
                    break;
                case 11: // Ctrl+k, delete from current to end of line.
                    raw_buffer.erase(raw_cursor);
                    prompt_refresh();
                    break;
                case 1: // Ctrl+a, go to the start of the line
                    raw_cursor = 0;
                    prompt_refresh();
                    break;
                case 5: // ctrl+e, go to the end of the line
                    raw_cursor = raw_buffer.size();
                    prompt_refresh();
                    break;
                case 12: // ctrl+l, clear screen
                    clear();
                    prompt_refresh();
                }
            }
            return raw_buffer.size();
        }