home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJ9206.ZIP / DFLT12.ZIP / EDITBOX.C < prev    next >
Text File  |  1992-03-26  |  36KB  |  1,138 lines

  1. /* ------------- editbox.c ------------ */
  2. #include "dflat.h"
  3.  
  4. #define EditBufLen(wnd) (isMultiLine(wnd) ? EDITLEN : ENTRYLEN)
  5. #define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
  6. #define isWhite(c)     ((c)==' '||(c)=='\n')
  7. /* ---------- local prototypes ----------- */
  8. static void SaveDeletedText(WINDOW, char *, int);
  9. static void Forward(WINDOW);
  10. static void Backward(WINDOW);
  11. static void End(WINDOW);
  12. static void Home(WINDOW);
  13. static void Downward(WINDOW);
  14. static void Upward(WINDOW);
  15. static void StickEnd(WINDOW);
  16. static void NextWord(WINDOW);
  17. static void PrevWord(WINDOW);
  18. static void ModTextPointers(WINDOW, int, int);
  19. /* -------- local variables -------- */
  20. static BOOL KeyBoardMarking, ButtonDown;
  21. static BOOL TextMarking;
  22. static int ButtonX, ButtonY;
  23. static int PrevY = -1;
  24.  
  25. /* ----------- CREATE_WINDOW Message ---------- */
  26. static int CreateWindowMsg(WINDOW wnd)
  27. {
  28.     int rtn = BaseWndProc(EDITBOX, wnd, CREATE_WINDOW, 0, 0);
  29.     wnd->MaxTextLength = MAXTEXTLEN+1;
  30.     wnd->textlen = EditBufLen(wnd);
  31.     wnd->InsertMode = TRUE;
  32.     SendMessage(wnd, CLEARTEXT, 0, 0);
  33.     return rtn;
  34. }
  35. /* ----------- SETTEXT Message ---------- */
  36. static int SetTextMsg(WINDOW wnd, PARAM p1)
  37. {
  38.     int rtn = FALSE;
  39.     if (strlen((char *)p1) <= wnd->MaxTextLength)
  40.         rtn = BaseWndProc(EDITBOX, wnd, SETTEXT, p1, 0);
  41.     return rtn;
  42. }
  43. /* ----------- CLEARTEXT Message ------------ */
  44. static int ClearTextMsg(WINDOW wnd)
  45. {
  46.     int rtn = BaseWndProc(EDITBOX, wnd, CLEARTEXT, 0, 0);
  47.     unsigned blen = EditBufLen(wnd)+2;
  48.     wnd->text = DFrealloc(wnd->text, blen);
  49.     memset(wnd->text, 0, blen);
  50.     wnd->wlines = 0;
  51.     wnd->CurrLine = 0;
  52.     wnd->CurrCol = 0;
  53.     wnd->WndRow = 0;
  54.     wnd->wleft = 0;
  55.     wnd->wtop = 0;
  56.     wnd->textwidth = 0;
  57.     wnd->TextChanged = FALSE;
  58.     return rtn;
  59. }
  60. /* ----------- ADDTEXT Message ---------- */
  61. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  62. {
  63.     int rtn = FALSE;
  64.     if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
  65.         rtn = BaseWndProc(EDITBOX, wnd, ADDTEXT, p1, p2);
  66.         if (rtn != FALSE)    {
  67.             if (!isMultiLine(wnd))    {
  68.                 wnd->CurrLine = 0;
  69.                 wnd->CurrCol = strlen((char *)p1);
  70.                 if (wnd->CurrCol >= ClientWidth(wnd))    {
  71.                     wnd->wleft = wnd->CurrCol-ClientWidth(wnd);
  72.                     wnd->CurrCol -= wnd->wleft;
  73.                 }
  74.                 wnd->BlkEndCol = wnd->CurrCol;
  75.                 SendMessage(wnd, KEYBOARD_CURSOR,
  76.                                      WndCol, wnd->WndRow);
  77.             }
  78.         }
  79.     }
  80.     return rtn;
  81. }
  82. /* ----------- GETTEXT Message ---------- */
  83. static int GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  84. {
  85.     char *cp1 = (char *)p1;
  86.     char *cp2 = wnd->text;
  87.     if (cp2 != NULL)    {
  88.         while (p2-- && *cp2 && *cp2 != '\n')
  89.             *cp1++ = *cp2++;
  90.         *cp1 = '\0';
  91.         return TRUE;
  92.     }
  93.     return FALSE;
  94. }
  95. /* ----------- SETTEXTLENGTH Message ---------- */
  96. static int SetTextLengthMsg(WINDOW wnd, unsigned int len)
  97. {
  98.     if (++len < MAXTEXTLEN)    {
  99.         wnd->MaxTextLength = len;
  100.         if (len < wnd->textlen)    {
  101.             wnd->text=DFrealloc(wnd->text, len+2);
  102.             wnd->textlen = len;
  103.             *((wnd->text)+len) = '\0';
  104.             *((wnd->text)+len+1) = '\0';
  105.             BuildTextPointers(wnd);
  106.         }
  107.         return TRUE;
  108.     }
  109.     return FALSE;
  110. }
  111. /* ----------- KEYBOARD_CURSOR Message ---------- */
  112. static void KeyboardCursorMsg(WINDOW wnd, PARAM p1, PARAM p2)
  113. {
  114.     wnd->CurrCol = (int)p1 + wnd->wleft;
  115.     wnd->WndRow = (int)p2;
  116.     wnd->CurrLine = (int)p2 + wnd->wtop;
  117.     if (wnd == inFocus)    {
  118.         if (CharInView(wnd, (int)p1, (int)p2))
  119.             SendMessage(NULL, SHOW_CURSOR, wnd->InsertMode, 0);
  120.         else
  121.             SendMessage(NULL, HIDE_CURSOR, 0, 0);
  122.     }
  123. }
  124. /* ----------- SIZE Message ---------- */
  125. int SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  126. {
  127.     int rtn = BaseWndProc(EDITBOX, wnd, SIZE, p1, p2);
  128.     if (WndCol > ClientWidth(wnd)-1)
  129.         wnd->CurrCol = ClientWidth(wnd)-1 + wnd->wleft;
  130.     if (wnd->WndRow > ClientHeight(wnd)-1)    {
  131.         wnd->WndRow = ClientHeight(wnd)-1;
  132.         SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
  133.     }
  134.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  135.     return rtn;
  136. }
  137. /* ----------- SCROLL Message ---------- */
  138. static int ScrollMsg(WINDOW wnd, PARAM p1)
  139. {
  140.     int rtn = FALSE;
  141.     if (isMultiLine(wnd))    {
  142.         rtn = BaseWndProc(EDITBOX,wnd,SCROLL,p1,0);
  143.         if (rtn != FALSE)    {
  144.             if (p1)    {
  145.                 /* -------- scrolling up --------- */
  146.                 if (wnd->WndRow == 0)    {
  147.                     wnd->CurrLine++;
  148.                     StickEnd(wnd);
  149.                 }
  150.                 else
  151.                     --wnd->WndRow;
  152.             }
  153.             else    {
  154.                 /* -------- scrolling down --------- */
  155.                 if (wnd->WndRow == ClientHeight(wnd)-1)    {
  156.                     if (wnd->CurrLine > 0)
  157.                         --wnd->CurrLine;
  158.                     StickEnd(wnd);
  159.                 }
  160.                 else
  161.                     wnd->WndRow++;
  162.             }
  163.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  164.         }
  165.     }
  166.     return rtn;
  167. }
  168. /* ----------- HORIZSCROLL Message ---------- */
  169. static int HorizScrollMsg(WINDOW wnd, PARAM p1)
  170. {
  171.     int rtn = FALSE;
  172.     char *currchar = CurrChar;
  173.     if (!(p1 &&
  174.             wnd->CurrCol == wnd->wleft && *currchar == '\n'))  {
  175.         rtn = BaseWndProc(EDITBOX, wnd, HORIZSCROLL, p1, 0);
  176.         if (rtn != FALSE)    {
  177.             if (wnd->CurrCol < wnd->wleft)
  178.                 wnd->CurrCol++;
  179.             else if (WndCol == ClientWidth(wnd))
  180.                 --wnd->CurrCol;
  181.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  182.         }
  183.     }
  184.     return rtn;
  185. }
  186. /* ----------- SCROLLPAGE Message ---------- */
  187. static int ScrollPageMsg(WINDOW wnd, PARAM p1)
  188. {
  189.     int rtn = FALSE;
  190.     if (isMultiLine(wnd))    {
  191.         rtn = BaseWndProc(EDITBOX, wnd, SCROLLPAGE, p1, 0);
  192.         SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
  193.         StickEnd(wnd);
  194.         SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  195.     }
  196.     return rtn;
  197. }
  198. /* ----------- HORIZSCROLLPAGE Message ---------- */
  199. static int HorizPageMsg(WINDOW wnd, PARAM p1)
  200. {
  201.     int rtn = BaseWndProc(EDITBOX, wnd, HORIZPAGE, p1, 0);
  202.     if ((int) p1 == FALSE)    {
  203.         if (wnd->CurrCol > wnd->wleft+ClientWidth(wnd)-1)
  204.             wnd->CurrCol = wnd->wleft+ClientWidth(wnd)-1;
  205.     }
  206.     else if (wnd->CurrCol < wnd->wleft)
  207.         wnd->CurrCol = wnd->wleft;
  208.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  209.     return rtn;
  210. }
  211. /* ----- Extend the marked block to the new x,y position ---- */
  212. static void ExtendBlock(WINDOW wnd, int x, int y)
  213. {
  214.     int bbl, bel;
  215.     int ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
  216.     int pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
  217.     char *lp = TextLine(wnd, wnd->wtop+y);
  218.     int len = (int) (strchr(lp, '\n') - lp);
  219.     x = min(x, len-wnd->wleft);
  220.     wnd->BlkEndCol = x+wnd->wleft;
  221.     wnd->BlkEndLine = y+wnd->wtop;
  222.     bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
  223.     bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
  224.     while (ptop < bbl)    {
  225.         WriteTextLine(wnd, NULL, ptop, FALSE);
  226.         ptop++;
  227.     }
  228.     for (y = bbl; y <= bel; y++)
  229.         WriteTextLine(wnd, NULL, y, FALSE);
  230.     while (pbot > bel)    {
  231.         WriteTextLine(wnd, NULL, pbot, FALSE);
  232.         --pbot;
  233.     }
  234. }
  235. /* ----------- LEFT_BUTTON Message ---------- */
  236. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  237. {
  238.     int MouseX = (int) p1 - GetClientLeft(wnd);
  239.     int MouseY = (int) p2 - GetClientTop(wnd);
  240.     RECT rc = ClientRect(wnd);
  241.     char *lp;
  242.     int len;
  243.     if (KeyBoardMarking)
  244.         return TRUE;
  245.     if (WindowMoving || WindowSizing)
  246.         return FALSE;
  247.     if (isMultiLine(wnd))    {
  248.         if (TextMarking)    {
  249.             if (!InsideRect(p1, p2, rc))    {
  250.                 if ((int)p1 == GetLeft(wnd))
  251.                     if (SendMessage(wnd, HORIZSCROLL, 0, 0))
  252.                         ExtendBlock(wnd, MouseX-1, MouseY);
  253.                 if ((int)p1 == GetRight(wnd))
  254.                     if (SendMessage(wnd, HORIZSCROLL, TRUE, 0))
  255.                         ExtendBlock(wnd, MouseX+1, MouseY);
  256.                 if ((int)p2 == GetTop(wnd))
  257.                     if (SendMessage(wnd, SCROLL, FALSE, 0))
  258.                         ExtendBlock(wnd, MouseX, MouseY+1);
  259.                 if ((int)p2 == GetBottom(wnd))
  260.                     if (SendMessage(wnd, SCROLL, TRUE, 0))
  261.                         ExtendBlock(wnd, MouseX, MouseY-1);
  262.                 SendMessage(wnd, PAINT, 0, 0);
  263.             }
  264.             return TRUE;
  265.         }
  266.         if (!InsideRect(p1, p2, rc))
  267.             return FALSE;
  268.         if (TextBlockMarked(wnd))    {
  269.             ClearTextBlock(wnd);
  270.             SendMessage(wnd, PAINT, 0, 0);
  271.         }
  272.         if (wnd->wlines)    {
  273.             if (MouseY > wnd->wlines-1)
  274.                 return TRUE;
  275.             lp = TextLine(wnd, MouseY+wnd->wtop);
  276.             len = (int) (strchr(lp, '\n') - lp);
  277.             MouseX = min(MouseX, len);
  278.             if (MouseX < wnd->wleft)    {
  279.                 MouseX = 0;
  280.                 SendMessage(wnd, KEYBOARD, HOME, 0);
  281.             }
  282.             ButtonDown = TRUE;
  283.             ButtonX = MouseX;
  284.             ButtonY = MouseY;
  285.         }
  286.         else
  287.             MouseX = MouseY = 0;
  288.         wnd->WndRow = MouseY;
  289.         SetLinePointer(wnd, MouseY+wnd->wtop);
  290.     }
  291.     if (isMultiLine(wnd) ||
  292.         (!TextBlockMarked(wnd)
  293.             && MouseX+wnd->wleft < strlen(wnd->text)))
  294.         wnd->CurrCol = MouseX+wnd->wleft;
  295.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  296.     return TRUE;
  297. }
  298. /* ----------- MOUSE_MOVED Message ---------- */
  299. static int MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  300. {
  301.     int MouseX = (int) p1 - GetClientLeft(wnd);
  302.     int MouseY = (int) p2 - GetClientTop(wnd);
  303.     RECT rc = ClientRect(wnd);
  304.     if (!InsideRect(p1, p2, rc))
  305.         return FALSE;
  306.     if (MouseY > wnd->wlines-1)
  307.         return FALSE;
  308.     if (ButtonDown)    {
  309.         SetAnchor(wnd, ButtonX+wnd->wleft, ButtonY+wnd->wtop);
  310.         TextMarking = TRUE;
  311.         rc = WindowRect(wnd);
  312.         SendMessage(NULL,MOUSE_TRAVEL,(PARAM) &rc, 0);
  313.         ButtonDown = FALSE;
  314.     }
  315.     if (TextMarking && !(WindowMoving || WindowSizing))    {
  316.         ExtendBlock(wnd, MouseX, MouseY);
  317.         return TRUE;
  318.     }
  319.     return FALSE;
  320. }
  321. static void StopMarking(WINDOW wnd)
  322. {
  323.     TextMarking = FALSE;
  324.     if (wnd->BlkBegLine > wnd->BlkEndLine)    {
  325.         swap(wnd->BlkBegLine, wnd->BlkEndLine);
  326.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  327.     }
  328.     if (wnd->BlkBegLine == wnd->BlkEndLine &&
  329.             wnd->BlkBegCol > wnd->BlkEndCol)
  330.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  331. }
  332. /* ----------- BUTTON_RELEASED Message ---------- */
  333. static int ButtonReleasedMsg(WINDOW wnd)
  334. {
  335.     if (isMultiLine(wnd))    {
  336.         ButtonDown = FALSE;
  337.         if (TextMarking && !(WindowMoving || WindowSizing))  {
  338.             /* release the mouse ouside the edit box */
  339.             SendMessage(NULL, MOUSE_TRAVEL, 0, 0);
  340.             StopMarking(wnd);
  341.             return TRUE;
  342.         }
  343.         else
  344.             PrevY = -1;
  345.     }
  346.     return FALSE;
  347. }
  348. /* ---- Process text block keys for multiline text box ---- */
  349. static void DoMultiLines(WINDOW wnd, int c, PARAM p2)
  350. {
  351.     if (isMultiLine(wnd))    {
  352.         if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))    {
  353.             int kx, ky;
  354.             SendMessage(NULL, CURRENT_KEYBOARD_CURSOR,
  355.                 (PARAM) &kx, (PARAM) &ky);
  356.             kx -= GetClientLeft(wnd);
  357.             ky -= GetClientTop(wnd);
  358.             switch (c)    {
  359.                 case HOME:
  360.                 case END:
  361.                 case CTRL_HOME:
  362.                 case CTRL_END:
  363.                 case PGUP:
  364.                 case PGDN:
  365.                 case CTRL_PGUP:
  366.                 case CTRL_PGDN:
  367.                 case UP:
  368.                 case DN:
  369.                 case FWD:
  370.                 case BS:
  371.                 case CTRL_FWD:
  372.                 case CTRL_BS:
  373.                     if (!KeyBoardMarking)    {
  374.                         if (TextBlockMarked(wnd))    {
  375.                             ClearTextBlock(wnd);
  376.                             SendMessage(wnd, PAINT, 0, 0);
  377.                         }
  378.                         KeyBoardMarking = TextMarking = TRUE;
  379.                         SetAnchor(wnd, kx+wnd->wleft,
  380.                                                 ky+wnd->wtop);
  381.                     }
  382.                     break;
  383.                 default:
  384.                     break;
  385.             }
  386.         }
  387.     }
  388. }
  389. /* ---------- page/scroll keys ----------- */
  390. static int DoScrolling(WINDOW wnd, int c, PARAM p2)
  391. {
  392.     switch (c)    {
  393.         case PGUP:
  394.         case PGDN:
  395.             if (isMultiLine(wnd))
  396.                 BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  397.             break;
  398.         case CTRL_PGUP:
  399.         case CTRL_PGDN:
  400.             BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  401.             break;
  402.         case HOME:
  403.             Home(wnd);
  404.             break;
  405.         case END:
  406.             End(wnd);
  407.             break;
  408.         case CTRL_FWD:
  409.             NextWord(wnd);
  410.             break;
  411.         case CTRL_BS:
  412.             PrevWord(wnd);
  413.             break;
  414.         case CTRL_HOME:
  415.             if (isMultiLine(wnd))    {
  416.                 SendMessage(wnd, SCROLLDOC, TRUE, 0);
  417.                 wnd->CurrLine = 0;
  418.                 wnd->WndRow = 0;
  419.             }
  420.             Home(wnd);
  421.             break;
  422.         case CTRL_END:
  423.             if (isMultiLine(wnd) &&
  424.                     wnd->WndRow+wnd->wtop+1 < wnd->wlines
  425.                         && wnd->wlines > 0) {
  426.                 SendMessage(wnd, SCROLLDOC, FALSE, 0);
  427.                 SetLinePointer(wnd, wnd->wlines-1);
  428.                 wnd->WndRow =
  429.                     min(ClientHeight(wnd)-1, wnd->wlines-1);
  430.                 Home(wnd);
  431.             }
  432.             End(wnd);
  433.             break;
  434.         case UP:
  435.             if (isMultiLine(wnd))
  436.                 Upward(wnd);
  437.             break;
  438.         case DN:
  439.             if (isMultiLine(wnd))
  440.                 Downward(wnd);
  441.             break;
  442.         case FWD:
  443.             Forward(wnd);
  444.             break;
  445.         case BS:
  446.             Backward(wnd);
  447.             break;
  448.         default:
  449.             return FALSE;
  450.     }
  451.     if (!KeyBoardMarking && TextBlockMarked(wnd))    {
  452.         ClearTextBlock(wnd);
  453.         SendMessage(wnd, PAINT, 0, 0);
  454.     }
  455.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  456.     return TRUE;
  457. }
  458. /* -------------- Del key ---------------- */
  459. static void DelKey(WINDOW wnd)
  460. {
  461.     char *currchar = CurrChar;
  462.     int repaint = *currchar == '\n';
  463.     if (TextBlockMarked(wnd))    {
  464.         SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  465.         SendMessage(wnd, PAINT, 0, 0);
  466.         return;
  467.     }
  468.     if (isMultiLine(wnd) && *(currchar+1) == '\0')
  469.         return;
  470.     strcpy(currchar, currchar+1);
  471.     if (repaint)    {
  472.         BuildTextPointers(wnd);
  473.         SendMessage(wnd, PAINT, 0, 0);
  474.     }
  475.     else    {
  476.         ModTextPointers(wnd, wnd->CurrLine+1, -1);
  477.         WriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
  478.     }
  479.     wnd->TextChanged = TRUE;
  480. }
  481. /* ------------ Tab key ------------ */
  482. static void TabKey(WINDOW wnd, PARAM p2)
  483. {
  484.     if (isMultiLine(wnd))    {
  485.         int insmd = wnd->InsertMode;
  486.         do  {
  487.             char *cc = CurrChar+1;
  488.             if (!insmd && *cc == '\0')
  489.                 break;
  490.             if (wnd->textlen == wnd->MaxTextLength)
  491.                 break;
  492.             SendMessage(wnd,KEYBOARD,insmd ? ' ' : FWD,0);
  493.         } while (wnd->CurrCol % cfg.Tabs);
  494.     }
  495.     else
  496.         PostMessage(GetParent(wnd), KEYBOARD, '\t', p2);
  497. }
  498. /* ------------ Shift+Tab key ------------ */
  499. static void ShiftTabKey(WINDOW wnd, PARAM p2)
  500. {
  501.     if (isMultiLine(wnd))    {
  502.         do  {
  503.             if (CurrChar == GetText(wnd))
  504.                 break;
  505.             SendMessage(wnd,KEYBOARD,BS,0);
  506.         } while (wnd->CurrCol % cfg.Tabs);
  507.     }
  508.     else
  509.         PostMessage(GetParent(wnd), KEYBOARD, SHIFT_HT, p2);
  510. }
  511. /* --------- All displayable typed keys ------------- */
  512. static void KeyTyped(WINDOW wnd, int c)
  513. {
  514.     char *currchar = CurrChar;
  515.     if ((c != '\n' && c < ' ') || (c & 0x1000))
  516.         /* ---- not recognized by editor --- */
  517.         return;
  518.     if (!isMultiLine(wnd) && TextBlockMarked(wnd))    {
  519.         SendMessage(wnd, CLEARTEXT, 0, 0);
  520.         currchar = CurrChar;
  521.     }
  522.     /* ---- test typing at end of text ---- */
  523.     if (currchar == wnd->text+wnd->MaxTextLength)    {
  524.         /* ---- typing at the end of maximum buffer ---- */
  525.         beep();
  526.         return;
  527.     }
  528.     if (*currchar == '\0')    {
  529.         /* --- insert a newline at end of text --- */
  530.         *currchar = '\n';
  531.         *(currchar+1) = '\0';
  532.         BuildTextPointers(wnd);
  533.     }
  534.     /* --- displayable char or newline --- */
  535.     if (c == '\n' || wnd->InsertMode || *currchar == '\n') {
  536.         /* ------ inserting the keyed character ------ */
  537.         if (wnd->text[wnd->textlen-1] != '\0')    {
  538.             /* --- the current text buffer is full --- */
  539.             if (wnd->textlen == wnd->MaxTextLength)    {
  540.                 /* --- text buffer is at maximum size --- */
  541.                 beep();
  542.                 return;
  543.             }
  544.             /* ---- increase the text buffer size ---- */
  545.             wnd->textlen += GROWLENGTH;
  546.             /* --- but not above maximum size --- */
  547.             if (wnd->textlen > wnd->MaxTextLength)
  548.                 wnd->textlen = wnd->MaxTextLength;
  549.             wnd->text = DFrealloc(wnd->text, wnd->textlen+2);
  550.             wnd->text[wnd->textlen-1] = '\0';
  551.             currchar = CurrChar;
  552.         }
  553.         memmove(currchar+1, currchar, strlen(currchar)+1);
  554.         ModTextPointers(wnd, wnd->CurrLine+1, 1);
  555.         if (isMultiLine(wnd) && wnd->wlines > 1)
  556.             wnd->textwidth = max(wnd->textwidth,
  557.                 (int) (TextLine(wnd, wnd->CurrLine+1)-
  558.                 TextLine(wnd, wnd->CurrLine)));
  559.         else
  560.             wnd->textwidth = max(wnd->textwidth,
  561.                 strlen(wnd->text));
  562.         WriteTextLine(wnd, NULL,
  563.             wnd->wtop+wnd->WndRow, FALSE);
  564.     }
  565.     /* ----- put the char in the buffer ----- */
  566.     *currchar = c;
  567.     wnd->TextChanged = TRUE;
  568.     if (c == '\n')    {
  569.         wnd->wleft = 0;
  570.         BuildTextPointers(wnd);
  571.         End(wnd);
  572.         Forward(wnd);
  573.         SendMessage(wnd, PAINT, 0, 0);
  574.         return;
  575.     }
  576.     /* ---------- test end of window --------- */
  577.     if (WndCol == ClientWidth(wnd)-1)    {
  578.         if (!isMultiLine(wnd))    {
  579.                 if (!(currchar == wnd->text+wnd->MaxTextLength-2))
  580.                 SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  581.         }
  582.         else    {
  583.             char *cp = currchar;
  584.             while (*cp != ' ' && cp != TextLine(wnd, wnd->CurrLine))
  585.                 --cp;
  586.             if (cp == TextLine(wnd, wnd->CurrLine) ||
  587.                     !wnd->WordWrapMode)
  588.                 SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  589.             else    {
  590.                 int dif = 0;
  591.                 if (c != ' ')    {
  592.                     dif = (int) (currchar - cp);
  593.                     wnd->CurrCol -= dif;
  594.                     SendMessage(wnd, KEYBOARD, DEL, 0);
  595.                     --dif;
  596.                 }
  597.                 SendMessage(wnd, KEYBOARD, '\r', 0);
  598.                 currchar = CurrChar;
  599.                 wnd->CurrCol = dif;
  600.                 if (c == ' ')
  601.                     return;
  602.             }
  603.         }
  604.     }
  605.     /* ------ display the character ------ */
  606.     SetStandardColor(wnd);
  607.     PutWindowChar(wnd, c, WndCol, wnd->WndRow);
  608.     /* ----- advance the pointers ------ */
  609.     wnd->CurrCol++;
  610. }
  611. /* ------------ screen changing key strokes ------------- */
  612. static void DoKeyStroke(WINDOW wnd, int c, PARAM p2)
  613. {
  614.     switch (c)    {
  615.         case RUBOUT:
  616.             if (wnd->CurrCol == 0 && wnd->CurrLine == 0)
  617.                 break;
  618.             Backward(wnd);
  619.         case DEL:
  620.             DelKey(wnd);
  621.             break;
  622.         case SHIFT_HT:
  623.             ShiftTabKey(wnd, p2);
  624.             break;
  625.         case '\t':
  626.             TabKey(wnd, p2);
  627.             break;
  628.         case '\r':
  629.             if (!isMultiLine(wnd))    {
  630.                 PostMessage(GetParent(wnd), KEYBOARD, c, p2);
  631.                 break;
  632.             }
  633.             c = '\n';
  634.         default:
  635.             if (TextBlockMarked(wnd))    {
  636.                 SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  637.                 SendMessage(wnd, PAINT, 0, 0);
  638.             }
  639.             KeyTyped(wnd, c);
  640.             break;
  641.     }
  642. }
  643. /* ----------- KEYBOARD Message ---------- */
  644. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  645. {
  646.     int c = (int) p1;
  647.     if (WindowMoving || WindowSizing || ((int)p2 & ALTKEY))
  648.         return FALSE;
  649.     switch (c)    {
  650.         /* --- these keys get processed by lower classes --- */
  651.         case ESC:
  652.         case F1:
  653.         case F2:
  654.         case F3:
  655.         case F4:
  656.         case F5:
  657.         case F6:
  658.         case F7:
  659.         case F8:
  660.         case F9:
  661.         case F10:
  662.         case INS:
  663.         case SHIFT_INS:
  664.         case SHIFT_DEL:
  665.             return FALSE;
  666.         /* --- these keys get processed here --- */
  667.         case CTRL_FWD:
  668.         case CTRL_BS:
  669.         case CTRL_HOME:
  670.         case CTRL_END:
  671.         case CTRL_PGUP:
  672.         case CTRL_PGDN:
  673.             break;
  674.         default:
  675.             /* other ctrl keys get processed by lower classes */
  676.             if ((int)p2 & CTRLKEY)
  677.                 return FALSE;
  678.             /* --- all other keys get processed here --- */
  679.             break;
  680.     }
  681.     DoMultiLines(wnd, c, p2);
  682.     if (DoScrolling(wnd, c, p2))    {
  683.         if (KeyBoardMarking)
  684.             ExtendBlock(wnd, WndCol, wnd->WndRow);
  685.     }
  686.     else if (!TestAttribute(wnd, READONLY))    {
  687.         DoKeyStroke(wnd, c, p2);
  688.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  689.     }
  690.     return TRUE;
  691. }
  692. /* ----------- SHIFT_CHANGED Message ---------- */
  693. static void ShiftChangedMsg(WINDOW wnd, PARAM p1)
  694. {
  695.     if (!((int)p1 & (LEFTSHIFT | RIGHTSHIFT)) &&
  696.                                    KeyBoardMarking)    {
  697.         StopMarking(wnd);
  698.         KeyBoardMarking = FALSE;
  699.     }
  700. }
  701. /* ----------- ID_DELETETEXT Command ---------- */
  702. static void DeleteTextCmd(WINDOW wnd)
  703. {
  704.     if (TextBlockMarked(wnd))    {
  705.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  706.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  707.         int len = (int) (bel - bbl);
  708.         SaveDeletedText(wnd, bbl, len);
  709.         wnd->TextChanged = TRUE;
  710.         strcpy(bbl, bel);
  711.         wnd->CurrLine = TextLineNumber(wnd, bbl-wnd->BlkBegCol);
  712.         wnd->CurrCol = wnd->BlkBegCol;
  713.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  714.         if (wnd->WndRow < 0)    {
  715.             wnd->wtop = wnd->BlkBegLine;
  716.             wnd->WndRow = 0;
  717.         }
  718.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  719.         ClearTextBlock(wnd);
  720.         BuildTextPointers(wnd);
  721.     }
  722. }
  723. /* ----------- ID_CLEAR Command ---------- */
  724. static void ClearCmd(WINDOW wnd)
  725. {
  726.     if (TextBlockMarked(wnd))    {
  727.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  728.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  729.         int len = (int) (bel - bbl);
  730.         SaveDeletedText(wnd, bbl, len);
  731.         wnd->CurrLine = TextLineNumber(wnd, bbl);
  732.         wnd->CurrCol = wnd->BlkBegCol;
  733.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  734.         if (wnd->WndRow < 0)    {
  735.             wnd->WndRow = 0;
  736.             wnd->wtop = wnd->BlkBegLine;
  737.         }
  738.         /* ------ change all text lines in block to \n ----- */
  739.         while (bbl < bel)    {
  740.             char *cp = strchr(bbl, '\n');
  741.             if (cp > bel)
  742.                 cp = bel;
  743.             strcpy(bbl, cp);
  744.             bel -= (int) (cp - bbl);
  745.             bbl++;
  746.         }
  747.         ClearTextBlock(wnd);
  748.         BuildTextPointers(wnd);
  749.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  750.         SendMessage(wnd, PAINT, 0, 0);
  751.         wnd->TextChanged = TRUE;
  752.     }
  753. }
  754. /* ----------- ID_UNDO Command ---------- */
  755. static void UndoCmd(WINDOW wnd)
  756. {
  757.     if (wnd->DeletedText != NULL)    {
  758.         PasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
  759.         free(wnd->DeletedText);
  760.         wnd->DeletedText = NULL;
  761.         wnd->DeletedLength = 0;
  762.         SendMessage(wnd, PAINT, 0, 0);
  763.     }
  764. }
  765. /* ----------- ID_PARAGRAPH Command ---------- */
  766. static void ParagraphCmd(WINDOW wnd)
  767. {
  768.     int bc, ec, fl, el, Blocked;
  769.     char *bl, *bbl, *bel, *bb;
  770.  
  771.     if (!TextBlockMarked(wnd))    {
  772.         Blocked = FALSE;
  773.         /* ---- forming paragraph from cursor position --- */
  774.         fl = wnd->wtop + wnd->WndRow;
  775.         bbl = bel = bl = TextLine(wnd, wnd->CurrLine);
  776.         if ((bc = wnd->CurrCol) >= ClientWidth(wnd))
  777.             bc = 0;
  778.         Home(wnd);
  779.         /* ---- locate the end of the paragraph ---- */
  780.         while (*bel)    {
  781.             int blank = TRUE;
  782.             char *bll = bel;
  783.             /* --- blank line marks end of paragraph --- */
  784.             while (*bel && *bel != '\n')    {
  785.                 if (*bel != ' ')
  786.                     blank = FALSE;
  787.                 bel++;
  788.             }
  789.             if (blank)    {
  790.                 bel = bll;
  791.                 break;
  792.             }
  793.             if (*bel)
  794.                 bel++;
  795.         }
  796.         if (bel == bbl)    {
  797.             SendMessage(wnd, KEYBOARD, DN, 0);
  798.             return;
  799.         }
  800.         if (*bel == '\0')
  801.             --bel;
  802.         if (*bel == '\n')
  803.             --bel;
  804.     }
  805.     else    {
  806.         /* ---- forming paragraph from marked block --- */
  807.         Blocked = TRUE;
  808.         el = wnd->BlkEndLine;
  809.         ec = wnd->BlkEndCol;
  810.         bbl = TextLine(wnd, wnd->BlkBegLine) + wnd->BlkBegCol;
  811.         bel = TextLine(wnd, wnd->BlkEndLine) + wnd->BlkEndCol;
  812.         fl = wnd->CurrLine = wnd->BlkBegLine;
  813.         bc = wnd->CurrCol = wnd->BlkBegCol;
  814.         if (fl < wnd->wtop)
  815.             wnd->wtop = fl;
  816.         wnd->WndRow = fl - wnd->wtop;
  817.         SendMessage(wnd, KEYBOARD, '\r', 0);
  818.         el++, fl++;
  819.         if (bc != 0)    {
  820.             SendMessage(wnd, KEYBOARD, '\r', 0);
  821.             el++, fl ++;
  822.         }
  823.         bc = 0;
  824.         bl = TextLine(wnd, fl);
  825.         wnd->CurrLine = fl;
  826.         bbl = bl + bc;
  827.         bel = TextLine(wnd, el) + ec;
  828.     }
  829.     /* --- change all newlines in block to spaces --- */
  830.     while (CurrChar < bel)    {
  831.         if (*CurrChar == '\n')    {
  832.             *CurrChar = ' ';
  833.             wnd->CurrLine++;
  834.             wnd->CurrCol = 0;
  835.         }
  836.         else
  837.             wnd->CurrCol++;
  838.     }
  839.     /* ---- insert newlines at new margin boundaries ---- */
  840.     bb = bbl;
  841.     while (bbl < bel)    {
  842.         bbl++;
  843.         if ((int)(bbl - bb) == ClientWidth(wnd)-1)    {
  844.             while (*bbl != ' ' && bbl > bb)
  845.                 --bbl;
  846.             if (*bbl != ' ')    {
  847.                 bbl = strchr(bbl, ' ');
  848.                 if (bbl == NULL || bbl >= bel)
  849.                     break;
  850.             }
  851.             *bbl = '\n';
  852.             bb = bbl+1;
  853.         }
  854.     }
  855.     ec = (int)(bel - bb);
  856.     BuildTextPointers(wnd);
  857.     if (Blocked)    {
  858.         /* ---- position cursor at end of new paragraph ---- */
  859.         if (el < wnd->wtop ||
  860.                 wnd->wtop + ClientHeight(wnd) < el)
  861.             wnd->wtop = el-ClientHeight(wnd);
  862.         if (wnd->wtop < 0)
  863.             wnd->wtop = 0;
  864.         wnd->WndRow = el - wnd->wtop;
  865.         wnd->CurrLine = el;
  866.         wnd->CurrCol = ec;
  867.         SendMessage(wnd, KEYBOARD, '\r', 0);
  868.         SendMessage(wnd, KEYBOARD, '\r', 0);
  869.     }
  870.     else    {
  871.         /* --- put cursor back at beginning --- */
  872.         wnd->CurrLine = TextLineNumber(wnd, bl);
  873.         wnd->CurrCol = bc;
  874.         if (fl < wnd->wtop)
  875.             wnd->wtop = fl;
  876.         wnd->WndRow = fl - wnd->wtop;
  877.     }
  878.     SendMessage(wnd, PAINT, 0, 0);
  879.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  880.     wnd->TextChanged = TRUE;
  881.     BuildTextPointers(wnd);
  882. }
  883. /* ----------- COMMAND Message ---------- */
  884. static int CommandMsg(WINDOW wnd, PARAM p1)
  885. {
  886.     switch ((int)p1)    {
  887.         case ID_DELETETEXT:
  888.             DeleteTextCmd(wnd);
  889.             return TRUE;
  890.         case ID_CLEAR:
  891.             ClearCmd(wnd);
  892.             return TRUE;
  893.         case ID_UNDO:
  894.             UndoCmd(wnd);
  895.             return TRUE;
  896.         case ID_PARAGRAPH:
  897.             ParagraphCmd(wnd);
  898.             return TRUE;
  899.         default:
  900.             break;
  901.     }
  902.     return FALSE;
  903. }
  904. /* ---------- CLOSE_WINDOW Message ----------- */
  905. static int CloseWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  906. {
  907.     int rtn;
  908.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  909.     if (wnd->DeletedText != NULL)
  910.         free(wnd->DeletedText);
  911.     rtn = BaseWndProc(EDITBOX, wnd, CLOSE_WINDOW, p1, p2);
  912.     if (wnd->text != NULL)    {
  913.         free(wnd->text);
  914.         wnd->text = NULL;
  915.     }
  916.     return rtn;
  917. }
  918. /* ------- Window processing module for EDITBOX class ------ */
  919. int EditBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  920. {
  921.     int rtn;
  922.     switch (msg)    {
  923.         case CREATE_WINDOW:
  924.             return CreateWindowMsg(wnd);
  925.         case ADDTEXT:
  926.             return AddTextMsg(wnd, p1, p2);
  927.         case SETTEXT:
  928.             return SetTextMsg(wnd, p1);
  929.         case CLEARTEXT:
  930.             return ClearTextMsg(wnd);
  931.         case GETTEXT:
  932.             return GetTextMsg(wnd, p1, p2);
  933.         case SETTEXTLENGTH:
  934.             return SetTextLengthMsg(wnd, (unsigned) p1);
  935.         case KEYBOARD_CURSOR:
  936.             KeyboardCursorMsg(wnd, p1, p2);
  937.             return TRUE;
  938.         case SETFOCUS:
  939.             if (!(int)p1)
  940.                 SendMessage(NULL, HIDE_CURSOR, 0, 0);
  941.         case PAINT:
  942.         case MOVE:
  943.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  944.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  945.             return rtn;
  946.         case SIZE:
  947.             return SizeMsg(wnd, p1, p2);
  948.         case SCROLL:
  949.             return ScrollMsg(wnd, p1);
  950.         case HORIZSCROLL:
  951.             return HorizScrollMsg(wnd, p1);
  952.         case SCROLLPAGE:
  953.             return ScrollPageMsg(wnd, p1);
  954.         case HORIZPAGE:
  955.             return HorizPageMsg(wnd, p1);
  956.         case LEFT_BUTTON:
  957.             if (LeftButtonMsg(wnd, p1, p2))
  958.                 return TRUE;
  959.             break;
  960.         case MOUSE_MOVED:
  961.             if (MouseMovedMsg(wnd, p1, p2))
  962.                 return TRUE;
  963.             break;
  964.         case BUTTON_RELEASED:
  965.             if (ButtonReleasedMsg(wnd))
  966.                 return TRUE;
  967.             break;
  968.         case KEYBOARD:
  969.             if (KeyboardMsg(wnd, p1, p2))
  970.                 return TRUE;
  971.             break;
  972.         case SHIFT_CHANGED:
  973.             ShiftChangedMsg(wnd, p1);
  974.             break;
  975.         case COMMAND:
  976.             if (CommandMsg(wnd, p1))
  977.                 return TRUE;
  978.             break;
  979.         case CLOSE_WINDOW:
  980.             return CloseWindowMsg(wnd, p1, p2);
  981.         default:
  982.             break;
  983.     }
  984.     return BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  985. }
  986. /* ------ save deleted text for the Undo command ------ */
  987. static void SaveDeletedText(WINDOW wnd, char *bbl, int len)
  988. {
  989.     wnd->DeletedLength = len;
  990.     wnd->DeletedText=DFrealloc(wnd->DeletedText,len);
  991.     memmove(wnd->DeletedText, bbl, len);
  992. }
  993. /* ---- cursor right key: right one character position ---- */
  994. static void Forward(WINDOW wnd)
  995. {
  996.     char *cc = CurrChar+1;
  997.     if (*cc == '\0')
  998.         return;
  999.     if (*CurrChar == '\n')    {
  1000.         Home(wnd);
  1001.         Downward(wnd);
  1002.     }
  1003.     else    {
  1004.         wnd->CurrCol++;
  1005.         if (WndCol == ClientWidth(wnd))
  1006.             SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  1007.     }
  1008. }
  1009. /* ----- stick the moving cursor to the end of the line ---- */
  1010. static void StickEnd(WINDOW wnd)
  1011. {
  1012.     char *cp = TextLine(wnd, wnd->CurrLine);
  1013.     char *cp1 = strchr(cp, '\n');
  1014.     int len = cp1 ? (int) (cp1 - cp) : 0;
  1015.     wnd->CurrCol = min(len, wnd->CurrCol);
  1016.     if (wnd->wleft > wnd->CurrCol)    {
  1017.         wnd->wleft = max(0, wnd->CurrCol - 4);
  1018.         SendMessage(wnd, PAINT, 0, 0);
  1019.     }
  1020.     else if (wnd->CurrCol-wnd->wleft >= ClientWidth(wnd))    {
  1021.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1022.         SendMessage(wnd, PAINT, 0, 0);
  1023.     }
  1024. }
  1025. /* --------- cursor down key: down one line --------- */
  1026. static void Downward(WINDOW wnd)
  1027. {
  1028.     if (isMultiLine(wnd) &&
  1029.             wnd->WndRow+wnd->wtop+1 < wnd->wlines)  {
  1030.         wnd->CurrLine++;
  1031.         if (wnd->WndRow == ClientHeight(wnd)-1)
  1032.             BaseWndProc(EDITBOX, wnd, SCROLL, TRUE, 0);
  1033.         else
  1034.             wnd->WndRow++;
  1035.         StickEnd(wnd);
  1036.     }
  1037. }
  1038. /* -------- cursor up key: up one line ------------ */
  1039. static void Upward(WINDOW wnd)
  1040. {
  1041.     if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1042.         --wnd->CurrLine;
  1043.         if (wnd->WndRow == 0)
  1044.             BaseWndProc(EDITBOX, wnd, SCROLL, FALSE, 0);
  1045.         else
  1046.             --wnd->WndRow;
  1047.         StickEnd(wnd);
  1048.     }
  1049. }
  1050. /* ---- cursor left key: left one character position ---- */
  1051. static void Backward(WINDOW wnd)
  1052. {
  1053.     if (wnd->CurrCol)    {
  1054.         --wnd->CurrCol;
  1055.         if (wnd->CurrCol < wnd->wleft)
  1056.             SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  1057.     }
  1058.     else if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1059.         Upward(wnd);
  1060.         End(wnd);
  1061.     }
  1062. }
  1063. /* -------- End key: to end of line ------- */
  1064. static void End(WINDOW wnd)
  1065. {
  1066.     while (*CurrChar && *CurrChar != '\n')
  1067.         ++wnd->CurrCol;
  1068.     if (WndCol >= ClientWidth(wnd))    {
  1069.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1070.         SendMessage(wnd, PAINT, 0, 0);
  1071.     }
  1072. }
  1073. /* -------- Home key: to beginning of line ------- */
  1074. static void Home(WINDOW wnd)
  1075. {
  1076.     wnd->CurrCol = 0;
  1077.     if (wnd->wleft != 0)    {
  1078.         wnd->wleft = 0;
  1079.         SendMessage(wnd, PAINT, 0, 0);
  1080.     }
  1081. }
  1082. /* -- Ctrl+cursor right key: to beginning of next word -- */
  1083. static void NextWord(WINDOW wnd)
  1084. {
  1085.     int savetop = wnd->wtop;
  1086.     int saveleft = wnd->wleft;
  1087.     ClearVisible(wnd);
  1088.     while (!isWhite(*CurrChar))    {
  1089.         char *cc = CurrChar+1;
  1090.         if (*cc == '\0')
  1091.             break;
  1092.         Forward(wnd);
  1093.     }
  1094.     while (isWhite(*CurrChar))    {
  1095.         char *cc = CurrChar+1;
  1096.         if (*cc == '\0')
  1097.             break;
  1098.         Forward(wnd);
  1099.     }
  1100.     SetVisible(wnd);
  1101.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1102.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1103.         SendMessage(wnd, PAINT, 0, 0);
  1104. }
  1105. /* -- Ctrl+cursor left key: to beginning of previous word -- */
  1106. static void PrevWord(WINDOW wnd)
  1107. {
  1108.     int savetop = wnd->wtop;
  1109.     int saveleft = wnd->wleft;
  1110.     ClearVisible(wnd);
  1111.     Backward(wnd);
  1112.     while (isWhite(*CurrChar))    {
  1113.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1114.             break;
  1115.         Backward(wnd);
  1116.     }
  1117.     while (wnd->CurrCol != 0 && !isWhite(*CurrChar))
  1118.         Backward(wnd);
  1119.     if (isWhite(*CurrChar))
  1120.         Forward(wnd);
  1121.     SetVisible(wnd);
  1122.     if (wnd->wleft != saveleft)
  1123.         if (wnd->CurrCol >= saveleft)
  1124.             if (wnd->CurrCol - saveleft < ClientWidth(wnd))
  1125.                 wnd->wleft = saveleft;
  1126.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1127.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1128.         SendMessage(wnd, PAINT, 0, 0);
  1129. }
  1130. /* ----- modify text pointers from a specified position
  1131.                 by a specified plus or minus amount ----- */
  1132. static void ModTextPointers(WINDOW wnd, int lineno, int var)
  1133. {
  1134.     while (lineno < wnd->wlines)
  1135.         *((wnd->TextPointers) + lineno++) += var;
  1136. }
  1137.  
  1138.