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