home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 09 / stevens.lis < prev    next >
File List  |  1988-08-22  |  12KB  |  502 lines

  1.  
  2. _C PROGRAMMING_
  3. by
  4. Al Stevens
  5.  
  6. Listing One 
  7.  
  8. /* ---------- window.h ----------- */
  9.  
  10. void establish_window(int,int,int,int,int,int,int);
  11. void window_title(char *);
  12. void clear_window(void);
  13. void delete_window(void);
  14. void scroll_window(int);
  15. void text_window(char **, int);
  16. int select_window(int, int, int, int (*func)(int,int));
  17. int getkey(void);
  18. void hidecursor(void);
  19. void set_cursor_type(unsigned);
  20. void clear_screen(void);
  21. void writeline(int, int, char *);
  22. void current_window(void);
  23. void error_message(char *);
  24.  
  25. #define MAX_WINDOWS 10      /* maximum windows open at once */
  26.  
  27. #define TRUE        1
  28. #define FALSE       0
  29. #define ERROR      -1
  30.  
  31. #define BELL        7
  32. #define ESC        27
  33. #define SHIFT_HT  143
  34. #define CTRL_T     20
  35. #define CTRL_B      2
  36. #define CTRL_D      4
  37. #define ALT_D     160
  38. #define ALT_F     161
  39. #define ALT_E     146
  40. #define ALT_O     152
  41. #define ALT_S     159
  42.  
  43. #define F1        187
  44. #define F2        188
  45. #define F3        189
  46. #define F4        190
  47. #define F5        191
  48. #define F6        192
  49. #define F7        193
  50. #define F8        194
  51. #define F9        195
  52. #define F10       196
  53. #define ALT_F7    238
  54.  
  55. #define HOME      199
  56. #define UP        200
  57. #define PGUP      201
  58. #define BS        203
  59. #define FWD       205
  60. #define END       207
  61. #define DN        208
  62. #define PGDN      209
  63. #define INS       210
  64. #define DEL       211
  65.  
  66. #define CTRL_HOME 247
  67. #define CTRL_BS   243
  68. #define CTRL_FWD  244
  69. #define CTRL_END  245
  70.  
  71. /* --------- window definition structure ------------ */
  72. struct wn {
  73.     int lf,tp,rt,bt;        /* window position */
  74.     int ht,wd;              /* window dimensions */
  75.     int wx, wy;             /* window cursor */
  76.     int wtop;               /* top text line */
  77.     int wlines;             /* total text lines */
  78.     int fg,bg;              /* window colors */
  79.     char *wsave;            /* video memory save buffer */
  80.     char **wtext;           /* pointer to text */
  81. };
  82.  
  83. /* ------ internal Turbo C stuff ------- */
  84. void far * pascal __vptr(int, int);
  85. void pascal __vram(void far *, void far *, int);
  86. extern struct {
  87.     char filler1[4];
  88.     char attribute;
  89.     char filler2[5];
  90.     char snow;
  91. } _video;
  92.  
  93. /* ------------ window colors --------------- */
  94. #define TEXTFG  WHITE    /* data display screen */
  95. #define TEXTBG  BLACK
  96. #define BLOCKFG BLACK    /* data blocks */
  97. #define BLOCKBG WHITE
  98. #define HELPBG  WHITE    /* help windows */
  99. #define HELPFG  BLACK
  100. #define MENUBG  WHITE    /* menus */
  101. #define MENUFG  BLACK
  102. #define SELECTBG BLACK    /* menu selector bars */
  103. #define SELECTFG WHITE
  104. #define ENTRYFG WHITE     /* data entry windows */
  105. #define ENTRYBG BLACK
  106. #define FIELDFG BLACK     /* data entry fields  */
  107. #define FIELDBG WHITE
  108. #define ERRORFG BLACK    /* error messages */
  109. #define ERRORBG WHITE
  110.  
  111.  
  112.  
  113. Listing Two 
  114.  
  115. /* ----------------------- window.c --------------------- */
  116.  
  117. #include <stdio.h>
  118. #include <alloc.h>
  119. #include <string.h>
  120. #include <conio.h>
  121. #include <mem.h>
  122. #include <dos.h>
  123. #include <stdlib.h>
  124. #include "window.h"
  125.  
  126. /* --------- window border characters ---------------- */
  127. #define NW   '\332'
  128. #define NE   '\277'
  129. #define SE   '\331'
  130. #define SW   '\300'
  131. #define SIDE '\263'
  132. #define LINE '\304'
  133.  
  134. int editing;
  135. static union REGS rg;
  136.  
  137. /* --------- window definition structure ------------ */
  138. struct wn wdo [MAX_WINDOWS];
  139. int curr_wnd;   /* current window */
  140. struct wn wkw;   /* a working window structure */
  141.  
  142. static void upline(void);
  143. static void downline(void);
  144. static void firstline(void);
  145. static void lastline(void);
  146. static void dline(int, int, int);
  147.  
  148. /* ----------- establish a new window -------------- */
  149. void establish_window(left,top,right,bottom,foreg,backg,save)
  150. {
  151.    if (curr_wnd < MAX_WINDOWS)   {
  152.       if (curr_wnd)
  153.          wdo[curr_wnd-1] = wkw;
  154.       setmem(&wkw, sizeof(wkw), 0);
  155.       wkw.lf = left;
  156.       wkw.tp = top;
  157.       wkw.rt = right;
  158.       wkw.bt = bottom;
  159.       wkw.fg = foreg;
  160.       wkw.bg = backg;
  161.       wkw.wd = right+1-left;
  162.       wkw.ht = bottom-top-1;
  163.       if (save)   {
  164.          if ((wkw.wsave=malloc((wkw.ht+2)*wkw.wd*2)) == NULL)
  165.             return;
  166.          gettext(left, top, right, bottom, wkw.wsave);
  167.       }
  168.       wdo[curr_wnd++] = wkw;
  169.       current_window();
  170.       clear_window();
  171.    }
  172. }
  173.  
  174. /* ------- initialize the working window as current -------- */
  175. void current_window()
  176. {
  177.    window(wkw.lf,wkw.tp,wkw.rt,wkw.bt);
  178.    hidecursor();
  179.    if (wkw.fg || wkw.bg)   {
  180.       textcolor(wkw.fg);
  181.       textbackground(wkw.bg);
  182.     }
  183. }
  184.  
  185. /* ----------- set a window's title -------------- */
  186. void window_title(char *ttl)
  187. {
  188.    writeline((wkw.wd-strlen(ttl)) / 2, 1, ttl);
  189. }
  190.  
  191. /* ------------ remove a window ------------------ */
  192. void delete_window()
  193. {
  194.    if (curr_wnd)   {
  195.       if (wkw.wsave)   {
  196.          puttext(wkw.lf,wkw.tp,wkw.rt,wkw.bt,wkw.wsave);
  197.          free(wkw.wsave);
  198.       }
  199.       setmem(wdo+curr_wnd-1, sizeof (struct wn), 0);
  200.       --curr_wnd;
  201.       if (curr_wnd)   {
  202.          wkw = wdo[curr_wnd-1];
  203.          current_window();
  204.       }
  205.    }
  206. }
  207.  
  208. /* ---- clear the window area and display the border ----- */
  209. void clear_window()
  210. {
  211.    int height, width, y = 1;
  212.    char line1[81], line2[81];
  213.  
  214.    height = wkw.ht;
  215.    width = wkw.wd;
  216.    setmem(line1 + 1, width-1, LINE);
  217.    setmem(line2 + 1, width-1, ' ');
  218.    *line1 = NW;
  219.    line1[width-1] = NE;
  220.    line1[width] = '\0';
  221.    *line2 = SIDE;
  222.    line2[width-1] = SIDE;
  223.    line2[width] = '\0';
  224.    line1[width] = line2[width] = '\0';
  225.    writeline(1, y++, line1);
  226.    while (height--)
  227.       writeline(1, y++, line2);
  228.    *line1 = SW;
  229.    line1[width-1] = SE;
  230.    writeline(1, y, line1);
  231. }
  232.  
  233. /* --------- scroll the window. d: 1 = up, 0 = dn ---------- */
  234. void scroll_window(d)
  235. {
  236.    if (_video.snow == 0)
  237.       movetext(wkw.lf+1, wkw.tp+1+d,
  238.            wkw.rt-1, wkw.bt-2+d,
  239.            wkw.lf+1, wkw.tp+2-d);
  240.    else   {
  241.       rg.h.ah = d ? 6 : 7;
  242.       rg.h.al = 1;
  243.       rg.h.bh = _video.attribute;
  244.       rg.h.cl = wkw.lf;
  245.       rg.h.ch = wkw.tp;
  246.       rg.h.dl = wkw.rt-2;
  247.       rg.h.dh = wkw.bt-2;
  248.       int86(16, &rg, &rg);
  249.    }
  250. }
  251.  
  252. /* ---------- display text in a window --------------- */
  253. void text_window(char *txt[], int ln)
  254. {
  255.    int height = wkw.ht;
  256.  
  257.    wkw.wtext = txt;
  258.    wkw.wtop = ln;
  259.    wkw.wy = 1;
  260.    while (height-- && txt[ln-1])
  261.       dline(ln++, wkw.fg, wkw.bg);
  262.    wkw.wlines = 0;
  263.    while (*txt++)
  264.       wkw.wlines++;
  265. }
  266.  
  267. static int lineno;
  268. /* -------- page and scroll through a window of text -------- */
  269. int
  270. select_window(int ln,int foreg,int backg,int (*func)(int,int))
  271. {
  272.    int c = 0;
  273.    int frtn;
  274.    int height, dln, ptop;
  275.  
  276.    if (ln > wkw.wtop + wkw.ht-1 || ln < wkw.wtop)
  277.       text_window(wkw.wtext, ln);
  278.    else
  279.       wkw.wy = ln - wkw.wtop + 1;
  280.    while (TRUE)   {
  281.       lineno = wkw.wtop + wkw.wy - 1;
  282.       ptop = wkw.wtop;
  283.       dline(lineno, foreg, backg);
  284.       if (wkw.wx == 0)
  285.          hidecursor();
  286.       else
  287.          gotoxy(wkw.wx, wkw.wy+1);
  288.       c = getkey();
  289.       if (c == '\r' || c == ESC)
  290.          break;
  291.       switch (c)   {
  292.          case CTRL_HOME:
  293.             firstline();
  294.             break;
  295.          case CTRL_END:
  296.             lastline();
  297.             break;
  298.          case PGUP:
  299.             wkw.wtop -= wkw.ht;
  300.             if (wkw.wtop < 1)
  301.                wkw.wtop = 1;
  302.             break;
  303.          case PGDN:
  304.             wkw.wtop += wkw.ht;
  305.             if (wkw.wtop > wkw.wlines - (wkw.ht-1))   {
  306.                wkw.wtop = wkw.wlines - (wkw.ht-1);
  307.                if (wkw.wtop < 1)
  308.                   wkw.wtop = 1;
  309.             }
  310.             break;
  311.          case UP:
  312.             upline();
  313.             break;
  314.          case DN:
  315.             downline();
  316.             break;
  317.          default:
  318.             if (!editing && wkw.wlines <= wkw.ht)   {
  319.                if (c == HOME)   {
  320.                   firstline();
  321.                   break;
  322.                }
  323.                if (c == END)   {
  324.                   lastline();
  325.                   break;
  326.                }
  327.             }
  328.             if (func)   {
  329.                frtn = (*func)(c, lineno);
  330.                if (frtn == ERROR)
  331.                   putch(BELL);
  332.                else if (frtn)   {
  333.                   wkw.wy = frtn;
  334.                   return frtn;
  335.                }
  336.                c = 0;
  337.             }
  338.             break;
  339.       }
  340.       switch (c)   {
  341.          case HOME:
  342.          case CTRL_HOME:
  343.          case END:
  344.          case CTRL_END:
  345.          case PGUP:
  346.          case PGDN:  if (wkw.wtop != ptop)   {
  347.                      height = wkw.ht;
  348.                      dln = wkw.wtop;
  349.                      while (height-- && wkw.wtext[dln-1])
  350.                         dline(dln++, wkw.fg, wkw.bg);
  351.                      break;
  352.                   }
  353.          default:    dline(lineno, wkw.fg, wkw.bg);
  354.                      break;
  355.       }
  356.    }
  357.    return c == ESC ? 0 : lineno;
  358. }
  359.  
  360. /* ---------- move up one line --------------- */
  361. static void upline()
  362. {
  363.    if (lineno > 1)   {
  364.       if (wkw.wy == 1)   {
  365.          if (wkw.wtop > 1)   {
  366.             --wkw.wtop;
  367.             scroll_window(0);
  368.          }
  369.       }
  370.       else
  371.          --wkw.wy;
  372.    }
  373.    else if (wkw.wlines <= wkw.ht)
  374.       lastline();
  375. }
  376.  
  377. /* ----------- move down one line ------------- */
  378. static void downline()
  379. {
  380.    if (lineno < wkw.wlines)   {
  381.       if (wkw.wy == wkw.ht)   {
  382.          scroll_window(1);
  383.          wkw.wtop++;
  384.       }
  385.       else
  386.          wkw.wy++;
  387.    }
  388.    else if (wkw.wlines <= wkw.ht)
  389.       firstline();
  390. }
  391.  
  392. /* -------- move to the first line --------- */
  393. static void firstline()
  394. {
  395.    wkw.wtop = wkw.wy = 1;
  396. }
  397.  
  398. /* -------- move to the last line --------- */
  399. static void lastline()
  400. {
  401.    wkw.wtop = wkw.wlines - (wkw.ht-1);
  402.    if (wkw.wtop < 1)
  403.       wkw.wtop = 1;
  404.    wkw.wy = wkw.ht;
  405.    if (wkw.wy > wkw.wlines)
  406.       wkw.wy = wkw.wlines;
  407. }
  408.  
  409. char spaces[80] =
  410. "                                                                               ";
  411. /* ------- display a line of text, highlight or normal ------ */
  412. static void dline(ln, foreg, backg)
  413. {
  414.    if (foreg || backg)   {
  415.       textcolor(foreg);
  416.       textbackground(backg);
  417.       --ln;
  418.       writeline(2, ln-wkw.wtop+3, *(wkw.wtext + ln));
  419.       if (strlen(*(wkw.wtext + ln)) < wkw.wd-2)
  420.          writeline(2+strlen(*(wkw.wtext + ln)),
  421.                  ln-wkw.wtop+3,
  422.                  spaces + 79 - wkw.wd +
  423.                  strlen(*(wkw.wtext + ln)) + 2 );
  424.    }
  425. }
  426.  
  427. /* --------- write a line of text to video window ----------- */
  428. void writeline(int x, int y, char *str)
  429. {
  430.    int cl[80], *cp = cl;
  431.  
  432.    while (*str)
  433.       *cp++ = (*str++ & 255) | (_video.attribute << 8);
  434.       __vram(__vptr(x+wkw.lf-1,y+wkw.tp-1),MK_FP(_DS,cl),cp-cl);
  435. }
  436.  
  437. /* ------- use BIOS to hide the cursor ---------- */
  438. void hidecursor()
  439. {
  440.    rg.h.ah = 2;
  441.    rg.x.dx = 0x1900;
  442.    rg.h.bh = 0;
  443.    int86(0x10, &rg, &rg);
  444. }
  445.  
  446. /* ----------- use BIOS to set the cursor type -------------- */
  447. void set_cursor_type(unsigned t)
  448. {
  449.    rg.x.ax = 0x0100;
  450.    rg.x.bx = 0;
  451.    rg.x.cx = t;
  452.    int86(0x10, &rg, &rg);
  453. }
  454.  
  455. /* ----------- use BIOS to clear the screen ---------------- */
  456. void clear_screen()
  457. {
  458.    window(1,1,80,25);
  459.    gotoxy(1,1);
  460.    rg.h.al = ' ';
  461.    rg.h.ah = 9;
  462.    rg.x.bx = 7;
  463.    rg.x.cx = 2000;
  464.    int86(0x10, &rg, &rg);
  465. }
  466.  
  467. void (*helpfunc)(void);
  468. int helpkey;
  469.  
  470. /* ------------- read the keyboard ---------------- */
  471. int getkey()
  472. {
  473.    int c;
  474.  
  475.    if ((c = getch()) == 0)
  476.       c = getch() | 128;
  477.    if (c == helpkey && helpfunc)   {
  478.       (*helpfunc)();
  479.       c = getkey();
  480.    }
  481.    return c;
  482. }
  483.  
  484. /* ------- write an error message ------------- */
  485. void error_message(char *ermsg)
  486. {
  487.    int lf = (80-strlen(ermsg)+2)/2;
  488.    int rt = lf+max(strlen(ermsg)+2,15);
  489.    establish_window(lf, 11, rt, 14, ERRORFG, ERRORBG, TRUE);
  490.    gotoxy(2,2);
  491.    cputs(ermsg);
  492.    gotoxy(2,3);
  493.    cputs("(Press [Esc])");
  494.    hidecursor();
  495.    do
  496.       putch(BELL);
  497.    while (getkey() != ESC);
  498.    delete_window();
  499. }
  500.  
  501.  
  502.