#include #include #include #include "addrs.h" #include "screen.h" #include "edbox.h" #include "keyclick.h" /* TODO: tab completion */ int edbox_visible = 0; static u16 edbox_pos; /* range 0 to EDBOX_SIZE - 1 */ static 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) { extern void __fastcall__ bell(void); if(!c) return; /* no inserting nulls */ 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 fake_keystroke(char c) { keyclick(); OS.ch = 0xff; edbox_putc(c); } 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 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(); } static void normal_keystroke(void) { char c; c = cgetc(); switch(c) { case CH_EOL: // hide_cursor(); // already done by the caller edbox_hide(); if(edbox_callback) (*edbox_callback)(); edbox_clear(); break; case CH_CLR: edbox_hide(); /* fall thru */ case CH_DELLINE: edbox_clear(); break; case 0x15: /* ^U */ del_to_start(); break; case 0x0b: /* ^K */ del_to_end(); break; case CH_DEL: backspace(); break; case 0x02: /* ^B */ back_word(); break; case 0x06: /* ^F */ forward_word(); break; case 0x17: /* ^W */ del_word(); break; case CH_CURS_LEFT: if(edbox_pos) edbox_pos--; break; case CH_CURS_RIGHT: if(edbox_pos < edbox_len) edbox_pos++; break; case CH_CURS_UP: if(edbox_pos > 39) edbox_pos -= 40; break; case CH_CURS_DOWN: if(edbox_pos < edbox_len - 40) edbox_pos += 40; else edbox_pos = edbox_len; break; case CH_DELCHR: del_char(); break; case 0x01: /* ^A */ edbox_pos = 0; break; case 0x05: /* ^E */ edbox_pos = edbox_len; break; default: edbox_putc(c); break; } } void edbox_keystroke(void) { char c; while(OS.ch == 0xff) ; /* filter out all ctrl-shift key combos except the ones we actually support */ if(OS.ch == 0xce) { /* ctrl-shift-up, same as ^B = back 1 word */ OS.ch = 0x95; } else if(OS.ch == 0xcf) { /* ctrl-shift-down, same as ^F = forward 1 word */ OS.ch = 0xb8; } else if(OS.ch > 0xbf) { OS.ch = 0xff; return; } edbox_show(); c = 0; switch(OS.ch) { case 0xa0: /* key: ctrl [ */ c = 0x7b; /* ascii: { */ break; case 0xa2: /* key: ctrl ] */ c = 0x7d; /* ascii: } */ break; case 0x1c: /* key: ESC */ c = 0x60; /* ascii: ` */ break; case 0x5c: /* key: shift ESC */ case 0x9c: /* key: ctrl ESC */ c = 0x7e; /* ascii: ~ */ break; case 0x3c: /* caps */ case 0x7c: /* shift-caps */ case 0xbc: /* ctrl-caps */ OS.shflok ^= 0x40; keyclick(); OS.ch = 0xff; return; break; case 0x27: /* atari key */ case 0x67: /* ...w/shift */ case 0xa7: /* ...w/ctrl */ c = 0x02; /* ^B = IRC bold formatting char */ break; case 0x9a: /* ctrl-3 (crash if cgetc() reads it!) */ OS.ch = 0xff; /* ignore it! */ return; break; default: break; } hide_cursor(); if(c) { fake_keystroke(c); } else { normal_keystroke(); } if(edbox_visible) edbox_show(); show_cursor(); }