home *** CD-ROM | disk | FTP | other *** search
- /*
- ** edit.c: hterm 'History Editor' for copy&paste, history, local editting
- *
- * Author: HIRANO Satoshi
- * (C) 1989 Halca Computer Science Laboratory TM
- * University of Tokyo
- *
- * 1.1 89/07/24 Halca.Hirano creation
- * history, roll up, roll down, copy & paste (kanji is only to see.)
- * I used simple and stupid screen rewriting algolithm.
- * (I rewrite entire screen for each inserting character!)
- * Don't worry, hterm is fast enough even if on my sloooow IBM-PC/AT.
- * ---- V2.3.-1 distribution ----
- * 1.2 89/09/18 Halca.Hirano
- * User can chagne buffer size by environment variable
- * 1.3 89/09/24 Halca.Hirano
- * change paste strategy. We can paste in commnunication mode.
- * ---- V2.4.0 distribution ----
- * 1.4 89/12/08 Halca.Hirano
- * logging off
- * 2.1 90/06/10 Halca.Hirano rewrite entirely.
- * 1) use standard hterm console interface rather than show/saveLine()
- * interface.
- * 2) marking is made by reverse attributed console write instead of
- * reverse() function.
- * 2.2 90/06/24 Halca.Hirano change some key binding
- * 2.3 90/06/29 Halca.Hirano
- * add kill line and insert line
- * 2.4 90/07/01 Halca.Hirano
- * support hemacs functions (WARAERU!)
- * 2.5 90/07/12 Halca.Hirano
- * fix 25 line mode initial cursor bug
- *
- * NOTE:
- * History buffer has ring buffer structure. Kanji is represented
- * in EUC code for all machine archtecture.
- * This is because NEC PC9801's screen code is a variant of JIS code.
- * And JIS -> EUC conversion is faster than JIS -> SJIS conversion.
- * The most important thing is to keep speed of scrolling in communication
- * mode. saveLine() which is called from scrlUp() in console.c
- * gets disappearing line on VRAM, then save it into tail of the
- * history buffer.
- * Sorry AX users.
- *
- * CAUTION:
- * History Editor uses max 128K bytes.
- * To reduce memory usage, set environ variable HTHISTORY and HTCOPYBUF.
- *
- * I think MSC5.1 is brain damaged.
- * For instance,
- * main()
- * {
- * u_char (*beg)[MAX_COLUMN], (*end)[MAX_COLUMN];
- *
- * beg = (void *)0;
- * end = beg+400; end > 0x8000
- * printf("%d\n", end-beg);
- * }
- * produces MINUS value. not 400!
- * Thus I use array of array for history buffer representation,
- * instead of pointer to array.
- *
- * $Header: edit.cv 1.12 90/07/04 01:38:00 hirano Exp $
- *
- */
-
- #include "option.h"
- #if defined(COPY_PASTE) | defined(HEMACS)
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "config.h"
- #include "hterm.h"
- #include "default.h"
- #include "global.h"
-
-
- #define DOT(x) ((x)-view)
- #define HUGENUM 10000
-
- /*
- ** static storage
- */
- u_char (FAR *histBuf)[][MAX_COLUMN]; /* history buffer (RING) */
- static int maxHistLines; /* history buffer lines */
- static int histEnd; /* history buffer end */
- static int histHead; /* next in line */
- static int histTail; /* next out line */
- static int oldHistTail; /* histTail at enterEdit */
-
- static int view; /* virtual lineNo at left upper */
- /* on the screen */
- static int oldView; /* oldView */
- static int viewMaxLine; /* lines on the screen */
- static int viewBottomLine; /* bottom line of the screen */
-
- static int histX; /* current column number on history */
- static int histY; /* current virtual line number on history */
- static int histHomeX; /* last screen cursor X, Y position */
- static int histHomeY; /* on history buffer */
- static int histLines; /* actual lines in history buf */
- static int markX; /* mark X begin position */
- static int markY; /* mark Y begin position */
- static int markEndX; /* region end X position */
- static int markEndY; /* region end Y possition */
- static int marked; /* marked or not marked flag */
-
- static u_short maxCopyBuf; /* copy buffer size */
- u_char FAR *copyBuffer; /* copy buffer (SJIS text) */
- u_char FAR *copyBufferPtr; /* next in pointer */
- u_short copyBufferRealSize; /* copy buffer contents */
- static char copyFile[66]; /* copy file name */
- static int timer = PASTE_TIMER; /* paste wait timer to prevent XOFF */
- /* from the remote system */
-
- static int oldMode;
- static char statusLineUsed; /* status line was used */
-
- static u_char searchString[60] = "";
-
- void enterEdit(void );
- void localUp(void);
- void localDown(void);
- void localRight(void);
- void localLeft(void);
- void localPgUp(void);
- void localPgDn(void);
- void localTOL(void);
- void localEOL(void);
- void gotoLine(void);
- void localBOF(void);
- void localHome(void);
- void searchForward(void);
- void searchBackward(void);
- void xngCurMark(void);
- void localMark(void);
- void localAppend(void);
- void localCopy(void);
- void clearCopyBuf(void);
- void copyBufWrite(void);
- void localLoadFile(void);
- void moveView(void);
- void localHelp(void);
- void leaveEdit(u_short);
- void localBS(void);
- void localDel(void);
- void localKill(void);
- void localCR(void);
- void localChar(u_short);
-
- void localInsertLine(int);
- void localDeleteLine(int);
- void localClearColumn(int, int, int);
- int findEOL(int);
- int copyOneLine(int, int, int);
- void paste(void);
- u_short getCopyBuffer(void);
- void redrawView(void);
- findCharBoundary(int, int);
- void putNChar(int, int);
- int cmpCursorMark(void);
- u_char FAR *virtualToReal(int);
- void scrollBar(void);
- void statusLine(void);
- void showLine(int, int);
-
- /*
- * function table
- */
- #define X_PRE 1
- #define E_PRE 2
- #define T_PRE 4
- #define BAD 0xffff
- struct _funcTab {
- u_short prefix; /* X-prefix or M-prefix */
- u_short code; /* cursor key */
- u_short tabCode; /* bind table key */
- void (*func)(); /* function */
- } funcTab[] = {
- {0, UP_KEY, C_UP, localUp},
- {0, DOWN_KEY, C_DOWN, localDown},
- {0, RIGHT_KEY, C_RIGHT, localRight},
- {0, LEFT_KEY, C_LEFT, localLeft},
- #ifdef PC98
- {0, PGDN_KEY, C_PP, localPgUp},
- #else
- {0, PGUP_KEY, C_PP, localPgUp},
- #endif
- #ifdef PC98
- {0, PGUP_KEY, C_NP, localPgDn},
- #else
- {0, PGDN_KEY, C_NP, localPgDn},
- #endif
- {0, HOME_KEY, C_TOL, localTOL},
- {0, END_KEY, C_EOL, localEOL},
- {E_PRE, 'g', C_GOTO, gotoLine},
- {E_PRE, '<', C_TOP, localBOF},
- {E_PRE, '>', C_HOME, localHome},
- {0, BAD, C_SEARCHF, searchForward},
- {0, BAD, C_SEARCHB, searchBackward},
- {X_PRE, CTRL('X'), C_XNG, xngCurMark},
- {0, INS_KEY, C_MARK, localMark},
- {E_PRE, ' ', BAD, localMark},
- {E_PRE, 'w', C_COPY, localAppend},
- {E_PRE, TAB, C_CBUF, clearCopyBuf},
- {X_PRE, CTRL('W'), C_WRITE, copyBufWrite},
- {X_PRE, CTRL('F'), BAD, localLoadFile},
- {0, BAD, C_REDRAW, moveView},
- {E_PRE, '?', BAD, localHelp},
- {0, HELP_KEY, BAD, localHelp},
- {0, CR, BAD, leaveEdit},
- {0, PF_HIST_EDIT, BAD, leaveEdit},
- {0, SETUP_KEY, BAD, leaveEdit},
- {E_PRE, ESC, BAD, leaveEdit},
- {X_PRE, CTRL('C'), BAD, leaveEdit},
- {0, BS, BAD, localBS},
- {0, DEL, BAD, localBS},
- {0, BAD, C_DEL, localDel},
- {0, BAD, C_KILLEND, localKill},
- #ifdef HEMACS
- {0, CR, BAD, localCR},
- #else
- {0, LF, BAD, localCR},
- #endif
- };
-
-
- /*
- ** void editInit()
- *
- * allocate buffer, initialize internals
- */
- void editInit()
- {
- char *p, *getenv();
-
- /*
- * allocate history buffer
- */
- #ifdef HEMACS
- maxHistLines = MAX_HIST_LINES;
- maxCopyBuf = MAX_COPY_BUF_SIZE;
- #else
- if ((p = getenv("HTHISTORY")) == NULL) {
- maxHistLines = DEFAULT_HIST_LINES;
- } else {
- maxHistLines = atoi(p);
- if (maxHistLines <= MAX_LINE_25_MODE) {
- maxHistLines = 0;
- return; /* history Off */
- }
- if (maxHistLines > MAX_HIST_LINES)
- maxHistLines = MAX_HIST_LINES;
- }
-
- if ((p = getenv("HTCOPYBUF")) == NULL) {
- maxCopyBuf = DEFAULT_COPY_BUF_SIZE;
- } else {
- maxCopyBuf = (u_short)atoi(p);
- if (maxCopyBuf > MAX_COPY_BUF_SIZE)
- maxCopyBuf = MAX_COPY_BUF_SIZE;
- }
- #endif /* HEMACS */
-
- histBuf = allocMem((long)maxHistLines*MAX_COLUMN);
- if (histBuf == 0) {
- fprintf(stderr, msg_alloc, "history, check $HTHISTORY\n");
- exit(1);
- }
- histHead = histTail = 0;
- histEnd = maxHistLines;
-
- /*
- * allocate copy buffer
- */
- if (maxCopyBuf) {
- copyBuffer = (u_char FAR *)allocMem((long)maxCopyBuf);
- if (copyBuffer == 0) {
- fprintf(stderr, msg_alloc, "history, $HTCOPYBUF\n");
- exit(1);
- }
- }
- copyBufferPtr = copyBuffer;
- copyBufferSize = copyBufferRealSize = 0;
- strcpy(copyFile, COPY_BUF_FILE);
- }
-
- /*
- ** void editEnd()
- *
- * clean up at hterm exit time; return balk of memory
- */
- void editEnd()
- {
- if (maxHistLines <= 0)
- return;
- if (maxCopyBuf)
- freeMem(copyBuffer);
- freeMem(histBuf);
- }
-
- /*
- ** void historyEditor()
- *
- * history editor main loop
- */
- void historyEditor()
- {
- u_short c;
- short prefix;
- struct _funcTab *f;
- int i;
-
- /*
- * If history is disabled, return immediatly
- */
- if (maxHistLines <= 0)
- return;
- /*
- * set up edit mode
- */
- enterEdit();
-
- statusLineUsed = NO;
- /*
- * OK, enjoy modification of your history!
- */
- for (;;) {
- /*
- * read one char
- */
- prefix = NO;
- while ((short)(c = keyin()) == -1)
- ;
- if (statusLineUsed)
- clearStatus();
-
- /*
- * process prefix char
- */
- if (c == CTRL('X')) {
- prefix = X_PRE;
- putStatus("^X-");
- goto readNext;
- }
- if (c == bindTab[C_ESC]) {
- prefix = E_PRE;
- putStatus("ESC-");
- readNext:
- while ((short)(c = keyin()) == -1)
- ;
- c = tolower(c);
- clearStatus();
- }
-
- /*
- * call appropreate function
- */
- if (!prefix && (((c & 0xff00) && (c & 0x00ff))
- || (0x20 <= c && c <= 0x7e) || c == TAB || c == bindTab[C_QUOTE]))
- localChar(c); /* self insert keys */
- else {
- for (i = (sizeof(funcTab)/sizeof(struct _funcTab))-1; i >= 0; --i) {
- f = &funcTab[i];
- if ((prefix == f->prefix && f->code != BAD && c == f->code) ||
- (prefix == 0 && f->tabCode != BAD && c == bindTab[f->tabCode])) {
-
- (*f->func)(c);
- if (f->func == leaveEdit)
- return;
- break;
- }
- }
- if (i < 0) {
- putStatus("key not bound"); bell();
- statusLineUsed = YES;
- }
- }
- }
- }
-
- /*
- ** localBOF()
- *
- * beginning of a file
- */
- static void localBOF()
- {
- histY = histX = 0;
- moveView();
- }
-
- /*
- ** localHelp()
- *
- */
- static void localHelp()
- {
- helpSystem("hist-editor key");
- while (keyin() == -1)
- ;
- oldView = HUGENUM;
- redrawView();
- }
-
- /*
- ** static void enterEdit()
- *
- * initialize history editor
- */
- static void enterEdit()
- {
- int y;
- int oldCursorX = cursorX;
- int oldCursorY = cursorY;
- int oldBottomLine = bottomLine;
-
- /*
- * save curpage in history
- */
- oldHistTail = histTail; /* may be used future */
- #ifndef HEMACS
- for (y = 0; y <= bottomLine; y++)
- saveHist(y, YES);
- #endif
- /*
- * save page0 and show page1
- */
- oldMode = mode;
- mode = M_HISTORY;
- showPage1();
- cursorOnOff(YES);
- marked = NO;
- copyBufferPtr = copyBuffer;
- copyBufferSize = copyBufferRealSize = 0;
- viewMaxLine = realMaxLine - 3;
- viewBottomLine = realMaxLine - 4;
- lowScrRegion = viewBottomLine; /* create text window */
-
- if (histHead <= histTail)
- histLines = histTail - histHead;
- else
- histLines = maxHistLines - (histHead - histTail);
- /*
- * reset pointers
- */
- histHomeX = histX = oldCursorX;
- histHomeY = histY = histLines - (oldBottomLine - oldCursorY) - 1;
- /*
- * show last history
- */
- oldView = HUGENUM; /* force to rewrite entire screen */
- statusLine();
- #ifdef HEMACS
- histX = histY = histHomeX = 0;
- histHomeY = histLines - 1;
- redrawView();
- #else
- localHome();
- #endif
- }
-
- /*
- ** leaveEdit()
- *
- * termination of history editor
- */
- static void leaveEdit(c)
- u_short c;
- {
- if (marked) /* paste */
- localCopy();
- showPage0();
- histTail = oldHistTail; /* remove last page from histry buffer */
- mode = oldMode;
- if (c == CR)
- paste();
- }
-
- /*
- ** localChar(c)
- *
- * self insert to history buffer
- */
- static void localChar(c)
- u_short c; /* c is hterm kanji code */
- {
- u_char FAR *at = virtualToReal(histY);
- u_char FAR *p;
- u_char FAR *q;
- int oldHistX = histX;
- int len, i;
- int grow = (cmpCursorMark() >= 0);
-
- if (c == bindTab[C_QUOTE])
- while ((c = keyin()) == -1);
-
- len = (c & 0xff00) ? 2 : 1; /* kanji or ascii*/
- if (histX+len > LAST_COLUMN)
- return; /* line overflow */
-
- /*
- * make space in the buffer
- */
- p = &at[LAST_COLUMN-len];
- q = &at[LAST_COLUMN];
- for (i = MAX_COLUMN-histX-len; i > 0; --i, --p, --q)
- *q = *p;
-
- /*
- * insert char in the buffer
- */
- p = &at[histX];
- if (len == 2) {
- *p++ = ((c>>8)|0x80);
- *p++ = ((c&0xff)|0x80);
- } else
- *p++ = c;
-
- /*
- * make room on the screen
- */
- insertChar(histX, len);
-
- histX += len;
-
- if (histY == markY && oldHistX < markX)
- markX += len;
- if (markX > MAX_COLUMN)
- markX = MAX_COLUMN;
- /*
- * put it
- */
- if (marked) {
- if (grow) { /* grow reverse */
- reverseMode();
- conWrite(c);
- normalMode();
- } else { /* shrink reverse */
- conWrite(c); /* put the char on oldHistX position */
- locate(histX, DOT(histY));
- reverseMode();
- putNChar(histX, histY);
- normalMode();
- }
- } else
- conWrite(c);
- locate(histX, DOT(histY));
- }
-
- static void localBS()
- {
- u_char FAR *at = virtualToReal(histY);
-
- if (histX == 0)
- return;
- --histX;
- if (isEUC(at[histX]) && histX > 0)
- --histX;
- localDel();
- }
-
- static void localDel()
- {
- u_char FAR *at = virtualToReal(histY);
- int len;
-
- len = isEUC(at[histX]) ? 2 : 1;
- moveData(&at[histX], &at[histX+len], MAX_COLUMN-histX-len);
- at[LAST_COLUMN] = SPACE;
- if (len == 2)
- at[LAST_COLUMN-1] = SPACE;
- if (marked && histY == markY && histX < markX)
- markX -= len;
- showLine(DOT(histY), histY);
- locate(histX, DOT(histY));
- }
-
- static void localKill()
- {
- int eol = findEOL(histY);
- int oldMarkX = markX;
-
- if (histX < eol) { /* erase within a line */
- localClearColumn(histX, MAX_COLUMN, histY);
- if (marked && histY == markY && histX < markX)
- markX = histX;
- showLine(DOT(histY), histY);
- } else if (histY < histLines-1) { /* remove a line */
- if (eol == 0) {
- localDeleteLine(histY);
- } else {
- moveData((u_char FAR *)XFerBuffer, virtualToReal(histY+1), MAX_COLUMN-histX);
- localDeleteLine(histY+1);
- moveData(&(virtualToReal(histY)[histX]), (u_char FAR *)XFerBuffer, MAX_COLUMN-histX);
- if (marked && histY+1 == markY) {
- markY = histY;
- markX = histX + oldMarkX;
- if (markX > MAX_COLUMN)
- markX = MAX_COLUMN;
- }
- }
- oldView = HUGENUM;
- redrawView();
- }
- locate(histX, DOT(histY));
- }
-
- static void localCR()
- {
- int oldMarkX = markX;
- int oldMarkY = markY;
- u_char FAR *at = virtualToReal(histY);
-
- moveData((u_char FAR *)XFerBuffer, &at[histX], MAX_COLUMN-histX);
- localClearColumn(histX, MAX_COLUMN, histY);
- localInsertLine(histY);
- moveData(at, (u_char FAR *)XFerBuffer, MAX_COLUMN-histX);
- histX = 0;
- if (marked) {
- if (oldMarkY == histY && histX <= oldMarkX) {
- markX = oldMarkX - histX;
- markY = histY;
- }
- }
- oldView = HUGENUM;
- redrawView();
- }
-
- static void localInsertLine(y)
- int y;
- {
- int i;
-
- for (i = 1; i <= y; i++)
- moveData(virtualToReal(i-1), virtualToReal(i), MAX_COLUMN);
- localClearColumn(0, MAX_COLUMN, y);
- if (marked) {
- if (markY <= y)
- --markY;
- if (markY < 0)
- markX = markY = 0;
- }
- }
-
- static void localDeleteLine(y)
- int y;
- {
- int i, j;
-
- if (y < histLines-1)
- for (j = histLines-y-1, i = y; j >= 1; --j, i++)
- moveData(virtualToReal(i), virtualToReal(i+1), MAX_COLUMN);
- localClearColumn(0, MAX_COLUMN, histLines-1);
- if (marked) {
- if (y < markY)
- --markY;
- else if (markY == y) {
- markX = 0;
- }
- }
- }
-
- static void localClearColumn(from, to, y)
- int from;
- int to; /* to - 1 */
- int y;
- {
- u_char FAR *at = virtualToReal(y);
- u_char FAR *p;
- int i;
-
- for (p = &at[from], i = to-from; i > 0; --i)
- *p++ = SPACE;
- }
-
- /*
- ** static localPgUp()
- *
- * show previous page
- */
- static void localPgUp()
- {
- if (view < viewMaxLine) {
- histY -= view;
- view = 0;
- } else {
- view -= viewMaxLine;
- histY -= viewMaxLine;
- }
- redrawView();
- }
-
- /*
- ** static localPgDn()
- *
- * next page
- */
- static void localPgDn()
- {
- if (view + viewMaxLine*2 > histLines) {
- histY += histLines - viewMaxLine - view;
- view = histLines - viewMaxLine;
- } else {
- histY += viewMaxLine;
- view += viewMaxLine;
- }
- redrawView();
- }
-
- /*
- ** static localRight()
- *
- * move cursor to right (no wrap)
- */
- static void localRight()
- {
- u_char FAR *at = virtualToReal(histY);
- int grow = (cmpCursorMark() >= 0);
- int len = isEUC(at[histX]) ? 2 : 1;
- int oldHistX = histX;
-
- if (histX + len > LAST_COLUMN)
- return; /* if right end of the line, do nothing */
- if (marked && grow) {
- reverseMode();
- putNChar(histX, histY); /* grow reverse */
- normalMode();
- }
- histX += len;
- if (marked && !grow) {
- putNChar(oldHistX, histY);
- locate(histX, DOT(histY));
- putNChar(histX, histY); /* shurink reverse */
- }
- locate(histX, DOT(histY));
- }
-
- /*
- ** static localLeft()
- *
- * move cursor to left (no wrap)
- */
- static void localLeft()
- {
- u_char FAR *at = virtualToReal(histY);
- int oldHistX = histX;
- int grow = (cmpCursorMark() <= 0);
-
- if (--histX < 0) {
- histX = 0;
- return; /* do nothing if top of the line */
- }
- if (isEUC(at[histX]))
- --histX; /* if left char is kanji, move to the char */
- if (marked) {
- if (grow) {
- reverseMode(); /* grow reverse */
- locate(oldHistX, DOT(histY));
- putNChar(oldHistX, histY);
- locate(histX, DOT(histY));
- putNChar(histX, histY);
- normalMode();
- } else { /* shrink reverse */
- locate(histX, DOT(histY));
- putNChar(histX, histY);
- }
- }
- locate(histX, DOT(histY));
- }
-
- /*
- ** static int localUp()
- *
- * up cursor
- */
- static void localUp()
- {
- int newY = histY;
-
- if (--newY < 0)
- return;
- histX = findCharBoundary(histX, newY);
- histY = newY;
- if (histY < view) {
- /*
- * out of view, scroll
- */
- showLine(DOT(histY+1), histY+1);
- moveView();
- return;
- }
- if (marked) { /* rewrite current line and new Y line */
- showLine(DOT(histY+1), histY+1);
- showLine(DOT(histY), histY);
- }
- locate(histX, DOT(histY));
- }
-
- /*
- ** static localDown()
- *
- * down cursor
- */
- static void localDown()
- {
- int newY = histY;
-
- if (++newY >= histLines)
- return;
- histX = findCharBoundary(histX, newY);
- histY = newY;
- if (histY >= view + viewMaxLine) {
- /*
- * out of view, scroll
- */
- showLine(DOT(histY-1), histY-1);
- moveView();
- return;
- }
- if (marked) { /* rewrite current line and new Y line */
- showLine(DOT(histY-1), histY-1);
- showLine(DOT(histY), histY);
- }
- locate(histX, DOT(histY));
- }
-
- /*
- ** static localTOL()
- *
- * move cursor to top of line
- */
- static void localTOL()
- {
- histX = 0;
- showLine(DOT(histY), histY);
- locate(histX, DOT(histY));
- }
-
- /*
- ** static localEOL()
- *
- * move cursor to end of line
- */
- static void localEOL()
- {
- histX = findEOL(histY);
- showLine(DOT(histY), histY);
- locate(histX, DOT(histY));
- }
-
- /*
- ** findEOL(int x, int y)
- *
- * find end of line; return eol + 1
- */
- static int findEOL(y)
- int y;
- {
- u_char FAR *at = virtualToReal(y);
- int x;
-
- for (x = LAST_COLUMN; x > 0 && at[x] == SPACE; --x)
- ;
- if (at[x] != SPACE)
- if (x == LAST_COLUMN) {
- if (isEUC(at[x])) /* full char in this line */
- --x;
- } else
- x++; /* move cursor to real eol+1 */
- return(x);
- }
-
- /*
- ** static gotoLine()
- *
- * jump to specified line
- */
- static void gotoLine()
- {
- tmpBuf[0] = '\0';
- if (emacs("Goto line: ", tmpBuf, 10, E_NO_HELP) == ERR) {
- statusLineUsed = YES;
- return;
- }
- if (tmpBuf[0] == '\0') {
- return;
- }
- histY = atoi(tmpBuf);
- if (histY < 0)
- histY = 0;
- else if (histY >= histLines)
- histY = histLines - 1;
- histX = 0;
- moveView();
- }
-
- /*
- ** static localHome()
- *
- * move cursor to home position
- */
- static void localHome()
- {
- histX = histHomeX; histY = histHomeY;
- view = histLines - viewMaxLine;
- redrawView();
- }
-
- /*
- ** static searchForward()
- *
- * search string forward
- */
- static void searchForward()
- {
- register u_char FAR *x1, FAR *at;
- register u_char *s1, *s;
- register int i, len, x, y;
-
- strcpy(tmpBuf, searchString);
- if (emacs("Search forward: ", tmpBuf, 65, E_NO_HELP) == ERR) {
- return;
- }
- strcpy((char *)searchString, tmpBuf);
- x = histX+1;
- y = histY;
- if (x > LAST_COLUMN) {
- y++;
- x = 0;
- }
- s = searchString;
- if ((len = strlen((char *)s)) == 0)
- return;
- for (; y < histLines; y++) {
- at = virtualToReal(y);
- for (;x <= MAX_COLUMN-len; x++) {
- for (i = len, x1 = &at[x], s1 = s; i > 0; --i)
- if (*x1++ != *s1++)
- break;
- if (i == 0) { /* found */
- histY = y;
- #if 0
- if (histY < view || view + viewMaxLine <= histY) {
- histX = x;
- moveView();
- } else
- moveWithinLine(x);
- #else
- histX = x;
- moveView();
- #endif
- return;
- }
- }
- x = 0;
- }
- sprintf(tmpBuf, "%s not found", searchString); /* buggy */
- putStatus(tmpBuf);
- statusLineUsed++;
- bell();
- }
-
- /*
- ** static searchBackward()
- *
- * search string backward
- * NOTE:
- * If string is found, cursor stay at the end of string.
- * This is useful to find prompt pattern and to edit users input.
- */
- static void searchBackward()
- {
- register u_char *s1;
- register u_char FAR *x1, FAR *at;
- register u_char *s;
- register int i, len, x, y;
-
- strcpy(tmpBuf, searchString);
- if (emacs("Search backward: ", tmpBuf, 65, E_NO_HELP) == ERR) {
- return;
- }
- strcpy(searchString, tmpBuf);
- x = histX-1;
- y = histY;
- if (x < 0) {
- --y;
- x = LAST_COLUMN;
- }
- if ((len = strlen(searchString)) == 0)
- return;
- s = &searchString[len];
- for (; y >= 0; --y) {
- at = virtualToReal(y);
- for (;x >= len-1; --x) {
- for (i = len, x1 = &at[x+1], s1 = s; i > 0; --i)
- if (*--x1 != *--s1)
- break;
- if (i == 0) { /* found */
- histY = y;
- #if 0
- if (histY < view || view + viewMaxLine <= histY) {
- histX = x;
- moveView();
- } else
- moveWithinLine(x);
- #else
- histX = x;
- moveView();
- #endif
- return;
- }
- }
- x = LAST_COLUMN;
- }
- sprintf(tmpBuf, "%s not found", searchString); /* buggy */
- putStatus(tmpBuf);
- statusLineUsed++;
- bell();
- }
-
- /*
- ** static localMark()
- *
- * set mark on current cursor position
- */
- static void localMark()
- {
- if (marked) {
- marked = NO;
- oldView = HUGENUM; /* force to rewrite */
- redrawView();
- } else {
- marked = YES;
- markX = histX;
- markY = histY;
- scrollBar();
- }
- }
-
- /*
- ** static clearCopyBuf()
- *
- * clear copy buffer
- */
- static void clearCopyBuf()
- {
- copyBufferRealSize = 0;
- copyBufferPtr = copyBuffer;
- scrollBar();
- statusLine();
- }
-
- /*
- ** static xngCurMark()
- *
- * exchange cursor and mark
- */
- static void xngCurMark()
- {
- int tmpX, tmpY;
-
- if (!marked)
- return;
- tmpX = histX; tmpY = histY;
- histX = markX; histY = markY;
- markX = tmpX; markY = tmpY;
- if (histY < view || view + viewMaxLine <= histY) {
- moveView();
- return;
- }
- redrawView();
- }
-
- /*
- ** static localCopy()
- *
- * clear copy buffer, and append region to copy buffer
- */
- static void localCopy()
- {
- if (marked == YES) {
- copyBufferRealSize = 0;
- copyBufferPtr = copyBuffer;
- }
- localAppend();
- }
-
- /*
- ** static localAppend()
- *
- * append region to copy buffer
- */
- static void localAppend()
- {
- int endX;
- u_char FAR *cBufPtrSave = copyBufferPtr;
- u_short cBufSizeSave = copyBufferRealSize;
-
- if (marked) {
- if (cmpCursorMark() >= 0) {
- markEndX = histX; markEndY = histY;
- } else {
- markEndX = markX; markEndY = markY;
- markX = histX; markY = histY;
- }
- endX = MAX_COLUMN;
- for (;markY <= markEndY; markY++) {
- if (markY == markEndY)
- endX = markEndX;
- if (copyOneLine(markX, endX, markY) == ERR) {
- putStatus("Copy buffer overflow"); bell();
- statusLineUsed++;
- copyBufferPtr = cBufPtrSave;
- copyBufferRealSize = cBufSizeSave;
- locate(histX, DOT(histY));
- return;
- }
- markX = 0;
- }
- marked = NO;
- oldView = HUGENUM; /* force to rewrite */
- redrawView();
- }
- scrollBar();
- statusLine();
- }
-
- /*
- ** static copyOneLine(xBeg, xEnd, y)
- *
- * copy one line from history buffer to copy buffer
- * NOTE: strip trailing blanks and add \n
- */
- static int copyOneLine(xBeg, xEnd, y)
- int xBeg, xEnd, y;
- {
- u_char FAR *at = virtualToReal(y);
- int eol;
- int lf = NO;
-
- eol = findEOL(y); /* skip trailing blank */
- /*
- * if this line has no character to write, only newline will be put
- */
- if (eol == 0 && at[0] == SPACE)
- lf = YES;
- else {
- /*
- * find end point to write
- */
- if (eol < xEnd) { /* if cursor is greater than eol */
- if (at[eol] != SPACE) /* if this line is fully used */
- {
- xEnd = MAX_COLUMN; /* write entire line and */
- }
- else
- xEnd = eol;
- lf = YES; /* add newline char */
- }
- /*
- * copy the line to buffer
- */
- for (; xBeg < xEnd; xBeg++) {
- if (++copyBufferRealSize > maxCopyBuf)
- return(ERR);
- *copyBufferPtr++ = at[xBeg];
- }
- }
- if (lf) {
- if (++copyBufferRealSize > maxCopyBuf)
- return(ERR);
- *copyBufferPtr++ = '\n';
- }
- return(OK);
- }
-
- /*
- ** paste()
- *
- * prepare to put characters in copy buffer
- */
- void paste()
- {
- copyBufferPtr = copyBuffer;
- copyBufferSize = copyBufferRealSize;
- timer = upLoadDelay;
- }
-
- /*
- ** u_short getCopyBuffer()
- *
- * pass one char to hterm from copy buffer
- * NOTE: char is hterm internal format.
- */
- u_short getCopyBuffer()
- {
- u_short c;
-
- if (--timer > 0)
- return(ERR);
- timer = upLoadDelay;
- --copyBufferSize;
- if ((c = (u_short)*copyBufferPtr++) == (u_short)'\n')
- c = (u_short)CR;
- #ifdef KANJI
- else if (isEUC(c) && copyBufferSize > 0) {
- c = ((c << 8) | *copyBufferPtr++) & 0x7f7f;
- --copyBufferSize;
- }
- #endif /* KANJI */
- return(c);
- }
-
- /*
- ** static copyBufWrite()
- *
- * write copy buffer to file
- */
- static void copyBufWrite()
- {
- FILE *fp;
- u_char c;
- u_short sjis;
-
- if (marked) {
- localAppend();
- }
- strcpy(tmpBuf, copyFile);
- if (emacs("File Name (ESC for abort): ", tmpBuf, 65, E_NO_HELP) == ERR) {
- locate(histX, DOT(histY));
- cursorOnOff(YES);
- return;
- }
- cursorOnOff(YES);
- strcpy(copyFile, tmpBuf);
- if ((fp = fopen(tmpBuf, COPY_FILE_ATTR)) == NULL) {
- sprintf(tmpBuf, msg_cantOpen, copyFile);
- putStatus(tmpBuf); bell();
- locate(histX, DOT(histY));
- return;
- }
- copyBufferPtr = copyBuffer;
- while (copyBufferRealSize > 0) {
- c = *copyBufferPtr++;
- #ifdef KANJI
- if (isEUC(c) && copyBufferRealSize > 0) {
- sjis = JIStoSJIS(c & 0x7f, (*copyBufferPtr++) & 0x7f);
- putc(sjis >> 8, fp);
- --copyBufferRealSize;
- c = sjis & 0xff;
- }
- #endif /* KANJI */
- putc(c, fp);
- --copyBufferRealSize;
- }
- fclose(fp);
- copyBufferRealSize = 0;
- copyBufferPtr = copyBuffer;
- scrollBar();
- statusLine();
- }
-
- /*
- ** static localLoadFile()
- *
- * load new file
- */
- void localLoadFile()
- {
- FILE *fp;
-
- tmpBuf[0] = '\0';
- if (emacs("File Name (ESC for abort): ", tmpBuf, 65, E_NO_HELP | E_FILE) == ERR) {
- oldView = HUGENUM;
- redrawView();
- return;
- }
- if ((fp = fopen(tmpBuf, "r")) == NULL) {
- putStatus("can't open file");
- oldView = HUGENUM;
- redrawView();
- return;
- }
- marked = NO;
- histHead = histTail = 0;
- histEnd = maxHistLines;
- copyBufferPtr = copyBuffer;
- copyBufferSize = copyBufferRealSize = 0;
- loadFile(fp);
- fclose(fp);
- if (histHead <= histTail)
- histLines = histTail - histHead;
- else
- histLines = maxHistLines - (histHead - histTail);
- oldView = HUGENUM; /* force to rewrite entire screen */
- statusLine();
- histX = histY = histHomeX = 0;
- histHomeY = histLines - 1;
- moveView();
- }
-
- void loadFile(fp)
- FILE *fp;
- {
- register int c, c2;
- int i;
- char *p;
- int lines = 0;
-
- /*
- * push contents of the file to history buffer
- */
- p = XFerBuffer;
- memset(XFerBuffer, SPACE, MAX_COLUMN);
- i = 0;
- while ((c = getc(fp)) != EOF) {
- if (c == '\n') {
- saveHist(0, NO);
- p = XFerBuffer;
- memset(XFerBuffer, SPACE, MAX_COLUMN);
- i = 0;
- lines++;
- } else if (isSJIS1(c)) {
- c2 = getc(fp);
- c = SJIStoJIS(c, c2) | 0x8080; /* SJIS to EUC */
- *p++ = c>>8;
- *p++ = c & 0xff;
- i += 2;
- } else {
- *p++ = c;
- i++;
- }
- if (i >= MAX_COLUMN) {
- saveHist(0, NO);
- p = XFerBuffer;
- memset(XFerBuffer, SPACE, MAX_COLUMN);
- i = 0;
- lines++;
- }
- }
- saveHist(0, NO);
- /*
- * fill screen
- */
- memset(XFerBuffer, SPACE, MAX_COLUMN);
- while (lines++ < realMaxLine-3/*viewMaxLine*/)
- saveHist(0, NO);
- }
-
- /*
- ** static moveView()
- *
- * recenter cursor in view
- */
- static void moveView()
- {
- if (histY < viewMaxLine/2)
- view = 0;
- else if (histY >= histLines - viewMaxLine/2)
- view = histLines - viewMaxLine;
- else
- view = histY - viewMaxLine/2;
- redrawView();
- }
-
- /*
- ** static redrawView()
- *
- * redraw screen
- */
- static void redrawView()
- {
- int y;
- int i;
- int dif = view - oldView;
-
- cursor = NO;
- cursorOnOff(NO);
- if (marked) {
- /*
- * this is simplest way, but slow
- */
- for (y = 0, i = view; y <= viewBottomLine; y++, i++)
- showLine(y, i);
- } else {
- locate(0, 0);
- if (dif > 0 && dif < viewMaxLine) {
- deleteLine(dif); /* scroll old view up */
- y = viewMaxLine-dif;
- i = view+viewMaxLine-dif;
- } else if (dif < 0 && -dif < viewMaxLine) {
- insertLine(-dif); /* scroll old view down */
- y = 0;
- dif = -dif;
- i = view;
- } else if (dif != 0) {
- dif = viewMaxLine;
- y = 0;
- i = view;
- }
- for (; dif > 0; y++, i++, --dif)
- showLine(y, i);
- }
- cursor = YES;
- cursorOnOff(YES);
- oldView = view;
- scrollBar();
- }
-
- /*
- ** static findCharBoundary(x, y)
- *
- * find nearest character boundary
- */
- static int findCharBoundary(x, y)
- int x;
- int y;
- {
- u_char FAR *at = virtualToReal(y);
- register u_char FAR *p;
- register int i;
-
- p = &at[0];
- for (i = 0; i < x; i++)
- if (isEUC(*p++)) {
- p++;
- i++;
- }
- if (i > x && isEUC(*--p))
- return(i-2);
- return(i);
- }
-
- static void putNChar(x, y)
- int x, y;
- {
- u_char FAR *buf = virtualToReal(y);
- short c;
-
- c = buf[x];
- if (isEUC(c))
- c = ((c<< 8)|buf[x+1]) & 0x7f7f;
- conWrite(c);
- }
-
- /*
- ** static int cmpCursorMark()
- *
- * compare cursor position and mark position
- *
- * return 0 if cursor == mark
- * plus if mark < cursor
- * minus if cursor < mark
- */
- static int cmpCursorMark()
- {
- if (histY > markY)
- return(1);
- if (histY < markY)
- return(-1);
- return(histX - markX);
- }
-
- /*
- ** static u_char FAR *virtualToReal(y)
- *
- * convert virtual line to line address on the history buffer
- */
- static u_char FAR *virtualToReal(y)
- int y;
- {
- if ((histEnd - histHead) -1 >= y)
- return(&(*histBuf)[histHead + y][0]);
- else
- return(&(*histBuf)[y - (histEnd - histHead)][0]);
- }
-
- /*
- ** saveHist(y, saveFlag)
- *
- * save line y on the screen to end of the history buffer
- */
- void saveHist(y, saveFlag)
- int y;
- int saveFlag;
- {
- if (maxHistLines <= 0)
- return; /* history Off */
- if (saveFlag)
- saveLine(y, &(*histBuf)[histTail][0]);
- else
- moveData(&(*histBuf)[histTail][0], (char FAR *)XFerBuffer, MAX_COLUMN);
- if (++histTail >= histEnd)
- histTail = 0;
- if (histTail == histHead)
- if (++histHead >= histEnd)
- histHead = 0;
- }
-
- /*
- ** static scrollBar()
- *
- * display scroll bar
- */
- static void scrollBar()
- {
- int where, num;
- register int i;
-
- /*
- * total lines in the history buffer
- */
- where = (int)(((u_short)view * MAX_COLUMN) / (u_short)histLines);
- num = (int)(((u_short)viewMaxLine * MAX_COLUMN) / (u_short)histLines);
- if (view + viewMaxLine == histLines)
- num++;
- /*
- * scroll bar
- */
- cursor = NO;
- locate(0, viewBottomLine+1);
- for (i = 0; i < where; i++)
- conWrite(softFont? SOFT_FONT_EBOX : EBOX_CHAR);
- for (; (i < MAX_COLUMN) && (--num >= 0); i++)
- conWrite(softFont? SOFT_FONT_FBOX : FBOX_CHAR);
- for (; i < MAX_COLUMN; i++)
- conWrite(softFont? SOFT_FONT_EBOX : EBOX_CHAR);
- /*
- * indicate mark point
- */
- if (marked) {
- locate((u_short)markY * MAX_COLUMN/histLines, viewBottomLine+1);
- conWrite('M');
- }
- cursor = YES;
- locate(histX, DOT(histY));
- }
-
- /*
- ** static statusLine()
- *
- * display status line
- */
- static void statusLine()
- {
- u_char buf[MAX_COLUMN];
- long x;
-
- #if 1
- /*
- * display copybuffer usage %
- */
- x = copyBufferRealSize * 100L / maxCopyBuf;
- locate(0, viewBottomLine+2);
- conPrint("ESC-ESC:END ENTER:COPY-PASTE-END INS:MARK ESC-?:HELP COPYBUF ");
- sprintf(buf, "%3u%%", (u_short)x);
- conPrint(buf);
- #else /* debug */
- /*
- * display internal variables
- */
- sprintf(buf, "lines %d histY %d view %d head %d tail %d %u/%u BYTES",
- histLines, histY, view, histHead, histTail,
- (u_short)copyBufferRealSize, (u_short)maxCopyBuf);
- locate(0, viewBottomLine+2);
- conPrint(buf);
- #endif
- locate(histX, DOT(histY));
- }
-
- /*
- ** static showLine(y, buf)
- *
- * show buffer at line y
- * Kanji code in buffer is UEC.
- */
- static void showLine(screenY, bufferY)
- int screenY;
- int bufferY;
- {
- register int x;
- register u_short c;
- register u_char FAR *buf = virtualToReal(bufferY);
- long mark = (long)markY * MAX_COLUMN + (long)markX;
- long hist = (long)histY * MAX_COLUMN + (long)histX;
- long y = (long)bufferY * MAX_COLUMN;
- long pos;
- int state;
- int oldState;
- int cursorSave = cursor;
-
- #define inRegion() ((mark <= hist) ? \
- (mark <= pos && pos < hist) : \
- (hist <= pos && pos < mark))
-
- cursor = NO;
- cursorOnOff(NO);
- locate(0, screenY);
-
- pos = y;
- oldState = inRegion();
- if (marked && oldState)
- reverseMode();
- for (x = 0; x < MAX_COLUMN; x++) {
- if (marked) {
- pos = y + x;
- state = inRegion();
- if (oldState != state)
- if (oldState)
- normalMode();
- else
- reverseMode();
- oldState = state;
- }
- if (isEUC(c = *buf++)) {
- c = ((u_short)(c<<8)|*buf++) & 0x7f7f;
- x++;
- }
- conWrite(c);
- }
- normalMode();
- cursor = cursorSave;
- if (cursor)
- cursorOnOff(YES);
- }
-
- #endif /* COPY_PASTE */
-