home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 05 / d_flat / window.c < prev   
Text File  |  1991-03-13  |  16KB  |  511 lines

  1. /* ---------- window.c ------------- */
  2.  
  3. #include <stdio.h>
  4. #include <conio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "dflat.h"
  8.  
  9. WINDOW inFocus = NULLWND;
  10.  
  11. int foreground, background;   /* current video colors */
  12.  
  13. static void InsertTitle(WINDOW, char *);
  14. static void DisplayTitle(WINDOW, RECT);
  15.  
  16. /* --------- create a window ------------ */
  17. WINDOW CreateWindow(
  18.     CLASS class,              /* class of this window       */
  19.     char *ttl,                /* title or NULL              */
  20.     int left, int top,        /* upper left coordinates     */
  21.     int height, int width,    /* dimensions                 */
  22.     void *extension,          /* pointer to additional data */
  23.     WINDOW parent,            /* parent of this window      */
  24.     int (*wndproc)(struct window *,enum messages,PARAM,PARAM),
  25.     int attrib)               /* window attribute           */
  26. {
  27.     WINDOW wnd = malloc(sizeof(struct window));
  28.     get_videomode();
  29.     if (wnd != NULLWND)    {
  30.         int base;
  31.         /* ----- coordinates -1, -1 = center the window ---- */
  32.         if (left == -1)
  33.             wnd->rc.lf = (SCREENWIDTH-width)/2;
  34.         else
  35.             wnd->rc.lf = left;
  36.         if (top == -1)
  37.             wnd->rc.tp = (SCREENHEIGHT-height)/2;
  38.         else
  39.             wnd->rc.tp = top;
  40.         wnd->attrib = attrib;
  41.         if (ttl != NULL)
  42.             AddAttribute(wnd, TITLEBAR);
  43.         if (wndproc == NULL)
  44.             wnd->wndproc = classdefs[FindClass(class)].wndproc;
  45.         else
  46.             wnd->wndproc = wndproc;
  47.         /* ---- derive attributes of base classes ---- */
  48.         base = class;
  49.         while (base != -1)    {
  50.             int tclass = FindClass(base);
  51.             AddAttribute(wnd, classdefs[tclass].attrib);
  52.             base = classdefs[tclass].base;
  53.         }
  54.         if (parent && !TestAttribute(wnd, NOCLIP))    {
  55.             /* -- keep upper left within borders of parent -- */
  56.             wnd->rc.lf = max(wnd->rc.lf, GetClientLeft(parent));
  57.             wnd->rc.tp = max(wnd->rc.tp, GetClientTop(parent) +
  58.                 (TestAttribute(parent, HASMENUBAR) ? 1 : 0));
  59.         }
  60.         wnd->class = class;
  61.         wnd->extension = extension;
  62.         wnd->rc.rt = GetLeft(wnd)+width-1;
  63.         wnd->rc.bt = GetTop(wnd)+height-1;
  64.         wnd->ht = height;
  65.         wnd->wd = width;
  66.         wnd->title = ttl;
  67.         if (ttl != NULL)
  68.             InsertTitle(wnd, ttl);
  69.         wnd->next = wnd->prev = wnd->dFocus = NULLWND;
  70.         wnd->parent = parent;
  71.         wnd->videosave = NULL;
  72.         wnd->condition = ISRESTORED;
  73.         wnd->RestoredRC = wnd->rc;
  74.         wnd->PrevKeyboard = wnd->PrevMouse = NULL;
  75.         wnd->DeletedText = NULL;
  76.         SendMessage(wnd, CREATE_WINDOW, 0, 0);
  77.         if (isVisible(wnd))
  78.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  79.     }
  80.     return wnd;
  81. }
  82.  
  83. /* -------- add a title to a window --------- */
  84. void AddTitle(WINDOW wnd, char *ttl)
  85. {
  86.     InsertTitle(wnd, ttl);
  87.     SendMessage(wnd, BORDER, 0, 0);
  88. }
  89.  
  90. /* ----- insert a title into a window ---------- */
  91. static void InsertTitle(WINDOW wnd, char *ttl)
  92. {
  93.     if ((wnd->title = malloc(strlen(ttl)+1)) != NULL)
  94.         strcpy(wnd->title, ttl);
  95. }
  96.  
  97. /* ------- write a character to a window at x,y ------- */
  98. void PutWindowChar(WINDOW wnd, int x, int y, int c)
  99. {
  100.     int x1 = GetClientLeft(wnd)+x;
  101.     int y1 = GetClientTop(wnd)+y;
  102.  
  103.     if (isVisible(wnd))    {
  104.         if (!TestAttribute(wnd, NOCLIP))    {
  105.             WINDOW wnd1 = GetParent(wnd);
  106.             while (wnd1 != NULLWND)    {
  107.                 /* --- clip character to parent's borders --- */
  108.                 if (x1 < GetClientLeft(wnd1)   ||
  109.                     x1 > GetClientRight(wnd1)  ||
  110.                     y1 > GetClientBottom(wnd1) ||
  111.                     y1 < GetClientTop(wnd1)    ||
  112.                     (y1 < GetTop(wnd1)+2 &&
  113.                             TestAttribute(wnd1, HASMENUBAR)))
  114.                         return;
  115.                 wnd1 = GetParent(wnd1);
  116.             }
  117.         }
  118.         if (x1 < SCREENWIDTH && y1 < SCREENHEIGHT)
  119.             wputch(wnd, c, x, y);
  120.     }
  121. }
  122.  
  123. static char line[161];
  124.  
  125. /* ----- clip line if it extends below the bottom of the
  126.              parent window ------ */
  127. static int clipbottom(WINDOW wnd, int y)
  128. {
  129.     if (!TestAttribute(wnd, NOCLIP))    {
  130.         WINDOW wnd1 = GetParent(wnd);
  131.         while (wnd1 != NULLWND)    {
  132.             if (GetClientTop(wnd)+y > GetBottom(wnd1))
  133.                 return TRUE;
  134.             wnd1 = GetParent(wnd1);
  135.         }
  136.     }
  137.     return GetClientTop(wnd)+y > SCREENHEIGHT;
  138. }
  139.  
  140. /* ------ clip the portion of a line that extends past the
  141.                      right margin of the parent window ----- */
  142. void clipline(WINDOW wnd, int x, char *ln)
  143. {
  144.     WINDOW pwnd = GetParent(wnd);
  145.     int x1 = strlen(ln);
  146.     int i = 0;
  147.  
  148.     if (!TestAttribute(wnd, NOCLIP))    {
  149.         while (pwnd != NULLWND)    {
  150.             x1 = GetRight(pwnd) - GetLeft(wnd) - x;
  151.             pwnd = GetParent(pwnd);
  152.         }
  153.     }
  154.     else if (GetLeft(wnd) + x > SCREENWIDTH)
  155.         x1 = SCREENWIDTH-GetLeft(wnd) - x;
  156.     /* --- adjust the clipping offset for color controls --- */
  157.     if (x1 < 0)
  158.         x1 = 0;
  159.     while (i < x1)    {
  160.         if ((unsigned char) ln[i] == CHANGECOLOR)
  161.             i += 3, x1 += 3;
  162.         else if ((unsigned char) ln[i] == RESETCOLOR)
  163.             i++, x1++;
  164.         else 
  165.             i++;
  166.     }
  167.     ln[x1] = '\0';
  168. }
  169.  
  170. /* ------ write a line to video window client area ------ */
  171. void writeline(WINDOW wnd, char *str, int x, int y, int pad)
  172. {
  173.     char wline[120];
  174.  
  175.     if (TestAttribute(wnd, HASBORDER))    {
  176.         x++;
  177.         y++;
  178.     }
  179.     if (!clipbottom(wnd, y))    {
  180.         char *cp;
  181.         int len;
  182.         int dif;
  183.  
  184.         memset(wline, 0, sizeof wline);
  185.         len = LineLength(str);
  186.         dif = strlen(str) - len;
  187.         strncpy(wline, str, ClientWidth(wnd) + dif);
  188.         if (pad)    {
  189.             cp = wline+strlen(wline);
  190.             while (len++ < ClientWidth(wnd)-x)
  191.                 *cp++ = ' ';
  192.         }
  193.         clipline(wnd, x, wline);
  194.         wputs(wnd, wline, x, y);
  195.     }
  196. }
  197.  
  198. /* -- write a line to video window (including the border) -- */
  199. void writefull(WINDOW wnd, char *str, int y)
  200. {
  201.     if (!clipbottom(wnd, y))    {
  202.         strcpy(line, str);
  203.         clipline(wnd, 0, line);
  204.         wputs(wnd, line, 0, y);
  205.     }
  206. }
  207.  
  208. /* -------- display a window's title --------- */
  209. static void DisplayTitle(WINDOW wnd, RECT rc)
  210. {
  211.     int tlen = min(strlen(wnd->title), WindowWidth(wnd)-2);
  212.     int tend = WindowWidth(wnd)-4;
  213.  
  214.     if (SendMessage(wnd, TITLE, 0, 0))    {
  215.         if (wnd == inFocus)    {
  216.             foreground = cfg.clr.InFocusTitleFG;
  217.             background = cfg.clr.InFocusTitleBG;
  218.         }
  219.         else    {
  220.             foreground = cfg.clr.TitleFG;
  221.             background = cfg.clr.TitleBG;
  222.         }
  223.         memset(line,' ',WindowWidth(wnd)-2);
  224.         if (wnd->condition != ISMINIMIZED)
  225.             strncpy(line + ((WindowWidth(wnd)-2 - tlen) / 2),
  226.                 wnd->title, tlen);
  227.         line[WindowWidth(wnd)-2] = '\0';
  228.         if (TestAttribute(wnd, CONTROLBOX))
  229.             line[1] = CONTROLBOXCHAR;
  230.         if (TestAttribute(wnd, MINMAXBOX))    {
  231.             switch (wnd->condition)    {
  232.                 case ISRESTORED:
  233.                     line[tend+1] = MAXPOINTER;
  234.                     line[tend]   = MINPOINTER;
  235.                     break;
  236.                 case ISMINIMIZED:
  237.                     line[tend+1] = MAXPOINTER;
  238.                     break;
  239.                 case ISMAXIMIZED:
  240.                     line[tend]   = MINPOINTER;
  241.                     line[tend+1] = RESTOREPOINTER;
  242.                     break;
  243.                 default:
  244.                     break;
  245.             }
  246.         }
  247.         line[RectRight(rc)+1] = '\0';
  248.         writeline(wnd, line+RectLeft(rc),
  249.                     RectLeft(rc), -1, FALSE);
  250.     }
  251. }
  252.  
  253. /* --- display right border shadow character of a window --- */
  254. static void near shadow_char(WINDOW wnd, int y)
  255. {
  256.     int fg = foreground;
  257.     int bg = background;
  258.     int x = WindowWidth(wnd);
  259.     int c = videochar(GetLeft(wnd)+x, GetTop(wnd)+y+1);
  260.  
  261.     if (TestAttribute(wnd, SHADOW) == 0)
  262.         return;
  263.     foreground = SHADOWFG;
  264.     background = BLACK;
  265.     PutWindowChar(wnd, x-1, y, c);
  266.     foreground = fg;
  267.     background = bg;
  268. }
  269.  
  270. /* --- display the bottom border shadow line for a window --- */
  271. static void near shadowline(WINDOW wnd, RECT rc)
  272. {
  273.     int i;
  274.     int y = GetBottom(wnd)+1;
  275.     if ((TestAttribute(wnd, SHADOW)) == 0)
  276.         return;
  277.     if (!clipbottom(wnd, WindowHeight(wnd)))    {
  278.         int fg = foreground;
  279.         int bg = background;
  280.         for (i = 0; i < WindowWidth(wnd); i++)
  281.             line[i] = videochar(GetLeft(wnd)+i+1, y);
  282.         line[i] = '\0';
  283.         foreground = SHADOWFG;
  284.         background = BLACK;
  285.         clipline(wnd, 1, line);
  286.         line[RectRight(rc)+3] = '\0';
  287.         wputs(wnd, line+RectLeft(rc), 1+RectLeft(rc),
  288.             WindowHeight(wnd));
  289.         foreground = fg;
  290.         background = bg;
  291.     }
  292. }
  293.  
  294. /* ------- display a window's border ----- */
  295. void RepaintBorder(WINDOW wnd, RECT *rcc)
  296. {
  297.     int y;
  298.     int lin, side, ne, nw, se, sw;
  299.     RECT rc, clrc;
  300.  
  301.     if (!TestAttribute(wnd, HASBORDER))
  302.         return;
  303.     if (rcc == NULL)    {
  304.         rc = SetRect(0, 0, WindowWidth(wnd)-1,
  305.                 WindowHeight(wnd)-1);
  306.         if (TestAttribute(wnd, SHADOW))    {
  307.             rc.rt++;
  308.             rc.bt++;
  309.         }
  310.     }
  311.     else
  312.         rc = *rcc;
  313.     clrc = rc;
  314.     /* -------- adjust the client rectangle ------- */
  315.     if (RectLeft(rc) == 0)
  316.         --clrc.rt;
  317.     else
  318.         --clrc.lf;
  319.     if (RectTop(rc) == 0)
  320.         --clrc.bt;
  321.     else
  322.         --clrc.tp;
  323.     RectRight(clrc) = min(RectRight(clrc), WindowWidth(wnd)-3);
  324.     RectBottom(clrc) =
  325.                      min(RectBottom(clrc), WindowHeight(wnd)-3);
  326.     if (wnd == inFocus)    {
  327.         lin  = FOCUS_LINE;
  328.         side = FOCUS_SIDE;
  329.         ne   = FOCUS_NE;
  330.         nw   = FOCUS_NW;
  331.         se   = FOCUS_SE;
  332.         sw   = FOCUS_SW;
  333.     }
  334.     else    {
  335.         lin  = LINE;
  336.         side = SIDE;
  337.         ne   = NE;
  338.         nw   = NW;
  339.         se   = SE;
  340.         sw   = SW;
  341.     }
  342.     line[WindowWidth(wnd)] = '\0';
  343.     /* ---------- window title ------------ */
  344.     if (RectTop(rc) == 0)
  345.         if (TestAttribute(wnd, TITLEBAR))
  346.             DisplayTitle(wnd, clrc);
  347.     foreground = FrameForeground(wnd);
  348.     background = FrameBackground(wnd);
  349.     /* -------- top frame corners --------- */
  350.     if (RectTop(rc) == 0)    {
  351.         if (RectLeft(rc) == 0)
  352.             PutWindowChar(wnd, -1, -1, nw);
  353.         if (RectRight(rc) >= WindowWidth(wnd)-1)
  354.             PutWindowChar(wnd, WindowWidth(wnd)-2, -1, ne);
  355.  
  356.         if (TestAttribute(wnd, TITLEBAR) == 0)    {
  357.             /* ----------- top line ------------- */
  358.             memset(line,lin,WindowWidth(wnd)-1);
  359.             line[RectRight(clrc)+1] = '\0';
  360.             if (strlen(line+RectLeft(clrc)) > 1 ||
  361.                             TestAttribute(wnd, SHADOW) == 0)
  362.                 writeline(wnd, line+RectLeft(clrc),
  363.                         RectLeft(clrc), -1, FALSE);
  364.         }
  365.     }
  366.     /* ----------- window body ------------ */
  367.     for (y = 0; y < ClientHeight(wnd); y++)    {
  368.         int ch;
  369.         if (y >= RectTop(clrc) && y <= RectBottom(clrc))    {
  370.             if (RectLeft(rc) == 0)
  371.                 PutWindowChar(wnd, -1, y, side);
  372.             if (RectRight(rc) >= ClientWidth(wnd))    {
  373.                 if (TestAttribute(wnd, VSCROLLBAR))
  374.                     ch = (    y == 0 ? UPSCROLLBOX      :
  375.                               y == WindowHeight(wnd)-3  ?
  376.                                    DOWNSCROLLBOX        :
  377.                               y == wnd->VScrollBox      ?
  378.                                    SCROLLBOXCHAR        :
  379.                                    SCROLLBARCHAR );
  380.                 else
  381.                     ch = side;
  382.                 PutWindowChar(wnd, WindowWidth(wnd)-2, y, ch);
  383.             }
  384.             if (RectRight(rc) == WindowWidth(wnd))
  385.                 shadow_char(wnd, y);
  386.         }
  387.     }
  388.     if (RectBottom(rc) >= WindowHeight(wnd)-1)    {
  389.         /* -------- bottom frame corners ---------- */
  390.         if (RectLeft(rc) == 0)
  391.             PutWindowChar(wnd, -1, WindowHeight(wnd)-2, sw);
  392.         if (RectRight(rc) >= WindowWidth(wnd)-1)
  393.             PutWindowChar(wnd, WindowWidth(wnd)-2,
  394.                 WindowHeight(wnd)-2, se);
  395.         /* ----------- bottom line ------------- */
  396.         memset(line,lin,WindowWidth(wnd)-1);
  397.         if (TestAttribute(wnd, HSCROLLBAR))    {
  398.             line[0] = LEFTSCROLLBOX;
  399.             line[WindowWidth(wnd)-3] = RIGHTSCROLLBOX;
  400.             memset(line+1, SCROLLBARCHAR, WindowWidth(wnd)-4);
  401.             line[wnd->HScrollBox] = SCROLLBOXCHAR;
  402.         }
  403.         line[RectRight(clrc)+1] = '\0';
  404.         if (strlen(line+RectLeft(clrc)) > 1 ||
  405.                         TestAttribute(wnd, SHADOW) == 0)
  406.             writeline(wnd,
  407.                 line+RectLeft(clrc),
  408.                 RectLeft(clrc),
  409.                 WindowHeight(wnd)-2,
  410.                 FALSE);
  411.         if (RectRight(rc) == WindowWidth(wnd))
  412.             shadow_char(wnd, WindowHeight(wnd)-2);
  413.     }
  414.     if (RectBottom(rc) == WindowHeight(wnd))
  415.         /* ---------- bottom shadow ------------- */
  416.         shadowline(wnd, clrc);
  417. }
  418.  
  419. /* ------ clear the data space of a window -------- */
  420. void ClearWindow(WINDOW wnd, RECT *rcc, int clrchar)
  421. {
  422.     if (isVisible(wnd))    {
  423.         int y;
  424.         RECT rc;
  425.  
  426.         if (rcc == NULL)
  427.             rc = SetRect(0, 0, ClientWidth(wnd)-1,
  428.                 ClientHeight(wnd)-1);
  429.         else
  430.             rc = *rcc;
  431.         SetStandardColor(wnd);
  432.         memset(line, clrchar, RectWidth(rc));
  433.         line[RectWidth(rc)] = '\0';
  434.         for (y = RectTop(rc); y <= RectBottom(rc); y++)
  435.             writeline(wnd, line, RectLeft(rc), y, FALSE);
  436.     }
  437. }
  438.  
  439. /* -- adjust a window's rectangle to clip it to its parent -- */
  440. static RECT near AdjustRect(WINDOW wnd)
  441. {
  442.     RECT rc = wnd->rc;
  443.     if (TestAttribute(wnd, SHADOW))    {
  444.         RectBottom(rc)++;
  445.         RectRight(rc)++;
  446.     }
  447.     if (!TestAttribute(wnd, NOCLIP))    {
  448.         WINDOW pwnd = GetParent(wnd);
  449.         if (pwnd != NULLWND)    {
  450.             RectTop(rc) = max(RectTop(rc),
  451.                         GetClientTop(pwnd));
  452.             RectLeft(rc) = max(RectLeft(rc),
  453.                         GetClientLeft(pwnd));
  454.             RectRight(rc) = min(RectRight(rc),
  455.                         GetClientRight(pwnd));
  456.             RectBottom(rc) = min(RectBottom(rc),
  457.                         GetClientBottom(pwnd));
  458.         }
  459.     }
  460.     RectRight(rc) = min(RectRight(rc), SCREENWIDTH-1);
  461.     RectBottom(rc) = min(RectBottom(rc), SCREENHEIGHT-1);
  462.     RectLeft(rc) = min(RectLeft(rc), SCREENWIDTH-1);
  463.     RectTop(rc) = min(RectTop(rc), SCREENHEIGHT-1);
  464.     return rc;
  465. }
  466.  
  467. /* --- get the video memory that is to be used by a window -- */
  468. void GetVideoBuffer(WINDOW wnd)
  469. {
  470.     RECT rc;
  471.     int ht;
  472.     int wd;
  473.  
  474.     rc = AdjustRect(wnd);
  475.     ht = RectBottom(rc) - RectTop(rc) + 1;
  476.     wd = RectRight(rc) - RectLeft(rc) + 1;
  477.     wnd->videosave = realloc(wnd->videosave, (ht * wd * 2));
  478.     get_videomode();
  479.     if (wnd->videosave != NULL)
  480.         getvideo(rc, wnd->videosave);
  481. }
  482.  
  483. /* --- restore the video memory that was used by a window --- */
  484. void RestoreVideoBuffer(WINDOW wnd)
  485. {
  486.     if (wnd->videosave != NULL)    {
  487.         RECT rc = AdjustRect(wnd);
  488.         storevideo(rc, wnd->videosave);
  489.         free(wnd->videosave);
  490.         wnd->videosave = NULL;
  491.     }
  492. }
  493.  
  494. /* ------- compute the logical line length of a window ------ */
  495. int LineLength(char *ln)
  496. {
  497.     int len = strlen(ln);
  498.     char *cp = ln;
  499.     while ((cp = strchr(cp, CHANGECOLOR)) != NULL)    {
  500.         cp++;
  501.         len -= 3;
  502.     }
  503.     cp = ln;
  504.     while ((cp = strchr(cp, RESETCOLOR)) != NULL)    {
  505.         cp++;
  506.         --len;
  507.     }
  508.     return len;
  509. }
  510.  
  511.