/* ================== CON_Print ================== */ void CON_Print(const char *msg) { int col; bool scroll = (lastline > scrollline && lastline <= scrollline + LOG_LINES); if (!curses_on) { CON_Print_tty(msg); return; } // Print the message in the log window CON_ColorPrint(logwin, msg, qtrue); getyx(logwin, lastline, col); if (col) { lastline++; } if (scroll) { scrollline = lastline - LOG_LINES; if (scrollline < 0) { scrollline = 0; } pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); } // Add the message to the log buffer if (insert + strlen(msg) >= logbuf + sizeof(logbuf)) { memmove(logbuf, logbuf + sizeof(logbuf) / 2, sizeof(logbuf) / 2); memset(logbuf + sizeof(logbuf) / 2, 0, sizeof(logbuf) / 2); insert -= sizeof(logbuf) / 2; } strcpy(insert, msg); insert += strlen(msg); // Update the scrollbar CON_DrawScrollBar(); // Move the cursor back to the input field CON_UpdateCursor(); doupdate(); }
/* ================== CON_Input ================== */ char *CON_Input(void) { int chr, num_chars = 0; static char text[MAX_EDIT_LINE]; static int lasttime = -1; if (!curses_on) return CON_Input_tty(); if (com_ansiColor->modified) { CON_Resize(); com_ansiColor->modified = qfalse; } if (Com_RealTime(NULL) != lasttime) { lasttime = Com_RealTime(NULL); CON_UpdateClock(); num_chars++; } while (1) { chr = getch(); num_chars++; // Special characters switch (chr) { case ERR: if (num_chars > 1) { werase(inputwin); if (input_field.cursor < input_field.scroll) { input_field.scroll = input_field.cursor - INPUT_SCROLL; if (input_field.scroll < 0) input_field.scroll = 0; } else if (input_field.cursor >= input_field.scroll + input_field.widthInChars) input_field.scroll = input_field.cursor - input_field.widthInChars + INPUT_SCROLL; CON_ColorPrint(inputwin, input_field.buffer + input_field.scroll, qfalse); #ifdef _WIN32 wrefresh(inputwin); // If this is not done the cursor moves strangely #else wnoutrefresh(inputwin); #endif CON_UpdateCursor(); doupdate(); } return NULL; case '\n': case '\r': case KEY_ENTER: if (!input_field.buffer[0]) continue; Hist_Add(input_field.buffer); strcpy(text, input_field.buffer); Field_Clear(&input_field); werase(inputwin); wnoutrefresh(inputwin); CON_UpdateCursor(); //doupdate(); Com_Printf(PROMPT "^7%s\n", text); return text; case '\t': case KEY_STAB: Field_AutoComplete(&input_field, PROMPT); input_field.cursor = strlen(input_field.buffer); continue; case '\f': CON_Resize(); continue; case KEY_LEFT: if (input_field.cursor > 0) input_field.cursor--; continue; case KEY_RIGHT: if (input_field.cursor < strlen(input_field.buffer)) input_field.cursor++; continue; case KEY_UP: Q_strncpyz(input_field.buffer, Hist_Prev(), sizeof(input_field.buffer)); input_field.cursor = strlen(input_field.buffer); continue; case KEY_DOWN: Q_strncpyz(input_field.buffer, Hist_Next(input_field.buffer), sizeof(input_field.buffer)); input_field.cursor = strlen(input_field.buffer); continue; case KEY_HOME: input_field.cursor = 0; continue; case KEY_END: input_field.cursor = strlen(input_field.buffer); continue; case KEY_NPAGE: if (lastline > scrollline + LOG_LINES) { scrollline += LOG_SCROLL; if (scrollline + LOG_LINES > lastline) scrollline = lastline - LOG_LINES; pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); CON_DrawScrollBar(); } continue; case KEY_PPAGE: if (scrollline > 0) { scrollline -= LOG_SCROLL; if (scrollline < 0) scrollline = 0; pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); CON_DrawScrollBar(); } continue; case '\b': case 127: case KEY_BACKSPACE: if (input_field.cursor <= 0) continue; input_field.cursor--; // Fall through case KEY_DC: if (input_field.cursor < strlen(input_field.buffer)) { memmove(input_field.buffer + input_field.cursor, input_field.buffer + input_field.cursor + 1, strlen(input_field.buffer) - input_field.cursor); } continue; } // Normal characters if (chr >= ' ' && chr < 256 && strlen(input_field.buffer) + 1 < sizeof(input_field.buffer)) { memmove(input_field.buffer + input_field.cursor + 1, input_field.buffer + input_field.cursor, strlen(input_field.buffer) - input_field.cursor); input_field.buffer[input_field.cursor] = chr; input_field.cursor++; } } }
/* ================== CON_Init Initialize the console in curses mode, fall back to tty mode on failure ================== */ void CON_Init(void) { int col; #ifndef _WIN32 // If the process is backgrounded (running non interactively) // then SIGTTIN or SIGTOU is emitted, if not caught, turns into a SIGSTP signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); #endif // Make sure we're on a tty if (isatty(STDIN_FILENO) != 1 || isatty(STDOUT_FILENO) != 1 || isatty(STDERR_FILENO) != 1) { CON_Init_tty(); return; } // Initialize curses and set up the root window if (!curses_on) { SCREEN *test = newterm(NULL, stdout, stdin); if (!test) { CON_Init_tty(); CON_Print_tty("Couldn't initialize curses, falling back to tty\n"); return; } endwin(); delscreen(test); initscr(); cbreak(); noecho(); nonl(); intrflush(stdscr, FALSE); nodelay(stdscr, TRUE); keypad(stdscr, TRUE); wnoutrefresh(stdscr); // Set up colors if (has_colors()) { use_default_colors(); start_color(); init_pair(1, COLOR_BLACK, -1); init_pair(2, COLOR_RED, -1); init_pair(3, COLOR_GREEN, -1); init_pair(4, COLOR_YELLOW, -1); init_pair(5, COLOR_BLUE, -1); init_pair(6, COLOR_CYAN, -1); init_pair(7, COLOR_MAGENTA, -1); init_pair(8, -1, -1); } } // Create the border borderwin = newwin(LOG_LINES + 2, LOG_COLS + 2, 1, 0); CON_SetColor(borderwin, 2); box(borderwin, 0, 0); wnoutrefresh(borderwin); // Create the log window logwin = newpad(MAX_LOG_LINES, LOG_COLS); scrollok(logwin, TRUE); idlok(logwin, TRUE); if (curses_on) CON_ColorPrint(logwin, logbuf, qtrue); getyx(logwin, lastline, col); if (col) lastline++; scrollline = lastline - LOG_LINES; if (scrollline < 0) scrollline = 0; pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); // Create the scroll bar scrollwin = newwin(LOG_LINES, 1, 2, COLS - 1); CON_DrawScrollBar(); CON_SetColor(stdscr, 3); mvaddch(1, COLS - 1, SCRLBAR_UP); mvaddch(LINES - 2, COLS - 1, SCRLBAR_DOWN); // Create the input field inputwin = newwin(1, COLS - Q_PrintStrlen(PROMPT) - 8, LINES - 1, Q_PrintStrlen(PROMPT) + 8); input_field.widthInChars = COLS - Q_PrintStrlen(PROMPT) - 9; if (curses_on) { if (input_field.cursor < input_field.scroll) input_field.scroll = input_field.cursor; else if (input_field.cursor >= input_field.scroll + input_field.widthInChars) input_field.scroll = input_field.cursor - input_field.widthInChars + 1; CON_ColorPrint(inputwin, input_field.buffer + input_field.scroll, qfalse); } CON_UpdateCursor(); wnoutrefresh(inputwin); // Create the clock clockwin = newwin(1, 8, LINES - 1, 0); CON_UpdateClock(); // Display the title and input prompt move(0, (COLS - Q_PrintStrlen(TITLE)) / 2); CON_ColorPrint(stdscr, TITLE, qtrue); move(LINES - 1, 8); CON_ColorPrint(stdscr, PROMPT, qtrue); wnoutrefresh(stdscr); doupdate(); #ifndef _WIN32 // Catch window resizes signal(SIGWINCH, (void *)CON_Resize); #endif curses_on = qtrue; }