home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJ9302.ZIP / CPROG.ASC next >
Text File  |  1993-01-11  |  18KB  |  667 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. // -------------- applicat.h
  7. #ifndef APPLICAT_H
  8. #define APPLICAT_H
  9. #include "menubar.h"
  10. #include "statbar.h"
  11. class Application : public DFWindow    {
  12.     MenuBar *menubar;            // points to menu bar
  13.     StatusBar *statusbar;        // points to status bar
  14.     Bool takingfocus;            // true while taking focus
  15.     virtual void SetColors();
  16. protected:
  17.     // ------------- client window coordinate adjustments
  18.     virtual void AdjustBorders();
  19. public:
  20.     Application(char *ttl,int lf,int tp,int ht,int wd,MenuBarItem *Menu = NULL)
  21.                 : DFWindow(ttl, lf, tp, ht, wd, NULL)
  22.             { OpenWindow(Menu); }
  23.     Application(char *ttl, int ht, int wd, MenuBarItem *Menu = NULL)
  24.                 : DFWindow(ttl, ht, wd, NULL)
  25.             { OpenWindow(Menu); }
  26.     Application(int lf, int tp, int ht, int wd, MenuBarItem *Menu = NULL)
  27.                 : DFWindow(lf, tp, ht, wd, NULL)
  28.             { OpenWindow(Menu); }
  29.     Application(int ht, int wd, MenuBarItem *Menu = NULL)
  30.                 : DFWindow(ht, wd, NULL)
  31.             { OpenWindow(Menu); }
  32.     Application(char *ttl, MenuBarItem *Menu = NULL)
  33.                 : DFWindow(ttl)
  34.             { OpenWindow(Menu); }
  35.     virtual ~Application()
  36.             { if (windowstate != CLOSED) CloseWindow(); }
  37.     // -------- API messages
  38.     virtual void OpenWindow() { OpenWindow(NULL); }
  39.     void OpenWindow(MenuBarItem *menu);
  40.     virtual void CloseWindow();
  41.     virtual Bool SetFocus();
  42.     virtual void Show();
  43.     virtual void Keyboard(int key);
  44.     virtual void ClockTick();
  45.     void StatusMessage(String& Msg);
  46. };
  47. void DispatchEvents(Application *ApWnd);
  48. void InitializeEvents(void);
  49. #endif
  50.  
  51.  
  52. [LISTING TWO]
  53.  
  54. // ------------ applicat.cpp
  55. #include "dflatpp.h"
  56. void Application::OpenWindow(MenuBarItem *menu)
  57. {
  58.     extern DeskTop desktop;
  59.     desktop.SetApplication(this);
  60.     windowtype = ApplicationWindow;
  61.     if (windowstate == CLOSED)
  62.         DFWindow::OpenWindow();
  63.     SetAttribute(BORDER | SAVESELF | CONTROLBOX | STATUSBAR);
  64.     SetColors();
  65.     if (menu != NULL)       {
  66.         SetAttribute(MENUBAR);
  67.         menubar = new MenuBar(menu, this);
  68.     }
  69.     else
  70.         menubar = NULL;
  71.     statusbar = new StatusBar(this);
  72.     desktop.mouse().Show();
  73.     DFWindow::SetFocus();
  74.     takingfocus = False;
  75. }
  76. void Application::CloseWindow()
  77. {
  78.     if (menubar != NULL)
  79.         delete menubar;
  80.     if (statusbar != NULL)
  81.         delete statusbar;
  82.     desktop.SetApplication(NULL);
  83.     DFWindow::CloseWindow();
  84. }
  85. // -------- set the fg/bg colors for the window 
  86. void Application::SetColors()
  87. {
  88.     colors.fg = 
  89.     colors.sfg = 
  90.     colors.ffg = 
  91.     colors.hfg = LIGHTGRAY;
  92.     colors.bg = 
  93.     colors.sbg = 
  94.     colors.fbg = 
  95.     colors.hbg = BLUE;
  96. }
  97. void Application::AdjustBorders()
  98. {
  99.     DFWindow::AdjustBorders();
  100.     if (attrib & MENUBAR)
  101.         TopBorderAdj++;
  102.     if (attrib & STATUSBAR)
  103.         BottomBorderAdj = 1;
  104. }
  105. Bool Application::SetFocus()
  106. {
  107.     takingfocus = True;
  108.     DFWindow::SetFocus();
  109.     takingfocus = False;
  110.     return True;
  111. }
  112. void Application::Show()
  113. {
  114.     if (!takingfocus || !isVisible())
  115.         DFWindow::Show();
  116.     else
  117.         Border();
  118. }
  119. void Application::Keyboard(int key)
  120. {
  121.     switch (key)    {
  122.         case CTRL_F4:
  123.         case ALT_F4:
  124.             CloseWindow();
  125.             break;
  126.         default:
  127.             // ---- forward unprocessed keys to the menubar
  128.             if (menubar != NULL)
  129.                 menubar->Keyboard(key);
  130.             break;
  131.     }
  132. }
  133. void Application::ClockTick()
  134. {
  135.     if (statusbar != NULL)
  136.         statusbar->ClockTick();
  137. }
  138. void Application::StatusMessage(String& Msg)
  139. {
  140.     if (statusbar != NULL)
  141.         statusbar->StatusMessage(Msg);
  142. }
  143.  
  144.  
  145.  
  146. [LISTING THREE]
  147.  
  148. // ---------- control.h
  149. #ifndef CONTROL_H
  150. #define CONTROL_H
  151. #include "dfwindow.h"
  152. class TextBox;
  153. class Control : public DFWindow    {
  154.     Bool enabled;       // true if control is enabled
  155. public:
  156.     Control(char *ttl,int lf,int tp,int ht,int wd,DFWindow *par)
  157.                         : DFWindow(ttl, lf, tp, ht, wd, par)
  158.         { OpenControl(); }
  159.     Control(char *ttl, int ht, int wd, DFWindow *par)
  160.                         : DFWindow(ttl, ht, wd, par)
  161.         { OpenControl(); }
  162.     Control(int lf, int tp, int ht, int wd, DFWindow *par)
  163.                         : DFWindow(lf, tp, ht, wd, par)
  164.         { OpenControl(); }
  165.     Control(int ht,int wd,DFWindow *par) : DFWindow(ht,wd,par)
  166.         { OpenControl(); }
  167.     Control(char *ttl)    : DFWindow(ttl)
  168.         { OpenControl(); }
  169.     virtual ~Control() { /* null */ }
  170.     virtual void Keyboard(int key);
  171.     void OpenControl() { Enable(); }
  172.     void Enable()      { enabled = True; }
  173.     void Disable()     { enabled = False; }
  174.     Bool isEnabled()   { return enabled; }
  175. };
  176. #endif
  177.  
  178.  
  179.  
  180. [LISTING FOUR]
  181.  
  182. // ------------ control.cpp
  183. #include "control.h"
  184. #include "desktop.h"
  185. void Control::Keyboard(int key)
  186. {
  187.     DFWindow *Wnd;
  188.     switch (key)    {
  189.         case UP:
  190.             Wnd = desktop.InFocus();
  191.             do {
  192.                 PrevSiblingFocus();
  193.                 if (Wnd == desktop.InFocus())
  194.                     break;
  195.             } while (desktop.InFocus()->WindowType() == MenubarWindow);
  196.             break;
  197.         case '\t':
  198.         case DN:
  199.         case ALT_F6:
  200.             Wnd = desktop.InFocus();
  201.             do {
  202.                 NextSiblingFocus();
  203.                 if (Wnd == desktop.InFocus())
  204.                     break;
  205.             } while (desktop.InFocus()->WindowType() ==
  206.                     MenubarWindow);
  207.             break;
  208.         default:
  209.             DFWindow::Keyboard(key);
  210.             break;
  211.     }
  212. }
  213.  
  214.  
  215.  
  216. [LISTING FIVE]
  217.  
  218. // ------------- textbox.h
  219. #ifndef TEXTBOX_H
  220. #define TEXTBOX_H
  221. #include "control.h"
  222. const int SHORTCUTCHAR = '~';
  223. const int InitialBufferSize = 1024;
  224. class ScrollBar;
  225. class TextBox : public Control    {
  226.     ScrollBar *hscrollbar;  // horizontal scroll bar
  227.     ScrollBar *vscrollbar;  // vertical scroll bar
  228.     unsigned *TextPointers; // -> list of line offsets
  229.     Bool resetscrollbox;
  230. protected:
  231.     // ---- text buffer
  232.     String *text;           // window text
  233.     unsigned int bufflen;   // length of buffer
  234.     int wlines;             // number of lines of text
  235.     unsigned int textlen;   // text length
  236.     int textwidth;          // width of longest line in textbox
  237.     // ---- text display
  238.     int wtop;               // text line on top of display
  239.     int wleft;              // left position in window viewport
  240.     int BlkBegLine;         // beginning line of marked block
  241.     int BlkBegCol;          // beginning column of marked block
  242.     int BlkEndLine;         // ending line of marked block
  243.     int BlkEndCol;          // ending column of marked block
  244.     int shortcutfg;         // shortcut key color
  245.     char *TextLine(int line)
  246.         { return (char *)(*text) + *(TextPointers+line); }
  247.     int DisplayShortcutField(
  248.         String sc, int x, int y, int fg, int bg);
  249.     void WriteShortcutLine(int lno, int fg, int bg);
  250.     void WriteTextLine(int lno, int fg, int bg);
  251.     void BuildTextPointers();
  252.     void SetScrollBoxes();
  253.     virtual void SetColors();
  254. public:
  255.     TextBox(char *ttl,int lf,int tp,int ht,int wd,DFWindow *par)
  256.                         : Control(ttl, lf, tp, ht, wd, par)
  257.             { OpenWindow(); }
  258.     TextBox(char *ttl, int ht, int wd, DFWindow *par)
  259.                         : Control(ttl, ht, wd, par)
  260.             { OpenWindow(); }
  261.     TextBox(int lf, int tp, int ht, int wd, DFWindow *par)
  262.                         : Control(lf, tp, ht, wd, par)
  263.             { OpenWindow(); }
  264.     TextBox(int ht, int wd, DFWindow *par) : Control(ht,wd,par)
  265.             { OpenWindow(); }
  266.     TextBox(char *ttl)    : Control(ttl)
  267.             { OpenWindow(); }
  268.     virtual ~TextBox()
  269.         { if (windowstate != CLOSED) CloseWindow(); }
  270.     // -------- textbox API messages
  271.     virtual void ScrollUp();
  272.     virtual void ScrollDown();
  273.     virtual void ScrollRight();
  274.     virtual void ScrollLeft();
  275.     virtual void PageUp();
  276.     virtual void PageDown();
  277.     virtual void PageRight();
  278.     virtual void PageLeft();
  279.     virtual void Home();
  280.     virtual void End();
  281.     virtual void OpenWindow();
  282.     virtual void CloseWindow();
  283.     virtual void AddText(char *txt);
  284.     virtual void SetText(char *txt);
  285.     virtual void SetTextLength(unsigned int len);
  286.     virtual void ClearText();
  287.     virtual void Show();
  288.     virtual void Paint();
  289.     virtual void Keyboard(int key);
  290.     String ExtractTextLine(int lno);
  291.     void ClearTextBlock()
  292.         { BlkBegLine=BlkEndLine=BlkBegCol=BlkEndCol=0; }
  293.     void HorizontalPagePosition(int pct);
  294.     void VerticalPagePosition(int pct);
  295. };
  296. #endif
  297.  
  298.  
  299.  
  300. [LISTING SIX]
  301.  
  302. // ------------- textbox.cpp
  303. #include "desktop.h"
  304. #include "textbox.h"
  305. #include "scrolbar.h"
  306. // ----------- common constructor code
  307. void TextBox::OpenWindow()
  308. {
  309.     windowtype = TextboxWindow;
  310.     if (windowstate == CLOSED)
  311.         Control::OpenWindow();
  312.     text = NULL;
  313.     bufflen = InitialBufferSize;
  314.     hscrollbar = vscrollbar = NULL;
  315.     TextPointers = NULL;
  316.     ClearText();
  317.     SetColors();
  318. }
  319. void TextBox::CloseWindow()
  320. {
  321.     ClearText();
  322.     if (hscrollbar != NULL)
  323.         delete hscrollbar;
  324.     if (vscrollbar != NULL)
  325.         delete vscrollbar;
  326.     Control::CloseWindow();
  327. }
  328. // ------ show the textbox
  329. void TextBox::Show()
  330. {
  331.     if ((attrib & HSCROLLBAR) && hscrollbar == NULL)    {
  332.         hscrollbar = new ScrollBar(HORIZONTAL, this);
  333.         hscrollbar->SetAttribute(FRAMEWND);
  334.     }
  335.     if ((attrib & VSCROLLBAR) && vscrollbar == NULL)    {
  336.         vscrollbar = new ScrollBar(VERTICAL, this);
  337.         vscrollbar->SetAttribute(FRAMEWND);
  338.     }
  339.     Control::Show();
  340. }
  341. // ------------ build the text line pointers
  342. void TextBox::BuildTextPointers()
  343. {
  344.     textwidth = wlines = 0;
  345.     // ---- count the lines of text
  346.     char *cp1, *cp = *text;
  347.     while (*cp)    {
  348.         wlines++;
  349.         while (*cp && *cp != '\n')
  350.             cp++;
  351.         if (*cp)
  352.             cp++;
  353.     }
  354.     // ----- build the pointer array
  355.     delete TextPointers;
  356.     TextPointers = new unsigned int[wlines];
  357.     unsigned int off;
  358.     cp = *text;
  359.     wlines = 0;
  360.     while (*cp)    {
  361.         off = (unsigned int) (cp - *text);
  362.         *(TextPointers + wlines++) = off;
  363.         cp1 = cp;
  364.         while (*cp && *cp != '\n')
  365.             cp++;
  366.         textwidth = max(textwidth, (unsigned int) (cp - cp1));
  367.         if (*cp)
  368.             cp++;
  369.     }
  370. }
  371. // --------- add a line of text to the textbox
  372. void TextBox::AddText(char *txt)
  373. {
  374.     String tx(txt);
  375.     int len = tx.Strlen();
  376.     if (tx[len-1] != '\n')
  377.         textlen++;
  378.     textlen += len;
  379.     if (text == NULL)
  380.         text = new String(bufflen);
  381.     if (textlen > text->StrBufLen())
  382.         text->ChangeLength(max(bufflen, textlen));
  383.     *text += tx;
  384.     if (*text[len-1] != '\n')
  385.         *text += String("\n");
  386.     BuildTextPointers();
  387. }
  388. // --------- set the textbox's text buffer to new text
  389. void TextBox::SetText(char *txt)
  390. {
  391.     ClearText();
  392.     AddText(txt);
  393. }
  394. // ------ set the length of the text buffer
  395. void TextBox::SetTextLength(unsigned int len)
  396. {
  397.     if (text != NULL)
  398.         text->ChangeLength(len);
  399.     bufflen = len;
  400. }
  401. // --------- clear the text from the textbox
  402. void TextBox::ClearText()
  403. {
  404.     if (text != NULL)
  405.         delete text;
  406.     textlen = 0;
  407.     wlines = 0;
  408.     textwidth = 0;
  409.     wtop = wleft = 0;
  410.     ClearTextBlock();
  411.     if (TextPointers != NULL)
  412.         delete TextPointers;
  413. }
  414. // -------- set the fg/bg colors for the window 
  415. void TextBox::SetColors()
  416. {
  417.     colors.fg = BLACK;
  418.     colors.bg = LIGHTGRAY;
  419.     colors.sfg = LIGHTGRAY;
  420.     colors.sbg = BLACK;
  421.     colors.ffg = BLACK;
  422.     colors.fbg = LIGHTGRAY;
  423.     colors.hfg = BLACK;
  424.     colors.hbg = LIGHTGRAY;
  425.     shortcutfg = BLUE;
  426. }
  427. // ------- extract a text line
  428. String TextBox::ExtractTextLine(int lno)
  429. {
  430.     char *lp = TextLine(lno);
  431.     int offset = lp - (char *) *text;
  432.     for (int len = 0; *(lp+len) && *(lp+len) != '\n'; len++)
  433.         ;
  434.     return text->mid(len, offset);
  435. }
  436. // ---- display a line with a shortcut key character
  437. void TextBox::WriteShortcutLine(int lno, int fg, int bg)
  438. {
  439.     String sc = ExtractTextLine(lno);
  440.     int x = sc.Strlen();
  441.     int y = lno-wtop;
  442.     x -= DisplayShortcutField(sc, 0, y, fg, bg);
  443.     // --------- pad the line
  444.     int wd = ClientWidth() - x;
  445.     if (wd > 0)
  446.         WriteClientString(String(wd, ' '), x, y, fg, bg);
  447. }
  448. // ---- display a shortcut field character
  449. int TextBox::DisplayShortcutField(String sc, int x, int y, int fg, int bg)
  450. {
  451.     int scs = 0;
  452.     int off = sc.FindChar(SHORTCUTCHAR);
  453.     if (off != -1)    {
  454.         scs++;
  455.         if (off != 0)    {
  456.             String ls = sc.left(off);
  457.             WriteClientString(ls, x, y, fg, bg);
  458.         }
  459.         WriteClientChar(sc[off+1], x+off, y, shortcutfg, bg);
  460.         int len = sc.Strlen()-off-2;
  461.         if (len > 0)    {
  462.             String rs = sc.right(len);
  463.             scs += DisplayShortcutField(rs, x+off+1, y, fg, bg);
  464.         }
  465.     }
  466.     else
  467.         WriteClientString(sc, x, y, fg, bg);
  468.     return scs;
  469. }
  470. // ------- write a text line to the textbox
  471. void TextBox::WriteTextLine(int lno, int fg, int bg)
  472. {
  473.     if (lno < wtop || lno >= wtop + ClientHeight())
  474.         return;
  475.     int wd = ClientWidth();
  476.     String tl = ExtractTextLine(lno);
  477.     String ln = tl.mid(wd, wleft);
  478.     int dif = wd-ln.Strlen();
  479.     if (dif > 0)
  480.         ln = ln + String(dif, ' ');    // pad the line with spaces
  481.     // ----- display the line
  482.     WriteClientString(ln, 0, lno-wtop, fg, bg);
  483. }
  484. // ---------- paint the textbox
  485. void TextBox::Paint()
  486. {
  487.     if (text == NULL)
  488.         Control::Paint();
  489.     else    {
  490.         int ht = ClientHeight();
  491.         int wd = ClientWidth();
  492.         int fg = colors.fg;
  493.         int bg = colors.bg;
  494.         for (int i = 0; i < min(wlines-wtop,ht); i++)
  495.             WriteTextLine(wtop+i, fg, bg);
  496.         // ---- pad the bottom lines in the window
  497.         String line(wd, ' ');
  498.         while (i < ht)
  499.             WriteClientString(line, 0, i++, fg, bg);
  500.         if (resetscrollbox)
  501.             SetScrollBoxes();
  502.         resetscrollbox = False;
  503.     }
  504. }
  505. // ------ process a textbox keystroke
  506. void TextBox::Keyboard(int key)
  507. {
  508.     switch (key)    {
  509.         case UP:
  510.             if (ClientTop() == ClientBottom())
  511.                 break;
  512.             ScrollDown();
  513.             return;
  514.         case DN:
  515.             if (ClientTop() == ClientBottom())
  516.                 break;
  517.             ScrollUp();
  518.             return;
  519.         case FWD:
  520.             ScrollLeft();
  521.             return;
  522.         case BS:
  523.             ScrollRight();
  524.             return;
  525.         case PGUP:
  526.             PageUp();
  527.             return;
  528.         case PGDN:
  529.             PageDown();
  530.             return;
  531.         case CTRL_PGUP:
  532.             PageLeft();
  533.             return;
  534.         case CTRL_PGDN:
  535.             PageRight();
  536.             return;
  537.         case HOME:
  538.             Home();
  539.             return;
  540.         case END:
  541.             End();
  542.             return;
  543.         default:
  544.             break;
  545.     }
  546.     Control::Keyboard(key);
  547. }
  548. // ------- scroll up one line
  549. void TextBox::ScrollUp()
  550. {
  551.     if (wtop < wlines-1)    {
  552.         int fg = colors.fg;
  553.         int bg = colors.bg;
  554.         desktop.screen().Scroll(ClientRect(), 1, fg, bg);
  555.         wtop++;
  556.         int ln = wtop+ClientHeight()-1;
  557.         if (ln < wlines)
  558.             WriteTextLine(ln, fg, bg);
  559.         SetScrollBoxes();
  560.     }
  561. }
  562. // ------- scroll down one line
  563. void TextBox::ScrollDown()
  564. {
  565.     if (wtop)    {
  566.         int fg = colors.fg;
  567.         int bg = colors.bg;
  568.         desktop.screen().Scroll(ClientRect(), 0, fg, bg);
  569.         --wtop;
  570.         WriteTextLine(wtop, fg, bg);
  571.         SetScrollBoxes();
  572.     }
  573. }
  574. // ------- scroll left one character
  575. void TextBox::ScrollLeft()
  576. {
  577.     if (wleft < textwidth-1)
  578.         wleft++;
  579.     Paint();
  580. }
  581. // ------- scroll right one character
  582. void TextBox::ScrollRight()
  583. {
  584.     if (wleft > 0)
  585.         --wleft;
  586.     Paint();
  587. }
  588. // ------- page up one screenfull
  589. void TextBox::PageUp()
  590. {
  591.     if (wtop)    {
  592.         wtop -= ClientHeight();
  593.         if (wtop < 0)
  594.             wtop = 0;
  595.         resetscrollbox = True;
  596.         Paint();
  597.     }
  598. }
  599. // ------- page down one screenfull
  600. void TextBox::PageDown()
  601. {
  602.     if (wtop < wlines-1)    {
  603.         wtop += ClientHeight();
  604.         if (wlines < wtop)
  605.             wtop = wlines-1;
  606.         resetscrollbox = True;
  607.         Paint();
  608.     }
  609. }
  610. // ------- page right one screenwidth
  611. void TextBox::PageRight()
  612. {
  613.     if (wleft < textwidth-1)    {
  614.         wleft += ClientWidth();
  615.         if (textwidth < wleft)
  616.             wleft = textwidth-1;
  617.         resetscrollbox = True;
  618.         Paint();
  619.     }
  620. }
  621. // ------- page left one screenwidth
  622. void TextBox::PageLeft()
  623. {
  624.     if (wleft)    {
  625.         wleft -= ClientWidth();
  626.         if (wleft < 0)
  627.             wleft = 0;
  628.         resetscrollbox = True;
  629.         Paint();
  630.     }
  631. }
  632. // ----- move to the first line of the textbox
  633. void TextBox::Home()
  634. {
  635.     wtop = 0;
  636.     Paint();
  637. }
  638. // ----- move to the last line of the textbox
  639. void TextBox::End()
  640. {
  641.     wtop = wlines-ClientHeight();
  642.     if (wtop < 0)
  643.         wtop = 0;
  644.     Paint();
  645. }
  646. // ----- position the scroll boxes
  647. void TextBox::SetScrollBoxes()
  648. {
  649.     if (vscrollbar != NULL)
  650.         vscrollbar->TextPosition(wlines ? (wtop*100)/wlines : 0);
  651.     if (hscrollbar != NULL)
  652.         hscrollbar->TextPosition(textwidth ? (wleft*100)/textwidth : 0);
  653. }
  654. // ---- compute the horizontal page position
  655. void TextBox::HorizontalPagePosition(int pct)
  656. {
  657.     wleft = (textwidth * pct) / 100;
  658.     Paint();
  659. }
  660. // ---- compute the vertical page position
  661. void TextBox::VerticalPagePosition(int pct)
  662. {
  663.     wtop = (wlines * pct) / 100;
  664.     Paint();
  665. }
  666.  
  667.