/* TUIpeer works in conjunction with an implementation of java.awt.Toolkit to provide a Text User Interface for programs using the Java AWT. Copyright (C) 1997-2000 Stuart D. Gathman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma implementation #include #include #include #include #include "browse.h" //#include BrowserBase::BrowserBase() { topline = leftcol = 0; modified = false; desc[0] = 0; } BrowserBase::~BrowserBase() { } bool EditorBase::cmdmode = false; bool EditorBase::compose = true; EditorBase::EditorBase() { linemode = 0; readonly = false; } EditorBase::~EditorBase() { } void BrowserBase::cmd(int c) { int currow,curcol; getyx(currow,curcol); //int topline = currow - row; switch (c) { #if 0 // don't want to pull in Prompt (and a whole parallel textedit tree) case EDIT_SEARCH: { PromptWin p("Search String:",pat); if (p.run() == KEY_F(1)) return; pat = p.get(); } // fall through case EDIT_AGAIN: search(pat); return; #endif case EDIT_FWD: move(topline + 2 * size().height - 1,curcol); move(currow + size().height,curcol); return; case EDIT_REV: if (currow <= size().height) move(0,curcol); else { move(topline - size().height,curcol); move(currow - size().height,curcol); } return; case FILE_PRINT: print(); return; } Controller::cmd(c); } void EditorBase::cmd(int c) { int currow,curcol; if (!readonly) switch (c) { case EDIT_INSLINE: getyx(currow,curcol); insertln(currow); sync(); return; case EDIT_DELLINE: getyx(currow,curcol); deleteln(currow); sync(); return; } BrowserBase::cmd(c); } void BrowserBase::key(int ky) { int currow, curcol; int inc; getyx(currow,curcol); switch (ky) { case KEY_F(5): cmd(EDIT_REFORM); break; case KEY_FIND: case KEY_F(11): case '/': cmd(EDIT_SEARCH); break; case KEY_SFIND: case KEY_F(16): case 'n': cmd(EDIT_AGAIN); break; case KEY_SHOME: case 'T': move(0,0); break; case KEY_UP: case 'k': move(DIR_UP); break; case KEY_DOWN: case 'j': move(DIR_DOWN); break; case KEY_LEFT: case KEY_BACKSPACE: case 'h': move(DIR_LEFT); break; case KEY_RIGHT: case 'l': move(DIR_RIGHT); break; case KEY_ENTER: case KEY_LL: move(++currow,0); break; case KEY_F(2): case KEY_PPAGE: // prev PAGE case KEY_SR: case 2: // prev SCREEN cmd(EDIT_REV); break; case KEY_F(3): case KEY_NPAGE: // next PAGE case KEY_SF: case 6: // next SCREEN cmd(EDIT_FWD); break; case 'H': // top of window move(topline,curcol); break; case 'M': // middle of window move(topline + size().height / 2,curcol); break; case 'L': // bottom of window move(topline + size().height - 1,curcol); break; case '<': // 52 columns left inc = 52; if (curcol <= inc) move(currow,0); else { move(currow, leftcol - inc); move(currow,curcol - inc); } break; case '>': // 52 columns right inc = 52; move(currow,leftcol + size().width - 1 + inc); move(currow,curcol + inc); break; case KEY_SLEFT: // shift screen left if (curcol > 0) { inc = curcol - leftcol; move(currow,leftcol - 1); if (inc >= size().width - 1) --curcol; move(currow,curcol); } break; case KEY_SRIGHT: // shift screen right inc = curcol - leftcol; move(currow,leftcol + size().width); if (inc == 0) ++curcol; move(currow,curcol); break; case 4: // half page forward (^D) inc = size().height / 2; move(topline + size().height - 1 + inc,curcol); move(currow + inc,curcol); break; case 5: // one line forward (^E) inc = currow - topline; move(topline + size().height,curcol); if (inc == 0) ++currow; move(currow,curcol); break; case 21: // half page back (^U) inc = size().height / 2; if (currow <= inc) move(0,curcol); else { move(topline - inc,curcol); move(currow - inc,curcol); } break; case 25: // one line back (^Y) inc = currow - topline; move(topline - 1,curcol); if (inc >= size().height - 1) --currow; move(currow,curcol); break; case KEY_END: case '$': move(currow+1,-1); break; case KEY_HOME: case '0': move(currow,0); break; case KEY_TAB: move(currow,(curcol & ~7) + 8); break; case KEY_BTAB: if (curcol > 7) move(currow,(curcol & ~7) - 8); break; case KEY_SEND: case 'G': move(-1,-1); break; default: Controller::key(ky); return; } sync(); } void EditorBase::key(int ky) { if (readonly && ky != KEY_TAB && ky != KEY_BTAB) { BrowserBase::key(ky); return; } int currow, curcol; if (commandMode()) { switch (ky) { case 'D': clrtoeol(); return; case 'x': delch(); sync(); return; case 's': delch(); break; case 'a': BrowserBase::key(KEY_RIGHT); case 'i': break; case 'o': BrowserBase::key(KEY_DOWN); case 'O': cmd(EDIT_INSLINE); break; case 'R': insert_mode = 0; commandMode(false); sync(); return; case KEY_TAB: case KEY_BTAB: case KEY_LEFT: case KEY_RIGHT: case KEY_UP: case KEY_DOWN: Controller::key(ky); return; default: BrowserBase::key(ky); return; } insert_mode = 1; commandMode(false); sync(); return; } switch (ky) { case KEY_COMMAND: commandMode(true); break; case KEY_F(7): case KEY_IL: cmd(EDIT_INSLINE); return; case KEY_F(8): case KEY_DL: cmd(EDIT_DELLINE); return; case KEY_SIC: compose = ~compose; break; case KEY_SELECT: linemode = ++linemode % 3; if (linemode) last_dir = DIR_NONE; break; case KEY_IC: insert_mode = ~insert_mode; break; case KEY_UP: /* if (linemode) linemove(DIR_UP); */ move(DIR_UP); break; case KEY_DOWN: /* if (linemode) linemove(DIR_DOWN); */ move(DIR_DOWN); break; case KEY_LEFT: /* if (linemode) linemove(DIR_LEFT); */ move(DIR_LEFT); break; case KEY_RIGHT: /* if (linemode) linemove(DIR_RIGHT); */ move(DIR_RIGHT); break; case KEY_BACKSPACE: getyx(currow,curcol); /* if (linemode) { linedel(); break; } */ if (curcol > 0) { --curcol; move(currow,curcol); if (insert_mode) delch(); else { addch(' '); move(currow,curcol); } } break; case KEY_DC: delch(); break; case KEY_EOL: clrtoeol(); break; default: if (isascii(ky) && isprint(ky)) { if (compose) { int ky2 = composeChar(ky); if (ky2 != ky) { addch(ky2); break; } } if (insert_mode) insch(ky); else addch(ky); break; } BrowserBase::key(ky); return; } sync(); } int EditorBase::composeChar(int ky) { int row, col; getyx(row,col); int ch = (*this)(row,col) & 0xff; if (ch == ' ') return ky; unsigned short p1 = (ch << 8) | ky; unsigned short p2 = (ky << 8) | ch; # define PAIR(c1,c2,c3) {((c1 << 8) | c2),c3} static const struct ptbl { unsigned short p; unsigned short c; } pairtable[] = { PAIR('C',',',0x80), PAIR('u','"',0x81), PAIR('e','\'',0x82), PAIR('a','^',0x83), PAIR('a','"',0x84), PAIR('a','`',0x85), PAIR('a','.',0x86), PAIR('c',',',0x87), PAIR('e','^',0x88), PAIR('e','"',0x89), PAIR('e','`',0x8A), PAIR('i','"',0x8B), PAIR('i','^',0x8C), PAIR('i','`',0x8D), PAIR('A','"',0x8E), PAIR('A','.',0x8F), PAIR('E','\'',0x90), PAIR('a','e',0x91), PAIR('A','E',0x92), PAIR('o','^',0x93), PAIR('o','"',0x94), PAIR('o','`',0x95), PAIR('u','^',0x96), PAIR('u','`',0x97), PAIR('y','"',0x98), PAIR('O','"',0x99), PAIR('U','"',0x9A), PAIR('c','/',0x9B), PAIR('L','-',0x9C), PAIR('Y','=',0x9D), PAIR('P','t',0x9E), PAIR('f','-',0x9f), PAIR('a','\'',0xA0), PAIR('i','\'',0xA1), PAIR('o','\'',0xA2), PAIR('u','\'',0xA3), PAIR('n','~',0xA4), PAIR('N','~',0xA5), PAIR('a','_',0xA6), PAIR('o','_',0xA7), PAIR('?','?',0xA8), PAIR('[','_',0xA9), PAIR(']','_',0xAA), PAIR('1','2',0xAB), PAIR('1','4',0xAC), PAIR('!','!',0xAD), PAIR('<','<',0xAE), PAIR('>','>',0xAF), PAIR('a','l',0xE0), PAIR('b','e',0xE1), PAIR('G','a',0xE2), PAIR('p','i',0xE3), PAIR('S','i',0xE4), PAIR('s','i',0xE5), PAIR('m','u',0xE6), PAIR('t','a',0xE7), PAIR('P','h',0xE8), PAIR('t','h',0xE9), PAIR('O','m',0xEA), PAIR('d','e',0xEB), PAIR('8','8',0xEC), PAIR('P','h',0xED), PAIR('e','p',0xEE), PAIR('U','U',0xEF), PAIR('=','=',0xF0), PAIR('+','-',0xF1), PAIR('>','=',0xF2), PAIR('<','=',0xF3), PAIR('s','(',0xF4), PAIR('s',')',0xF5), PAIR(':','-',0xF6), PAIR('~','~',0xF7), PAIR('o','o',0xF8), PAIR('o','.',0xF9), PAIR('.','.',0xFA), PAIR('v','_',0xFB), PAIR('^','n',0xFC), PAIR('^','2',0xFD), PAIR('[',']',0xFE), PAIR(0,0,0) }; # undef PAIR for (const ptbl *p = pairtable; p->p; ++p) if (p->p == p1 || p->p == p2) return p->c; return ky; } void BrowserBase::sync() { int row, col; getyx(row,col); sprintf(desc,"Row: %2d Col: %2d", row, col); } void EditorBase::sync() { int row, col; getyx(row,col); #if 0 ostrstream os(desc,sizeof desc); os << "Row:" << row << " Col:" << col; if (modified) os << " (modified)"; os << ends; os.freeze(); #else char lmode[16]; lmode[0] = 0; if (linemode) sprintf(lmode,"(line%d)",linemode); sprintf(desc,"Row: %2d Col: %2d%s%s%s%s", row, col, modified ? " (mod)" : "", insert_mode ? " (ins)" : "", (commandMode()) ? " (cmd)" : "", lmode ); #endif } void BrowserBase::move(Dir d) { int currow, curcol; getyx(currow,curcol); switch (d) { case DIR_UP: if (currow) move(--currow,curcol); break; case DIR_DOWN: move(++currow,curcol); break; case DIR_LEFT: move(currow,--curcol); break; case DIR_RIGHT: move(currow,++curcol); break; default: break; } }