home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / df3os2.zip / TEXTBOX.CPP < prev    next >
C/C++ Source or Header  |  1993-09-27  |  10KB  |  416 lines

  1. // ------------- textbox.cpp
  2.  
  3. #include "desktop.h"
  4. #include "textbox.h"
  5. #include "scrolbar.h"
  6.  
  7. static Color col = {
  8.     BLACK,                // fg
  9.     LIGHTGRAY,            // bg
  10.     LIGHTGRAY,            // selected fg
  11.     BLACK,                // selected bg
  12.     LIGHTGRAY,            // frame fg
  13.     BLACK,                // frame bg
  14.     LIGHTGRAY,            // highlighted fg
  15.     BLUE                // highlighted bg
  16. };
  17.  
  18. // ----------- common constructor code
  19. void TextBox::OpenWindow()
  20. {
  21.     windowtype = TextboxWindow;
  22.     text = 0;
  23.     hscrollbar = vscrollbar = 0;
  24.     TextPointers = 0;
  25.     colors = col;
  26.     ClearText();
  27. }
  28.  
  29. void TextBox::CloseWindow()
  30. {
  31.     ClearText();
  32.     delete hscrollbar;
  33.     delete vscrollbar;
  34.     Control::CloseWindow();
  35. }
  36.  
  37.  
  38. // ------ show the textbox
  39. void TextBox::Show()
  40. {
  41.     if ((attrib & HSCROLLBAR) && hscrollbar == 0)    {
  42.         hscrollbar = new ScrollBar(HORIZONTAL, this);
  43.         hscrollbar->SetAttribute(FRAMEWND);
  44.     }
  45.     if ((attrib & VSCROLLBAR) && vscrollbar == 0)    {
  46.         vscrollbar = new ScrollBar(VERTICAL, this);
  47.         vscrollbar->SetAttribute(FRAMEWND);
  48.     }
  49.     Control::Show();
  50. }
  51.  
  52. // ------------ build the text line pointers
  53. void TextBox::BuildTextPointers()
  54. {
  55.     textwidth = wlines = 0;
  56.     // ---- count the lines of text
  57.     const char *cp = *text;
  58.     while (*cp)    {
  59.         wlines++;
  60.         while (*cp && *cp != '\n')
  61.             cp++;
  62.         if (*cp)
  63.             cp++;
  64.     }
  65.     // ----- build the pointer array
  66.     delete TextPointers;
  67.     TextPointers = new unsigned int[wlines+1];
  68.     unsigned int off = 0;
  69.     cp = *text;
  70.     wlines = 0;
  71.     while (*cp)    {
  72.         *(TextPointers + wlines++) = off;
  73.         const char *cp1 = cp;
  74.         while (*cp && *cp != '\n')
  75.             cp++;
  76.         textwidth = max(textwidth, (unsigned int) (cp - cp1));
  77.         if (*cp)
  78.             cp++;
  79.         off = (unsigned int) (cp - *text);
  80.     }
  81.     *(TextPointers + wlines) = off;
  82. }
  83.  
  84. // --------- add a line of text to the textbox
  85. void TextBox::AddText(const char *txt)
  86. {
  87.     if (text == 0)
  88.         text = new String(txt);
  89.     else 
  90.         *text += txt;
  91.     if (txt[strlen(txt)-1] != '\n')
  92.         *text += "\n";
  93.     BuildTextPointers();
  94. }
  95.  
  96. // --------- set the textbox's text buffer to new text
  97. void TextBox::SetText(const char *txt)
  98. {
  99.     ClearText();
  100.     AddText(txt);
  101. }
  102.  
  103. // ------ set the length of the text buffer
  104. void TextBox::SetTextLength(unsigned int len)
  105. {
  106.     if (text != 0)
  107.         text->ChangeLength(len);
  108. }
  109.  
  110. // --------- clear the text from the textbox
  111. void TextBox::ClearText()
  112. {
  113.     delete text;
  114.     text = 0;
  115.     wlines = 0;
  116.     textwidth = 0;
  117.     wtop = wleft = 0;
  118.     ClearTextBlock();
  119.     delete TextPointers;
  120.     TextPointers = 0;
  121. }
  122.  
  123. // ------- extract a text line
  124. String TextBox::ExtractTextLine(int lno)
  125. {
  126.     const char *lp = TextLine(lno);
  127.     int offset = lp - (const char *) *text;
  128.     for (int len = 0; *(lp+len) && *(lp+len) != '\n'; len++)
  129.         ;
  130.     return text->mid(len, offset);
  131. }
  132.  
  133. // ---- display a line with a shortcut key character
  134. void TextBox::WriteShortcutLine(int lno, int fg, int bg)
  135. {
  136.     if (!visible)
  137.         return;
  138.     String sc = ExtractTextLine(lno);
  139.     int x = sc.Strlen();
  140.     int y = lno-wtop;
  141.     x -= DisplayShortcutField(sc, 0, y, fg, bg);
  142.     // --------- pad the line
  143.     int wd = ClientWidth() - x;
  144.     if (wd > 0)
  145.         WriteClientString(String(wd, ' '), x, y, fg, bg);
  146. }
  147.  
  148. // ---- display a shortcut field character
  149. int TextBox::DisplayShortcutField(String sc, int x, int y,
  150.                                                 int fg, int bg)
  151. {
  152.     int scs = 0;
  153.     if (visible)    {
  154.         int off = sc.FindChar(SHORTCUTCHAR);
  155.         if (off != -1)    {
  156.             scs++;
  157.             if (off != 0)    {
  158.                 String ls = sc.left(off);
  159.                 WriteClientString(ls, x, y, fg, bg);
  160.             }
  161.             WriteClientChar(sc[off+1], x+off, y, shortcutfg, bg);
  162.             int len = sc.Strlen()-off-2;
  163.             if (len > 0)    {
  164.                 String rs = sc.right(len);
  165.                 scs += DisplayShortcutField(rs, x+off+1, y, fg, bg);
  166.             }
  167.         }
  168.         else
  169.             WriteClientString(sc, x, y, fg, bg);
  170.     }
  171.     return scs;
  172. }
  173.  
  174. // ------- write a text line to the textbox
  175. void TextBox::WriteTextLine(int lno, int fg, int bg)
  176. {
  177.     if (!visible || lno < wtop || lno >= wtop + ClientHeight())
  178.         return;
  179.     int wd = ClientWidth();
  180.     String tl = ExtractTextLine(lno);
  181.     String ln = tl.mid(wd, wleft);
  182.     int dif = wd-ln.Strlen();
  183.     if (dif > 0)
  184.         ln = ln + String(dif, ' ');    // pad the line with spaces
  185.     // ----- display the line
  186.     WriteClientString(ln, 0, lno-wtop, fg, bg);
  187. }
  188.  
  189. // ---------- paint the textbox
  190. void TextBox::Paint()
  191. {
  192.     if (visible)    {
  193.         if (text == 0 || wlines == 0)
  194.             Control::Paint();
  195.         else    {
  196.             int ht = ClientHeight();
  197.             int wd = ClientWidth();
  198.             int fg = colors.fg;
  199.             int bg = colors.bg;
  200.             for (int i = 0; i < min(wlines-wtop,ht); i++)
  201.                 WriteTextLine(wtop+i, fg, bg);
  202.             // ---- pad the bottom lines in the window
  203.             String line(wd, ' ');
  204.             while (i < ht)
  205.                 WriteClientString(line, 0, i++, fg, bg);
  206.             if (resetscrollbox)
  207.                 SetScrollBoxes();
  208.             resetscrollbox = False;
  209.         }
  210.     }
  211. }
  212.  
  213. // ------ process a textbox keystroke
  214. void TextBox::Keyboard(int key)
  215. {
  216.     switch (key)    {
  217.         case UP:
  218.             if (ClientTop() == ClientBottom())
  219.                 break;
  220.             ScrollDown();
  221.             return;
  222.         case DN:
  223.             if (ClientTop() == ClientBottom())
  224.                 break;
  225.             ScrollUp();
  226.             return;
  227.         case FWD:
  228.             ScrollLeft();
  229.             return;
  230.         case BS:
  231.             ScrollRight();
  232.             return;
  233.         case PGUP:
  234.             PageUp();
  235.             return;
  236.         case PGDN:
  237.             PageDown();
  238.             return;
  239.         case CTRL_PGUP:
  240.             PageLeft();
  241.             return;
  242.         case CTRL_PGDN:
  243.             PageRight();
  244.             return;
  245.         case HOME:
  246.             Home();
  247.             return;
  248.         case END:
  249.             End();
  250.             return;
  251.         default:
  252.             break;
  253.     }
  254.     Control::Keyboard(key);
  255. }
  256.  
  257. // ------- scroll up one line
  258. void TextBox::ScrollUp()
  259. {
  260.     if (wtop < wlines-1)    {
  261.         int fg = colors.fg;
  262.         int bg = colors.bg;
  263.         desktop.screen().Scroll(ClientRect(), 1, fg, bg);
  264.         wtop++;
  265.         int ln = wtop+ClientHeight()-1;
  266.         if (ln < wlines)
  267.             WriteTextLine(ln, fg, bg);
  268.         SetScrollBoxes();
  269.     }
  270. }
  271.  
  272. // ------- scroll down one line
  273. void TextBox::ScrollDown()
  274. {
  275.     if (wtop)    {
  276.         int fg = colors.fg;
  277.         int bg = colors.bg;
  278.         desktop.screen().Scroll(ClientRect(), 0, fg, bg);
  279.         --wtop;
  280.         WriteTextLine(wtop, fg, bg);
  281.         SetScrollBoxes();
  282.     }
  283. }
  284.  
  285. // ------- scroll left one character
  286. void TextBox::ScrollLeft()
  287. {
  288.     if (wleft < textwidth-1)
  289.         wleft++;
  290.     Paint();
  291. }
  292.  
  293. // ------- scroll right one character
  294. void TextBox::ScrollRight()
  295. {
  296.     if (wleft > 0)
  297.         --wleft;
  298.     Paint();
  299. }
  300.  
  301. // ------- page up one screenfull
  302. void TextBox::PageUp()
  303. {
  304.     if (wtop)    {
  305.         wtop -= ClientHeight();
  306.         if (wtop < 0)
  307.             wtop = 0;
  308.         resetscrollbox = True;
  309.         Paint();
  310.     }
  311. }
  312.  
  313. // ------- page down one screenfull
  314. void TextBox::PageDown()
  315. {
  316.     if (wtop < wlines-1)    {
  317.         wtop += ClientHeight();
  318.         if (wlines < wtop)
  319.             wtop = wlines-1;
  320.         resetscrollbox = True;
  321.         Paint();
  322.     }
  323. }
  324.  
  325. // ------- page right one screenwidth
  326. void TextBox::PageRight()
  327. {
  328.     if (wleft < textwidth-1)    {
  329.         wleft += ClientWidth();
  330.         if (textwidth < wleft)
  331.             wleft = textwidth-1;
  332.         resetscrollbox = True;
  333.         Paint();
  334.     }
  335. }
  336.  
  337. // ------- page left one screenwidth
  338. void TextBox::PageLeft()
  339. {
  340.     if (wleft)    {
  341.         wleft -= ClientWidth();
  342.         if (wleft < 0)
  343.             wleft = 0;
  344.         resetscrollbox = True;
  345.         Paint();
  346.     }
  347. }
  348.  
  349. // ----- move to the first line of the textbox
  350. void TextBox::Home()
  351. {
  352.     wtop = 0;
  353.     Paint();
  354. }
  355.  
  356. // ----- move to the last line of the textbox
  357. void TextBox::End()
  358. {
  359.     wtop = wlines-ClientHeight();
  360.     if (wtop < 0)
  361.         wtop = 0;
  362.     Paint();
  363. }
  364.  
  365. // ----- position the scroll boxes
  366. void TextBox::SetScrollBoxes()
  367. {
  368.     if (vscrollbar != 0)
  369.         vscrollbar->TextPosition(wlines ? (wtop*100)/wlines : 0);
  370.     if (hscrollbar != 0)
  371.         hscrollbar->TextPosition(textwidth ? (wleft*100)/textwidth : 0);
  372. }
  373.  
  374. // ---- compute the horizontal page position
  375. void TextBox::HorizontalPagePosition(int pct)
  376. {
  377.     wleft = (textwidth * pct) / 100;
  378.     Paint();
  379. }
  380.  
  381. // ---- compute the vertical page position
  382. void TextBox::VerticalPagePosition(int pct)
  383. {
  384.     wtop = (wlines * pct) / 100;
  385.     Paint();
  386. }
  387.  
  388. void TextBox::SetScrollBars()
  389. {
  390.     if (LineCount() > ClientHeight())
  391.         SetAttribute(VSCROLLBAR);
  392.     else    {
  393.         ClearAttribute(VSCROLLBAR);
  394.         delete vscrollbar;
  395.         vscrollbar = 0;
  396.     }
  397.     if (TextWidth() > ClientWidth())
  398.         SetAttribute(HSCROLLBAR);
  399.     else    {
  400.         ClearAttribute(HSCROLLBAR);
  401.         delete hscrollbar;
  402.         hscrollbar = 0;
  403.     }
  404. }
  405.  
  406. // ---- determine the length of a line of text
  407. int TextBox::LineLength(int lno)
  408. {
  409.     const char *tp = TextLine(lno);
  410.     int len = 0;
  411.     while (*(tp + len) && *(tp + len) != '\n')
  412.         len++;
  413.     return len;
  414. }
  415.  
  416.