home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / COMM / MISC / SRC26_2.ZIP / SRC / EDIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  33.7 KB  |  1,630 lines

  1. /*
  2. ** edit.c: hterm 'History Editor' for copy&paste, history, local editting
  3.  *
  4.  * Author: HIRANO Satoshi
  5.  * (C) 1989  Halca Computer Science Laboratory TM
  6.  *             University of Tokyo
  7.  *
  8.  * 1.1 89/07/24 Halca.Hirano creation
  9.  *    history, roll up, roll down, copy & paste (kanji is only to see.)
  10.  *    I used simple and stupid screen rewriting algolithm.
  11.  *    (I rewrite entire screen for each inserting character!)
  12.  *    Don't worry, hterm is fast enough even if on my sloooow IBM-PC/AT.
  13.  *    ---- V2.3.-1 distribution ----
  14.  * 1.2 89/09/18 Halca.Hirano
  15.  *    User can chagne buffer size by environment variable
  16.  * 1.3 89/09/24 Halca.Hirano
  17.  *    change paste strategy. We can paste in commnunication mode.
  18.  *        ---- V2.4.0 distribution ----
  19.  * 1.4 89/12/08 Halca.Hirano
  20.  *    logging off
  21.  * 2.1 90/06/10 Halca.Hirano rewrite entirely.
  22.  *    1) use standard hterm console interface rather than show/saveLine()
  23.  *        interface.
  24.  *    2) marking is made by reverse attributed console write instead of
  25.  *        reverse() function.
  26.  * 2.2 90/06/24 Halca.Hirano change some key binding
  27.  * 2.3 90/06/29 Halca.Hirano
  28.  *    add kill line and insert line
  29.  * 2.4 90/07/01 Halca.Hirano
  30.  *    support hemacs functions (WARAERU!)
  31.  * 2.5 90/07/12 Halca.Hirano
  32.  *    fix 25 line mode initial cursor bug
  33.  *
  34.  * NOTE:
  35.  *    History buffer has ring buffer structure. Kanji is represented
  36.  *    in EUC code for all machine archtecture. 
  37.  *    This is because NEC PC9801's screen code is a variant of JIS code.
  38.  *    And JIS -> EUC conversion is faster than JIS -> SJIS conversion. 
  39.  *    The most important thing is to keep speed of scrolling in communication
  40.  *    mode. saveLine() which is called from scrlUp() in console.c
  41.  *    gets disappearing line on VRAM, then save it into tail of the
  42.  *    history buffer.
  43.  *    Sorry AX users.
  44.  *
  45.  * CAUTION:
  46.  *    History Editor uses max 128K bytes.
  47.  *    To reduce memory usage, set environ variable HTHISTORY and HTCOPYBUF.
  48.  *
  49.  *    I think MSC5.1 is brain damaged.
  50.  *    For instance,
  51.  *        main()
  52.  *        {
  53.  *            u_char (*beg)[MAX_COLUMN], (*end)[MAX_COLUMN];
  54.  *    
  55.  *         beg = (void *)0;
  56.  *            end = beg+400;       end > 0x8000
  57.  *            printf("%d\n", end-beg);
  58.  *        }
  59.  *    produces MINUS value. not 400!
  60.  *    Thus I use array of array for history buffer representation,
  61.  *    instead of pointer to array.
  62.  * 
  63.  * $Header: edit.cv  1.12  90/07/04 01:38:00  hirano  Exp $
  64.  *
  65.  */
  66.  
  67. #include "option.h"
  68. #if defined(COPY_PASTE) | defined(HEMACS)
  69. #include <stdio.h>
  70. #include <string.h>
  71. #include <stdlib.h>
  72. #include <ctype.h>
  73. #include "config.h"
  74. #include "hterm.h"
  75. #include "default.h"
  76. #include "global.h"
  77.  
  78.  
  79. #define DOT(x) ((x)-view)
  80. #define HUGENUM    10000
  81.  
  82. /*
  83. ** static storage
  84.  */
  85. u_char (FAR *histBuf)[][MAX_COLUMN];    /* history buffer (RING)    */
  86. static int maxHistLines;        /* history buffer lines        */
  87. static int histEnd;                /* history buffer end        */
  88. static int histHead;            /* next in line            */
  89. static int histTail;            /* next out line               */
  90. static int oldHistTail;            /* histTail at enterEdit        */
  91.  
  92. static int view;                /* virtual lineNo at left upper */
  93.                                 /*     on the screen                */
  94. static int oldView;                /* oldView                        */
  95. static int viewMaxLine;            /* lines on the screen            */
  96. static int viewBottomLine;        /* bottom line of the screen    */
  97.  
  98. static int histX;                /* current column number on history */
  99. static int histY;                /* current virtual line number on history */
  100. static int histHomeX;            /* last screen cursor X, Y position */
  101. static int histHomeY;            /*    on history buffer            */
  102. static int histLines;            /* actual lines in history buf    */
  103. static int markX;                /* mark X begin position        */
  104. static int markY;                /* mark Y begin position        */
  105. static int markEndX;            /* region end X position        */
  106. static int markEndY;            /* region end Y possition        */
  107. static int marked;                /* marked or not marked flag    */
  108.  
  109. static u_short maxCopyBuf;        /* copy buffer size             */
  110. u_char FAR *copyBuffer;            /* copy buffer (SJIS text)        */
  111. u_char FAR *copyBufferPtr;        /* next in pointer                */
  112. u_short copyBufferRealSize;        /* copy buffer contents            */
  113. static char copyFile[66];        /* copy file name                */
  114. static int timer = PASTE_TIMER;    /* paste wait timer to prevent XOFF */
  115.                                 /*      from the remote system    */
  116.  
  117. static int oldMode;
  118. static char statusLineUsed;        /* status line was used            */
  119.  
  120. static u_char searchString[60] = "";
  121.  
  122. void enterEdit(void );
  123. void localUp(void);
  124. void localDown(void);
  125. void localRight(void);
  126. void localLeft(void);
  127. void localPgUp(void);
  128. void localPgDn(void);
  129. void localTOL(void);
  130. void localEOL(void);
  131. void gotoLine(void);
  132. void localBOF(void);
  133. void localHome(void);
  134. void searchForward(void);
  135. void searchBackward(void);
  136. void xngCurMark(void);
  137. void localMark(void);
  138. void localAppend(void);
  139. void localCopy(void);
  140. void clearCopyBuf(void);
  141. void copyBufWrite(void);
  142. void localLoadFile(void);
  143. void moveView(void);
  144. void localHelp(void);
  145. void leaveEdit(u_short);
  146. void localBS(void);
  147. void localDel(void);
  148. void localKill(void);
  149. void localCR(void);
  150. void localChar(u_short);
  151.  
  152. void localInsertLine(int);
  153. void localDeleteLine(int);
  154. void localClearColumn(int, int, int);
  155. int findEOL(int);
  156. int copyOneLine(int, int, int);
  157. void paste(void);
  158. u_short getCopyBuffer(void);
  159. void redrawView(void);
  160. findCharBoundary(int, int);
  161. void putNChar(int, int);
  162. int cmpCursorMark(void);
  163. u_char FAR *virtualToReal(int);
  164. void scrollBar(void);
  165. void statusLine(void);
  166. void showLine(int, int);
  167.  
  168. /*
  169.  * function table
  170.  */
  171. #define X_PRE 1
  172. #define E_PRE 2
  173. #define T_PRE 4
  174. #define BAD 0xffff
  175. struct _funcTab {
  176.     u_short prefix;        /* X-prefix or M-prefix    */
  177.     u_short code;        /* cursor key             */
  178.     u_short tabCode;    /* bind table key        */
  179.     void (*func)();        /* function                */
  180. } funcTab[] = {
  181.     {0,                UP_KEY,        C_UP,        localUp},
  182.     {0,                DOWN_KEY,    C_DOWN,        localDown},
  183.     {0,                RIGHT_KEY,    C_RIGHT,    localRight},
  184.     {0,                LEFT_KEY,    C_LEFT,        localLeft},
  185. #ifdef PC98
  186.     {0,                PGDN_KEY,    C_PP,        localPgUp},
  187. #else
  188.     {0,                PGUP_KEY,    C_PP,        localPgUp},
  189. #endif
  190. #ifdef PC98
  191.     {0,                PGUP_KEY,    C_NP,        localPgDn},
  192. #else
  193.     {0,                PGDN_KEY,    C_NP,        localPgDn},
  194. #endif
  195.     {0,                HOME_KEY,    C_TOL,        localTOL},
  196.     {0,                END_KEY,    C_EOL,        localEOL},
  197.     {E_PRE,            'g',        C_GOTO,        gotoLine},
  198.     {E_PRE,            '<',        C_TOP,        localBOF},
  199.     {E_PRE,            '>',        C_HOME,        localHome},
  200.     {0,                BAD,        C_SEARCHF,    searchForward},
  201.     {0,                BAD,        C_SEARCHB,    searchBackward},
  202.     {X_PRE,            CTRL('X'),    C_XNG,        xngCurMark},
  203.     {0,                INS_KEY,    C_MARK,        localMark},
  204.     {E_PRE,            ' ',        BAD,        localMark},
  205.     {E_PRE,            'w',        C_COPY,        localAppend},
  206.     {E_PRE,            TAB,        C_CBUF,        clearCopyBuf},
  207.     {X_PRE,            CTRL('W'),    C_WRITE,    copyBufWrite},
  208.     {X_PRE,            CTRL('F'),    BAD,        localLoadFile},
  209.     {0,                BAD,        C_REDRAW,    moveView},
  210.     {E_PRE,            '?',        BAD,        localHelp},
  211.     {0,                HELP_KEY,    BAD,        localHelp},
  212.     {0,                CR,            BAD,        leaveEdit},
  213.     {0,                PF_HIST_EDIT,    BAD,    leaveEdit},
  214.     {0,                SETUP_KEY,    BAD,        leaveEdit},
  215.     {E_PRE,            ESC,        BAD,        leaveEdit},
  216.     {X_PRE,            CTRL('C'),    BAD,        leaveEdit},
  217.     {0,                BS,            BAD,        localBS},
  218.     {0,                DEL,        BAD,        localBS},
  219.     {0,                BAD,        C_DEL,        localDel},
  220.     {0,                BAD,        C_KILLEND,    localKill},
  221. #ifdef HEMACS
  222.     {0,                CR,            BAD,        localCR},
  223. #else
  224.     {0,                LF,            BAD,        localCR},
  225. #endif
  226. };
  227.  
  228.  
  229. /*
  230. ** void editInit()
  231.  *
  232.  * allocate buffer, initialize internals
  233.  */
  234. void editInit()
  235. {
  236.     char *p, *getenv();
  237.  
  238.     /*
  239.      * allocate history buffer
  240.      */
  241. #ifdef HEMACS
  242.         maxHistLines = MAX_HIST_LINES;
  243.         maxCopyBuf = MAX_COPY_BUF_SIZE;
  244. #else
  245.     if ((p = getenv("HTHISTORY")) == NULL) {
  246.         maxHistLines = DEFAULT_HIST_LINES;
  247.     } else {
  248.         maxHistLines = atoi(p);
  249.         if (maxHistLines <= MAX_LINE_25_MODE) {
  250.             maxHistLines = 0;
  251.             return;        /* history Off    */
  252.         }
  253.         if (maxHistLines > MAX_HIST_LINES)
  254.             maxHistLines = MAX_HIST_LINES;
  255.     }
  256.  
  257.     if ((p = getenv("HTCOPYBUF")) == NULL) {
  258.         maxCopyBuf = DEFAULT_COPY_BUF_SIZE;
  259.     } else {
  260.         maxCopyBuf = (u_short)atoi(p);
  261.         if (maxCopyBuf > MAX_COPY_BUF_SIZE)
  262.             maxCopyBuf = MAX_COPY_BUF_SIZE;
  263.     }
  264. #endif /* HEMACS */
  265.  
  266.     histBuf = allocMem((long)maxHistLines*MAX_COLUMN);
  267.     if (histBuf == 0) {
  268.         fprintf(stderr, msg_alloc, "history, check $HTHISTORY\n");
  269.         exit(1);
  270.     }
  271.     histHead = histTail = 0;
  272.     histEnd = maxHistLines;
  273.  
  274.     /*
  275.      * allocate copy buffer
  276.      */
  277.     if (maxCopyBuf) {
  278.         copyBuffer = (u_char FAR *)allocMem((long)maxCopyBuf);
  279.         if (copyBuffer == 0) {
  280.             fprintf(stderr, msg_alloc, "history, $HTCOPYBUF\n");
  281.             exit(1);
  282.         }
  283.     }
  284.     copyBufferPtr = copyBuffer;
  285.     copyBufferSize = copyBufferRealSize = 0;
  286.     strcpy(copyFile, COPY_BUF_FILE);
  287. }
  288.  
  289. /*
  290. ** void editEnd()
  291.  *
  292.  * clean up at hterm exit time; return balk of memory
  293.  */
  294. void editEnd()
  295. {
  296.     if (maxHistLines <= 0)
  297.         return;
  298.     if (maxCopyBuf)
  299.         freeMem(copyBuffer);
  300.     freeMem(histBuf);
  301. }
  302.  
  303. /*
  304. ** void historyEditor()
  305.  *
  306.  * history editor main loop
  307.  */
  308. void historyEditor()
  309. {
  310.     u_short c;
  311.     short prefix;
  312.     struct _funcTab *f;
  313.     int i;
  314.  
  315.     /*
  316.      * If history is disabled, return immediatly
  317.      */
  318.     if (maxHistLines <= 0)
  319.         return;
  320.     /*
  321.      * set up edit mode
  322.      */
  323.     enterEdit();
  324.  
  325.     statusLineUsed = NO;
  326.     /*
  327.      * OK, enjoy modification of your history!
  328.      */
  329.     for (;;) {
  330.         /*
  331.          * read one char
  332.          */
  333.         prefix = NO;
  334.         while ((short)(c = keyin()) == -1)
  335.             ;
  336.         if (statusLineUsed)
  337.             clearStatus();
  338.  
  339.         /*
  340.          * process prefix char
  341.          */
  342.         if (c == CTRL('X')) {
  343.             prefix = X_PRE;
  344.             putStatus("^X-");
  345.             goto readNext;
  346.         }
  347.         if (c == bindTab[C_ESC]) {
  348.             prefix = E_PRE;
  349.             putStatus("ESC-");
  350.         readNext:
  351.             while ((short)(c = keyin()) == -1)
  352.                 ;
  353.             c = tolower(c);
  354.             clearStatus();
  355.         }
  356.  
  357.         /*
  358.          * call appropreate function
  359.          */
  360.         if (!prefix && (((c & 0xff00) && (c & 0x00ff))
  361.             || (0x20 <= c && c <= 0x7e) || c == TAB || c == bindTab[C_QUOTE]))
  362.             localChar(c);        /* self insert keys    */
  363.         else {
  364.             for (i = (sizeof(funcTab)/sizeof(struct _funcTab))-1; i >= 0; --i) {
  365.                 f = &funcTab[i];
  366.                 if ((prefix == f->prefix && f->code != BAD && c == f->code) ||
  367.                     (prefix == 0 && f->tabCode != BAD && c == bindTab[f->tabCode])) {
  368.                         
  369.                     (*f->func)(c);
  370.                     if (f->func == leaveEdit)
  371.                         return;
  372.                     break;
  373.                 }
  374.             }
  375.             if (i < 0) {
  376.                 putStatus("key not bound"); bell();
  377.                 statusLineUsed = YES;
  378.             }
  379.         }
  380.     }
  381. }
  382.  
  383. /*
  384. ** localBOF()
  385.  *
  386.  * beginning of a file
  387.  */
  388. static void localBOF()
  389. {
  390.     histY = histX = 0; 
  391.     moveView(); 
  392. }
  393.  
  394. /*
  395. ** localHelp()
  396.  *
  397.  */
  398. static void localHelp()
  399. {
  400.     helpSystem("hist-editor key");
  401.     while (keyin() == -1)
  402.         ;
  403.     oldView = HUGENUM;
  404.     redrawView();
  405. }
  406.  
  407. /*
  408. ** static void enterEdit()
  409.  *
  410.  * initialize history editor
  411.  */
  412. static void enterEdit()
  413. {
  414.     int y;
  415.     int oldCursorX = cursorX;
  416.     int oldCursorY = cursorY;
  417.     int oldBottomLine = bottomLine;
  418.  
  419.     /* 
  420.      * save curpage in history 
  421.      */
  422.     oldHistTail = histTail;        /* may be used future   */
  423. #ifndef HEMACS
  424.     for (y = 0; y <= bottomLine; y++)
  425.         saveHist(y, YES);
  426. #endif
  427.     /*
  428.      * save page0 and show page1
  429.      */
  430.     oldMode = mode;
  431.     mode = M_HISTORY;
  432.     showPage1();
  433.     cursorOnOff(YES);
  434.     marked = NO;
  435.     copyBufferPtr = copyBuffer;
  436.     copyBufferSize = copyBufferRealSize = 0;
  437.     viewMaxLine = realMaxLine - 3;
  438.     viewBottomLine = realMaxLine - 4;
  439.     lowScrRegion = viewBottomLine;        /* create text window    */
  440.  
  441.     if (histHead <= histTail)
  442.         histLines = histTail - histHead;
  443.     else
  444.         histLines = maxHistLines - (histHead - histTail);
  445.     /*
  446.      * reset pointers
  447.      */
  448.     histHomeX = histX = oldCursorX;
  449.     histHomeY = histY = histLines - (oldBottomLine - oldCursorY) - 1;
  450.     /* 
  451.      * show last history 
  452.      */
  453.     oldView = HUGENUM;           /* force to rewrite entire screen    */
  454.     statusLine();
  455. #ifdef HEMACS
  456.     histX = histY = histHomeX = 0;
  457.     histHomeY = histLines - 1;
  458.     redrawView();
  459. #else
  460.     localHome();
  461. #endif
  462. }
  463.  
  464. /*
  465. ** leaveEdit()
  466.  *
  467.  * termination of history editor
  468.  */
  469. static void leaveEdit(c)
  470. u_short c;
  471. {
  472.     if (marked)         /* paste    */
  473.         localCopy();
  474.     showPage0();
  475.     histTail = oldHistTail;        /* remove last page from histry buffer */
  476.     mode = oldMode;
  477.     if (c == CR)
  478.         paste();
  479. }
  480.  
  481. /*
  482. ** localChar(c)
  483.  *
  484.  * self insert to history buffer
  485.  */
  486. static void localChar(c)
  487. u_short c;            /* c is hterm kanji code    */
  488. {
  489.     u_char FAR *at = virtualToReal(histY);
  490.     u_char FAR *p;
  491.     u_char FAR *q;
  492.     int oldHistX = histX;
  493.     int len, i;
  494.     int grow = (cmpCursorMark() >= 0);
  495.  
  496.     if (c == bindTab[C_QUOTE])
  497.         while ((c = keyin()) == -1);
  498.  
  499.     len = (c & 0xff00) ? 2 : 1;        /* kanji or ascii*/
  500.     if (histX+len > LAST_COLUMN)
  501.         return;            /* line overflow   */
  502.  
  503.     /*
  504.      * make space in the buffer
  505.      */
  506.     p = &at[LAST_COLUMN-len];
  507.     q = &at[LAST_COLUMN];
  508.     for (i = MAX_COLUMN-histX-len; i > 0; --i, --p, --q)
  509.         *q = *p;
  510.  
  511.     /*
  512.      * insert char in the buffer
  513.      */
  514.     p = &at[histX];
  515.     if (len == 2) {
  516.         *p++ = ((c>>8)|0x80);
  517.         *p++  = ((c&0xff)|0x80);
  518.     } else
  519.         *p++ = c;
  520.  
  521.     /*
  522.      * make room on the screen
  523.      */
  524.     insertChar(histX, len);
  525.  
  526.     histX += len;
  527.  
  528.     if (histY == markY && oldHistX < markX)
  529.         markX += len;
  530.         if (markX > MAX_COLUMN)
  531.             markX = MAX_COLUMN;
  532.     /*
  533.      * put it
  534.      */
  535.     if (marked) {
  536.         if (grow) {                    /* grow reverse        */
  537.             reverseMode();
  538.             conWrite(c);
  539.             normalMode();
  540.         } else {                    /* shrink reverse    */
  541.             conWrite(c);            /* put the char on oldHistX position    */
  542.             locate(histX, DOT(histY));
  543.             reverseMode();
  544.             putNChar(histX, histY);
  545.             normalMode();
  546.         }
  547.     } else
  548.         conWrite(c);
  549.     locate(histX, DOT(histY));
  550. }
  551.  
  552. static void localBS()
  553. {
  554.     u_char FAR *at = virtualToReal(histY);
  555.  
  556.     if (histX == 0) 
  557.         return;
  558.     --histX;
  559.     if (isEUC(at[histX]) && histX > 0)
  560.         --histX;
  561.     localDel();
  562. }
  563.  
  564. static void localDel()
  565. {
  566.     u_char FAR *at = virtualToReal(histY);
  567.     int len;
  568.  
  569.     len = isEUC(at[histX]) ? 2 : 1;
  570.     moveData(&at[histX], &at[histX+len], MAX_COLUMN-histX-len);
  571.     at[LAST_COLUMN] = SPACE;
  572.     if (len == 2)
  573.         at[LAST_COLUMN-1] = SPACE;
  574.     if (marked && histY == markY && histX < markX)
  575.         markX -= len;
  576.     showLine(DOT(histY), histY);
  577.     locate(histX, DOT(histY));
  578. }
  579.  
  580. static void localKill()
  581. {
  582.     int eol = findEOL(histY);
  583.     int oldMarkX = markX;
  584.     
  585.     if (histX < eol) {                        /* erase within a line    */
  586.         localClearColumn(histX, MAX_COLUMN, histY);
  587.         if (marked && histY == markY && histX < markX)
  588.             markX = histX;
  589.         showLine(DOT(histY), histY);
  590.     } else if (histY < histLines-1) {        /* remove a line        */
  591.         if (eol == 0) {
  592.             localDeleteLine(histY);
  593.         } else  {
  594.             moveData((u_char FAR *)XFerBuffer, virtualToReal(histY+1), MAX_COLUMN-histX);
  595.             localDeleteLine(histY+1);
  596.             moveData(&(virtualToReal(histY)[histX]), (u_char FAR *)XFerBuffer, MAX_COLUMN-histX);
  597.             if (marked && histY+1 == markY) {
  598.                 markY = histY;
  599.                 markX = histX + oldMarkX;
  600.                 if (markX > MAX_COLUMN)
  601.                     markX = MAX_COLUMN;
  602.             }
  603.         }
  604.         oldView = HUGENUM;
  605.         redrawView();
  606.     }
  607.     locate(histX, DOT(histY));
  608. }
  609.  
  610. static void localCR()
  611. {
  612.     int oldMarkX = markX;
  613.     int oldMarkY = markY;
  614.     u_char FAR *at = virtualToReal(histY);
  615.  
  616.     moveData((u_char FAR *)XFerBuffer, &at[histX], MAX_COLUMN-histX);
  617.     localClearColumn(histX, MAX_COLUMN, histY);
  618.     localInsertLine(histY);
  619.     moveData(at, (u_char FAR *)XFerBuffer, MAX_COLUMN-histX);
  620.     histX = 0;
  621.     if (marked) {
  622.         if (oldMarkY == histY && histX <= oldMarkX) {
  623.             markX = oldMarkX - histX;
  624.             markY = histY;
  625.         }
  626.     }
  627.     oldView = HUGENUM;
  628.     redrawView();
  629. }
  630.  
  631. static void localInsertLine(y)
  632. int y;
  633. {
  634.     int i;
  635.  
  636.     for (i = 1; i <= y; i++)
  637.         moveData(virtualToReal(i-1), virtualToReal(i), MAX_COLUMN);
  638.     localClearColumn(0, MAX_COLUMN, y);
  639.     if (marked) {
  640.         if (markY <= y)
  641.             --markY;
  642.         if (markY < 0)
  643.             markX = markY = 0;
  644.     }
  645. }
  646.  
  647. static void localDeleteLine(y)
  648. int y;
  649. {
  650.     int i, j;
  651.  
  652.     if (y < histLines-1)
  653.         for (j = histLines-y-1, i = y; j >= 1; --j, i++)
  654.             moveData(virtualToReal(i), virtualToReal(i+1), MAX_COLUMN);
  655.     localClearColumn(0, MAX_COLUMN, histLines-1);
  656.     if (marked) {
  657.         if (y < markY)
  658.             --markY;
  659.         else if (markY == y) {
  660.             markX = 0;
  661.         }
  662.     }
  663. }
  664.  
  665. static void localClearColumn(from, to, y)
  666. int from;
  667. int to;        /* to - 1 */
  668. int y;
  669. {
  670.     u_char FAR *at = virtualToReal(y);
  671.     u_char FAR *p;
  672.     int i;
  673.  
  674.     for (p = &at[from], i = to-from; i > 0; --i)
  675.         *p++ = SPACE;
  676. }
  677.  
  678. /*
  679. ** static localPgUp()
  680.  *
  681.  * show previous page
  682.  */
  683. static void localPgUp()
  684. {
  685.     if (view < viewMaxLine) {
  686.         histY -= view;
  687.         view = 0;
  688.     } else {
  689.         view -= viewMaxLine;
  690.         histY -= viewMaxLine;
  691.     }
  692.     redrawView();
  693. }
  694.  
  695. /*
  696. ** static localPgDn()
  697.  *
  698.  * next page
  699.  */
  700. static void localPgDn()
  701. {
  702.     if (view + viewMaxLine*2 > histLines) {
  703.         histY += histLines - viewMaxLine - view;
  704.         view = histLines - viewMaxLine;
  705.     } else {
  706.         histY += viewMaxLine;
  707.         view += viewMaxLine;
  708.     }
  709.     redrawView();
  710. }
  711.  
  712. /*
  713. ** static localRight()
  714.  *
  715.  * move cursor to right (no wrap)
  716.  */
  717. static void localRight()
  718. {
  719.     u_char FAR *at = virtualToReal(histY);
  720.     int grow = (cmpCursorMark() >= 0);
  721.     int len = isEUC(at[histX]) ? 2 : 1;
  722.     int oldHistX = histX;
  723.  
  724.     if (histX + len > LAST_COLUMN)
  725.         return;                            /* if right end of the line, do nothing    */
  726.     if (marked && grow) {
  727.         reverseMode();
  728.         putNChar(histX, histY);            /* grow reverse        */
  729.         normalMode();
  730.     }
  731.     histX += len;
  732.     if (marked && !grow) {
  733.         putNChar(oldHistX, histY);
  734.         locate(histX, DOT(histY));
  735.         putNChar(histX, histY);            /* shurink reverse */
  736.     }
  737.     locate(histX, DOT(histY));
  738. }
  739.  
  740. /*
  741. ** static localLeft()
  742.  *
  743.  * move cursor to left (no wrap)
  744.  */
  745. static void localLeft()
  746. {
  747.     u_char FAR *at = virtualToReal(histY);
  748.     int oldHistX = histX;
  749.     int grow = (cmpCursorMark() <= 0);
  750.  
  751.     if (--histX < 0) {
  752.         histX = 0;
  753.         return;                        /* do nothing if top of the line    */
  754.     }
  755.     if (isEUC(at[histX]))
  756.         --histX;                    /* if left char is kanji, move to the char    */
  757.     if (marked) {
  758.         if (grow) {
  759.             reverseMode();            /* grow reverse                */
  760.             locate(oldHistX, DOT(histY));
  761.             putNChar(oldHistX, histY);
  762.             locate(histX, DOT(histY));
  763.             putNChar(histX, histY);
  764.             normalMode();
  765.         } else {                    /* shrink reverse            */
  766.             locate(histX, DOT(histY));
  767.             putNChar(histX, histY);
  768.         }
  769.     }
  770.     locate(histX, DOT(histY));
  771. }
  772.  
  773. /*
  774. ** static int localUp()
  775.  *
  776.  * up cursor
  777.  */
  778. static void localUp()
  779. {
  780.     int newY = histY;
  781.  
  782.     if (--newY < 0)
  783.         return;
  784.     histX = findCharBoundary(histX, newY);
  785.     histY = newY;
  786.     if (histY < view) {
  787.         /*
  788.          * out of view, scroll
  789.          */
  790.         showLine(DOT(histY+1), histY+1);
  791.         moveView();
  792.         return;
  793.     }
  794.     if (marked) {    /* rewrite current line and new Y line */
  795.         showLine(DOT(histY+1), histY+1);
  796.         showLine(DOT(histY), histY);
  797.     }
  798.     locate(histX, DOT(histY));
  799. }
  800.  
  801. /*
  802. ** static localDown()
  803.  *
  804.  * down cursor
  805.  */
  806. static void localDown()
  807. {
  808.     int newY = histY;
  809.  
  810.     if (++newY >= histLines)
  811.         return;
  812.     histX = findCharBoundary(histX, newY);
  813.     histY = newY;
  814.     if (histY >= view + viewMaxLine) {
  815.         /*
  816.          * out of view, scroll
  817.          */
  818.         showLine(DOT(histY-1), histY-1);
  819.         moveView();
  820.         return;
  821.     }
  822.     if (marked) {    /* rewrite current line and new Y line */
  823.         showLine(DOT(histY-1), histY-1);
  824.         showLine(DOT(histY), histY);
  825.     }
  826.     locate(histX, DOT(histY));
  827. }
  828.  
  829. /*
  830. ** static localTOL()
  831.  *
  832.  * move cursor to top of line
  833.  */
  834. static void localTOL()
  835. {
  836.     histX = 0;
  837.     showLine(DOT(histY), histY);
  838.     locate(histX, DOT(histY));
  839. }
  840.  
  841. /*
  842. ** static localEOL()
  843.  *
  844.  * move cursor to end of line
  845.  */
  846. static void localEOL()
  847. {
  848.     histX = findEOL(histY);
  849.     showLine(DOT(histY), histY);
  850.     locate(histX, DOT(histY));
  851. }
  852.  
  853. /*
  854. ** findEOL(int x, int y)
  855.  *
  856.  * find end of line; return eol + 1
  857.  */
  858. static int findEOL(y)
  859. int y;
  860. {
  861.     u_char FAR *at = virtualToReal(y);
  862.     int x;
  863.     
  864.     for (x = LAST_COLUMN; x > 0 && at[x] == SPACE; --x)
  865.         ;
  866.     if (at[x] != SPACE)
  867.         if (x == LAST_COLUMN) {
  868.             if (isEUC(at[x]))     /* full char in this line        */
  869.                 --x;
  870.         } else
  871.             x++;                                /* move cursor to real eol+1    */
  872.     return(x);
  873. }
  874.  
  875. /*
  876. ** static gotoLine()
  877.  *
  878.  * jump to specified line
  879.  */
  880. static void gotoLine()
  881. {
  882.     tmpBuf[0] = '\0';
  883.     if (emacs("Goto line: ", tmpBuf, 10, E_NO_HELP) == ERR) {
  884.         statusLineUsed = YES;
  885.         return;
  886.     }
  887.     if (tmpBuf[0] == '\0') {
  888.         return;
  889.     }
  890.     histY = atoi(tmpBuf);
  891.     if (histY < 0)
  892.         histY = 0;
  893.     else if (histY >= histLines)
  894.         histY = histLines - 1;
  895.     histX = 0;
  896.     moveView();
  897. }
  898.  
  899. /*
  900. ** static localHome()
  901.  *
  902.  * move cursor to home position
  903.  */
  904. static void localHome()
  905. {
  906.     histX = histHomeX; histY = histHomeY;
  907.     view = histLines - viewMaxLine;
  908.     redrawView();
  909. }
  910.  
  911. /*
  912. ** static searchForward()
  913.  *
  914.  * search string forward
  915.  */
  916. static void searchForward()
  917. {
  918.     register u_char FAR *x1, FAR *at;
  919.     register u_char *s1, *s;
  920.     register int i, len, x, y;
  921.  
  922.     strcpy(tmpBuf, searchString);
  923.     if (emacs("Search forward: ", tmpBuf, 65, E_NO_HELP) == ERR) {
  924.         return;
  925.     }
  926.     strcpy((char *)searchString, tmpBuf);
  927.     x = histX+1;
  928.     y = histY;
  929.     if (x > LAST_COLUMN) {
  930.         y++;
  931.         x = 0;
  932.     }
  933.     s = searchString;
  934.     if ((len = strlen((char *)s)) == 0)
  935.         return;
  936.     for (; y < histLines; y++) {
  937.         at = virtualToReal(y);
  938.         for (;x <= MAX_COLUMN-len; x++) {
  939.             for (i = len, x1 = &at[x], s1 = s; i > 0; --i)
  940.                 if (*x1++ != *s1++)
  941.                     break;
  942.             if (i == 0) {     /* found */
  943.                 histY = y;
  944. #if 0
  945.                 if (histY < view || view + viewMaxLine <= histY) {
  946.                     histX = x;
  947.                     moveView();
  948.                 } else
  949.                     moveWithinLine(x);
  950. #else
  951.                 histX = x;
  952.                 moveView();
  953. #endif
  954.                 return;
  955.             }
  956.         }
  957.         x = 0;
  958.     }
  959.     sprintf(tmpBuf, "%s not found", searchString); /* buggy    */
  960.     putStatus(tmpBuf); 
  961.     statusLineUsed++;
  962.     bell();
  963. }
  964.     
  965. /*
  966. ** static searchBackward()
  967.  *
  968.  * search string backward
  969.  * NOTE:
  970.  *     If string is found, cursor stay at the end of string.
  971.  *     This is useful to find prompt pattern and to edit users input.
  972.  */
  973. static void searchBackward()
  974. {
  975.     register u_char *s1;
  976.     register u_char FAR *x1, FAR *at;
  977.     register u_char *s;
  978.     register int i, len, x, y;
  979.  
  980.     strcpy(tmpBuf, searchString);
  981.     if (emacs("Search backward: ", tmpBuf, 65, E_NO_HELP) == ERR) {
  982.         return;
  983.     }
  984.     strcpy(searchString, tmpBuf);
  985.     x = histX-1;
  986.     y = histY;
  987.     if (x < 0) {
  988.         --y;
  989.         x = LAST_COLUMN;
  990.     }
  991.     if ((len = strlen(searchString)) == 0)
  992.         return;
  993.     s = &searchString[len];
  994.     for (; y >= 0; --y) {
  995.         at = virtualToReal(y);
  996.         for (;x >= len-1; --x) {
  997.             for (i = len, x1 = &at[x+1], s1 = s; i > 0; --i)
  998.                 if (*--x1 != *--s1)
  999.                     break;
  1000.             if (i == 0) {     /* found */
  1001.                 histY = y;
  1002. #if 0
  1003.                 if (histY < view || view + viewMaxLine <= histY) {
  1004.                     histX = x;
  1005.                     moveView();
  1006.                 } else
  1007.                     moveWithinLine(x);
  1008. #else
  1009.                 histX = x;
  1010.                 moveView();
  1011. #endif
  1012.                 return;
  1013.             }
  1014.         }
  1015.         x = LAST_COLUMN;
  1016.     }
  1017.     sprintf(tmpBuf, "%s not found", searchString); /* buggy    */
  1018.     putStatus(tmpBuf); 
  1019.     statusLineUsed++;
  1020.     bell();
  1021. }
  1022.     
  1023. /*
  1024. ** static localMark()
  1025.  *
  1026.  * set mark on current cursor position
  1027.  */
  1028. static void localMark()
  1029. {
  1030.     if (marked) {
  1031.         marked = NO;
  1032.         oldView = HUGENUM;          /* force to rewrite */
  1033.         redrawView();
  1034.     } else {
  1035.         marked = YES;
  1036.         markX = histX;
  1037.         markY = histY;
  1038.         scrollBar();
  1039.     }
  1040. }
  1041.  
  1042. /*
  1043. ** static clearCopyBuf()
  1044.  *
  1045.  * clear copy buffer
  1046.  */
  1047. static void clearCopyBuf()
  1048. {
  1049.     copyBufferRealSize = 0;
  1050.     copyBufferPtr = copyBuffer;
  1051.     scrollBar();
  1052.     statusLine();
  1053. }
  1054.  
  1055. /*
  1056. ** static xngCurMark()
  1057.  *
  1058.  * exchange cursor and mark
  1059.  */
  1060. static void xngCurMark()
  1061. {
  1062.     int tmpX, tmpY;
  1063.  
  1064.     if (!marked)
  1065.         return;
  1066.     tmpX = histX; tmpY = histY;
  1067.     histX = markX; histY = markY;
  1068.     markX = tmpX; markY = tmpY;
  1069.     if (histY < view || view + viewMaxLine <= histY) {
  1070.         moveView();
  1071.         return;
  1072.     }
  1073.     redrawView();
  1074. }
  1075.  
  1076. /*
  1077. ** static localCopy()
  1078.  *
  1079.  * clear copy buffer, and append region to copy buffer
  1080.  */
  1081. static void localCopy()
  1082. {
  1083.     if (marked == YES) {
  1084.         copyBufferRealSize = 0;
  1085.         copyBufferPtr = copyBuffer;
  1086.     }
  1087.     localAppend();
  1088. }
  1089.  
  1090. /*
  1091. ** static localAppend()
  1092.  *
  1093.  * append region to copy buffer
  1094.  */
  1095. static void localAppend()
  1096. {
  1097.     int endX;
  1098.     u_char FAR *cBufPtrSave = copyBufferPtr;
  1099.     u_short cBufSizeSave = copyBufferRealSize;
  1100.  
  1101.     if (marked) {
  1102.         if (cmpCursorMark() >= 0) {
  1103.             markEndX = histX; markEndY = histY;
  1104.         } else {
  1105.             markEndX = markX; markEndY = markY;
  1106.             markX = histX; markY = histY;
  1107.         }
  1108.         endX = MAX_COLUMN;
  1109.         for (;markY <= markEndY; markY++) {
  1110.             if (markY == markEndY)
  1111.                 endX = markEndX;
  1112.             if (copyOneLine(markX, endX, markY) == ERR) {
  1113.                 putStatus("Copy buffer overflow"); bell();
  1114.                 statusLineUsed++;
  1115.                 copyBufferPtr = cBufPtrSave;
  1116.                 copyBufferRealSize = cBufSizeSave;
  1117.                 locate(histX, DOT(histY));
  1118.                 return;
  1119.             }
  1120.             markX = 0;
  1121.         }
  1122.         marked = NO;
  1123.         oldView = HUGENUM;          /* force to rewrite */
  1124.         redrawView();
  1125.     }
  1126.     scrollBar();
  1127.     statusLine();
  1128. }
  1129.  
  1130. /*
  1131. ** static copyOneLine(xBeg, xEnd, y)
  1132.  *
  1133.  * copy one line from history buffer to copy buffer
  1134.  * NOTE: strip trailing blanks and add \n
  1135.  */
  1136. static int copyOneLine(xBeg, xEnd, y)
  1137. int xBeg, xEnd, y;
  1138. {
  1139.     u_char FAR *at = virtualToReal(y);
  1140.     int eol;
  1141.     int lf = NO;
  1142.  
  1143.     eol = findEOL(y);                /* skip trailing blank    */
  1144.     /*
  1145.      * if this line has no character to write, only newline will be put
  1146.      */
  1147.     if (eol == 0 && at[0] == SPACE)
  1148.         lf = YES;
  1149.     else {
  1150.         /*
  1151.          * find end point to write
  1152.          */
  1153.         if (eol < xEnd) {            /* if cursor is greater than eol    */
  1154.             if (at[eol] != SPACE)    /* if this line is fully used */
  1155.             {
  1156.                 xEnd = MAX_COLUMN;    /* write entire line and    */
  1157.             }
  1158.             else
  1159.                 xEnd = eol;
  1160.             lf = YES;                /* add newline char            */
  1161.         }
  1162.         /*
  1163.          * copy the line to buffer
  1164.          */
  1165.         for (; xBeg < xEnd; xBeg++) {
  1166.             if (++copyBufferRealSize > maxCopyBuf)
  1167.                 return(ERR);
  1168.             *copyBufferPtr++ = at[xBeg];
  1169.         }
  1170.     }
  1171.     if (lf) {
  1172.         if (++copyBufferRealSize > maxCopyBuf)
  1173.             return(ERR);
  1174.         *copyBufferPtr++ = '\n';
  1175.     }
  1176.     return(OK);
  1177. }
  1178.  
  1179. /*
  1180. ** paste()
  1181.  *
  1182.  * prepare to put characters in copy buffer
  1183.  */
  1184. void paste()
  1185. {
  1186.     copyBufferPtr = copyBuffer;
  1187.     copyBufferSize = copyBufferRealSize;
  1188.     timer = upLoadDelay;
  1189. }
  1190.     
  1191. /*
  1192. ** u_short getCopyBuffer()
  1193.  *
  1194.  * pass one char to hterm from copy buffer
  1195.  * NOTE: char is hterm internal format.
  1196.  */
  1197. u_short getCopyBuffer()
  1198. {
  1199.     u_short c;
  1200.  
  1201.     if (--timer > 0)
  1202.         return(ERR);
  1203.     timer = upLoadDelay;
  1204.     --copyBufferSize;
  1205.     if ((c = (u_short)*copyBufferPtr++) == (u_short)'\n')
  1206.         c = (u_short)CR;
  1207. #ifdef KANJI
  1208.     else if (isEUC(c) && copyBufferSize > 0) {
  1209.         c = ((c << 8) | *copyBufferPtr++) & 0x7f7f;
  1210.         --copyBufferSize;
  1211.     }
  1212. #endif /* KANJI */
  1213.     return(c);
  1214. }
  1215.  
  1216. /*
  1217. ** static copyBufWrite()
  1218.  *
  1219.  * write copy buffer to file
  1220.  */
  1221. static void copyBufWrite()
  1222. {
  1223.     FILE *fp;
  1224.     u_char c;
  1225.     u_short sjis;
  1226.  
  1227.     if (marked) {
  1228.         localAppend();
  1229.     }
  1230.     strcpy(tmpBuf, copyFile);
  1231.     if (emacs("File Name (ESC for abort): ", tmpBuf, 65, E_NO_HELP) == ERR) {
  1232.         locate(histX, DOT(histY));
  1233.         cursorOnOff(YES);
  1234.         return;
  1235.     }
  1236.     cursorOnOff(YES);
  1237.     strcpy(copyFile, tmpBuf);
  1238.     if ((fp = fopen(tmpBuf, COPY_FILE_ATTR)) == NULL) {
  1239.         sprintf(tmpBuf, msg_cantOpen, copyFile);
  1240.         putStatus(tmpBuf); bell();
  1241.         locate(histX, DOT(histY));
  1242.         return;
  1243.     }
  1244.     copyBufferPtr = copyBuffer;
  1245.     while (copyBufferRealSize > 0) {
  1246.         c = *copyBufferPtr++;
  1247. #ifdef KANJI
  1248.         if (isEUC(c) && copyBufferRealSize > 0) {
  1249.             sjis = JIStoSJIS(c & 0x7f, (*copyBufferPtr++) & 0x7f);
  1250.             putc(sjis >> 8, fp);
  1251.             --copyBufferRealSize;
  1252.             c = sjis & 0xff;
  1253.         }
  1254. #endif /* KANJI */
  1255.         putc(c, fp);
  1256.         --copyBufferRealSize;
  1257.     }
  1258.     fclose(fp);
  1259.     copyBufferRealSize = 0;
  1260.     copyBufferPtr = copyBuffer;
  1261.     scrollBar();
  1262.     statusLine();
  1263. }
  1264.  
  1265. /*
  1266. ** static localLoadFile()
  1267.  *
  1268.  * load new file
  1269.  */
  1270. void localLoadFile()
  1271. {
  1272.     FILE *fp;
  1273.  
  1274.     tmpBuf[0] = '\0';
  1275.     if (emacs("File Name (ESC for abort): ", tmpBuf, 65, E_NO_HELP | E_FILE) == ERR) {
  1276.         oldView = HUGENUM;
  1277.         redrawView();
  1278.         return;
  1279.     }
  1280.     if ((fp = fopen(tmpBuf, "r")) == NULL) {
  1281.         putStatus("can't open file");
  1282.         oldView = HUGENUM;
  1283.         redrawView();
  1284.         return;
  1285.     }
  1286.     marked = NO;
  1287.     histHead = histTail = 0;
  1288.     histEnd = maxHistLines;
  1289.     copyBufferPtr = copyBuffer;
  1290.     copyBufferSize = copyBufferRealSize = 0;
  1291.     loadFile(fp);
  1292.     fclose(fp);
  1293.     if (histHead <= histTail)
  1294.         histLines = histTail - histHead;
  1295.     else
  1296.         histLines = maxHistLines - (histHead - histTail);
  1297.     oldView = HUGENUM;           /* force to rewrite entire screen    */
  1298.     statusLine();
  1299.     histX = histY = histHomeX = 0;
  1300.     histHomeY = histLines - 1;
  1301.     moveView();
  1302. }
  1303.  
  1304. void loadFile(fp)
  1305. FILE *fp;
  1306. {
  1307.     register int c, c2;
  1308.     int i;
  1309.     char *p;
  1310.     int lines = 0;
  1311.  
  1312.     /*
  1313.      * push contents of the file to history buffer
  1314.      */
  1315.     p = XFerBuffer;
  1316.     memset(XFerBuffer, SPACE, MAX_COLUMN);
  1317.     i = 0;
  1318.     while ((c = getc(fp)) != EOF) {
  1319.         if (c == '\n') {
  1320.             saveHist(0, NO);
  1321.             p = XFerBuffer;
  1322.             memset(XFerBuffer, SPACE, MAX_COLUMN);
  1323.             i = 0;
  1324.             lines++;
  1325.         } else if (isSJIS1(c)) {
  1326.             c2 = getc(fp);
  1327.             c = SJIStoJIS(c, c2) | 0x8080;    /* SJIS to EUC */
  1328.             *p++ = c>>8;
  1329.             *p++ = c & 0xff;
  1330.             i += 2;
  1331.         } else {
  1332.             *p++ = c;
  1333.             i++;
  1334.         }
  1335.         if (i >= MAX_COLUMN) {
  1336.             saveHist(0, NO);
  1337.             p = XFerBuffer;
  1338.             memset(XFerBuffer, SPACE, MAX_COLUMN);
  1339.             i = 0;
  1340.             lines++;
  1341.         }
  1342.     }
  1343.     saveHist(0, NO);
  1344.     /*
  1345.      * fill screen
  1346.      */
  1347.     memset(XFerBuffer, SPACE, MAX_COLUMN);
  1348.     while (lines++ < realMaxLine-3/*viewMaxLine*/)
  1349.         saveHist(0, NO);
  1350. }
  1351.  
  1352. /*
  1353. ** static moveView()
  1354.  *
  1355.  * recenter cursor in view
  1356.  */
  1357. static void moveView()
  1358. {
  1359.     if (histY < viewMaxLine/2)
  1360.         view = 0;
  1361.     else if (histY >= histLines - viewMaxLine/2)
  1362.         view = histLines - viewMaxLine;
  1363.     else
  1364.         view = histY - viewMaxLine/2;
  1365.     redrawView();
  1366. }
  1367.     
  1368. /*
  1369. ** static redrawView()
  1370.  *
  1371.  * redraw screen
  1372.  */
  1373. static void redrawView()
  1374. {
  1375.     int y;
  1376.     int i;
  1377.     int dif = view - oldView;
  1378.  
  1379.     cursor = NO;
  1380.     cursorOnOff(NO);
  1381.     if (marked) {
  1382.         /*
  1383.          * this is simplest way, but slow
  1384.          */
  1385.         for (y = 0, i = view; y <= viewBottomLine; y++, i++)
  1386.             showLine(y, i);        
  1387.     } else {
  1388.         locate(0, 0);
  1389.         if (dif > 0 && dif < viewMaxLine) {
  1390.             deleteLine(dif);        /* scroll old view up    */
  1391.             y = viewMaxLine-dif;
  1392.             i = view+viewMaxLine-dif;
  1393.         } else if (dif < 0 && -dif < viewMaxLine) {
  1394.             insertLine(-dif);        /* scroll old view down     */
  1395.             y = 0;
  1396.             dif = -dif;
  1397.             i = view;
  1398.         } else if (dif != 0) {
  1399.             dif = viewMaxLine;
  1400.             y = 0;
  1401.             i = view;
  1402.         }
  1403.         for (; dif > 0; y++, i++, --dif)
  1404.             showLine(y, i);
  1405.     }
  1406.     cursor = YES;
  1407.     cursorOnOff(YES);
  1408.     oldView = view;
  1409.     scrollBar();
  1410. }
  1411.  
  1412. /*
  1413. ** static findCharBoundary(x, y)
  1414.  *
  1415.  * find nearest character boundary
  1416.  */
  1417. static int findCharBoundary(x, y)
  1418. int x;
  1419. int y;
  1420. {
  1421.     u_char FAR *at = virtualToReal(y);
  1422.     register u_char FAR *p;
  1423.     register int i;
  1424.  
  1425.     p = &at[0]; 
  1426.     for (i = 0; i < x; i++)
  1427.         if (isEUC(*p++)) {
  1428.             p++;
  1429.             i++;
  1430.         }
  1431.     if (i > x && isEUC(*--p))
  1432.         return(i-2);
  1433.     return(i);
  1434. }
  1435.  
  1436. static void putNChar(x, y)
  1437. int x, y;
  1438. {
  1439.     u_char FAR *buf = virtualToReal(y);
  1440.     short c;
  1441.  
  1442.     c = buf[x];
  1443.     if (isEUC(c))
  1444.         c = ((c<< 8)|buf[x+1]) & 0x7f7f;
  1445.     conWrite(c);
  1446. }
  1447.  
  1448. /*
  1449. ** static int cmpCursorMark()
  1450.  *
  1451.  * compare cursor position and mark position
  1452.  *
  1453.  * return 0 if cursor == mark
  1454.  *     plus if mark < cursor
  1455.  *    minus if cursor < mark
  1456.  */
  1457. static int cmpCursorMark()
  1458. {
  1459.     if (histY > markY)
  1460.         return(1);
  1461.     if (histY < markY)
  1462.         return(-1);
  1463.     return(histX - markX);
  1464. }
  1465.  
  1466. /*
  1467. ** static u_char FAR *virtualToReal(y)
  1468.  *
  1469.  * convert virtual line to line address on the history buffer
  1470.  */
  1471. static u_char FAR *virtualToReal(y)
  1472. int y;
  1473. {
  1474.     if ((histEnd  - histHead) -1 >= y)
  1475.         return(&(*histBuf)[histHead + y][0]);
  1476.     else
  1477.         return(&(*histBuf)[y - (histEnd - histHead)][0]);
  1478. }
  1479.  
  1480. /*
  1481. ** saveHist(y, saveFlag)
  1482.  *
  1483.  * save line y on the screen to end of the history buffer
  1484.  */
  1485. void saveHist(y, saveFlag)
  1486. int y;
  1487. int saveFlag;
  1488. {
  1489.     if (maxHistLines <= 0)
  1490.         return;            /* history Off        */
  1491.     if (saveFlag)
  1492.         saveLine(y, &(*histBuf)[histTail][0]);
  1493.     else
  1494.         moveData(&(*histBuf)[histTail][0], (char FAR *)XFerBuffer, MAX_COLUMN);
  1495.     if (++histTail >= histEnd)
  1496.         histTail = 0;
  1497.     if (histTail == histHead)
  1498.         if (++histHead >= histEnd)
  1499.             histHead = 0;
  1500. }
  1501.  
  1502. /*
  1503. ** static scrollBar()
  1504.  *
  1505.  * display scroll bar 
  1506.  */
  1507. static void scrollBar()
  1508. {
  1509.     int where, num;
  1510.     register int i;
  1511.  
  1512.     /*
  1513.      * total lines in the history buffer
  1514.      */
  1515.     where = (int)(((u_short)view * MAX_COLUMN) / (u_short)histLines);
  1516.     num = (int)(((u_short)viewMaxLine * MAX_COLUMN) / (u_short)histLines);
  1517.     if (view + viewMaxLine == histLines)
  1518.         num++;
  1519.     /*
  1520.      * scroll bar
  1521.      */
  1522.     cursor = NO;
  1523.     locate(0, viewBottomLine+1);
  1524.     for (i = 0; i < where; i++)
  1525.         conWrite(softFont? SOFT_FONT_EBOX : EBOX_CHAR);
  1526.     for (; (i < MAX_COLUMN) && (--num >= 0); i++)
  1527.         conWrite(softFont? SOFT_FONT_FBOX : FBOX_CHAR);
  1528.     for (; i < MAX_COLUMN; i++)
  1529.         conWrite(softFont? SOFT_FONT_EBOX : EBOX_CHAR);
  1530.     /*
  1531.      * indicate mark point
  1532.      */
  1533.     if (marked) {
  1534.          locate((u_short)markY * MAX_COLUMN/histLines, viewBottomLine+1);
  1535.         conWrite('M');
  1536.     }
  1537.     cursor = YES;
  1538.     locate(histX, DOT(histY));
  1539.  }
  1540.  
  1541. /*
  1542. ** static statusLine()
  1543.  *
  1544.  * display status line
  1545.  */
  1546. static void statusLine()
  1547.  {
  1548.     u_char buf[MAX_COLUMN];
  1549.     long    x;
  1550.  
  1551. #if 1
  1552.     /*
  1553.      * display copybuffer usage %
  1554.      */
  1555.     x = copyBufferRealSize * 100L / maxCopyBuf;
  1556.     locate(0, viewBottomLine+2);
  1557.     conPrint("ESC-ESC:END  ENTER:COPY-PASTE-END  INS:MARK  ESC-?:HELP  COPYBUF ");
  1558.     sprintf(buf, "%3u%%", (u_short)x);
  1559.     conPrint(buf);
  1560. #else    /* debug */
  1561.     /*
  1562.      * display internal variables
  1563.      */
  1564.     sprintf(buf, "lines %d histY %d view %d head %d tail %d %u/%u BYTES", 
  1565.         histLines, histY, view, histHead, histTail,
  1566.         (u_short)copyBufferRealSize, (u_short)maxCopyBuf);
  1567.     locate(0, viewBottomLine+2);
  1568.     conPrint(buf);
  1569. #endif
  1570.     locate(histX, DOT(histY));
  1571. }
  1572.  
  1573. /*
  1574. ** static showLine(y, buf)
  1575.  *
  1576.  * show buffer at line y
  1577.  * Kanji code in buffer is UEC.
  1578.  */
  1579. static void showLine(screenY, bufferY)
  1580. int screenY;
  1581. int bufferY;
  1582. {
  1583.     register int x;
  1584.     register u_short c;
  1585.     register u_char FAR *buf = virtualToReal(bufferY);
  1586.     long mark = (long)markY * MAX_COLUMN + (long)markX;
  1587.     long hist = (long)histY * MAX_COLUMN + (long)histX;
  1588.     long y = (long)bufferY * MAX_COLUMN;
  1589.     long pos;
  1590.     int state;
  1591.     int oldState;
  1592.     int cursorSave = cursor;
  1593.  
  1594. #define inRegion() ((mark <= hist) ? \
  1595.                     (mark <= pos && pos < hist) : \
  1596.                     (hist <= pos && pos < mark))
  1597.  
  1598.     cursor = NO;
  1599.     cursorOnOff(NO);
  1600.     locate(0, screenY);
  1601.  
  1602.     pos = y;
  1603.     oldState = inRegion();
  1604.     if (marked && oldState)
  1605.         reverseMode();
  1606.     for (x = 0; x < MAX_COLUMN; x++) {
  1607.         if (marked) {
  1608.             pos = y + x;
  1609.             state = inRegion();
  1610.             if (oldState != state)
  1611.                 if (oldState)
  1612.                     normalMode();
  1613.                 else
  1614.                     reverseMode();
  1615.             oldState = state;
  1616.         }
  1617.         if (isEUC(c = *buf++)) {
  1618.             c = ((u_short)(c<<8)|*buf++) & 0x7f7f;
  1619.             x++;
  1620.         }
  1621.         conWrite(c);
  1622.     }
  1623.     normalMode();
  1624.     cursor = cursorSave;
  1625.     if (cursor)
  1626.         cursorOnOff(YES);
  1627. }
  1628.         
  1629. #endif /* COPY_PASTE */
  1630.