home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / bbs / windkw.arc / WINDOW.C < prev    next >
C/C++ Source or Header  |  1985-11-12  |  19KB  |  741 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, wcls and
  19.  *        use of wn->cx for horizontal scrolling in wrt_txt().
  20.  *
  21.  *    1.2 -    Added oldx, oldy members to wcb structure and use them
  22.  *         in wopen() and wclose().
  23.  *
  24.  */
  25.  
  26. #include    <stdio.h>
  27. #include    "window.h"
  28.  
  29. int    page;        /* Active page number.    */
  30.  
  31. /************************************************************************
  32. * vwrtch(), write a character and attribute to a specific XY location    *
  33. *    on the screen. The attribute is the high byte of the character.    *
  34. ************************************************************************/
  35.  
  36. vwrtch(x, y, c)
  37. int        x, y, c;
  38. {
  39.     gotoxy(x, y, page);
  40.     vputca(c, page, 1);
  41. }
  42.  
  43.  
  44. /************************************************************************
  45. * vrdch(), return the character and attribute at screen XY        *
  46. ************************************************************************/
  47. vrdch(x, y)
  48. int        x, y;
  49. {
  50.     gotoxy(x, y, page);
  51.     return(vgetc(page));
  52. }
  53.  
  54.  
  55. /************************************************************************
  56. * draw_row(), output a row of one character/attribute at XY        *
  57. ************************************************************************/
  58.  
  59. draw_row(x, y, count, c)
  60. int        x, y, count,c;
  61. {
  62.     gotoxy(x, y, page);
  63.     vputca(c, page, count);
  64. }
  65.  
  66. /************************************************************************
  67. * wopen(),     open a window of given size with upper left corner at    *
  68. *        XY. Allocates buffers for the window control block and    *
  69. *        screen save buffers. Copies overwritten screen to the    *
  70. *        buffer. Draws the blank window. Returns the address of    *
  71. *        the window control block or NULL if no buffer space.    *
  72. *    NOTE:    The border attributes are given in the structure     *
  73. *        pointer bord and can be different than the window's    *
  74. *        contents attribute.                    *
  75. ************************************************************************/
  76.  
  77. WINDOW *wopen(wbd, x, y, width, height, attrib)
  78. BORDER *wbd;
  79. int    x, y, width, height, attrib;
  80. {
  81.     WINDOW *wn;
  82.     register int tx, ty, xend, yend;
  83.     int    *tptr, c;
  84.     char    *calloc();
  85.  
  86.     if ((wn = (WINDOW *)calloc(1, sizeof(WINDOW))) == NULL)
  87.         return(NULL);
  88.     else if ((wn->scrnsave = (int *)calloc((width+2) * (height+2),
  89.              sizeof(int))) == NULL)
  90.     {
  91.         free(wn);
  92.         return(NULL);
  93.     }
  94.     else
  95.     {
  96.         /* store parameters in window control block */
  97.  
  98.         wn->xmargin = wn->ymargin = 0;
  99.         wn->ulx = x;
  100.         wn->uly = y;
  101.         wn->xsize = width;
  102.         wn->ysize = height;
  103.         wn->cx = 1;
  104.         wn->cy = 1;
  105.         wn->atrib = attrib;
  106.         wn->oldx = getxy(page) & 255;
  107.         wn->oldy = getxy(page) >> 8;
  108.  
  109.         /* Copy existing text where the window will be placed    */
  110.         /* to the scrnsave buffer. Obviously, a less portable    */
  111.         /* routine could be much faster.            */
  112.  
  113.         tptr = wn->scrnsave;
  114.         xend = x + width + 2;
  115.         yend = y + height + 2;
  116.         for (ty = y; ty < yend; ty++)
  117.         {
  118.             for (tx = x; tx < xend; tx++)
  119.                 *tptr++ = vrdch(tx, ty);
  120.         }
  121.         /* draw the window border and clear the text area    */
  122.  
  123.         vwrtch(x, y, wbd->ul);         /* ul corner*/
  124.         draw_row(x + 1, y, width, wbd->h); /* horiz bar*/
  125.         vwrtch(x + width + 1, y, wbd->ur); /* ur corner*/
  126.  
  127.         yend = y + height;
  128.  
  129.         for (c=wbd->v,ty = y+1; ty <= yend; ty++)
  130.         {
  131.             vwrtch(x, ty, c);   /* draw the sides*/
  132.             vwrtch(x+width+1, ty, c);
  133.         }
  134.  
  135.         vwrtch(x, y + height + 1, wbd->ll);  /* ll corner*/
  136.     /* horiz bar */
  137.         draw_row(x + 1, y + height + 1, width, wbd->h);
  138.     /* lr corner */
  139.         vwrtch(x + width + 1, y + height + 1, wbd->lr);
  140.  
  141.         wcls(wn);
  142.         return(wn);
  143.     }
  144. }
  145.  
  146.  
  147. /************************************************************************
  148. * wclose(), erase the window at the window control block.        *
  149. *    Must be the "top" window if overlapping windows are        *
  150. *    used. "Tiled" windows could be removed randomly.        *
  151. ************************************************************************/
  152.  
  153. wclose(wn)
  154. WINDOW *wn;
  155. {
  156.     register
  157.     int        tx, ty,
  158.             xend, yend;
  159.     int        *tptr;
  160.  
  161.     /* just repaint the saved text at the appropriate location */
  162.  
  163.     tptr = wn->scrnsave;
  164.     xend = wn->ulx + wn->xsize + 2;
  165.     yend = wn->uly + wn->ysize + 2;
  166.  
  167.     for (ty = wn->uly; ty < yend; ty++)
  168.     {
  169.         for (tx = wn->ulx; tx < xend; tx++)
  170.             vwrtch(tx, ty, *tptr++);
  171.     }
  172.  
  173.     /* put cursor back where it was before this rude interruption */
  174.  
  175.     gotoxy(wn->oldx, wn->oldy, page);
  176.  
  177.     /* then release the dynamic storage used */
  178.  
  179.     free(wn->scrnsave);
  180.     free(wn);
  181. }
  182.  
  183.  
  184. /************************************************************************
  185. * wputstr(), print a string inside a window using cx, cy in WCB        *
  186. ************************************************************************/
  187.  
  188. wputstr(wn, string)
  189. register WINDOW *wn;
  190. register char    *string;
  191. {
  192.     int        tcx;
  193.  
  194.     /* Print as much of the string as will fit in the window.    *
  195.      * cx is used for relative left margin. If cx is negative then    *
  196.      * the first cx characters will be removed from the string to    *
  197.      * allow horizontal scrolling in the window.            */
  198.  
  199.     while(*string)
  200.         wputchar(wn, *string++);
  201.     return set_wcxy(wn,0,0);
  202. }
  203.  
  204.  
  205. /************************************************************************
  206. * wputs(), print a string inside a window using cx, cy in WCB.         *
  207. *    Note that the CR, LF, BS, TAB, and DEL keys are processed.    *
  208. ************************************************************************/
  209.  
  210. wputs(wn, string)
  211. register WINDOW *wn;
  212. register char    *string;
  213. {
  214.     while(*string)
  215.         wputch(wn, *string++);
  216.     return wbound(wn);
  217. }
  218.  
  219. /************************************************************************
  220. * wputch(), print a character inside a window using cx, cy in WCB    *
  221. *    while processing for CR, LF, BS, TAB, and DEL.            *
  222. ************************************************************************/
  223.  
  224. wputch(wn, c)
  225. register WINDOW *wn;
  226. char    c;
  227. {
  228.     int rcode;
  229.  
  230.     rcode = 0;
  231.     switch (c) {
  232.         case '\r':    /* Carriage return */
  233.             wn->cx = -wn->xmargin+1;
  234.             break;
  235.         case '\n':    /* Linefeed */
  236.             ++wn->cy;
  237.             break;
  238.         case '\b':    /* Backspace */
  239.             --wn->cx;
  240.             break;
  241.         case 0x7f:    /* Delete */
  242.             if(wn->cx < 1) {    /* If we are left of the */
  243.                 ++wn->cx;    /* window account for the */
  244.                 return;        /* delete. */
  245.             }
  246.             wputch(wn, 0x08);
  247.             wputchar(wn, ' ');
  248.             wputch(wn, 0x08);
  249.             break;
  250.         case 0x09:    /* Tab */
  251.             do
  252.                 wputchar(wn,' ');
  253.             while(wn->cx & 0x07);
  254.             break;
  255.         case 0x0c:    /* Formfeed */
  256.             wcls(wn);
  257.             break;
  258.         default:
  259.             wputchar(wn, c);
  260.             break;
  261.     }
  262.     return set_wcxy(wn,0,0);
  263. }
  264.  
  265. /************************************************************************
  266. * wputchar(), print a character as is where ever the cursor might be     *
  267. *     inside a window using cx, cy in WCB.                *
  268. *    Note that the negitive value of cx is handled and that the    *
  269. *       window is not scrolled.                    *
  270. ************************************************************************/
  271.  
  272. wputchar(wn, c)
  273. register WINDOW *wn;
  274. char    c;
  275. {
  276.     int rcode;
  277.  
  278.     if((rcode = wbound(wn))) {
  279.         ++wn->cx;
  280.         return (rcode);
  281.     }
  282.     gotoxy(wn->ulx + wn->cx++, wn->uly + wn->cy, page);
  283.     vputca(wn->atrib<<8|c, page, 1);
  284.     return(0);
  285. }
  286.  
  287.  
  288. /************************************************************************
  289. * wins_row(), insert a row of blanks by scrolling the lower portion    *
  290. *    of a window down.                        *
  291. *    The current (cy) row is inserted.                *
  292. ************************************************************************/
  293.  
  294. wins_row(wn)
  295. register WINDOW *wn;
  296. {
  297.     int    rcode, scrlwn[4];
  298.  
  299.     /* Don't if we are not in the window. */
  300.     if((rcode = wbound(wn)))
  301.         return(rcode);
  302.  
  303.     /* If it is the last line in the window just delete it. */
  304.     if(wn->cy == wn->ysize)
  305.         draw_row(wn->ulx+1, wn->uly + wn->cy,
  306.              wn->xsize, (wn->atrib <<8) |' ');
  307.     else {            
  308.     /* calculate corners of the scrolling window */
  309.         scrlwn[0] = wn->ulx +1;            /* ulx */
  310.         scrlwn[1] = wn->uly + wn->cy;        /* uly */
  311.         scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  312.         scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  313.  
  314.         scrldn(scrlwn, 1, wn->atrib);
  315.     }
  316.     return(0);
  317. }
  318.  
  319.  
  320. /************************************************************************
  321. * wdel_row(), delete a row by scrolling the lower portion of a window     *
  322. *    up and inserting a row of blanks at the bottom row        *
  323. *    The current (cy) row is deleted.                *
  324. ************************************************************************/
  325.  
  326. wdel_row(wn)
  327. register WINDOW *wn;
  328. {
  329.     int    rcode, scrlwn[4];
  330.  
  331.     /* Don't if we are not in the window. */
  332.     if((rcode = wbound(wn)))
  333.         return(rcode);
  334.  
  335.     if(wn->cy == wn->ysize)
  336.         draw_row(wn->ulx+1, wn->uly + wn->cy,
  337.              wn->xsize, (wn->atrib <<8) |' ');
  338.     else {            
  339.     /* calculate corners of the scrolling window */
  340.         scrlwn[0] = wn->ulx + 1;        /* ulx */
  341.         scrlwn[1] = wn->uly + wn->cy;        /* uly */
  342.         scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  343.         scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  344.  
  345.         scrlup(scrlwn, 1, wn->atrib);
  346.     }
  347.     return(0);
  348. }
  349.  
  350.  
  351. /************************************************************************
  352. * wcls(), clear the "active" part of a window                *
  353. *    and "home" internal text cursor                    *
  354. ************************************************************************/
  355.  
  356. wcls(wn)
  357. register WINDOW *wn;
  358. {
  359.     int        scrlwn[4];
  360.  
  361.     /* calculate corners of the scrolling window */
  362.  
  363.     scrlwn[0] = wn->ulx + 1;            /* ulx */
  364.     scrlwn[1] = wn->uly + 1;            /* uly */
  365.     scrlwn[2] = wn->ulx + wn->xsize;    /* lrx */
  366.     scrlwn[3] = wn->uly + wn->ysize;    /* lry */
  367.  
  368.     scrlup(scrlwn, 0, wn->atrib);
  369.     wn->cx = 1;
  370.     wn->cy = 1;
  371. }
  372.  
  373. /************************************************************************
  374. * wceol(), clear to end of the line of the window.            *
  375. ************************************************************************/
  376.  
  377. wceol(wn)
  378. register WINDOW *wn;
  379. {
  380.     register int tx, ty;
  381.  
  382.     if((tx=wbound(wn)))
  383.         return(tx);
  384.     tx = wn->ulx + wn->cx;
  385.     ty = wn->uly + wn->cy;
  386.     draw_row(tx, ty, wn->xsize-wn->cx+1, (wn->atrib <<8) |' ');
  387.     gotoxy(tx, ty, page);
  388.     return(0);
  389. }
  390.  
  391. /************************************************************************
  392. * wcursor(), cursor controls for a window.                *
  393. ************************************************************************/
  394.  
  395. wcursor(wn,c)
  396. register WINDOW *wn;
  397. {
  398.     register int tcx, n, tx, ty;
  399.  
  400.     switch (c) {
  401.         case CUR_UP:    /* Cursor up */
  402.             --wn->cy;
  403.             break;
  404.         case CUR_DWN:    /* Cursor down */
  405.             ++wn->cy;
  406.             break;
  407.         case CUR_LEFT:    /* Cursor left */
  408.             --wn->cx;
  409.             break;
  410.         case CUR_RIGHT:    /* Cursor right */
  411.             ++wn->cx;
  412.             break;
  413.         case HOME:    /* Home cursor */
  414.             return set_wcxy(wn,1,1);
  415.         case END:    /* End cursor */
  416.             return set_wcxy(wn,1, wn->ysize);
  417.         default:
  418.             return(-1);
  419.     }
  420.     if(wn->cx <1) {
  421.         wn->cx = wn->xsize;
  422.     } else if(wn->cx > wn->xsize)
  423.         wn->cx = 1;
  424.     if(wn->cy <1)
  425.         wn->cy = wn->ysize;
  426.     else if(wn->cy > wn->ysize)
  427.         wn->cy = 1;
  428.     return set_wcxy(wn, wn->cx, wn->cy);
  429. }
  430.  
  431.  
  432. /************************************************************************
  433. * wdelch(), Deletes a character at the current window cursor position.    *
  434. ************************************************************************/
  435.  
  436. wdelch(wn)
  437. register WINDOW *wn;
  438. {
  439.     register int tx, ty, xend, rcode;
  440.  
  441.     /* Don't if we are not in the window. */
  442.     if((rcode = wbound(wn))) {
  443.         --wn->cx;
  444.         return(rcode);
  445.     }
  446.  
  447.     tx = wn->cx + wn->ulx;
  448.     ty = wn->cy + wn->uly;
  449.     xend = wn->ulx + wn->xsize;
  450.  
  451.     for(; tx < xend; ++tx)
  452.         vwrtch(tx, ty, vrdch(tx+1,ty));
  453.     vwrtch(tx, ty, wn->atrib<<8 | ' ');
  454.  
  455.     return set_wcxy(wn, 0, 0);
  456. }
  457.  
  458.  
  459. /************************************************************************
  460. * winsch(), Inserts a character at the current window cursor position.    *
  461. ************************************************************************/
  462.  
  463. winsch(wn,c)
  464. register WINDOW *wn;
  465. int c;
  466. {
  467.     int tcx, tcy;
  468.     register int tx, ty, n, rcode, xend;
  469.  
  470.     /* Don't if we are not in the window. */
  471.     if((rcode = wbound(wn))) {
  472.         ++wn->cx;
  473.         return(rcode);
  474.     }
  475.     tcx = wn->cx;
  476.     tcy = wn->cy;
  477.     tx = wn->cx + wn->ulx;
  478.     ty = wn->cy + wn->uly;
  479.     switch (c) {
  480.         case '\n':
  481.             if(wn->cy == wn->ysize) {
  482.                 wscroll(wn);
  483.                 if(wn->cy >1)
  484.                     --ty;
  485.             } else {
  486.                 ++wn->cy;
  487.                 ++tcy;
  488.                 wins_row(wn);
  489.             }
  490.             for( ; wn->cx <= wn->xsize;) {
  491.                 wputchar(wn, (n=vrdch(tx,ty)));
  492.                 vwrtch(tx++, ty, (n&0xff00)|' ');
  493.             }
  494.             break;
  495.         case '\b':
  496.             --tcx;
  497.             if(wn->cy == 1 && wn->cx ==1)
  498.                 break;
  499.             n=vrdch(tx,ty);
  500.             wputch(wn,c);
  501.             wputchar(wn,n);
  502.             wdelch(wn);
  503.             return set_wcxy(wn,-1,0);
  504.         case '\r':
  505.              return wputch(wn, c);
  506.         case 0x09:    /* Tab */
  507.             do
  508.                 winsch(wn,' ');
  509.             while(wn->cx & 0x07);
  510.             break;
  511.         default:
  512.             c |= (wn->atrib<<8);
  513.             if(wn->cx == wn->xsize) {
  514.                 vwrtch(tx,ty,c);
  515.                 ++tcx;
  516.                 break;
  517.             }
  518.             xend = wn->ulx + wn->xsize;
  519.             for( ; tx < xend; c=n) {
  520.                 n=vrdch(tx++,ty);
  521.                 vputca(c, page, 1);
  522.             }
  523.             ++tcx;
  524.             break;
  525.     }
  526.     return set_wcxy(wn, tcx, tcy);
  527. }
  528.  
  529. /************************************************************************
  530. * wgets(), Gets a string of characters at the current  window cursor    *
  531. *    position.  The number of characters to obtain cnt or reaching    *
  532. *    the end of the window terminates the function.  The number of    *
  533. *    charaters retrived is returned.                    * 
  534. ************************************************************************/
  535.  
  536. wgets(wn,s,cnt)
  537. register WINDOW *wn;
  538. char *s;        /* Where to place the null terminated string.    */
  539. int cnt;        /* Number of character to retrive.         */
  540. {
  541.     int xend; register int tx, ty, n;
  542.  
  543.     if(wbound(wn))
  544.         return(0);
  545.     tx = wn->ulx + wn->cx;
  546.     ty = wn->uly + wn->cy;
  547.     xend = wn->ulx + wn->xsize +1;
  548.     for(n=0; cnt-- && tx < xend; ++n)
  549.         *s++ = vrdch(tx++, ty);
  550.     *s = 0;
  551.     return(n);
  552. }
  553.  
  554. /************************************************************************
  555. * wscroll(), Scrolls the window up one line.                *
  556. ************************************************************************/
  557.  
  558. wscroll(wn)
  559. register WINDOW *wn;
  560. {
  561.     int tcy;
  562.     
  563.     tcy = wn->cy;
  564.     wn->cy =1;
  565.     wdel_row(wn);
  566.     wn->cy = tcy;
  567. }
  568.  
  569. /************************************************************************
  570. * wbound(), Check to see if cursor is within the window.        *
  571. *    Returns a code indicating whether the cursor is in the window.  *
  572. ************************************************************************/
  573.  
  574. wbound(wn)
  575. register WINDOW *wn;
  576. {
  577.     register int rcode;
  578.  
  579.     rcode =0;
  580.     if(wn->cx <1)
  581.         rcode = LEFT_OF;
  582.     else if(wn->cx > wn->xsize)
  583.         rcode = RIGHT_OF;
  584.     if(wn->cy <1)
  585.         rcode |= TOP_OF;
  586.     else if(wn->cy > wn->ysize)
  587.         rcode |= BOTTOM_OF;
  588.     return(rcode);
  589. }
  590.  
  591.  
  592. /************************************************************************
  593. * wgetch(), Returns the character at window cursor location or the    *
  594. *    boundry code if the location is not within the window.        *
  595. ************************************************************************/
  596.  
  597. wgetch(wn)
  598. register WINDOW *wn;
  599. {
  600.     int rcode;
  601.  
  602.     if((rcode=wbound(wn)))
  603.         return (rcode);
  604.     return (vrdch(wn->ulx + wn->cx, wn->uly + wn->cy) &0xff);
  605. }
  606.  
  607. /************************************************************************
  608. * set_wcxy(), Sets the relative window cursor to the give x,y location. *
  609. *    If either x or y is zero the cursor is moved in the given axis  *
  610. *     the number of spaces given, where positive x is to the right     *
  611. *    and positive y is down.                        *
  612. *    Note that the home position for a window is 1,1.        *
  613. ************************************************************************/
  614.  
  615. set_wcxy(wn,x,y)
  616. register WINDOW *wn;
  617. int x,y;
  618. {
  619.     if(x && y) {
  620.         wn->cx = x;
  621.         wn->cy = y;
  622.     } else {
  623.         if(!x && y)
  624.             wn->cy += y;
  625.         if(!y && x)
  626.             wn->cx += x;
  627.     }
  628.     gotoxy(wn->ulx + wn->cx, wn->uly + wn->cy, page);
  629.     return wbound(wn);
  630. }
  631.  
  632.  
  633. /************************************************************************
  634. * get_wcxy(), Gets the relative window cursor.                *
  635. *    x = get_wcur() & 0xff, and y = get_wcur() >> 8            *
  636. *    Note that the home position for a window is 1,1.        *
  637. ************************************************************************/
  638.  
  639. get_wcxy(wn)
  640. register WINDOW *wn;
  641. {
  642.     return((wn->cy << 8) | wn->cx);
  643. }
  644.  
  645. /************************************************************************
  646. * set_cxy(), Sets the screen cursor to the give x,y location.         *
  647. *    Note that the home position is 0,0.                *
  648. ************************************************************************/
  649.  
  650. set_cxy(x,y)
  651. register int x,y;
  652. {
  653.     if(!x || !y) {
  654.         if(!x && y)
  655.             y += (getxy(page)>>8);
  656.         if(!y && x)
  657.             x += (getxy(page) & 0xff);
  658.     }
  659.     gotoxy(x,y,page);
  660. }
  661.  
  662.  
  663. /************************************************************************
  664. * get_cxy(), Gets the screen cursor location of page 0.            *
  665. *    x = get_wcur() & 0xff, and y = get_wcur() >> 8            *
  666. *    Note that the home position is 0,0.                *
  667. ************************************************************************/
  668.  
  669. get_cxy()
  670. {
  671.     return(getxy(page));
  672. }
  673.  
  674. /************************************************************************
  675. * get_page(), Gets the current video page being used.
  676. ************************************************************************/
  677.  
  678. get_page()
  679. {
  680.     return (page);
  681. }
  682.  
  683. /************************************************************************
  684. * set_page(), Sets the active video page and udates page.        *
  685. ************************************************************************/
  686.  
  687. set_page(n)
  688. char n;
  689. {
  690.     switch (get_mode()) {
  691.         case 0:
  692.         case 1:
  693.             if(n > 7)
  694.                 return(-1);
  695.             break;
  696.         case 2:
  697.         case 3:
  698.             if(n > 3)
  699.                 return(-1);
  700.             break;
  701.         case 7:
  702.             if(n > 1)
  703.                 return(-1);
  704.             break;
  705.         default:
  706.             return(-1);
  707.     }
  708.     vsetpage(n);
  709.     page = n;
  710.     return(n);
  711. }
  712.  
  713. /************************************************************************
  714. * wprintf(), Works like printf for a window.                *
  715. ************************************************************************/
  716.  
  717. wprintf(wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
  718. WINDOW *wn;
  719. char *cs;
  720. {
  721.     static buf[256];
  722.  
  723.     sprintf(buf,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
  724.     return wputs(wn,buf);
  725. }
  726.  
  727.  
  728. /************************************************************************
  729. * wprinta(), Works like wprintf with the addtion of the x,y        *
  730. *    position.                            *
  731. ************************************************************************/
  732.  
  733. wprinta(x,y,wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
  734. int x,y;
  735. WINDOW *wn;
  736. char *cs;
  737. {
  738.     set_wcxy(wn,x,y);
  739.     return wprintf(wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
  740. }
  741.