home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / dflat.292 < prev    next >
Encoding:
Text File  |  1991-12-17  |  21.0 KB  |  745 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* ----------- clipbord.c ------------ */
  8. #include "dflat.h"
  9.  
  10. char *Clipboard;
  11. int ClipboardLength;
  12.  
  13. void CopyToClipboard(WINDOW wnd)
  14. {
  15.     if (TextBlockMarked(wnd))    {
  16.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  17.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  18.         ClipboardLength = (int) (bel - bbl);
  19.         Clipboard = realloc(Clipboard, ClipboardLength);
  20.         if (Clipboard != NULL)
  21.             memmove(Clipboard, bbl, ClipboardLength);
  22.     }
  23. }
  24.  
  25. void PasteText(WINDOW wnd, char *SaveTo, int len)
  26. {
  27.     if (SaveTo != NULL && len > 0)    {
  28.         int plen = strlen(wnd->text) + len;
  29.         char *bl, *el;
  30.  
  31.         if (plen > wnd->textlen)    {
  32.             wnd->text = realloc(wnd->text, plen+2);
  33.             wnd->textlen = plen;
  34.         }
  35.         if (wnd->text != NULL)    {
  36.             bl = CurrChar;
  37.             el = bl+len;
  38.             memmove(el, bl, strlen(bl)+1);
  39.             memmove(bl, SaveTo, len);
  40.             BuildTextPointers(wnd);
  41.             wnd->TextChanged = TRUE;
  42.         }
  43.     }
  44. }
  45.  
  46.  
  47.  
  48. [LISTING TWO]
  49.  
  50. /* ---------------- search.c ------------- */
  51. #include "dflat.h"
  52.  
  53. extern DBOX SearchTextDB;
  54. extern DBOX ReplaceTextDB;
  55. static int CheckCase = TRUE;
  56.  
  57. /* - case-insensitive, white-space-normalized char compare - */
  58. static int SearchCmp(int a, int b)
  59. {
  60.     if (b == '\n')
  61.         b = ' ';
  62.     if (CheckCase)
  63.         return a != b;
  64.     return tolower(a) != tolower(b);
  65. }
  66.  
  67. /* ----- replace a matching block of text ----- */
  68. static void replacetext(WINDOW wnd, char *cp1, DBOX *db)
  69. {
  70.     char *cr = GetEditBoxText(db, ID_REPLACEWITH);
  71.     char *cp = GetEditBoxText(db, ID_SEARCHFOR);
  72.     int oldlen = strlen(cp); /* length of text being replaced */
  73.     int newlen = strlen(cr); /* length of replacing text      */
  74.     int dif;
  75.     if (oldlen < newlen)    {
  76.         /* ---- new text expands text size ---- */
  77.         dif = newlen-oldlen;
  78.         if (wnd->textlen < strlen(wnd->text)+dif)    {
  79.             /* ---- need to reallocate the text buffer ---- */
  80.             int offset = (int)(cp1-wnd->text);
  81.             wnd->textlen += dif;
  82.             wnd->text = realloc(wnd->text, wnd->textlen+2);
  83.             if (wnd->text == NULL)
  84.                 return;
  85.             cp1 = wnd->text + offset;
  86.         }
  87.         memmove(cp1+dif, cp1, strlen(cp1)+1);
  88.     }
  89.     else if (oldlen > newlen)    {
  90.         /* ---- new text collapses text size ---- */
  91.         dif = oldlen-newlen;
  92.         memmove(cp1, cp1+dif, strlen(cp1)+1);
  93.     }
  94.     strncpy(cp1, cr, newlen);
  95. }
  96.  
  97. /* ------- search for the occurrance of a string ------- */
  98. static void SearchTextBox(WINDOW wnd, int Replacing, int incr)
  99. {
  100.     char *s1, *s2, *cp1;
  101.     DBOX *db = Replacing ? &ReplaceTextDB : &SearchTextDB;
  102.     char *cp = GetEditBoxText(db, ID_SEARCHFOR);
  103.     int rpl = TRUE, FoundOne = FALSE;
  104.  
  105.     while (rpl == TRUE && cp != NULL)    {
  106.         rpl = Replacing ?
  107.                 CheckBoxSetting(&ReplaceTextDB, ID_REPLACEALL) :
  108.                 FALSE;
  109.         if (TextBlockMarked(wnd))    {
  110.             ClearTextBlock(wnd);
  111.             SendMessage(wnd, PAINT, 0, 0);
  112.         }
  113.         /* search for a match starting at cursor position */
  114.         cp1 = CurrChar;
  115.         if (incr)
  116.             cp1++;    /* start past the last hit */
  117.         /* --- compare at each character position --- */
  118.         while (*cp1)    {
  119.             s1 = cp;
  120.             s2 = cp1;
  121.             while (*s1 && *s1 != '\n')    {
  122.                 if (SearchCmp(*s1, *s2))
  123.                     break;
  124.                 s1++, s2++;
  125.             }
  126.             if (*s1 == '\0' || *s1 == '\n')
  127.                 break;
  128.             cp1++;
  129.         }
  130.         if (*s1 == 0 || *s1 == '\n')    {
  131.             /* ----- match at *cp1 ------- */
  132.             FoundOne = TRUE;
  133.  
  134.             /* mark a block at beginning of matching text */
  135.             wnd->BlkEndLine = TextLineNumber(wnd, s2);
  136.             wnd->BlkBegLine = TextLineNumber(wnd, cp1);
  137.             if (wnd->BlkEndLine < wnd->BlkBegLine)
  138.                 wnd->BlkEndLine = wnd->BlkBegLine;
  139.             wnd->BlkEndCol =
  140.                 (int)(s2 - TextLine(wnd, wnd->BlkEndLine));
  141.             wnd->BlkBegCol =
  142.                 (int)(cp1 - TextLine(wnd, wnd->BlkBegLine));
  143.  
  144.             /* position the cursor at the matching text */
  145.             wnd->CurrCol = wnd->BlkBegCol;
  146.             wnd->CurrLine = wnd->BlkBegLine;
  147.             wnd->WndRow = wnd->CurrLine - wnd->wtop;
  148.  
  149.             /* align the window scroll to matching text */
  150.             if (WndCol > ClientWidth(wnd)-1)
  151.                 wnd->wleft = wnd->CurrCol;
  152.             if (wnd->WndRow > ClientHeight(wnd)-1)    {
  153.                 wnd->wtop = wnd->CurrLine;
  154.                 wnd->WndRow = 0;
  155.             }
  156.  
  157.             SendMessage(wnd, PAINT, 0, 0);
  158.             SendMessage(wnd, KEYBOARD_CURSOR,
  159.                 WndCol, wnd->WndRow);
  160.  
  161.             if (Replacing)    {
  162.                 if (rpl || YesNoBox("Replace the text?"))  {
  163.                     replacetext(wnd, cp1, db);
  164.                     wnd->TextChanged = TRUE;
  165.                     BuildTextPointers(wnd);
  166.                 }
  167.                 if (rpl)    {
  168.                     incr = TRUE;
  169.                     continue;
  170.                 }
  171.                 ClearTextBlock(wnd);
  172.                 SendMessage(wnd, PAINT, 0, 0);
  173.             }
  174.             return;
  175.         }
  176.         break;
  177.     }
  178.     if (!FoundOne)
  179.         MessageBox("Search/Replace Text", "No match found");
  180. }
  181.  
  182. /* ------- search for the occurrance of a string,
  183.         replace it with a specified string ------- */
  184. void ReplaceText(WINDOW wnd)
  185. {
  186.     if (CheckCase)
  187.         SetCheckBox(&ReplaceTextDB, ID_MATCHCASE);
  188.     if (DialogBox(wnd, &ReplaceTextDB, TRUE, NULL))    {
  189.         CheckCase=CheckBoxSetting(&ReplaceTextDB,ID_MATCHCASE);
  190.         SearchTextBox(wnd, TRUE, FALSE);
  191.     }
  192. }
  193.  
  194. /* ------- search for the first occurrance of a string ------ */
  195. void SearchText(WINDOW wnd)
  196. {
  197.     if (CheckCase)
  198.         SetCheckBox(&SearchTextDB, ID_MATCHCASE);
  199.     if (DialogBox(wnd, &SearchTextDB, TRUE, NULL))    {
  200.         CheckCase=CheckBoxSetting(&SearchTextDB,ID_MATCHCASE);
  201.         SearchTextBox(wnd, FALSE, FALSE);
  202.     }
  203. }
  204.  
  205. /* ------- search for the next occurrance of a string ------- */
  206. void SearchNext(WINDOW wnd)
  207. {
  208.     SearchTextBox(wnd, FALSE, TRUE);
  209. }
  210.  
  211.  
  212.  
  213.  
  214. [LISTING THREE]
  215.  
  216. /* -------------- pictbox.c -------------- */
  217.  
  218. #include "dflat.h"
  219.  
  220. typedef struct    {
  221.     enum VectTypes vt;
  222.     RECT rc;
  223. } VECT;
  224.  
  225. unsigned char CharInWnd[] = "D3Z?Y@EC4AB";
  226.  
  227. unsigned char VectCvt[3][11][2][4] = {
  228.     {   /* --- first character in collision vector --- */
  229.         /* ( drawing D ) ( drawing 3 ) */
  230.              {{"DDD"},     {"ZC@"}},
  231.              {{"ZB?"},     {"333"}},
  232.              {{"ZBB"},     {"ZCC"}},
  233.              {{"???"},     {"???"}},
  234.              {{"YYY"},     {"YYY"}},
  235.              {{"@AA"},     {"CC@"}},
  236.              {{"EEE"},     {"EEE"}},
  237.              {{"CEE"},     {"CCC"}},
  238.              {{"444"},     {"444"}},
  239.              {{"AAA"},     {"AAA"}},
  240.              {{"BBB"},     {"BEE"}}    },
  241.     {   /* --- middle character in collision vector --- */
  242.         /* ( drawing D ) ( drawing 3 ) */
  243.              {{"DDD"},     {"BEA"}},
  244.              {{"CE4"},     {"333"}},
  245.              {{"ZZZ"},     {"ZZZ"}},
  246.              {{"???"},     {"???"}},
  247.              {{"YYY"},     {"YYY"}},
  248.              {{"@@@"},     {"@@@"}},
  249.              {{"EEE"},     {"EEE"}},
  250.              {{"CCC"},     {"CCC"}},
  251.              {{"EE4"},     {"444"}},
  252.              {{"AAA"},     {"EEA"}},
  253.              {{"BBB"},     {"BBB"}}    },
  254.     {   /* --- last character in collision vector --- */
  255.         /* ( drawing D ) ( drawing 3 ) */
  256.              {{"DDD"},     {"?4Y"}},
  257.              {{"@AY"},     {"333"}},
  258.              {{"ZZZ"},     {"ZZZ"}},
  259.              {{"BB?"},     {"?44"}},
  260.              {{"AAY"},     {"44Y"}},
  261.              {{"@@@"},     {"@@@"}},
  262.              {{"EEE"},     {"EEE"}},
  263.              {{"CCC"},     {"CCC"}},
  264.              {{"EE4"},     {"444"}},
  265.              {{"AAA"},     {"EEA"}},
  266.              {{"BBB"},     {"BBB"}}    }
  267. };
  268.  
  269. /* -- compute whether character is first, middle, or last -- */
  270. static int FindVector(WINDOW wnd, RECT rc, int x, int y)
  271. {
  272.     RECT rcc;
  273.     VECT *vc = wnd->VectorList;
  274.     int i, coll = -1;
  275.     for (i = 0; i < wnd->VectorCount; i++)    {
  276.         if ((vc+i)->vt == VECTOR)    {
  277.             rcc = (vc+i)->rc;
  278.             /* --- skip the colliding vector --- */
  279.             if (rcc.lf == rc.lf && rcc.rt == rc.rt &&
  280.                     rcc.tp == rc.tp && rc.bt == rcc.bt)
  281.                 continue;
  282.             if (rcc.tp == rcc.bt)    {
  283.                 /* ---- horizontal vector,
  284.                     see if character is in it --- */
  285.                 if (rc.lf+x >= rcc.lf && rc.lf+x <= rcc.rt &&
  286.                         rc.tp+y == rcc.tp)    {
  287.                     /* --- it is --- */
  288.                     if (rc.lf+x == rcc.lf)
  289.                         coll = 0;
  290.                     else if (rc.lf+x == rcc.rt)
  291.                         coll = 2;
  292.                     else 
  293.                         coll = 1;
  294.                 }
  295.             }
  296.             else     {
  297.                 /* ---- vertical vector,
  298.                     see if character is in it --- */
  299.                 if (rc.tp+y >= rcc.tp && rc.tp+y <= rcc.bt &&
  300.                         rc.lf+x == rcc.lf)    {
  301.                     /* --- it is --- */
  302.                     if (rc.tp+y == rcc.tp)
  303.                         coll = 0;
  304.                     else if (rc.tp+y == rcc.bt)
  305.                         coll = 2;
  306.                     else 
  307.                         coll = 1;
  308.                 }
  309.             }
  310.         }
  311.     }
  312.     return coll;
  313. }
  314.  
  315. static void PaintVector(WINDOW wnd, RECT rc)
  316. {
  317.     int i, cw, fml, vertvect, coll, len;
  318.     unsigned int ch, nc;
  319.  
  320.     if (rc.rt == rc.lf)    {
  321.         /* ------ vertical vector ------- */
  322.         nc = '3';
  323.         vertvect = 1;
  324.         len = rc.bt-rc.tp+1;
  325.     }
  326.     else     {
  327.         /* ------ horizontal vector ------- */
  328.         nc = 'D';
  329.         vertvect = 0;
  330.         len = rc.rt-rc.lf+1;
  331.     }
  332.  
  333.     for (i = 0; i < len; i++)    {
  334.         unsigned int newch = nc;
  335.         int xi = 0, yi = 0;
  336.         if (vertvect)
  337.             yi = i;
  338.         else
  339.             xi = i;
  340.         ch = videochar(GetClientLeft(wnd)+rc.lf+xi,
  341.                     GetClientTop(wnd)+rc.tp+yi);
  342.         for (cw = 0; cw < sizeof(CharInWnd); cw++)    {
  343.             if (ch == CharInWnd[cw])    {
  344.                 /* ---- hit another vector character ---- */
  345.                 if ((coll=FindVector(wnd, rc, xi, yi)) != -1) {
  346.                     /* compute first/middle/last subscript */
  347.                     if (i == len-1)
  348.                         fml = 2;
  349.                     else if (i == 0)
  350.                         fml = 0;
  351.                     else
  352.                         fml = 1;
  353.                     newch = VectCvt[coll][cw][vertvect][fml];
  354.                 }
  355.             }
  356.         }
  357.         PutWindowChar(wnd, newch, rc.lf+xi, rc.tp+yi);
  358.     }
  359. }
  360.  
  361. static void PaintBar(WINDOW wnd, RECT rc, enum VectTypes vt)
  362. {
  363.     int i, vertbar, len;
  364.     unsigned int tys[] = {'[', '2', '1', '0'};
  365.     unsigned int nc = tys[vt-1];
  366.  
  367.     if (rc.rt == rc.lf)    {
  368.         /* ------ vertical bar ------- */
  369.         vertbar = 1;
  370.         len = rc.bt-rc.tp+1;
  371.     }
  372.     else     {
  373.         /* ------ horizontal bar ------- */
  374.         vertbar = 0;
  375.         len = rc.rt-rc.lf+1;
  376.     }
  377.  
  378.     for (i = 0; i < len; i++)    {
  379.         int xi = 0, yi = 0;
  380.         if (vertbar)
  381.             yi = i;
  382.         else
  383.             xi = i;
  384.         PutWindowChar(wnd, nc, rc.lf+xi, rc.tp+yi);
  385.     }
  386. }
  387.  
  388. static void PaintMsg(WINDOW wnd)
  389. {
  390.     int i;
  391.     VECT *vc = wnd->VectorList;
  392.     for (i = 0; i < wnd->VectorCount; i++)    {
  393.         if (vc->vt == VECTOR)
  394.             PaintVector(wnd, vc->rc);
  395.         else
  396.             PaintBar(wnd, vc->rc, vc->vt);
  397.         vc++;
  398.     }
  399. }
  400.  
  401. static void DrawVectorMsg(WINDOW wnd,PARAM p1,enum VectTypes vt)
  402. {
  403.     if (p1)    {
  404.         wnd->VectorList = realloc(wnd->VectorList,
  405.                 sizeof(VECT) * (wnd->VectorCount + 1));
  406.         if (wnd->VectorList != NULL)    {
  407.             VECT vc;
  408.             vc.vt = vt;
  409.             vc.rc = *(RECT *)p1;
  410.             *(((VECT *)(wnd->VectorList))+wnd->VectorCount)=vc;
  411.             wnd->VectorCount++;
  412.         }
  413.     }
  414. }
  415.  
  416. static void DrawBoxMsg(WINDOW wnd, PARAM p1)
  417. {
  418.     if (p1)    {
  419.         RECT rc = *(RECT *)p1;
  420.         rc.bt = rc.tp;
  421.         SendMessage(wnd, DRAWVECTOR, (PARAM) &rc, TRUE);
  422.         rc = *(RECT *)p1;
  423.         rc.lf = rc.rt;
  424.         SendMessage(wnd, DRAWVECTOR, (PARAM) &rc, FALSE);
  425.         rc = *(RECT *)p1;
  426.         rc.tp = rc.bt;
  427.         SendMessage(wnd, DRAWVECTOR, (PARAM) &rc, TRUE);
  428.         rc = *(RECT *)p1;
  429.         rc.rt = rc.lf;
  430.         SendMessage(wnd, DRAWVECTOR, (PARAM) &rc, FALSE);
  431.     }
  432. }
  433.  
  434. int PictureProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  435. {
  436.     switch (msg)    {
  437.         case PAINT:
  438.             BaseWndProc(PICTUREBOX, wnd, msg, p1, p2);
  439.             PaintMsg(wnd);
  440.             return TRUE;
  441.         case DRAWVECTOR:
  442.             DrawVectorMsg(wnd, p1, VECTOR);
  443.             return TRUE;
  444.         case DRAWBOX:
  445.             DrawBoxMsg(wnd, p1);
  446.             return TRUE;
  447.         case DRAWBAR:
  448.             DrawVectorMsg(wnd, p1, p2);
  449.             return TRUE;
  450.         case CLOSE_WINDOW:
  451.             if (wnd->VectorList != NULL)
  452.                 free(wnd->VectorList);
  453.             break;
  454.         default:
  455.             break;
  456.     }
  457.     return BaseWndProc(PICTUREBOX, wnd, msg, p1, p2);
  458. }
  459.  
  460. static RECT PictureRect(int x, int y, int len, int hv)
  461. {
  462.     RECT rc;
  463.     rc.lf = rc.rt = x;
  464.     rc.tp = rc.bt = y;
  465.     if (hv)
  466.         /* ---- horizontal vector ---- */
  467.         rc.rt += len-1;
  468.     else
  469.         /* ---- vertical vector ---- */
  470.         rc.bt += len-1;
  471.     return rc;
  472. }
  473.  
  474. void DrawVector(WINDOW wnd, int x, int y, int len, int hv)
  475. {
  476.     RECT rc = PictureRect(x,y,len,hv);
  477.     SendMessage(wnd, DRAWVECTOR, (PARAM) &rc, 0);
  478. }
  479.  
  480. void DrawBox(WINDOW wnd, int x, int y, int ht, int wd)
  481. {
  482.     RECT rc;
  483.     rc.lf = x;
  484.     rc.tp = y;
  485.     rc.rt = x+wd-1;
  486.     rc.bt = y+ht-1;
  487.     SendMessage(wnd, DRAWBOX, (PARAM) &rc, 0);
  488. }
  489.  
  490. void DrawBar(WINDOW wnd,enum VectTypes vt,int x,int y,int len,int hv)
  491. {
  492.     RECT rc = PictureRect(x,y,len,hv);
  493.     SendMessage(wnd, DRAWBAR, (PARAM) &rc, (PARAM) vt);
  494. }
  495.  
  496.  
  497.  
  498.  
  499.  
  500. [LISTING FOUR]
  501.  
  502. /* ------------- calendar.c ------------- */
  503. #include "dflat.h"
  504.  
  505. #ifndef TURBOC
  506.  
  507. #define CALHEIGHT 17
  508. #define CALWIDTH 33
  509.  
  510. static int DyMo[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  511. static struct tm ttm;
  512. static int dys[42];
  513. static WINDOW Cwnd;
  514.  
  515. static void FixDate(void)
  516. {
  517.     /* ---- adjust Feb for leap year ---- */
  518.     DyMo[1] = (ttm.tm_year % 4) ? 28 : 29;
  519. #ifndef BCPP
  520.     /* bug in the Borland C++ mktime function prohibits this */
  521.     ttm.tm_mday = min(ttm.tm_mday, DyMo[ttm.tm_mon]);
  522. #endif
  523. }
  524.  
  525. /* ---- build calendar dates array ---- */
  526. static void BuildDateArray(void)
  527. {
  528.     int offset, dy = 0;
  529.     memset(dys, 0, sizeof dys);
  530.     FixDate();
  531.     /* ----- compute the weekday for the 1st ----- */
  532.     offset = ((ttm.tm_mday-1) - ttm.tm_wday) % 7;
  533.     if (offset < 0)
  534.         offset += 7;
  535.     if (offset)
  536.         offset = (offset - 7) * -1;
  537.     /* ----- build the dates into the array ---- */
  538.     for (dy = 1; dy <= DyMo[ttm.tm_mon]; dy++)
  539.         dys[offset++] = dy;
  540. }
  541. static void CreateWindowMsg(WINDOW wnd)
  542. {
  543.     int x, y;
  544.     DrawBox(wnd, 1, 2, CALHEIGHT-4, CALWIDTH-4);
  545.     for (x = 5; x < CALWIDTH-4; x += 4)
  546.         DrawVector(wnd, x, 2, CALHEIGHT-4, FALSE);
  547.     for (y = 4; y < CALHEIGHT-3; y+=2)
  548.         DrawVector(wnd, 1, y, CALWIDTH-4, TRUE);
  549. }
  550. static void DisplayDates(WINDOW wnd)
  551. {
  552.     int week, day;
  553.     char dyln[10];
  554.     int offset;
  555.     char banner[CALWIDTH-1];
  556.     char banner1[30];
  557.  
  558.     SetStandardColor(wnd);
  559.     PutWindowLine(wnd, "Sun Mon Tue Wed Thu Fri Sat", 2, 1);
  560.     memset(banner, ' ', CALWIDTH-2);
  561.     strftime(banner1, 16, "%B, %Y", &ttm);
  562.     offset = (CALWIDTH-2 - strlen(banner1)) / 2;
  563.     strcpy(banner+offset, banner1);
  564.     strcat(banner, "    ");
  565.     PutWindowLine(wnd, banner, 0, 0);
  566.     BuildDateArray();
  567.     for (week = 0; week < 6; week++)    {
  568.         for (day = 0; day < 7; day++)    {
  569.             int dy = dys[week*7+day];
  570.             if (dy == 0)
  571.                 strcpy(dyln, "   ");
  572.             else    {
  573.                 if (dy == ttm.tm_mday)
  574.                     sprintf(dyln, "%c%c%c%2d %c",
  575.                         CHANGECOLOR,
  576.                         SelectForeground(wnd)+0x80,
  577.                         SelectBackground(wnd)+0x80,
  578.                         dy, RESETCOLOR);
  579.                 else
  580.                     sprintf(dyln, "%2d ", dy);
  581.             }
  582.             SetStandardColor(wnd);
  583.             PutWindowLine(wnd, dyln, 2 + day * 4, 3 + week*2);
  584.         }
  585.     }
  586. }
  587. static int KeyboardMsg(WINDOW wnd, PARAM p1)
  588. {
  589.     switch ((int)p1)    {
  590.         case PGUP:
  591.             if (ttm.tm_mon == 0)    {
  592.                 ttm.tm_mon = 12;
  593.                 ttm.tm_year--;
  594.             }
  595.             ttm.tm_mon--;
  596.             FixDate();
  597.             mktime(&ttm);
  598.             DisplayDates(wnd);
  599.             return TRUE;
  600.         case PGDN:
  601.             ttm.tm_mon++;
  602.             if (ttm.tm_mon == 12)    {
  603.                 ttm.tm_mon = 0;
  604.                 ttm.tm_year++;
  605.             }
  606.             FixDate();
  607.             mktime(&ttm);
  608.             DisplayDates(wnd);
  609.             return TRUE;
  610.         default:
  611.             break;
  612.     }
  613.     return FALSE;
  614. }
  615. static int CalendarProc(WINDOW wnd,MESSAGE msg,PARAM p1,PARAM p2)
  616. {
  617.     switch (msg)    {
  618.         case CREATE_WINDOW:
  619.             DefaultWndProc(wnd, msg, p1, p2);
  620.             CreateWindowMsg(wnd);
  621.             return TRUE;
  622.         case KEYBOARD:
  623.             if (KeyboardMsg(wnd, p1))
  624.                 return TRUE;
  625.             break;
  626.         case PAINT:
  627.             DefaultWndProc(wnd, msg, p1, p2);
  628.             DisplayDates(wnd);
  629.             return TRUE;
  630.         case COMMAND:
  631.             if ((int)p1 == ID_HELP)    {
  632.                 DisplayHelp(wnd, "Calendar");
  633.                 return TRUE;
  634.             }
  635.             break;
  636.         case CLOSE_WINDOW:
  637.             Cwnd = NULL;
  638.             break;
  639.         default:
  640.             break;
  641.     }
  642.     return DefaultWndProc(wnd, msg, p1, p2);
  643. }
  644. void Calendar(WINDOW pwnd)
  645. {
  646.     if (Cwnd == NULL)    {
  647.         time_t tim = time(NULL);
  648.         ttm = *localtime(&tim);
  649.         Cwnd = CreateWindow(PICTUREBOX,
  650.                     "Calendar",
  651.                     -1, -1, CALHEIGHT, CALWIDTH,
  652.                     NULL, pwnd, CalendarProc,
  653.                     SHADOW     |
  654.                     MINMAXBOX  |
  655.                     CONTROLBOX |
  656.                     MOVEABLE   |
  657.                     HASBORDER
  658.         );
  659.     }
  660.     SendMessage(Cwnd, SETFOCUS, TRUE, 0);
  661. }
  662.  
  663. #endif
  664.  
  665.  
  666.  
  667.  
  668. [LISTING FIVE]
  669.  
  670. /* ------------ barchart.c ----------- */
  671. #include "dflat.h"
  672.  
  673. #define BCHEIGHT 12
  674. #define BCWIDTH 44
  675. #define COLWIDTH 4
  676.  
  677. static WINDOW Bwnd;
  678.  
  679. /* ------- project schedule array ------- */
  680. static struct ProjChart {
  681.     char *prj;
  682.     int start, stop;
  683. } projs[] = {
  684.     {"Center St", 0,3},
  685.     {"City Hall", 0,5},
  686.     {"Rt 395   ", 1,4},
  687.     {"Sky Condo", 2,3},
  688.     {"Out Hs   ", 0,4},
  689.     {"Bk Palace", 1,5}
  690. };
  691.  
  692. static char *Title =  "              PROJECT SCHEDULE";
  693. static char *Months = "           Jan Feb Mar Apr May Jun";
  694.  
  695. static int BarChartProc(WINDOW wnd, MESSAGE msg,PARAM p1, PARAM p2)
  696. {
  697.     switch (msg)    {
  698.         case COMMAND:
  699.             if ((int)p1 == ID_HELP)    {
  700.                 DisplayHelp(wnd, "BarChart");
  701.                 return TRUE;
  702.             }
  703.             break;
  704.         case CLOSE_WINDOW:
  705.             Bwnd = NULL;
  706.             break;
  707.         default:
  708.             break;
  709.     }
  710.     return DefaultWndProc(wnd, msg, p1, p2);
  711. }
  712. void BarChart(WINDOW pwnd)
  713. {
  714.     int pct = sizeof projs / sizeof(struct ProjChart);
  715.     int i;
  716.  
  717.     if (Bwnd == NULL)    {
  718.         Bwnd = CreateWindow(PICTUREBOX,
  719.                     "BarChart",
  720.                     -1, -1, BCHEIGHT, BCWIDTH,
  721.                     NULL, pwnd, BarChartProc,
  722.                     SHADOW     |
  723.                     CONTROLBOX |
  724.                     MOVEABLE   |
  725.                     HASBORDER
  726.         );
  727.         SendMessage(Bwnd, ADDTEXT, (PARAM) Title, 0);
  728.         SendMessage(Bwnd, ADDTEXT, (PARAM) "", 0);
  729.         for (i = 0; i < pct; i++)    {
  730.             SendMessage(Bwnd,ADDTEXT,(PARAM)projs[i].prj,0);
  731.             DrawBar(Bwnd, SOLIDBAR+(i%4),
  732.                 11+projs[i].start*COLWIDTH, 2+i,
  733.                 (1 + projs[i].stop-projs[i].start) * COLWIDTH,
  734.                 TRUE);
  735.         }
  736.         SendMessage(Bwnd, ADDTEXT, (PARAM) "", 0);
  737.         SendMessage(Bwnd, ADDTEXT, (PARAM) Months, 0);
  738.         DrawBox(Bwnd, 10, 1, pct+2, 25);
  739.     }
  740.     SendMessage(Bwnd, SETFOCUS, TRUE, 0);
  741. }
  742.  
  743.  
  744.  
  745.