static void draw_row(int y, int sel, int top, int sbtop, int sbbot) { int i = (y - 4 - VSHIFT) + top; int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]); printf("\033[%d;%dH\1#1\016x\017%s ", y, MARGIN + 1 + HSHIFT, (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3"); if (i >= cm->nentries) { fputs(pad_line("", 0, WIDTH - 2 * MARGIN - 4), stdout); } else { display_entry(cm->menu_entries[i], (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3", (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4", WIDTH - 2 * MARGIN - 4); } if (cm->nentries <= MENU_ROWS) { printf(" \1#1\016x\017"); } else if (sbtop > 0) { if (y >= sbtop && y <= sbbot) printf(" \1#7\016a\017"); else printf(" \1#1\016x\017"); } else { putchar(' '); /* Don't modify the scrollbar */ } }
static void draw_menu(int sel, int top, int edit_line) { int x, y; int sbtop = 0, sbbot = 0; const char *tabmsg; int tabmsg_len; if (cm->nentries > MENU_ROWS) { int sblen = max(MENU_ROWS * MENU_ROWS / cm->nentries, 1); sbtop = ((MENU_ROWS - sblen + 1) * top / (cm->nentries - MENU_ROWS + 1)) + VSHIFT; sbbot = sbtop + sblen - 1; sbtop += 4; sbbot += 4; /* Starting row of scrollbar */ } printf("\033[%d;%dH\1#1\016l", VSHIFT + 1, HSHIFT + MARGIN + 1); for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) putchar('q'); printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x", VSHIFT + 2, HSHIFT + MARGIN + 1, pad_line(cm->title, 1, WIDTH - 2 * MARGIN - 4)); printf("\033[%d;%dH\1#1t", VSHIFT + 3, HSHIFT + MARGIN + 1); for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) putchar('q'); fputs("u\017", stdout); for (y = 4 + VSHIFT; y < 4 + VSHIFT + MENU_ROWS; y++) draw_row(y, sel, top, sbtop, sbbot); printf("\033[%d;%dH\1#1\016m", y, HSHIFT + MARGIN + 1); for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) putchar('q'); fputs("j\017", stdout); if (edit_line && cm->allowedit && !cm->menu_master_passwd) tabmsg = cm->messages[MSG_TAB]; else tabmsg = cm->messages[MSG_NOTAB]; tabmsg_len = strlen(tabmsg); printf("\1#8\033[%d;%dH%s", TABMSG_ROW, 1 + HSHIFT + ((WIDTH - tabmsg_len) >> 1), tabmsg); printf("\1#0\033[%d;1H", END_ROW); }
static const char *edit_cmdline(const char *input, int top) { static char cmdline[MAX_CMDLINE_LEN]; int key, len, prev_len, cursor; int redraw = 1; /* We enter with the menu already drawn */ strlcpy(cmdline, input, MAX_CMDLINE_LEN); cmdline[MAX_CMDLINE_LEN - 1] = '\0'; len = cursor = strlen(cmdline); prev_len = 0; for (;;) { if (redraw > 1) { /* Clear and redraw whole screen */ /* Enable ASCII on G0 and DEC VT on G1; do it in this order to avoid confusing the Linux console */ clear_screen(); draw_menu(-1, top, 1); prev_len = 0; } if (redraw > 0) { /* Redraw the command line */ printf("\033[?25l\033[%d;1H\1#9> \2#10%s", CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len))); printf("\2#10\033[%d;3H%s\033[?25h", CMDLINE_ROW, pad_line(cmdline, 0, cursor)); prev_len = len; redraw = 0; } key = mygetkey(0); switch (key) { case KEY_CTRL('L'): redraw = 2; break; case KEY_ENTER: case KEY_CTRL('J'): return cmdline; case KEY_ESC: case KEY_CTRL('C'): return NULL; case KEY_BACKSPACE: case KEY_DEL: if (cursor) { memmove(cmdline + cursor - 1, cmdline + cursor, len - cursor + 1); len--; cursor--; redraw = 1; } break; case KEY_CTRL('D'): case KEY_DELETE: if (cursor < len) { memmove(cmdline + cursor, cmdline + cursor + 1, len - cursor); len--; redraw = 1; } break; case KEY_CTRL('U'): if (len) { len = cursor = 0; cmdline[len] = '\0'; redraw = 1; } break; case KEY_CTRL('W'): if (cursor) { int prevcursor = cursor; while (cursor && my_isspace(cmdline[cursor - 1])) cursor--; while (cursor && !my_isspace(cmdline[cursor - 1])) cursor--; memmove(cmdline + cursor, cmdline + prevcursor, len - prevcursor + 1); len -= (prevcursor - cursor); redraw = 1; } break; case KEY_LEFT: case KEY_CTRL('B'): if (cursor) { cursor--; redraw = 1; } break; case KEY_RIGHT: case KEY_CTRL('F'): if (cursor < len) { putchar(cmdline[cursor++]); } break; case KEY_CTRL('K'): if (cursor < len) { cmdline[len = cursor] = '\0'; redraw = 1; } break; case KEY_HOME: case KEY_CTRL('A'): if (cursor) { cursor = 0; redraw = 1; } break; case KEY_END: case KEY_CTRL('E'): if (cursor != len) { cursor = len; redraw = 1; } break; case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: show_fkey(key); redraw = 1; break; default: if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) { if (cursor == len) { cmdline[len] = key; cmdline[++len] = '\0'; cursor++; putchar(key); prev_len++; } else { memmove(cmdline + cursor + 1, cmdline + cursor, len - cursor + 1); cmdline[cursor++] = key; len++; redraw = 1; } } break; } } }