#include #include #include #include "addrs.h" #include "screen.h" #include "edbox.h" #include "complete.h" #include "keytab.h" extern void __fastcall__ bell(void); char *old_edbox[EDBOX_SIZE]; static u16 old_len; static int typeover; int edbox_visible = 0; static u16 edbox_pos; /* range 0 to EDBOX_SIZE - 1 */ u16 edbox_len; /* idem */ void (*edbox_callback)(void); static void hide_cursor(void) { edit_box[edbox_pos] &= 0x7f; } static void show_cursor(void) { edit_box[edbox_pos] |= 0x80; } void edbox_clear(void) { memset(edit_box, 0, EDBOX_SIZE); edbox_pos = edbox_len = 0; show_cursor(); // not needed? seems it is.. } void edbox_show(void) { u16 addr; if(edbox_pos < 80) addr = (u16)edit_box; else addr = (u16)edit_box + edbox_pos - 79; scr_waitvcount(116); *dlist_status_lms = addr; *dlist_last_line = 0x02; /* ANTIC GR.0 */ edbox_visible = 1; show_cursor(); } void edbox_hide(void) { scr_end_scrollback(); /* exit Start+E mode */ edbox_visible = 0; scr_refresh(); } /* note: c will never be an EOL. idea: when the edbox is completely full (240 chars), go ahead and pretend the user pressed Return (call edbox_callback, etc). not sure if this is more or less annoying than just refusing to accept more input until Return is pressed. */ void edbox_putc(char c) { if(!c) return; /* no inserting nulls */ if(!typeover) memmove(edit_box + edbox_pos + 1, edit_box + edbox_pos, EDBOX_SIZE - edbox_pos - 1); edit_box[edbox_pos] = c; if(edbox_pos < EDBOX_SIZE - 1) { edbox_pos++; edbox_len++; } else { bell(); } } static void copy_to_old(void) { if(!edbox_len) return; memcpy(old_edbox, edit_box, edbox_len); memset(old_edbox + edbox_len, 0, (EDBOX_SIZE - 1) - edbox_len); old_len = edbox_len; } static void restore_old(void) { edbox_clear(); hide_cursor(); memcpy(edit_box, old_edbox, old_len); edbox_pos = edbox_len = old_len; } static void del_char(void) { if(!edbox_len) return; memmove(edit_box + edbox_pos, edit_box + edbox_pos + 1, EDBOX_SIZE - edbox_pos - 1); edbox_len--; } static void del_to_end(void) { while(edbox_len > edbox_pos) del_char(); } static void backspace(void) { if(!edbox_pos) return; edbox_pos--; del_char(); } static void up(void) { if(!edbox_len) { restore_old(); } else { if(edbox_pos > 39) edbox_pos -= 40; else edbox_pos = 0; } } static void down(void) { if(edbox_pos > 199) return; edbox_pos += 40; if(edbox_pos > edbox_len) edbox_pos = edbox_len; } static void word_left(char del) { if(!edbox_pos) return; if(!del) edbox_pos--; while(edbox_pos && edit_box[edbox_pos] == ' ') { if(del) del_char(); edbox_pos--; } while(edbox_pos && edit_box[edbox_pos] != ' ') { if(del) del_char(); edbox_pos--; } // XXX: what's this good for? if(del && !edbox_pos) edit_box[edbox_pos] = /* ' ' */ 0; } static void del_word(void) { word_left(1); } static void back_word(void) { word_left(0); } static void forward_word(void) { while(edbox_pos < edbox_len && edit_box[edbox_pos] == ' ') edbox_pos++; while(edbox_pos < edbox_len && edit_box[edbox_pos] != ' ') edbox_pos++; } static void del_to_start(void) { while(edbox_pos) backspace(); } void left(void) { if(edbox_pos) edbox_pos--; } void right(void) { if(edbox_pos < edbox_len) edbox_pos++; } void edbox_keystroke(char c) { extern char start_latch; extern void start_keystroke(char); if(c == CH_ESC) { start_latch = 1; return; } if(c != XCH_TAB) comp_complete_done(); if(c >= XCH_SCR1 && c <= XCH_SCR7) { start_keystroke(c & 0x7f); return; } else if(c == XCH_ACTIVE) { start_keystroke('a'); return; } edbox_show(); hide_cursor(); switch(c) { case CH_EOL: copy_to_old(); edbox_hide(); if(edbox_callback) (*edbox_callback)(); edbox_clear(); break; case XCH_TAB: comp_complete(); break; case XCH_UP: up(); break; case XCH_DOWN: down(); break; case XCH_LEFT: left(); break; case XCH_RIGHT: right(); break; case XCH_LWORD: back_word(); break; case XCH_RWORD: forward_word(); break; case XCH_CLS: edbox_clear(); edbox_hide(); return; case CH_DELCHR: case 0x18: /* ^X */ del_char(); break; case CH_DELLINE: edbox_clear(); break; case XCH_INSCHR: typeover = !typeover; break; case 0x15: /* ^U */ del_to_start(); break; case 0x0b: /* ^K */ del_to_end(); break; case XCH_BS: if(!edbox_len) edbox_hide(); else backspace(); break; case 0x17: /* ^W */ del_word(); break; case 0x01: /* ^A */ edbox_pos = 0; break; case 0x05: /* ^E */ edbox_pos = edbox_len; break; default: edbox_putc(c); break; } show_cursor(); if(edbox_visible) edbox_show(); } void edbox_addchr(char c) { edit_box[edbox_len++] = c; edbox_pos = edbox_len; } void edbox_space(void) { edbox_addchr(' '); } void edbox_set(char *contents) { edbox_clear(); while(*contents) { edit_box[edbox_len++] = *contents++; } edbox_pos = edbox_len; }