home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / msdos / cpluspls / menus.cpp < prev    next >
C/C++ Source or Header  |  1991-11-15  |  18KB  |  677 lines

  1. _C Programming_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6.  
  7. // ------------ menus.h
  8.  
  9. #ifndef MENUS
  10. #define MENUS
  11.  
  12. #include "window.h"
  13.  
  14. #define MAXSELECTIONS 12
  15. #define CHECK '\xfb' // IBM Graphics character set check mark
  16.  
  17. #define MENUFG CYAN
  18. #define MENUBG BLUE
  19. #define SELECTFG BLACK
  20. #define SELECTBG WHITE
  21. #define DISABLEFG LIGHTGRAY
  22. #define DISABLEBG BLUE
  23.  
  24. //
  25. //   SLIDING BAR MENUS
  26. //
  27. class SlideBar    {
  28.     int row;                       // menu screen row
  29.     void (**mfunc)(SlideBar&);     // selection functions
  30.     char **mtext;                  // selection titles
  31.     int selections;                // number of selections
  32.     int quitflag;                  // flag for appl to say quit
  33.     unsigned *msave;               // save area for menu bar
  34.     int selection;                 // selection position
  35.     int dispatch(int sel, int titlewidth);
  36. public:
  37.     SlideBar(int line, char **text, int sel, 
  38.         void (**func)(SlideBar&));
  39.     ~SlideBar();
  40.     void terminate(void)
  41.         { quitflag = 1; }
  42.     int current_selection(void)
  43.         { return selection; }
  44. };
  45.  
  46. //
  47. //    POPDOWN MENUS
  48. //
  49. class PopdownMenu : Window    {
  50.     int selections;               // number of selections
  51.     void (**mfunc)(PopdownMenu&); // selection functions
  52.     char **text;                  // address of menu text
  53.     int quitflag;                 // flag for appl to say quit
  54.     int selection;                // current selection position
  55.     // --- private methods
  56.     int get_selection(int sel);
  57.     int dispatch(int sel);
  58.     int menuheight(char **text);
  59.     int menuwidth(char **text);
  60.     void operator<<(char **text);
  61. public:
  62.     PopdownMenu(unsigned left, unsigned top, 
  63.             char **text, int sel, void (**func)(PopdownMenu&));
  64.     ~PopdownMenu(){};
  65.     void terminate(void)
  66.         { quitflag = 1; }
  67.     void disable_selection(int sel)
  68.         { *text[sel-1] = '-'; }
  69.     void enable_selection(int sel)
  70.         { *text[sel-1] = ' '; }
  71.     int test_toggle(int selection);
  72.     int current_selection(void)
  73.         { return selection; }
  74. };
  75.  
  76. #endif
  77.  
  78.  
  79.  
  80. [LISTING TWO]
  81.  
  82. // ----------- menus.c
  83.  
  84. #include <stddef.h>
  85. #include <string.h>
  86. #include <stdio.h>
  87. #include <ctype.h>
  88. #include <conio.h>
  89. #include "menus.h"
  90. #include "console.h"
  91.  
  92. static void select(int row,int sel, char *ttl,int set,int wd);
  93. #define ON  1
  94. #define OFF 0
  95.  
  96. //
  97. //   SLIDING BAR MENUS
  98. //
  99.  
  100. // ----------- constructor for a sliding menu bar
  101. SlideBar::SlideBar(int line, char **text, int sel,
  102.         void (**func)(SlideBar&))
  103. {
  104.     savecursor();
  105.     hidecursor();
  106.     initconsole();
  107.     // ------ menu variables
  108.     quitflag = 0;
  109.     mfunc = func;
  110.     mtext = text;
  111.     // -------- save video memory
  112.     msave = new unsigned[SCREENWIDTH];
  113.     row = min(line-1, 24);
  114.     savevideo(msave, row, 0, row, SCREENWIDTH-1);
  115.     // --------- display the menu bar
  116.     colors(MENUFG, MENUBG);
  117.     setcursor(0, row);
  118.     int cols = SCREENWIDTH;
  119.     while (cols--)
  120.         window_putc(' ');
  121.     // ---- compute the width of the selection texts
  122.     int titlewidth = 0;
  123.     for (int i = 0; mtext[i] && i < MAXSELECTIONS; i++)
  124.         titlewidth = max(titlewidth, strlen(mtext[i]));
  125.     // ----- save the selection count
  126.     selections = i;
  127.     // ------ display the selection texts
  128.     for (i = 0; i < selections; i++)
  129.         select(row, i+1, mtext[i], OFF, titlewidth);
  130.     // ------- dispatch the menu's selections
  131.     dispatch(sel, titlewidth);
  132. }
  133.  
  134. // ----------- destructor for a menu bar
  135. SlideBar::~SlideBar(void)
  136. {
  137.     restorevideo(msave, row, 0, row, SCREENWIDTH-1);
  138.     delete msave;
  139.     restorecursor();
  140.     unhidecursor();
  141. }
  142.  
  143. // ------ navigate the menu and dispatch a chosen function
  144. int SlideBar::dispatch(int sel, int titlewidth)
  145. {
  146.     savecursor();
  147.     int sliding = 1;
  148.     if (sel)
  149.         selection = sel;
  150.     while (sliding)    {
  151.         // ---- highlight the menu bar selection
  152.         select(row, selection, mtext[selection-1],
  153.                                         ON,titlewidth);
  154.         // ----- read a selection key
  155.         int c = getkey();
  156.         switch (c)    {
  157.             case ESC:
  158.                 // ----- ESC key quits
  159.                 sliding = 0;
  160.                 break;
  161.             case FWD:
  162.                 // ------ right-arrow cursor key
  163.                 select(row, selection, mtext[selection-1],OFF,
  164.                     titlewidth);
  165.                 if (selection++ == selections)
  166.                     selection = 1;
  167.                 break;
  168.             case BS:
  169.                 // ------ left-arrow cursor key
  170.                 select(row, selection, mtext[selection-1],OFF,
  171.                     titlewidth);
  172.                 if (--selection == 0)
  173.                     selection = selections;
  174.                 break;
  175.             default:
  176.                 // ---- test for 1st letter match
  177.                 for (int i = 0; i < selections; i++)
  178.                     if (tolower(c) == tolower(mtext[i][1]))   {
  179.                         // -- match, turn off current selection
  180.                         select(row, selection,
  181.                             mtext[selection-1],
  182.                             OFF,titlewidth);
  183.                         // --- turn on new selection
  184.                         selection = i+1;
  185.                         select(row, selection,
  186.                             mtext[selection-1],
  187.                             ON,titlewidth);
  188.                         break;
  189.                     }
  190.                 if (i == selections)
  191.                     break;
  192.             case '\r':
  193.                 // ------- ENTER key = user selection
  194.                 if (mfunc[selection-1])
  195.                     (*mfunc[selection-1])(*this);
  196.                     sliding = !(quitflag == 1);
  197.                 break;
  198.         }
  199.     }
  200.     restorecursor();
  201.     select(row,selection,mtext[selection-1],OFF,titlewidth);
  202.     return quitflag ? 0 : selection;
  203. }
  204.  
  205. // --- set or clear the highlight on a menu bar selection
  206. static void select(int row,int sel,char *ttl,int set,int wd)
  207. {
  208.     setcursor(5+(sel-1)*wd, row);
  209.     if (set == OFF)
  210.         colors(MENUFG, MENUBG);
  211.     else
  212.         colors(SELECTFG, SELECTBG);
  213.     window_printf(ttl);
  214. }
  215.  
  216. //
  217. //    POPDOWN MENUS
  218. //
  219.  
  220. // -------- constructor for the PopdownMenu
  221. PopdownMenu::PopdownMenu(unsigned left, unsigned top, 
  222.             char **mtext, int sel, void (**func)(PopdownMenu&))
  223.                 : (left, top, left+1+menuwidth(mtext),
  224.                     top+1+menuheight(mtext), MENUFG, MENUBG)
  225. {
  226.     *this << mtext;
  227.     mfunc = func;
  228.     text = mtext;
  229.     selection = sel;
  230.     selections = menuheight(text);
  231.     // ------ dispatch the menu selection
  232.     dispatch(sel);
  233. }
  234.  
  235. // ------- write text selections into the popdown menu
  236. void PopdownMenu::operator<<(char **mtext)
  237. {
  238.     hidecursor();
  239.     int y = 0;
  240.     // ----- a NULL-terminated array of character pointers
  241.     text = mtext;
  242.     while (*mtext != NULL)    {
  243.         cursor(0, y++);
  244.         char hold = **mtext;
  245.         if (**mtext == '-')    {
  246.             set_colors(DISABLEFG, DISABLEBG);
  247.             **mtext = ' ';
  248.         }
  249.         *this << *mtext;
  250.         **mtext++ = hold;
  251.         set_colors(MENUFG, MENUBG);
  252.     }
  253.     unhidecursor();
  254. }
  255.  
  256. // ------------ get a popdown menu selection
  257. int PopdownMenu::get_selection(int sel)
  258. {
  259.     // ---- set the initial selection
  260.     if (sel)
  261.         selection = sel;
  262.     int selecting = 1;
  263.     int c;
  264.     while (selecting)    {
  265.         // ------- display the menu's selection texts
  266.         *this << text;
  267.         // ------ watch for disabled selections
  268.         if (**(text+selection-1)=='-')
  269.             c = DN;        // force a key to
  270.                         // bypass a disabled selection
  271.         else    {
  272.             // ---- highlight the current selection
  273.             cursor(0, selection-1);
  274.             set_colors(SELECTFG, SELECTBG);
  275.             *this << *(text + selection - 1);
  276.             set_colors(MENUFG, MENUBG);
  277.             hidecursor();
  278.             c = getkey();    // --- read the next keystroke
  279.         }
  280.         switch (c)    {
  281.             case ESC:
  282.             case FWD:
  283.             case BS:
  284.                 // ---- ESC,FWD, or BS will terminate selection
  285.                 selecting = 0;
  286.                 break;
  287.             case UP:
  288.                 // ------- up-arrow cursor key
  289.                 do
  290.                     if (--selection == 0)
  291.                         selection = selections;
  292.                 while (**(text+selection-1) == '-');
  293.                 break;
  294.             case DN:
  295.                 // ------- down-arrow cursor key
  296.                 do
  297.                     if (selection++ == selections)
  298.                         selection = 1;
  299.                 while (**(text+selection-1) == '-');
  300.                 break;
  301.             default:
  302.                 // ----- other key, test first letter match
  303.                 for (int i = 0; i < selections; i++) {
  304.                     if (tolower(c) == tolower(text[i][1]) &&
  305.                              *(text[i]) != '-')   {
  306.                         selection = i+1;
  307.                         selecting = 0;
  308.                     }
  309.                 }
  310.                 break;
  311.             case '\r':
  312.                 // ---- ENTER key is a selection
  313.                 selecting = 0;
  314.                 break;
  315.         }
  316.     }
  317.     return c == '\r' ? selection : c;
  318. }
  319.  
  320. // ------------ get and dispatch a popdown menu selection
  321. int PopdownMenu::dispatch(int sel)
  322. {
  323.     int upanddown = 1;
  324.     while (upanddown)    {
  325.           // ---------- read a user selection
  326.         sel = get_selection(sel);
  327.         switch (sel)    {
  328.                // -------- these keys exit the menu
  329.             case FWD:
  330.             case BS:
  331.             case ESC:
  332.                 upanddown = 0;
  333.                 break;
  334.             default:
  335.                 // -------- user has made a menu selection
  336.                 if (mfunc[selection-1]) {
  337.                     // ----- execute a menu selection function
  338.                     hidewindow();
  339.                     (*mfunc[selection-1])(*this);
  340.                     upanddown = !(quitflag == 1);
  341.                     restorewindow();
  342.                 }
  343.                 else    {
  344.                     // ----- no function, must be a toggle
  345.                     char *cp = text[selection-1];
  346.                     cp += strlen(cp)-1;
  347.                     if (*cp == ' ')
  348.                         *cp = CHECK;
  349.                     else if ((*cp & 255) == CHECK)
  350.                         *cp = ' ';
  351.                 }
  352.                 break;
  353.         }
  354.     }
  355.     return sel == ESC ? ESC : 0;
  356. }
  357.  
  358. // --------- compute the height of a popdown menu
  359. int PopdownMenu::menuheight(char **text)
  360. {
  361.     int height = 0;
  362.     while (text[height])
  363.         height++;
  364.     return height;
  365. }
  366.  
  367. // --------- compute the width of a popdown menu
  368. int PopdownMenu::menuwidth(char **text)
  369. {
  370.     int width = 0;
  371.     while (*text)    {
  372.         width = max(width, strlen(*text));
  373.         text++;
  374.     }
  375.     return width;
  376. }
  377.  
  378. // ----- test the setting of a toggle selection
  379. int PopdownMenu::test_toggle(int sel)
  380. {
  381.     char *cp = text[sel-1];
  382.     cp += strlen(cp)-1;
  383.     return (*cp & 255) == CHECK;
  384. }
  385.  
  386.  
  387. [LISTING THREE]
  388.  
  389. // ---------- demoslid.c
  390.  
  391. #include <stddef.h>
  392. #include <conio.h>
  393. #include <stdio.h>
  394. #include "menus.h"
  395. #include "console.h"
  396.  
  397. // ----------- File menu
  398. static char *fmenu[] = {
  399.     " Load ",
  400.     " Save ",
  401.     " New  ",
  402.     " Quit ",
  403.     NULL
  404. };
  405.  
  406. static void load(SlideBar&);
  407. static void save(SlideBar&);
  408. static void newfile(SlideBar&);
  409. static void quit(SlideBar&);
  410.  
  411. static void (*ffuncs[])(SlideBar&)={load,save,newfile,quit};
  412.  
  413. void main(void)
  414. {
  415.     SlideBar menu(1, fmenu, 1, ffuncs);
  416. }
  417.  
  418. static void load(SlideBar& menu)
  419. {
  420.     Window wnd(20,10,40,20,BLACK,CYAN);
  421.     wnd.title("(Stub Function)");
  422.     wnd << "\n\n\n\n   LOAD A FILE";
  423.     getkey();
  424. }
  425.  
  426. static void save(SlideBar &menu)
  427. {
  428.     Window wnd(20,10,40,20,YELLOW,RED);
  429.     wnd.title("(Stub Function)");
  430.     wnd << "\n\n\n\n  SAVE A FILE";
  431.     getkey();
  432. }
  433.  
  434. static void newfile(SlideBar &menu)
  435. {
  436.     Window wnd(20,10,40,20,YELLOW,RED);
  437.     wnd.title("(Stub Function)");
  438.     wnd << "\n\n\n\n   NEW FILE";
  439.     getkey();
  440. }
  441.  
  442. static void quit(SlideBar& menu)
  443. {
  444.     YesNo yn("Quit");
  445.     if (yn.answer)
  446.         menu.terminate();
  447. }
  448.  
  449.  
  450.  
  451. [LISTING FOUR]
  452.  
  453. // ---------- demopop.c
  454.  
  455. #include <stddef.h>
  456. #include <conio.h>
  457. #include <stdio.h>
  458. #include "menus.h"
  459. #include "console.h"
  460.  
  461. // ----------- File menu
  462. static char *fmenu[] = {
  463.     " Load    ",
  464.     "-Save    ",
  465.     " New     ",
  466.     " Option  ",
  467.     " Quit    ",
  468.     NULL
  469. };
  470.  
  471. static void load(PopdownMenu&);
  472. static void save(PopdownMenu&);
  473. static void newfile(PopdownMenu&);
  474. static void quit(PopdownMenu&);
  475.  
  476. static void (*ffuncs[])(PopdownMenu&) =
  477.     { load, save, newfile, NULL, quit };
  478.  
  479. void main(void)
  480. {
  481.     PopdownMenu menu(20, 10, fmenu, 1, ffuncs);
  482. }
  483.  
  484. static void load(PopdownMenu& menu)
  485. {
  486.     Window wnd(20,10,40,20,BLACK,CYAN);
  487.     wnd.title("(Stub Function)");
  488.     wnd << "\n\n\n\n   LOAD A FILE";
  489.     menu.enable_selection(2);    // enable the save command
  490.     getkey();
  491. }
  492.  
  493. static void save(PopdownMenu &menu)
  494. {
  495.     Window wnd(20,10,40,20,YELLOW,RED);
  496.     wnd.title("(Stub Function)");
  497.     wnd << "\n\n\n\n  SAVE A FILE";
  498.     menu.disable_selection(2);    // disable the save command
  499.     getkey();
  500. }
  501.  
  502. static void newfile(PopdownMenu &menu)
  503. {
  504.     Window wnd(20,10,40,20,YELLOW,RED);
  505.     wnd.title("(Stub Function)");
  506.     wnd << "\n\n\n\n   NEW FILE";
  507.     menu.enable_selection(2);    // enable the save command
  508.     getkey();
  509. }
  510.  
  511. static void quit(PopdownMenu& menu)
  512. {
  513.     if (menu.test_toggle(4))
  514.         menu.terminate();
  515.     else    {
  516.         YesNo yn("Quit");
  517.         if (yn.answer)
  518.             menu.terminate();
  519.     }
  520. }
  521.  
  522.  
  523.  
  524. [LISTING FIVE]
  525.  
  526.  
  527. // -------- strings.h
  528.  
  529. #ifndef STRINGS
  530. #define STRINGS
  531.  
  532. #include <string.h>
  533.  
  534. class string    {
  535.     char *sptr;
  536. public:
  537.     //          CONSTRUCTORS 
  538.     // -------- construct a null string
  539.     string(void);
  540.     // ------- construct with a char * initializer
  541.     string(char *s);
  542.     // ------- construct with another string as initializer
  543.     string(string& s);
  544.     // -------- construct with just a size
  545.     string(int len);
  546.  
  547.     //          DESTRUCTOR
  548.     ~string(void) { delete sptr; }
  549.  
  550.     //          MEMBER FUNCTIONS
  551.     // ------ return the address of the string
  552.     const char *stradr(void) { return sptr; }
  553.  
  554.     //          SUBSTRINGS
  555.     // ------ substring: right len chars
  556.     string right(int len);
  557.     // ------ substring: left len chars
  558.     string left(int len);
  559.     // ------ substring: middle len chars starting from where
  560.     string mid(int len, int where);
  561.  
  562.     //          ASSIGNMENTS
  563.     // -------- assign a char array to a string
  564.     void operator=(char *s);
  565.     // ---------- assign a string to a string
  566.     void operator=(string& s) { *this = s.sptr; }
  567.  
  568.     //          CONCATENATORS
  569.     // ------- 1st concatenation operator (str1 += char *)
  570.     void operator+=(char *s);
  571.     // ------- 2nd concatenation operator (str1 += str2;)
  572.     void operator+=(string& s) { *this += s.sptr; }
  573.     // ------- 3rd concatenation operator (str1 = str2+char*;)
  574.     string operator+(char *s);
  575.     // ------- 4th concatenation operator (str1 = str2 + str3;)
  576.     string operator+(string& s) { return *this + s.sptr; }
  577.  
  578.     //          RELATIONAL OPERATORS
  579.     int operator==(string& s) { return strcmp(sptr,s.sptr)==0;}
  580.     int operator!=(string& s) { return strcmp(sptr,s.sptr)!=0;}
  581.     int operator<(string& s)  { return strcmp(sptr,s.sptr)< 0;}
  582.     int operator>(string& s)  { return strcmp(sptr,s.sptr)> 0;}
  583.     int operator<=(string& s) { return strcmp(sptr,s.sptr)<=0;}
  584.     int operator>=(string& s) { return strcmp(sptr,s.sptr)>=0;}
  585.     int operator==(char *s)   { return strcmp(sptr,s)==0; }
  586.     int operator!=(char *s)   { return strcmp(sptr,s)!=0; }
  587.     int operator<(char *s)    { return strcmp(sptr,s)< 0; }
  588.     int operator>(char *s)    { return strcmp(sptr,s)> 0; }
  589.     int operator<=(char *s)   { return strcmp(sptr,s)<=0; }
  590.     int operator>=(char *s)   { return strcmp(sptr,s)>=0; }
  591.  
  592.     //          SUBSCRIPTORS
  593.     char operator[](int n) { return *(sptr + n); }
  594.     char* operator+(int n) { return sptr + n; }
  595. };
  596.  
  597. #endif
  598.  
  599.  
  600.  
  601. [LISTING SIX]
  602.  
  603. // -------- strings.c
  604.  
  605. #include <stddef.h>
  606. #include <stream.hpp>
  607. #include "strings.h"
  608.  
  609. // -------- construct a null string
  610. string::string(void)
  611. {
  612.     sptr = new char;
  613.     *sptr = '\0';
  614. }
  615. // ------- construct with a char * initializer
  616. string::string(char *s)
  617. {
  618.     sptr = new char[strlen(s)+1];
  619.     strcpy(sptr, s);
  620. }
  621. // ------- construct with another string as initializer
  622. string::string(string& s)
  623. {
  624.     sptr = new char[strlen(s.sptr)+1];
  625.     strcpy(sptr, s.sptr);
  626. }
  627. // -------- construct with just a size
  628. string::string(int len)
  629. {
  630.     sptr = new char[len+1];
  631.     memset(sptr, 0, len+1);
  632. }
  633. // -------- assign a char array to a string
  634. void string::operator=(char *s)
  635. {
  636.     delete sptr;
  637.     sptr = new char[strlen(s)+1];
  638.     strcpy(sptr, s);
  639. }
  640. // ------- 1st concatenation operator (str1 += char *;)
  641. void string::operator+=(char *s)
  642. {
  643.     char *sp = new char[strlen(sptr) + strlen(s) + 1];
  644.     strcpy(sp, sptr);
  645.     strcat(sp, s);
  646.     delete sptr;
  647.     sptr = sp;
  648. }
  649. // ------- 3rd concatenation operator (str1 = str2 + char*;)
  650. string string::operator+(char *s)
  651. {
  652.     string tmp(*this);
  653.     tmp += s;
  654.     return tmp;
  655. }
  656. // ------ substring: right len chars
  657. string string::right(int len)
  658. {
  659.     string tmp(sptr + strlen(sptr) - len);
  660.     return tmp;
  661. }
  662. // ------ substring: left len chars
  663. string string::left(int len)
  664. {
  665.     string tmp(len+1);
  666.     strncpy(tmp.stradr(), sptr, len);
  667.     return tmp;
  668. }
  669. // ------ substring: middle len chars starting from where
  670. string string::mid(int len, int where)
  671. {
  672.     string tmp(len+1);
  673.     strncpy(tmp.stradr(),sptr+where-1,len);
  674.     return tmp;
  675. }
  676.  
  677.