home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 10 / c_colu / window.c < prev   
Text File  |  1988-08-30  |  8KB  |  388 lines

  1. /* ----------------------- window.c --------------------- */
  2.  
  3. #include <stdio.h>
  4. #include <alloc.h>
  5. #include <string.h>
  6. #include <conio.h>
  7. #include <mem.h>
  8. #include <dos.h>
  9. #include <stdlib.h>
  10. #include "window.h"
  11.  
  12. /* --------- window border characters ---------------- */
  13. #define NW   '\332'
  14. #define NE   '\277'
  15. #define SE   '\331'
  16. #define SW   '\300'
  17. #define SIDE '\263'
  18. #define LINE '\304'
  19.  
  20. int editing;
  21. static union REGS rg;
  22.  
  23. /* --------- window definition structure ------------ */
  24. struct wn wdo [MAX_WINDOWS];
  25. int curr_wnd;    /* current window */
  26. struct wn wkw;    /* a working window structure */
  27.  
  28. static void upline(void);
  29. static void downline(void);
  30. static void firstline(void);
  31. static void lastline(void);
  32. static void dline(int, int, int);
  33.  
  34. /* ----------- establish a new window -------------- */
  35. void establish_window(left,top,right,bottom,foreg,backg,save)
  36. {
  37.     if (curr_wnd < MAX_WINDOWS)    {
  38.         if (curr_wnd)
  39.             wdo[curr_wnd-1] = wkw;
  40.         setmem(&wkw, sizeof(wkw), 0);
  41.         wkw.lf = left;
  42.         wkw.tp = top;
  43.         wkw.rt = right;
  44.         wkw.bt = bottom;
  45.         wkw.fg = foreg;
  46.         wkw.bg = backg;
  47.         wkw.wd = right+1-left;
  48.         wkw.ht = bottom-top-1;
  49.         if (save)    {
  50.             if ((wkw.wsave=malloc((wkw.ht+2)*wkw.wd*2)) == NULL)
  51.                 return;
  52.             gettext(left, top, right, bottom, wkw.wsave);
  53.         }
  54.         wdo[curr_wnd++] = wkw;
  55.         current_window();
  56.         clear_window();
  57.     }
  58. }
  59.  
  60. /* ------- initialize the working window as current -------- */
  61. void current_window()
  62. {
  63.     window(wkw.lf,wkw.tp,wkw.rt,wkw.bt);
  64.     hidecursor();
  65.     if (wkw.fg || wkw.bg)    {
  66.         textcolor(wkw.fg);
  67.         textbackground(wkw.bg);
  68.      }
  69. }
  70.  
  71. /* ----------- set a window's title -------------- */
  72. void window_title(char *ttl)
  73. {
  74.     writeline((wkw.wd-strlen(ttl)) / 2, 1, ttl);
  75. }
  76.  
  77. /* ------------ remove a window ------------------ */
  78. void delete_window()
  79. {
  80.     if (curr_wnd)    {
  81.         if (wkw.wsave)    {
  82.             puttext(wkw.lf,wkw.tp,wkw.rt,wkw.bt,wkw.wsave);
  83.             free(wkw.wsave);
  84.         }
  85.         setmem(wdo+curr_wnd-1, sizeof (struct wn), 0);
  86.         --curr_wnd;
  87.         if (curr_wnd)    {
  88.             wkw = wdo[curr_wnd-1];
  89.             current_window();
  90.         }
  91.     }
  92. }
  93.  
  94. /* ---- clear the window area and display the border ----- */
  95. void clear_window()
  96. {
  97.     int height, width, y = 1;
  98.     char line1[81], line2[81];
  99.  
  100.     height = wkw.ht;
  101.     width = wkw.wd;
  102.     setmem(line1 + 1, width-1, LINE);
  103.     setmem(line2 + 1, width-1, ' ');
  104.     *line1 = NW;
  105.     line1[width-1] = NE;
  106.     line1[width] = '\0';
  107.     *line2 = SIDE;
  108.     line2[width-1] = SIDE;
  109.     line2[width] = '\0';
  110.     line1[width] = line2[width] = '\0';
  111.     writeline(1, y++, line1);
  112.     while (height--)
  113.         writeline(1, y++, line2);
  114.     *line1 = SW;
  115.     line1[width-1] = SE;
  116.     writeline(1, y, line1);
  117. }
  118.  
  119. /* --------- scroll the window. d: 1 = up, 0 = dn ---------- */
  120. void scroll_window(d)
  121. {
  122.     if (_video.snow == 0)
  123.         movetext(wkw.lf+1, wkw.tp+1+d,
  124.               wkw.rt-1, wkw.bt-2+d,
  125.               wkw.lf+1, wkw.tp+2-d);
  126.     else    {
  127.         rg.h.ah = d ? 6 : 7;
  128.         rg.h.al = 1;
  129.         rg.h.bh = _video.attribute;
  130.         rg.h.cl = wkw.lf;
  131.         rg.h.ch = wkw.tp;
  132.         rg.h.dl = wkw.rt-2;
  133.         rg.h.dh = wkw.bt-2;
  134.         int86(16, &rg, &rg);
  135.     }
  136. }
  137.  
  138. /* ---------- display text in a window --------------- */
  139. void text_window(char *txt[], int ln)
  140. {
  141.     int height = wkw.ht;
  142.  
  143.     wkw.wtext = txt;
  144.     wkw.wtop = ln;
  145.     wkw.wy = 1;
  146.     while (height-- && txt[ln-1])
  147.         dline(ln++, wkw.fg, wkw.bg);
  148.     wkw.wlines = 0;
  149.     while (*txt++)
  150.         wkw.wlines++;
  151. }
  152.  
  153. static int lineno;
  154. /* -------- page and scroll through a window of text -------- */
  155. int
  156. select_window(int ln,int foreg,int backg,int (*func)(int,int))
  157. {
  158.     int c = 0;
  159.     int frtn;
  160.     int height, dln, ptop;
  161.  
  162.     if (ln > wkw.wtop + wkw.ht-1 || ln < wkw.wtop)
  163.         text_window(wkw.wtext, ln);
  164.     else
  165.         wkw.wy = ln - wkw.wtop + 1;
  166.     while (TRUE)    {
  167.         lineno = wkw.wtop + wkw.wy - 1;
  168.         ptop = wkw.wtop;
  169.         dline(lineno, foreg, backg);
  170.         if (wkw.wx == 0)
  171.             hidecursor();
  172.         else
  173.             gotoxy(wkw.wx, wkw.wy+1);
  174.         c = getkey();
  175.         if (c == '\r' || c == ESC)
  176.             break;
  177.         switch (c)    {
  178.             case CTRL_HOME:
  179.                 firstline();
  180.                 break;
  181.             case CTRL_END:
  182.                 lastline();
  183.                 break;
  184.             case PGUP:
  185.                 wkw.wtop -= wkw.ht;
  186.                 if (wkw.wtop < 1)
  187.                     wkw.wtop = 1;
  188.                 break;
  189.             case PGDN:
  190.                 wkw.wtop += wkw.ht;
  191.                 if (wkw.wtop > wkw.wlines - (wkw.ht-1))    {
  192.                     wkw.wtop = wkw.wlines - (wkw.ht-1);
  193.                     if (wkw.wtop < 1)
  194.                         wkw.wtop = 1;
  195.                 }
  196.                 break;
  197.             case UP:
  198.                 upline();
  199.                 break;
  200.             case DN:
  201.                 downline();
  202.                 break;
  203.             default:
  204.                 if (!editing && wkw.wlines <= wkw.ht)    {
  205.                     if (c == HOME)    {
  206.                         firstline();
  207.                         break;
  208.                     }
  209.                     if (c == END)    {
  210.                         lastline();
  211.                         break;
  212.                     }
  213.                 }
  214.                 if (func)    {
  215.                     frtn = (*func)(c, lineno);
  216.                     if (frtn == ERROR)
  217.                         putch(BELL);
  218.                     else if (frtn)    {
  219.                         wkw.wy = frtn;
  220.                         return frtn;
  221.                     }
  222.                     c = 0;
  223.                 }
  224.                 break;
  225.         }
  226.         switch (c)    {
  227.             case HOME:
  228.             case CTRL_HOME:
  229.             case END:
  230.             case CTRL_END:
  231.             case PGUP:
  232.             case PGDN:    if (wkw.wtop != ptop)    {
  233.                             height = wkw.ht;
  234.                             dln = wkw.wtop;
  235.                             while (height-- && wkw.wtext[dln-1])
  236.                                 dline(dln++, wkw.fg, wkw.bg);
  237.                             break;
  238.                         }
  239.             default:    dline(lineno, wkw.fg, wkw.bg);
  240.                         break;
  241.         }
  242.     }
  243.     return c == ESC ? 0 : lineno;
  244. }
  245.  
  246. /* ---------- move up one line --------------- */
  247. static void upline()
  248. {
  249.     if (lineno > 1)    {
  250.         if (wkw.wy == 1)    {
  251.             if (wkw.wtop > 1)    {
  252.                 --wkw.wtop;
  253.                 scroll_window(0);
  254.             }
  255.         }
  256.         else
  257.             --wkw.wy;
  258.     }
  259.     else if (wkw.wlines <= wkw.ht)
  260.         lastline();
  261. }
  262.  
  263. /* ----------- move down one line ------------- */
  264. static void downline()
  265. {
  266.     if (lineno < wkw.wlines)    {
  267.         if (wkw.wy == wkw.ht)    {
  268.             scroll_window(1);
  269.             wkw.wtop++;
  270.         }
  271.         else
  272.             wkw.wy++;
  273.     }
  274.     else if (wkw.wlines <= wkw.ht)
  275.         firstline();
  276. }
  277.  
  278. /* -------- move to the first line --------- */
  279. static void firstline()
  280. {
  281.     wkw.wtop = wkw.wy = 1;
  282. }
  283.  
  284. /* -------- move to the last line --------- */
  285. static void lastline()
  286. {
  287.     wkw.wtop = wkw.wlines - (wkw.ht-1);
  288.     if (wkw.wtop < 1)
  289.         wkw.wtop = 1;
  290.     wkw.wy = wkw.ht;
  291.     if (wkw.wy > wkw.wlines)
  292.         wkw.wy = wkw.wlines;
  293. }
  294.  
  295. char spaces[80] =
  296. "                                                                               ";
  297. /* ------- display a line of text, highlight or normal ------ */
  298. static void dline(ln, foreg, backg)
  299. {
  300.     if (foreg || backg)    {
  301.         textcolor(foreg);
  302.         textbackground(backg);
  303.         --ln;
  304.         writeline(2, ln-wkw.wtop+3, *(wkw.wtext + ln));
  305.         if (strlen(*(wkw.wtext + ln)) < wkw.wd-2)
  306.             writeline(2+strlen(*(wkw.wtext + ln)),
  307.                       ln-wkw.wtop+3,
  308.                       spaces + 79 - wkw.wd +
  309.                       strlen(*(wkw.wtext + ln)) + 2 );
  310.     }
  311. }
  312.  
  313. /* --------- write a line of text to video window ----------- */
  314. void writeline(int x, int y, char *str)
  315. {
  316.     int cl[80], *cp = cl;
  317.  
  318.     while (*str)
  319.         *cp++ = (*str++ & 255) | (_video.attribute << 8);
  320.     __vram(__vptr(x+wkw.lf-1,y+wkw.tp-1),(int far *) cl,
  321.         (unsigned) ((int far *) cp - (int far *) cl));
  322. }
  323.  
  324. /* ------- use BIOS to hide the cursor ---------- */
  325. void hidecursor()
  326. {
  327.     rg.h.ah = 2;
  328.     rg.x.dx = 0x1900;
  329.     rg.h.bh = 0;
  330.     int86(0x10, &rg, &rg);
  331. }
  332.  
  333. /* ----------- use BIOS to set the cursor type -------------- */
  334. void set_cursor_type(unsigned t)
  335. {
  336.     rg.x.ax = 0x0100;
  337.     rg.x.bx = 0;
  338.     rg.x.cx = t;
  339.     int86(0x10, &rg, &rg);
  340. }
  341.  
  342. /* ----------- use BIOS to clear the screen ---------------- */
  343. void clear_screen()
  344. {
  345.     window(1,1,80,25);
  346.     gotoxy(1,1);
  347.     rg.h.al = ' ';
  348.     rg.h.ah = 9;
  349.     rg.x.bx = 7;
  350.     rg.x.cx = 2000;
  351.     int86(0x10, &rg, &rg);
  352. }
  353.  
  354. void (*helpfunc)(void);
  355. int helpkey;
  356.  
  357. /* ------------- read the keyboard ---------------- */
  358. int getkey()
  359. {
  360.     int c;
  361.  
  362.     if ((c = getch()) == 0)
  363.         c = getch() | 128;
  364.     if (c == helpkey && helpfunc)    {
  365.         (*helpfunc)();
  366.         c = getkey();
  367.     }
  368.     return c;
  369. }
  370.  
  371. /* ------- write an error message ------------- */
  372. void error_message(char *ermsg)
  373. {
  374.     int lf = (80-strlen(ermsg)+2)/2;
  375.     int rt = lf+max(strlen(ermsg)+2,15);
  376.     establish_window(lf, 11, rt, 14, ERRORFG, ERRORBG, TRUE);
  377.     gotoxy(2,2);
  378.     cputs(ermsg);
  379.     gotoxy(2,3);
  380.     cputs("(Press [Esc])");
  381.     hidecursor();
  382.     do
  383.         putch(BELL);
  384.     while (getkey() != ESC);
  385.     delete_window();
  386. }
  387.  
  388.