home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / window.c < prev   
Text File  |  1991-06-28  |  17KB  |  571 lines

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