home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / graphics / windsmet.arc / WINDOW.C < prev    next >
Text File  |  1985-08-04  |  9KB  |  308 lines

  1. /*    module:        window.c
  2.  *    programmer:    Ray L. McVay
  3.  *    started:    1 Aug 84
  4.  *    version:    1.2, 23 Aug 84
  5.  *
  6.  *    A simple window package based on the article and programs
  7.  *    by Edward Mitchell in the Jan 84 Dr. Dobb's Journal.  This
  8.  *    implementation uses dynamically allocated buffers for the
  9.  *    window control blocks and screen save buffers.
  10.  *
  11.  *    An assembly language support library called VLIB is used to
  12.  *    interface the DeSmet C compiler with the IBM ROM BIOS video
  13.  *    routines.  VLIB will undoubtedly have to be rewritten if the
  14.  *    window package is to be used with other compilers.
  15.  *
  16.  *    History -
  17.  *
  18.  *    1.1    -    Added style member to wcb structure, clr_window() and
  19.  *            use of wn->cx for horizontal scrolling in write_text().
  20.  *
  21.  *    1.2 -    Added oldx, oldy members to wcb structure and use them
  22.  *            in draw_window() and remove_window().
  23.  *
  24.  */
  25.  
  26. #include    <stdio.h>
  27.  
  28. typedef struct wcb    /* --- window control block    ---        */
  29. {
  30.     int        ulx,    /* upper left corner x coordinate    */
  31.             uly,    /* ditto y coordinate                */
  32.             xsize,    /* line width of inside of window    */
  33.             ysize,    /* number of lines inside of window    */
  34.             cx,        /* current cursor offset in window    */
  35.             cy,
  36.             style,    /* attribute to be used in window    */
  37.             *scrnsave,    /* pointer to screen save buffer */
  38.             oldx,    /* cursor position when window was    */
  39.             oldy;    /* opened (used for screen restore)    */
  40. } WINDOW, *WINDOWPTR;
  41.  
  42.  
  43. /************************************************************************
  44. * putch(), write a character and attribute to a specific XY location on *
  45. *           the screen. The attribute is the high byte of the character.    *
  46. ************************************************************************/
  47.  
  48. putch(x, y, c)
  49. int        x, y, c;
  50. {
  51.     gotoxy(x, y, 0);
  52.     vputca(c, 0, 1);
  53. }
  54.  
  55.  
  56. /************************************************************************
  57. * getch(), return the character and attribute at screen XY                *
  58. ************************************************************************/
  59.  
  60. getch(x, y)
  61. int        x, y;
  62. {
  63.     gotoxy(x, y, 0);
  64.     return(vgetc(0));
  65. }
  66.  
  67.  
  68. /************************************************************************
  69. * draw_row(), output a row of one character/attribute at XY                *
  70. ************************************************************************/
  71.  
  72. draw_row(x, y, count, c)
  73. int        x, y, count,c;
  74. {
  75.     gotoxy(x, y, 0);
  76.     vputca(c, 0, count);
  77. }
  78.  
  79.  
  80. /************************************************************************
  81. * draw_window(), open a window of given size with upper left corner at    *
  82. *                 XY. Allocates buffers for the window control block and *
  83. *                 screen save buffers. Copies overwritten screen to the    *
  84. *                 buffer. Draws the blank window. Returns the address of    *
  85. *                 the window control block or NULL if no buffer space.    *
  86. ************************************************************************/
  87.  
  88. WINDOWPTR draw_window(x, y, width, height, attrib)
  89. int        x, y, width, height, attrib;
  90. {
  91.     WINDOWPTR wn;
  92.     int        tx, ty,
  93.             xend, yend;
  94.     int        *tptr;
  95.     char    *calloc();
  96.  
  97.     if ((wn = (WINDOWPTR)calloc(1, sizeof(WINDOW))) == NULL)
  98.         return(NULL);
  99.     else if ((wn->scrnsave = (int *)calloc((width+2) * (height+2), sizeof(int))) == NULL)
  100.     {
  101.         free(wn);
  102.         return(NULL);
  103.     }
  104.     else
  105.     {
  106.         /* store parameters in window control block */
  107.  
  108.         wn->ulx = x;
  109.         wn->uly = y;
  110.         wn->xsize = width;
  111.         wn->ysize = height;
  112.         wn->cx = 1;
  113.         wn->cy = 1;
  114.         wn->style = attrib;
  115.         attrib <<= 8;    /* will make things below go quicker */
  116.         wn->oldx = getxy(0) & 255;
  117.         wn->oldy = getxy(0) >> 8;
  118.  
  119.         /* Copy existing text where the window will be placed */
  120.         /* to the scrnsave buffer. Obviously, a less portable */
  121.         /* routine could be much faster.                      */
  122.  
  123.         tptr = wn->scrnsave;
  124.         xend = x + width + 2;
  125.         yend = y + height + 2;
  126.  
  127.         for (ty = y; ty < yend; ty++)
  128.         {
  129.             for (tx = x; tx < xend; tx++)
  130.                 *tptr++ = getch(tx, ty);
  131.         }
  132.  
  133.         /* draw the window border and clear the text area */
  134.  
  135.         putch(x, y, 0xda + attrib);                    /* ul corner */
  136.         draw_row(x + 1, y, width, 0xc4 + attrib);    /* horiz bar */
  137.         putch(x + width + 1, y, 0xbf + attrib);        /* ur corner */
  138.  
  139.         yend = y + height;
  140.  
  141.         for (ty = y+1; ty <= yend; ty++)
  142.         {
  143.             putch(x, ty, 0xb3 + attrib);            /* draw the sides */
  144.             putch(x+width+1, ty, 0xb3 + attrib);
  145.         }
  146.  
  147.         putch(x, y + height + 1, 0xc0 + attrib);                /* ll corner */
  148.         draw_row(x + 1, y + height + 1, width, 0xc4 + attrib);    /* horiz bar */
  149.         putch(x + width + 1, y + height + 1, 0xd9 + attrib);    /* lr corner */
  150.  
  151.         clr_window(wn);
  152.  
  153.         return(wn);
  154.     }
  155. }
  156.  
  157.  
  158. /************************************************************************
  159. * remove_window(), erase the window at the window control block.        *
  160. *                   Must be the "top" window if overlapping windows are  *
  161. *                   used. "Tiled" windows could be removed randomly.        *
  162. ************************************************************************/
  163.  
  164. remove_window(wn)
  165. WINDOWPTR wn;
  166. {
  167.     int        tx, ty,
  168.             xend, yend;
  169.     int        *tptr;
  170.  
  171.     /* just repaint the saved text at the appropriate location */
  172.  
  173.     tptr = wn->scrnsave;
  174.     xend = wn->ulx + wn->xsize + 2;
  175.     yend = wn->uly + wn->ysize + 2;
  176.  
  177.     for (ty = wn->uly; ty < yend; ty++)
  178.     {
  179.         for (tx = wn->ulx; tx < xend; tx++)
  180.             putch(tx, ty, *tptr++);
  181.     }
  182.  
  183.     /* put cursor back where it was before this rude interruption */
  184.  
  185.     gotoxy(wn->oldx, wn->oldy, 0);
  186.  
  187.     /* then release the dynamic storage used */
  188.  
  189.     free(wn->scrnsave);
  190.     free(wn);
  191. }
  192.  
  193.  
  194. /************************************************************************
  195. * write_text(), print a string inside a window using cx, cy in WCB        *
  196. ************************************************************************/
  197.  
  198. write_text(wn, string)
  199. WINDOWPTR wn;
  200. char    *string;
  201. {
  202.     int        tx, ty, xend;
  203.  
  204.     /* first check to see if we're at the bottom of the window        */
  205.     /* if we are then scroll the contents of the window up            */
  206.  
  207.     if (wn->cy > wn->ysize)
  208.     {
  209.         delete_row(wn, 1);
  210.         --wn->cy;
  211.     }
  212.  
  213.     /* Print as much of the string as will fit in the window.        *
  214.      * cx is used for relative left margin. If cx is negative then    *
  215.      * the first cx characters will be removed from the string to    *
  216.      * allow horizontal scrolling in the window.                    *
  217.      * NOTE: This obviously simple-minded technique is usable for    *
  218.      *          displaying predetermined messages but a more general    *
  219.      *         console output intercept should be used for Star-like    *
  220.      *         environments.                                            */
  221.  
  222.     if (wn->cx > 0)
  223.         tx = wn->ulx + wn->cx;
  224.     else
  225.     {
  226.         if (-wn->cx < strlen(string))
  227.             string -= wn->cx;
  228.         else
  229.             *string = '\0';
  230.         tx = wn->ulx + 1;
  231.     }
  232.     xend = wn->ulx + wn->xsize + 1;
  233.     ty = wn->uly + wn->cy;
  234.     while ((tx < xend) && *string)
  235.     {
  236.         gotoxy(tx++, ty, 0);
  237.         vputc(*string++, 0, 1);
  238.     }
  239.     ++wn->cy;        /* move the internal cursor to the next line */
  240. }
  241.  
  242.  
  243. /************************************************************************
  244. * insert_row(), insert a row of blanks by scrolling the lower portion    *
  245. *                of a window down                                        *
  246. ************************************************************************/
  247.  
  248. insert_row(wn, row)
  249. WINDOWPTR wn;
  250. int        row;
  251. {
  252.     int        scrlwn[4];
  253.  
  254.     /* calculate corners of the scrolling window */
  255.  
  256.     scrlwn[0] = wn->ulx + 1;            /* ulx */
  257.     scrlwn[1] = wn->uly + row;            /* uly */
  258.     scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  259.     scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  260.  
  261.     scrldn(scrlwn, 1, wn->style);
  262. }
  263.  
  264.  
  265. /************************************************************************
  266. * delete_row(), delete a row by scrolling the lower portion of a window *
  267. *                up and inserting a row of blanks at the bottom row        *
  268. ************************************************************************/
  269.  
  270. delete_row(wn, row)
  271. WINDOWPTR wn;
  272. int        row;
  273. {
  274.     int        scrlwn[4];
  275.  
  276.     /* calculate corners of the scrolling window */
  277.  
  278.     scrlwn[0] = wn->ulx + 1;            /* ulx */
  279.     scrlwn[1] = wn->uly + row;            /* uly */
  280.     scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  281.     scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  282.  
  283.     scrlup(scrlwn, 1, wn->style);
  284. }
  285.  
  286.  
  287. /************************************************************************
  288. * clr_window(), clear the "active" part of a window    and "home" internal    *
  289. *                text cursor                                                *
  290. ************************************************************************/
  291.  
  292. clr_window(wn)
  293. WINDOWPTR wn;
  294. {
  295.     int        scrlwn[4];
  296.  
  297.     /* calculate corners of the scrolling window */
  298.  
  299.     scrlwn[0] = wn->ulx + 1;            /* ulx */
  300.     scrlwn[1] = wn->uly + 1;            /* uly */
  301.     scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  302.     scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  303.  
  304.     scrlup(scrlwn, 0, wn->style);
  305.     wn->cx = 1;
  306.     wn->cy = 1;
  307. }
  308.