home *** CD-ROM | disk | FTP | other *** search
/ Best Objectech Shareware Selections / UNTITLED.iso / boss / musi / misc / 013 / textwin.c < prev    next >
Text File  |  1993-04-10  |  14KB  |  603 lines

  1. /*
  2.  * TEXTWIN.C - Text-windowing system
  3.  * Turbo C 2.0
  4.  *
  5.  * Description: Provides a simple text-menuing interface. Includes pop-down
  6.  *              menus, and scrolling windows. To use, set up a main window
  7.  *              with the MainWindow() function.
  8.  *   eg. MainWindow("Title", 2, "Files", 'f', "Help", 'h');
  9.  *
  10.  *              Then set the commands and command-numbers for each menu use
  11.  *              the SetMenu function.
  12.  *   eg. SetMenu(0, 3, "Open",'o',0, "Close",'c',1, "Quit",'q',2);
  13.  *       SetMenu(1, 3, "Help",'h',3, "------------",-1,-1, "About",'a',4);
  14.  *
  15.  *              Now just make a call to Choice() and the number it returns
  16.  *              will be the command-number of the choice
  17.  *   eg. If Help|About is chosen, 4 will be returned.
  18.  *
  19.  *              If you want to get the user to select an option from a list
  20.  *              of options, make an array of strings with the option
  21.  *              descriptions in them (ensure final element is NULL). The
  22.  *              element number chosen will be returned (first element = 0)
  23.  *              after a call to ScrollChoice()
  24.  *   eg. If the array is a, and the maximum string length is l, make the call
  25.  *       ScrollChoice("BetterTitle", a, l);
  26.  *
  27.  *              To display test inside a box, call DrawBox() with a NULL-
  28.  *              terminated array of strings.
  29.  *   eg. If the array is a, call
  30.  *       DrawBox(a);
  31.  *
  32.  *              To display text inside a box, and then wait for a key to be
  33.  *              pressed, set up a NULL-terminated array of strings and call
  34.  *              the InfoBox() function
  35.  *   eg. If the array is a, make the call
  36.  *       InfoBox(a);
  37.  *
  38.  *              If you want to get input as well as print a box, make a call
  39.  *              to DialogBox(), if nothing is entered, a default string is
  40.  *              returned
  41.  *   eg. DialogBox(a, "C:\") would return "C:\" if nothing was entered.
  42.  *
  43.  *
  44.  * Author: Andrew Scott (Adrenalin Software)
  45.  *
  46.  * Date: 14/3/1993 ver 0.1
  47.  */
  48.  
  49. #include <conio.h>
  50. #include <stdlib.h>
  51. #include <stdio.h>
  52. #include <stdarg.h>
  53. #include <string.h>
  54. #include <ctype.h>
  55.  
  56. /* Maximum number of chars in a menu title */
  57. #define MAXMENUWIDTH 9
  58. /* Maximum number of chars in a menu command */
  59. #define MAXCOMMWIDTH 12
  60. /* Border graphics */
  61. #define CRNRTL '┌'
  62. #define CRNRTR '┐'
  63. #define CRNRBL '└'
  64. #define CRNRBR '┘'
  65. #define HORIBAR '─'
  66. #define VERTBAR '│'
  67.  
  68. typedef char *string;
  69.  
  70. struct MenuStruct {
  71.     char n[MAXCOMMWIDTH+1]; /* Item name ("" = no items) */
  72.     int k;                  /* Key-press selector (lower case) */
  73.     int x;                  /* Function reference number (-ve = no command) */
  74. };
  75. typedef struct MenuStruct *MenuItem;
  76.  
  77. struct MenuBar {
  78.     char n[MAXMENUWIDTH+1]; /* Menu name ("" = no menus) */
  79.     int k;                  /* Key-press selector (lower case) */
  80.     MenuItem m;             /* Menu items */
  81. } *Main;
  82.  
  83.  
  84. #if 0
  85. string parmlist(string bit, int n)
  86. {
  87.     string s, t;
  88.     int l;
  89.  
  90.     s = t = (string) malloc(1 + n * (l = strlen(bit)));
  91.     while (n--) {
  92.         strcpy(t, bit);
  93.         t += l;
  94.     }
  95.     return s;
  96. }
  97. #endif
  98.  
  99. void MainWindow(string title, int num, ...)
  100. /* Post: Screen is set up with a nice title and num menus */
  101. {
  102.     va_list args;
  103.     string t;
  104.     int i;
  105.     struct MenuBar *c;
  106.  
  107.     c = Main = (struct MenuBar *) malloc(sizeof(struct MenuBar) * (num + 1));
  108.     va_start(args, &num);
  109.     textmode(C80);
  110.     textcolor(CYAN);
  111.     textbackground(BLACK);
  112.     clrscr();
  113.     textbackground(BLUE);
  114.     textcolor(WHITE);
  115.     i = 80 - strlen(title);
  116.     cprintf("%*c%s%*c", i/2, ' ', title, i/2 + i%2, ' ');
  117.     textcolor(YELLOW);
  118.     cprintf(" ");
  119.     for (i = num; i--; c++) {
  120.         t = (va_arg(args, string));
  121.         strcpy(c->n, t);
  122.         cprintf("%-*s", MAXMENUWIDTH, t);
  123.         c->k = (va_arg(args, int));
  124.         c->m = NULL;
  125.     }
  126.     c->n[0] = 0;
  127.     cprintf("%*c", 79 - MAXMENUWIDTH * num, ' ');
  128.     va_end(args);
  129. }
  130.  
  131. void SetMenu(int menu, int n, ...)
  132. /* Post: n commands has been set in menu #menu (0 = 1st) */
  133. {
  134.     va_list args;
  135.     string t;
  136.     struct MenuBar *c1;
  137.     MenuItem c2;
  138.  
  139.     int i;
  140.  
  141.     for (i = menu, c1 = Main; i-- && c1->n[0] != 0; c1++);
  142.     if (! c1->n[0])
  143.         return; /* error */
  144.     c1->m = c2 = (MenuItem) malloc(sizeof(struct MenuStruct) * (n + 1));
  145.     va_start(args, &n);
  146.     for (; n--; c2++) {
  147.         t = va_arg(args, string);
  148.         strcpy(c2->n, t);
  149.         c2->k = va_arg(args, int);
  150.         c2->x = va_arg(args, int);
  151.     }
  152.     c2->n[0] = 0;
  153. }
  154.  
  155. int _Menulength_; /* ignore this unstructured global variable ;) */
  156.  
  157. void PrintMenu(MenuItem m, int x)
  158. /* Post: The menu which is pointed to by m is printed at column x */
  159. {
  160.     int i;
  161.     char t[MAXCOMMWIDTH + 3];
  162.  
  163.     i = MAXCOMMWIDTH+2;
  164.     t[i] = 0;
  165.     while (i--)
  166.         t[i] = HORIBAR;
  167.     textcolor(YELLOW);
  168.     textbackground(BLUE);
  169.     gotoxy(x, 3);
  170.     cprintf("%c%s%c", CRNRTL, t, CRNRTR);
  171.     _Menulength_ = 2;
  172.     i = 4;
  173.     while (m->n[0]) {
  174.         _Menulength_++;
  175.         gotoxy(x, i++);
  176.         cprintf("%c %-*s %c", VERTBAR, MAXCOMMWIDTH, (m++)->n, VERTBAR);
  177.     }
  178.     gotoxy(x, i);
  179.     cprintf("%c%s%c", CRNRBL, t, CRNRBR);
  180. }
  181.  
  182. void ClearMenu(int x)
  183. /* Post: The last menu printed at column x is now gone */
  184. {
  185.     int i = 3;
  186.  
  187.     textcolor(CYAN);
  188.     textbackground(BLACK);
  189.     while (_Menulength_--) {
  190.         gotoxy(x, i++);
  191.         cprintf("%*c", MAXCOMMWIDTH + 4, ' ');
  192.     }
  193. }
  194.  
  195. void PrintComm(MenuItem m, int x, int y)
  196. /* Post: Item *m is highlighted at column x, position y */
  197. {
  198.     gotoxy(x+1, y+4);
  199.     textcolor(MAGENTA);
  200.     textbackground(BLACK);
  201.     cprintf(" %-*s ", MAXCOMMWIDTH, m->n);
  202. }
  203.  
  204. void ClearComm(MenuItem m, int x, int y)
  205. /* Post: Item *m is normalized at column x, position y */
  206. {
  207.     gotoxy(x+1, y+4);
  208.     textcolor(YELLOW);
  209.     textbackground(BLUE);
  210.     cprintf(" %-*s ", MAXCOMMWIDTH, m->n);
  211. }
  212.  
  213. void PrintBar(string s, int w, int y)
  214. /* Post: String s (width w) is highlighted in the text window on line y */
  215. {
  216.     gotoxy(1, y+1);
  217.     textcolor(WHITE);
  218.     textbackground(BLACK);
  219.     cprintf(" %-*s ", w, s);
  220. }
  221.  
  222. void ClearBar(string s, int w, int y)
  223. /* Post: String s (width w) is normalized in the text window on line y */
  224. {
  225.     gotoxy(1, y+1);
  226.     textcolor(BLACK);
  227.     textbackground(CYAN);
  228.     cprintf(" %-*s ", w, s);
  229. }
  230.  
  231. void Beep()
  232. /* Post: Speaker has made a beep */
  233. {
  234.     printf("%c", 7);
  235. }
  236.  
  237. int Choice()
  238. /*
  239.  * Returns: a function reference number corresponding to a chosen command,
  240.  *   but returns -1 on an error.
  241.  */
  242. {
  243.     int ch;
  244.     struct MenuBar *c;
  245.     MenuItem p, q;
  246.     int i, fx = -1, y;
  247.  
  248.     textcolor(CYAN);
  249.     textbackground(BLACK);
  250.     gotoxy(1, 25);
  251.     do {
  252.         cprintf("\rPress the letter of the menu you wish to select.");
  253.         ch = tolower(getch());
  254.         for (c = Main, i = 0; c->n[0] && c->k != ch; c++, i++);
  255.         i = 2 + MAXMENUWIDTH * i;
  256.         if (c->n[0] != 0)
  257.             do {
  258.                 cprintf("\rPress a letter, or use cursor keys and <RETURN> to select a command.");
  259.                 gotoxy(i, 2);
  260.                 textbackground(BLUE);
  261.                 textcolor(LIGHTRED);
  262.                 cprintf("%-*s", MAXMENUWIDTH, c->n);
  263.                 PrintMenu(p = c->m, i);
  264.                 PrintComm(p, i, y = 0);
  265.                 do {
  266.                     ch = tolower(getch());
  267.                     if (!ch) {
  268.                         ch = -getch();
  269.                         if (ch==-72) /* up-arrow */
  270.                             if (!y)
  271.                                 Beep();
  272.                             else {
  273.                                 ClearComm(p--, i, y--);
  274.                                 PrintComm(p, i, y);
  275.                             }
  276.                         else if (ch==-80) /* down-arrow */
  277.                             if (! (p+1)->n[0])
  278.                                 Beep();
  279.                             else {
  280.                                 ClearComm(p++, i, y++);
  281.                                 PrintComm(p, i, y);
  282.                             }
  283.                     } else {
  284.                         for (q = c->m; q->n[0] && q->k != ch; q++);
  285.                         if (q->n[0])
  286.                             fx = q->x;
  287.                     }
  288.                 } while ((ch==-72 || ch==-80) && fx < 0);
  289.                 if (ch==13 && fx < 0)
  290.                     fx = p->x;
  291.                 ClearMenu(i);
  292.                 gotoxy(i, 2);
  293.                 textbackground(BLUE);
  294.                 textcolor(YELLOW);
  295.                 cprintf("%-*s", MAXMENUWIDTH, c->n);
  296.                 textcolor(CYAN);
  297.                 textbackground(BLACK);
  298.                 gotoxy(1, 25);
  299.                 cprintf("%52c", ' ');
  300.                 if (ch==-75)
  301.                     if (i==2)
  302.                         Beep();
  303.                     else {
  304.                         i -= MAXMENUWIDTH;
  305.                         c--;
  306.                     }
  307.                 else if (ch==-77)
  308.                     if (! (c+1)->n[0])
  309.                         Beep();
  310.                     else {
  311.                         i += MAXMENUWIDTH;
  312.                         c++;
  313.                     }
  314.             } while (ch != 27 && fx < 0);
  315.         clreol();
  316.     } while (fx < 0);
  317.     return fx;
  318. }
  319.  
  320. void ClearWin()
  321. /* Post: Area below command and title bars is clear */
  322. {
  323.