/* Shared */ #include "shared.h" #include "config.h" #include "console.h" #include "file.h" #include "head.h" #include "os.h" #include "page.h" #include "wio.h" #define CMD_LIMIT 256 void display(byte *s) { start_update(); while(*s) out_char(*s++); finish_update(); } void save_cursor(void) { save_attributes(0); } void restore_cursor(void) { restore_attributes(0); } #define bytes(s) (1+os_strlen(s)) static void draw_editable(int x, byte *s, int off, int log) { int dummy, y; get_xy(&dummy, &y); start_update(); set_xy(x, y); erase_to_eoln(); if(log) display(s); else raw_display(s); set_xy(x + off, y); finish_update(); } int getline(const byte *prompt, char *buff, int maxlen) { static int cmd_held = 0; static char cmd_buff[CMD_LIMIT]; int cmd_count = cmd_held; int font = 1; int c, off = 0; int x, y; force_update(); show_cursor(); raw_display(prompt); swap_font_status(&font); get_xy(&x, &y); buff[off] = '\0'; draw_editable(x, (byte *) buff, off, 0); while((c = get_ch()) != '\r') { switch(c) { case '\b': if(off > 0) { os_strcpy(&buff[off - 1], &buff[off]); --off; } break; case 'A' - '@': off = 0; break; case 'E' - '@': off = os_strlen(buff); break; case 'D' - '@': if(off < os_strlen(buff)) os_strcpy(&buff[off], &buff[off + 1]); break; case 'F' - '@': if(off < os_strlen(buff)) ++off; break; case 'B' - '@': if(off) --off; break; case 'P' - '@': case 'N' - '@': if(cmd_held) { if(c == 'P' - '@') { if(cmd_count == 0) cmd_count = cmd_held; cmd_count -= 2; while(cmd_count >= 0 && cmd_buff[cmd_count]) --cmd_count; ++cmd_count; } else { cmd_count += bytes(&cmd_buff[cmd_count]); if(cmd_count == cmd_held) cmd_count = 0; } off = bytes(&cmd_buff[cmd_count]); os_mcpy(buff, &cmd_buff[cmd_count], min(off, maxlen)); buff[maxlen - 1] = '\0'; off = os_strlen(buff); } break; case 'U' - '@': off = 0; /* Fall through */ case 'K' - '@': buff[off] = '\0'; break; default: if(bytes(buff) < maxlen && c >= 32) { os_mcpy(&buff[off + 1], &buff[off], os_strlen(&buff[off]) + 1); buff[off++] = c; } break; } draw_editable(x, (byte *) buff, off, 0); } off = os_strlen(buff); draw_editable(x, (byte *) buff, off, 1); hide_cursor(); out_char('\n'); swap_font_status(&font); game_saved = 0; /* Store in history */ if(off && off + 1 < CMD_LIMIT) { int i = 0; while(cmd_held + off - i >= CMD_LIMIT) i += bytes(&cmd_buff[i]); cmd_held -= i; os_mcpy(cmd_buff, &cmd_buff[i], cmd_held); os_strcpy(&cmd_buff[cmd_held], buff); cmd_held += off + 1; } return off; } void out_char(word c) { extern bool newlines_are_significant; extern bool windowing_enabled; extern word current_window; extern word status_height; extern bool enable_screen; extern int linecount; script_char(c); put_char(c); if(enable_screen) { if(c == '\n') { int page = !windowing_enabled || current_window == 0; if(page && newlines_are_significant) { int lose = windowing_enabled ? 0 : status_height; int high = hd_height() - lose - 3; if(linecount++ >= high) { force_update(); more(); newlines_are_significant = 0; linecount = 0; } } } else { newlines_are_significant = 1; } } } void raw_display(const byte *s) { start_update(); while(*s) put_char(*s++); finish_update(); } #if 0 /* Used for real-time support */ int kbd_hit(void) { return 1; } #endif