⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readline.c

📁 qemu虚拟机代码
💻 C
字号:
/* * QEMU readline utility *  * Copyright (c) 2003-2004 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"#define TERM_CMD_BUF_SIZE 4095#define TERM_MAX_CMDS 64#define NB_COMPLETIONS_MAX 256#define IS_NORM 0#define IS_ESC  1#define IS_CSI  2#define printf do_not_use_printfstatic char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];static int term_cmd_buf_index;static int term_cmd_buf_size;static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];static int term_last_cmd_buf_index;static int term_last_cmd_buf_size;static int term_esc_state;static int term_esc_param;static char *term_history[TERM_MAX_CMDS];static int term_hist_entry = -1;static int nb_completions;int completion_index;static char *completions[NB_COMPLETIONS_MAX];static ReadLineFunc *term_readline_func;static int term_is_password;static char term_prompt[256];static void *term_readline_opaque;static void term_show_prompt2(void){    term_printf("%s", term_prompt);    term_flush();    term_last_cmd_buf_index = 0;    term_last_cmd_buf_size = 0;    term_esc_state = IS_NORM;}static void term_show_prompt(void){    term_show_prompt2();    term_cmd_buf_index = 0;    term_cmd_buf_size = 0;}/* update the displayed command line */static void term_update(void){    int i, delta, len;    if (term_cmd_buf_size != term_last_cmd_buf_size ||        memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {        for(i = 0; i < term_last_cmd_buf_index; i++) {            term_printf("\033[D");        }        term_cmd_buf[term_cmd_buf_size] = '\0';        if (term_is_password) {            len = strlen(term_cmd_buf);            for(i = 0; i < len; i++)                term_printf("*");        } else {            term_printf("%s", term_cmd_buf);        }        term_printf("\033[K");        memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);        term_last_cmd_buf_size = term_cmd_buf_size;        term_last_cmd_buf_index = term_cmd_buf_size;    }    if (term_cmd_buf_index != term_last_cmd_buf_index) {        delta = term_cmd_buf_index - term_last_cmd_buf_index;        if (delta > 0) {            for(i = 0;i < delta; i++) {                term_printf("\033[C");            }        } else {            delta = -delta;            for(i = 0;i < delta; i++) {                term_printf("\033[D");            }        }        term_last_cmd_buf_index = term_cmd_buf_index;    }    term_flush();}static void term_insert_char(int ch){    if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {        memmove(term_cmd_buf + term_cmd_buf_index + 1,                term_cmd_buf + term_cmd_buf_index,                term_cmd_buf_size - term_cmd_buf_index);        term_cmd_buf[term_cmd_buf_index] = ch;        term_cmd_buf_size++;        term_cmd_buf_index++;    }}static void term_backward_char(void){    if (term_cmd_buf_index > 0) {        term_cmd_buf_index--;    }}static void term_forward_char(void){    if (term_cmd_buf_index < term_cmd_buf_size) {        term_cmd_buf_index++;    }}static void term_delete_char(void){    if (term_cmd_buf_index < term_cmd_buf_size) {        memmove(term_cmd_buf + term_cmd_buf_index,                term_cmd_buf + term_cmd_buf_index + 1,                term_cmd_buf_size - term_cmd_buf_index - 1);        term_cmd_buf_size--;    }}static void term_backspace(void){    if (term_cmd_buf_index > 0) {        term_backward_char();        term_delete_char();    }}static void term_bol(void){    term_cmd_buf_index = 0;}static void term_eol(void){    term_cmd_buf_index = term_cmd_buf_size;}static void term_up_char(void){    int idx;    if (term_hist_entry == 0)	return;    if (term_hist_entry == -1) {	/* Find latest entry */	for (idx = 0; idx < TERM_MAX_CMDS; idx++) {	    if (term_history[idx] == NULL)		break;	}	term_hist_entry = idx;    }    term_hist_entry--;    if (term_hist_entry >= 0) {	pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),                 term_history[term_hist_entry]);	term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);    }}static void term_down_char(void){    if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)	return;    if (term_history[++term_hist_entry] != NULL) {	pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),                term_history[term_hist_entry]);    } else {	term_hist_entry = -1;    }    term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);}static void term_hist_add(const char *cmdline){    char *hist_entry, *new_entry;    int idx;    if (cmdline[0] == '\0')	return;    new_entry = NULL;    if (term_hist_entry != -1) {	/* We were editing an existing history entry: replace it */	hist_entry = term_history[term_hist_entry];	idx = term_hist_entry;	if (strcmp(hist_entry, cmdline) == 0) {	    goto same_entry;	}    }    /* Search cmdline in history buffers */    for (idx = 0; idx < TERM_MAX_CMDS; idx++) {	hist_entry = term_history[idx];	if (hist_entry == NULL)	    break;	if (strcmp(hist_entry, cmdline) == 0) {	same_entry:	    new_entry = hist_entry;	    /* Put this entry at the end of history */	    memmove(&term_history[idx], &term_history[idx + 1],		    &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]);	    term_history[TERM_MAX_CMDS - 1] = NULL;	    for (; idx < TERM_MAX_CMDS; idx++) {		if (term_history[idx] == NULL)		    break;	    }	    break;	}    }    if (idx == TERM_MAX_CMDS) {	/* Need to get one free slot */	free(term_history[0]);	memcpy(term_history, &term_history[1],	       &term_history[TERM_MAX_CMDS] - &term_history[1]);	term_history[TERM_MAX_CMDS - 1] = NULL;	idx = TERM_MAX_CMDS - 1;    }    if (new_entry == NULL)	new_entry = strdup(cmdline);    term_history[idx] = new_entry;    term_hist_entry = -1;}/* completion support */void add_completion(const char *str){    if (nb_completions < NB_COMPLETIONS_MAX) {        completions[nb_completions++] = qemu_strdup(str);    }}static void term_completion(void){    int len, i, j, max_width, nb_cols;    char *cmdline;    nb_completions = 0;        cmdline = qemu_malloc(term_cmd_buf_index + 1);    if (!cmdline)        return;    memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);    cmdline[term_cmd_buf_index] = '\0';    readline_find_completion(cmdline);    qemu_free(cmdline);    /* no completion found */    if (nb_completions <= 0)        return;    if (nb_completions == 1) {        len = strlen(completions[0]);        for(i = completion_index; i < len; i++) {            term_insert_char(completions[0][i]);        }        /* extra space for next argument. XXX: make it more generic */        if (len > 0 && completions[0][len - 1] != '/')            term_insert_char(' ');    } else {        term_printf("\n");        max_width = 0;        for(i = 0; i < nb_completions; i++) {            len = strlen(completions[i]);            if (len > max_width)                max_width = len;        }        max_width += 2;        if (max_width < 10)            max_width = 10;        else if (max_width > 80)            max_width = 80;        nb_cols = 80 / max_width;        j = 0;        for(i = 0; i < nb_completions; i++) {            term_printf("%-*s", max_width, completions[i]);            if (++j == nb_cols || i == (nb_completions - 1)) {                term_printf("\n");                j = 0;            }        }        term_show_prompt2();    }}/* return true if command handled */void readline_handle_byte(int ch){    switch(term_esc_state) {    case IS_NORM:        switch(ch) {        case 1:            term_bol();            break;        case 4:            term_delete_char();            break;        case 5:            term_eol();            break;        case 9:            term_completion();            break;        case 10:        case 13:            term_cmd_buf[term_cmd_buf_size] = '\0';            if (!term_is_password)                term_hist_add(term_cmd_buf);            term_printf("\n");            /* NOTE: readline_start can be called here */            term_readline_func(term_readline_opaque, term_cmd_buf);            break;        case 27:            term_esc_state = IS_ESC;            break;        case 127:        case 8:            term_backspace();            break;	case 155:            term_esc_state = IS_CSI;	    break;        default:            if (ch >= 32) {                term_insert_char(ch);            }            break;        }        break;    case IS_ESC:        if (ch == '[') {            term_esc_state = IS_CSI;            term_esc_param = 0;        } else {            term_esc_state = IS_NORM;        }        break;    case IS_CSI:        switch(ch) {	case 'A':	case 'F':	    term_up_char();	    break;	case 'B':	case 'E':	    term_down_char();	    break;        case 'D':            term_backward_char();            break;        case 'C':            term_forward_char();            break;        case '0' ... '9':            term_esc_param = term_esc_param * 10 + (ch - '0');            goto the_end;        case '~':            switch(term_esc_param) {            case 1:                term_bol();                break;            case 3:                term_delete_char();                break;            case 4:                term_eol();                break;            }            break;        default:            break;        }        term_esc_state = IS_NORM;    the_end:        break;    }    term_update();}void readline_start(const char *prompt, int is_password,                    ReadLineFunc *readline_func, void *opaque){    pstrcpy(term_prompt, sizeof(term_prompt), prompt);    term_readline_func = readline_func;    term_readline_opaque = opaque;    term_is_password = is_password;    term_show_prompt();}const char *readline_get_history(unsigned int index){    if (index >= TERM_MAX_CMDS)        return NULL;    return term_history[index];}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -