home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: CUG301;
- TITLE: Graphics pull down menu system;
- DATE: 09/30/89;
- DESCRIPTION: "C language calls can be used to easily define pull-down
- menus by using this menu system. The routines currently
- only support graphics mode and not text mode.";
- KEYWORDS: user interface, graphics, quick prototype;
- FILENAME: MENU.C;
- WARNINGS: "The author claims copyrights and authorizes
- non-commercial use only.";
- AUTHORS: John Muczynski;
- COMPILERS: Turbo C version 2.0;
- */
- /*
- menu.c
-
- Pull down (graphics) menus.
-
-
-
- (c) Copyright 1989 by John Muczynski. All Rights Reserved.
- */
-
-
- /*
- bulletins
- jsm 09/01/89 creation
- jsm 09/01/89 need to work on
- -HORIZ/VERT
- -keys
- -longkeys
- -macros
- -saving screen position and shortname size
- jsm 09/03/89 finished debug
- known problems:
- 1. If a menu is too big to fit on the screen, getmaxx and getmaxy
- don't seem to flag the problem.
- 2. If a menu is too big to fit on the screen, the turbo routines to
- save and restore the screen data that is overwritten don't work
- properly. No data is restored.
- 3. Menu keys are not accepted in both upper and lower case (yet).
- 4. The macro editor is not complete.
- 5. The configuration of the database is not saved/restored to/from a
- file yet.
-
- jsm 09/04/89 started supporting upper/lower case conversion.
- The cursor is now passed to both the hotkeys as well
- as the menu functions.
- known 09/03/89 problems 1 and 2 are fixed.
- Adding utilities submenu.
- jsm 09/05/89 lower case works
- getmaxx and y are used in padtext now
- cursor now skips invisible menu entries
- menus now re-draw when using hotkeys to move a menu
- rootmenu is now in upper left corner all the way (0,0)
- 1 Utilities work okay except meta-hotkey.
- known 09/03/89 problems 3 4 and 5 are fixed.
- 2 not all of configuration is saved yet -- problem finding a
- representation for the menus -- don't want to use C.
- jsm 09/05/89 Fixed problems 1 from 09/05/89
- 1 note: horizontal menus's that don't fit can be changed
- into vertical menus.
- 2 need to complete and debug configuration read/write.
- hot key has problems.
-
- jsm 09/08/89 fixing hot key.
- fixing macro read/write from config file.
- Now config saves everything except the information contained
- in the menu structures.
- 3 Want to be able to change the names of keys and functions.
-
-
-
- FUTURE EXPANSION:
- JSM 09/29/89 -Need some facility to auto-run some macro when the program
- is doing initialization.
- -Need to auto-load the MENU.TMP file.
- -Need to make the words inside a menu both horizontal and
- vertical, just as the menu itself can be built horizontal
- or vertical.
- -Need to allow the menus to be called up from either text
- mode or graphics mode.
- -Need to add 'backspace' capability to the macro entry
- routine.
- -Need to add documentation.
- -Need to make a environment parameter for the name
- of the 'MENU.TMP' file (it's full path name).
- -Need to expand the config. file to include the data which
- is saved in the menu structures.
- -Mouse support would be nice...
- */
-
- /* define DEBUG */
- #define debug1 0
- #define debug2 0
- #define debug3 0
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <time.h>
- #include <ctype.h>
- #include <string.h>
-
- #include <bios.h>
- #include <graphics.h>
- #include <conio.h>
-
-
- static int accumx, accumy;
-
- typedef void fn();
-
-
-
- void my_wait_key(){}; /* default for above */
- fn *the_wait_key = my_wait_key;
-
- /* define how to wait for keys */
- void wait_key(fn funct)
- {
- the_wait_key = funct;
- };
-
-
-
- /* function to get a key from the user
- returns a keyboard value.
- */
- long int get_key()
- {
- int ext;
- int key;
- long int lkey;
-
- while (! bioskey(1)) {
- the_wait_key(); /* do what the user wants */
- };
-
-
- if (bioskey(1)) {
- key = bioskey(0);
- ext = bioskey(2);
-
- if (key&0xFF) {
- lkey = key&0xFF;
- }else{
- lkey=0l;
- if (ext&0x03) lkey = lkey ^ 0x10000l;
-
- lkey = lkey + key;
- };
- };
-
- return( 0x10000l + (0x1FFFFl & lkey) );
-
- };
-
-
- struct mac {
- long int fkey;
- struct mac *next;
- struct mac *prev;
- };
-
-
-
- #define LASTKEY 330
- int lastkey = 273;
- long int keys[LASTKEY+1] = {0}; /* keyboard values for each key */
- char *keynames[LASTKEY+1] = {0}; /* names for each key */
- struct mac *mac[LASTKEY+1] = {0}; /* macros for each key */
-
-
-
- /* yes, this table was generated by a program. */
- void init_keys()
- {
- keys[0] = 0x10001l;
- keynames[0] = "[CTRL-A]";
- keys[1] = 0x10002l;
- keynames[1] = "[CTRL-B]";
- keys[2] = 0x10004l;
- keynames[2] = "[CTRL-D]";
- keys[3] = 0x10005l;
- keynames[3] = "[CTRL-E]";
- keys[4] = 0x10006l;
- keynames[4] = "[CTRL-F]";
- keys[5] = 0x10007l;
- keynames[5] = "[CTRL-G]";
- keys[6] = 0x10008l;
- keynames[6] = "[BKSP]";
- keys[7] = 0x10009l;
- keynames[7] = "[TAB]";
- keys[8] = 0x1000Al;
- keynames[8] = "[CTRL-J]";
- keys[9] = 0x1000Bl;
- keynames[9] = "[CTRL-K]";
- keys[10] = 0x1000Cl;
- keynames[10] = "[CTRL-L]";
- keys[11] = 0x1000Dl;
- keynames[11] = "[ENTER]";
- keys[12] = 0x1000El;
- keynames[12] = "[CTRL-N]";
- keys[13] = 0x1000Fl;
- keynames[13] = "[CTRL-O]";
- keys[14] = 0x10010l;
- keynames[14] = "[CTRL-P]";
- keys[15] = 0x10011l;
- keynames[15] = "[CTRL-Q]";
- keys[16] = 0x10012l;
- keynames[16] = "[CTRL-R]";
- keys[17] = 0x10013l;
- keynames[17] = "[CTRL-S]";
- keys[18] = 0x10014l;
- keynames[18] = "[CTRL-T]";
- keys[19] = 0x10015l;
- keynames[19] = "[CTRL-U]";
- keys[20] = 0x10016l;
- keynames[20] = "[CTRL-V]";
- keys[21] = 0x10017l;
- keynames[21] = "[CTRL-W]";
- keys[22] = 0x10018l;
- keynames[22] = "[CTRL-X]";
- keys[23] = 0x10019l;
- keynames[23] = "[CTRL-Y]";
- keys[24] = 0x1001Al;
- keynames[24] = "[CTRL-Z]";
- keys[25] = 0x1001Bl;
- keynames[25] = "[ESCAPE]";
- keys[26] = 0x1001Cl;
- keynames[26] = "[CTRL-\]";
- keys[27] = 0x1001Dl;
- keynames[27] = "[CTRL-]]";
- keys[28] = 0x1001El;
- keynames[28] = "[CTRL-^]";
- keys[29] = 0x1001Fl;
- keynames[29] = "[CTRL-DASH]";
- keys[30] = 0x10020l;
- keynames[30] = "[SPACE]";
- keys[31] = 0x10021l;
- keynames[31] = "[!]";
- keys[32] = 0x10022l;
- keynames[32] = "[\"]";
- keys[33] = 0x10023l;
- keynames[33] = "[#]";
- keys[34] = 0x10024l;
- keynames[34] = "[$]";
- keys[35] = 0x10025l;
- keynames[35] = "[%]";
- keys[36] = 0x10026l;
- keynames[36] = "[&]";
- keys[37] = 0x10027l;
- keynames[37] = "[']";
- keys[38] = 0x10028l;
- keynames[38] = "[(]";
- keys[39] = 0x10029l;
- keynames[39] = "[)]";
- keys[40] = 0x1002Al;
- keynames[40] = "[*]";
- keys[41] = 0x1002Bl;
- keynames[41] = "[+]";
- keys[42] = 0x1002Cl;
- keynames[42] = "[,]";
- keys[43] = 0x1002Dl;
- keynames[43] = "[-]";
- keys[44] = 0x1002El;
- keynames[44] = "[.]";
- keys[45] = 0x1002Fl;
- keynames[45] = "[/]";
- keys[46] = 0x10030l;
- keynames[46] = "[0]";
- keys[47] = 0x10031l;
- keynames[47] = "[1]";
- keys[48] = 0x10032l;
- keynames[48] = "[2]";
- keys[49] = 0x10033l;
- keynames[49] = "[3]";
- keys[50] = 0x10034l;
- keynames[50] = "[4]";
- keys[51] = 0x10035l;
- keynames[51] = "[5]";
- keys[52] = 0x10036l;
- keynames[52] = "[6]";
- keys[53] = 0x10037l;
- keynames[53] = "[7]";
- keys[54] = 0x10038l;
- keynames[54] = "[8]";
- keys[55] = 0x10039l;
- keynames[55] = "[9]";
- keys[56] = 0x1003Al;
- keynames[56] = "[:]";
- keys[57] = 0x1003Bl;
- keynames[57] = "[;]";
- keys[58] = 0x1003Cl;
- keynames[58] = "[<]";
- keys[59] = 0x1003Dl;
- keynames[59] = "[=]";
- keys[60] = 0x1003El;
- keynames[60] = "[>]";
- keys[61] = 0x1003Fl;
- keynames[61] = "[?]";
- keys[62] = 0x10040l;
- keynames[62] = "[@]";
- keys[63] = 0x10041l;
- keynames[63] = "[A]";
- keys[64] = 0x10042l;
- keynames[64] = "[B]";
- keys[65] = 0x10043l;
- keynames[65] = "[C]";
- keys[66] = 0x10044l;
- keynames[66] = "[D]";
- keys[67] = 0x10045l;
- keynames[67] = "[E]";
- keys[68] = 0x10046l;
- keynames[68] = "[F]";
- keys[69] = 0x10047l;
- keynames[69] = "[G]";
- keys[70] = 0x10048l;
- keynames[70] = "[H]";
- keys[71] = 0x10049l;
- keynames[71] = "[I]";
- keys[72] = 0x1004Al;
- keynames[72] = "[J]";
- keys[73] = 0x1004Bl;
- keynames[73] = "[K]";
- keys[74] = 0x1004Cl;
- keynames[74] = "[L]";
- keys[75] = 0x1004Dl;
- keynames[75] = "[M]";
- keys[76] = 0x1004El;
- keynames[76] = "[N]";
- keys[77] = 0x1004Fl;
- keynames[77] = "[O]";
- keys[78] = 0x10050l;
- keynames[78] = "[P]";
- keys[79] = 0x10051l;
- keynames[79] = "[Q]";
- keys[80] = 0x10052l;
- keynames[80] = "[R]";
- keys[81] = 0x10053l;
- keynames[81] = "[S]";
- keys[82] = 0x10054l;
- keynames[82] = "[T]";
- keys[83] = 0x10055l;
- keynames[83] = "[U]";
- keys[84] = 0x10056l;
- keynames[84] = "[V]";
- keys[85] = 0x10057l;
- keynames[85] = "[W]";
- keys[86] = 0x10058l;
- keynames[86] = "[X]";
- keys[87] = 0x10059l;
- keynames[87] = "[Y]";
- keys[88] = 0x1005Al;
- keynames[88] = "[Z]";
- keys[89] = 0x1005Bl;
- keynames[89] = "[[]";
- keys[90] = 0x1005Cl;
- keynames[90] = "[\]";
- keys[91] = 0x1005Dl;
- keynames[91] = "[]]";
- keys[92] = 0x1005El;
- keynames[92] = "[^]";
- keys[93] = 0x1005Fl;
- keynames[93] = "[_]";
- keys[94] = 0x10060l;
- keynames[94] = "[`]";
- keys[95] = 0x10061l;
- keynames[95] = "[a]";
- keys[96] = 0x10062l;
- keynames[96] = "[b]";
- keys[97] = 0x10063l;
- keynames[97] = "[c]";
- keys[98] = 0x10064l;
- keynames[98] = "[d]";
- keys[99] = 0x10065l;
- keynames[99] = "[e]";
- keys[100] = 0x10066l;
- keynames[100] = "[f]";
- keys[101] = 0x10067l;
- keynames[101] = "[g]";
- keys[102] = 0x10068l;
- keynames[102] = "[h]";
- keys[103] = 0x10069l;
- keynames[103] = "[i]";
- keys[104] = 0x1006Al;
- keynames[104] = "[j]";
- keys[105] = 0x1006Bl;
- keynames[105] = "[k]";
- keys[106] = 0x1006Cl;
- keynames[106] = "[l]";
- keys[107] = 0x1006Dl;
- keynames[107] = "[m]";
- keys[108] = 0x1006El;
- keynames[108] = "[n]";
- keys[109] = 0x1006Fl;
- keynames[109] = "[o]";
- keys[110] = 0x10070l;
- keynames[110] = "[p]";
- keys[111] = 0x10071l;
- keynames[111] = "[q]";
- keys[112] = 0x10072l;
- keynames[112] = "[r]";
- keys[113] = 0x10073l;
- keynames[113] = "[s]";
- keys[114] = 0x10074l;
- keynames[114] = "[t]";
- keys[115] = 0x10075l;
- keynames[115] = "[u]";
- keys[116] = 0x10076l;
- keynames[116] = "[v]";
- keys[117] = 0x10077l;
- keynames[117] = "[w]";
- keys[118] = 0x10078l;
- keynames[118] = "[x]";
- keys[119] = 0x10079l;
- keynames[119] = "[y]";
- keys[120] = 0x1007Al;
- keynames[120] = "[z]";
- keys[121] = 0x1007Bl;
- keynames[121] = "[{]";
- keys[122] = 0x1007Cl;
- keynames[122] = "[|]";
- keys[123] = 0x1007Dl;
- keynames[123] = "[}]";
- keys[124] = 0x1007El;
- keynames[124] = "[~]";
- keys[125] = 0x1007Fl;
- keynames[125] = "[CTRL-BACKSPACE]";
- keys[126] = 0x100D2l;
- keynames[126] = "[WHAT]";
- keys[127] = 0x10300l;
- keynames[127] = "[CTRL-2]";
- keys[128] = 0x11000l;
- keynames[128] = "[ALT-Q]";
- keys[129] = 0x11100l;
- keynames[129] = "[ALT-W]";
- keys[130] = 0x11200l;
- keynames[130] = "[ALT-E]";
- keys[131] = 0x11300l;
- keynames[131] = "[ALT-R]";
- keys[132] = 0x11400l;
- keynames[132] = "[ALT-T]";
- keys[133] = 0x11500l;
- keynames[133] = "[ALT-Y]";
- keys[134] = 0x11600l;
- keynames[134] = "[ALT-U]";
- keys[135] = 0x11700l;
- keynames[135] = "[ALT-I]";
- keys[136] = 0x11800l;
- keynames[136] = "[ALT-O]";
- keys[137] = 0x11900l;
- keynames[137] = "[ALT-P]";
- keys[138] = 0x11E00l;
- keynames[138] = "[ALT-A]";
- keys[139] = 0x11F00l;
- keynames[139] = "[ALT-S]";
- keys[140] = 0x12000l;
- keynames[140] = "[ALT-D]";
- keys[141] = 0x12100l;
- keynames[141] = "[ALT-E]";
- keys[142] = 0x12200l;
- keynames[142] = "[ALT-G]";
- keys[143] = 0x12300l;
- keynames[143] = "[ALT-H]";
- keys[144] = 0x12400l;
- keynames[144] = "[ALT-J]";
- keys[145] = 0x12500l;
- keynames[145] = "[ALT-K]";
- keys[146] = 0x12600l;
- keynames[146] = "[ALT-L]";
- keys[147] = 0x12C00l;
- keynames[147] = "[ALT-Z]";
- keys[148] = 0x12D00l;
- keynames[148] = "[ALT-X]";
- keys[149] = 0x12E00l;
- keynames[149] = "[ALT-C]";
- keys[150] = 0x12F00l;
- keynames[150] = "[ALT-V]";
- keys[151] = 0x13000l;
- keynames[151] = "[ALT-B]";
- keys[152] = 0x13100l;
- keynames[152] = "[ALT-N]";
- keys[153] = 0x13200l;
- keynames[153] = "[ALT-M]";
- keys[154] = 0x13B00l;
- keynames[154] = "[F1]";
- keys[155] = 0x13C00l;
- keynames[155] = "[F2]";
- keys[156] = 0x13D00l;
- keynames[156] = "[F3]";
- keys[157] = 0x13E00l;
- keynames[157] = "[F4]";
- keys[158] = 0x13F00l;
- keynames[158] = "[F5]";
- keys[159] = 0x14000l;
- keynames[159] = "[F6]";
- keys[160] = 0x14100l;
- keynames[160] = "[F7]";
- keys[161] = 0x14200l;
- keynames[161] = "[F8]";
- keys[162] = 0x14300l;
- keynames[162] = "[F9]";
- keys[163] = 0x14400l;
- keynames[163] = "[F10]";
- keys[164] = 0x14700l;
- keynames[164] = "[HOME]";
- keys[165] = 0x14800l;
- keynames[165] = "[ARROW-UP]";
- keys[166] = 0x14900l;
- keynames[166] = "[PAGE-UP]";
- keys[167] = 0x14B00l;
- keynames[167] = "[ARROW-LEFT]";
- keys[168] = 0x14D00l;
- keynames[168] = "[ARROW-RIGHT]";
- keys[169] = 0x14F00l;
- keynames[169] = "[END]";
- keys[170] = 0x15000l;
- keynames[170] = "[ARROW-DOWN]";
- keys[171] = 0x15100l;
- keynames[171] = "[PAGE-DOWN]";
- keys[172] = 0x15200l;
- keynames[172] = "[INSERT]";
- keys[173] = 0x15300l;
- keynames[173] = "[DELETE]";
- keys[174] = 0x15E00l;
- keynames[174] = "[CTRL-F1]";
- keys[175] = 0x15F00l;
- keynames[175] = "[CTRL-F2]";
- keys[176] = 0x16000l;
- keynames[176] = "[CTRL-F3]";
- keys[177] = 0x16100l;
- keynames[177] = "[CTRL-F4]";
- keys[178] = 0x16200l;
- keynames[178] = "[CTRL-F5]";
- keys[179] = 0x16300l;
- keynames[179] = "[CTRL-F6]";
- keys[180] = 0x16400l;
- keynames[180] = "[CTRL-F7]";
- keys[181] = 0x16500l;
- keynames[181] = "[CTRL-F8]";
- keys[182] = 0x16600l;
- keynames[182] = "[CTRL-F9]";
- keys[183] = 0x16700l;
- keynames[183] = "[CTRL-F10]";
- keys[184] = 0x16800l;
- keynames[184] = "[ALT-F1]";
- keys[185] = 0x16900l;
- keynames[185] = "[ALT-F2]";
- keys[186] = 0x16A00l;
- keynames[186] = "[ALT-F3]";
- keys[187] = 0x16B00l;
- keynames[187] = "[ALT-F4]";
- keys[188] = 0x16C00l;
- keynames[188] = "[ALT-F5]";
- keys[189] = 0x16D00l;
- keynames[189] = "[ALT-F6]";
- keys[190] = 0x16E00l;
- keynames[190] = "[ALT-F7]";
- keys[191] = 0x16F00l;
- keynames[191] = "[ALT-F8]";
- keys[192] = 0x17000l;
- keynames[192] = "[ALT-F9]";
- keys[193] = 0x17100l;
- keynames[193] = "[ALT-F10]";
- keys[194] = 0x17300l;
- keynames[194] = "[CTRL-ARROW-LEFT]";
- keys[195] = 0x17400l;
- keynames[195] = "[CTRL-ARROW-RIGHT]";
- keys[196] = 0x17500l;
- keynames[196] = "[CTRL-END]";
- keys[197] = 0x17600l;
- keynames[197] = "[CTRL-PAGE-DOWN]";
- keys[198] = 0x17700l;
- keynames[198] = "[CTRL-HOME]";
- keys[199] = 0x17800l;
- keynames[199] = "[ALT-1]";
- keys[200] = 0x17900l;
- keynames[200] = "[ALT-2]";
- keys[201] = 0x17A00l;
- keynames[201] = "[ALT-3]";
- keys[202] = 0x17B00l;
- keynames[202] = "[ALT-4]";
- keys[203] = 0x17C00l;
- keynames[203] = "[ALT-5]";
- keys[204] = 0x17D00l;
- keynames[204] = "[ALT-6]";
- keys[205] = 0x17E00l;
- keynames[205] = "[ALT-7]";
- keys[206] = 0x17F00l;
- keynames[206] = "[ALT-8]";
- keys[207] = 0x18000l;
- keynames[207] = "[SHIFT-ALT-9]";
- keys[208] = 0x18100l;
- keynames[208] = "[SHIFT-ALT-0]";
- keys[209] = 0x18200l;
- keynames[209] = "[ALT-UNDERSCORE]";
- keys[210] = 0x18300l;
- keynames[210] = "[ALT-PLUS]";
- keys[211] = 0x20300l;
- keynames[211] = "[CTRL-@]";
- keys[212] = 0x20F00l;
- keynames[212] = "[BACKTAB]";
- keys[213] = 0x21000l;
- keynames[213] = "[SHIFT-ALT-Q]";
- keys[214] = 0x21100l;
- keynames[214] = "[SHIFT-ALT-W]";
- keys[215] = 0x21200l;
- keynames[215] = "[SHIFT-ALT-E]";
- keys[216] = 0x21300l;
- keynames[216] = "[SHIFT-ALT-R]";
- keys[217] = 0x21400l;
- keynames[217] = "[SHIFT-ALT-T]";
- keys[218] = 0x21500l;
- keynames[218] = "[SHIFT-ALT-Y]";
- keys[219] = 0x21600l;
- keynames[219] = "[SHIFT-ALT-U]";
- keys[220] = 0x21700l;
- keynames[220] = "[SHIFT-ALT-I]";
- keys[221] = 0x21800l;
- keynames[221] = "[SHIFT-ALT-O]";
- keys[222] = 0x21900l;
- keynames[222] = "[SHIFT-ALT-P]";
- keys[223] = 0x21E00l;
- keynames[223] = "[SHIFT-ALT-A]";
- keys[224] = 0x21F00l;
- keynames[224] = "[SHIFT-ALT-S]";
- keys[225] = 0x22000l;
- keynames[225] = "[SHIFT-ALT-D]";
- keys[226] = 0x22100l;
- keynames[226] = "[SHIFT-ALT-F]";
- keys[227] = 0x22200l;
- keynames[227] = "[SHIFT-ALT-G]";
- keys[228] = 0x22300l;
- keynames[228] = "[SHIFT-ALT-H]";
- keys[229] = 0x22400l;
- keynames[229] = "[SHIFT-ALT-J]";
- keys[230] = 0x22500l;
- keynames[230] = "[SHIFT-ALT-K]";
- keys[231] = 0x22600l;
- keynames[231] = "[SHIFT-ALT-L]";
- keys[232] = 0x22C00l;
- keynames[232] = "[SHIFT-ALT-Z]";
- keys[233] = 0x22D00l;
- keynames[233] = "[SHIFT-ALT-X]";
- keys[234] = 0x22E00l;
- keynames[234] = "[SHIFT-ALT-C]";
- keys[235] = 0x22F00l;
- keynames[235] = "[SHIFT-ALT-V]";
- keys[236] = 0x23000l;
- keynames[236] = "[SHIFT-ALT-B]";
- keys[237] = 0x23100l;
- keynames[237] = "[SHIFT-ALT-N]";
- keys[238] = 0x23200l;
- keynames[238] = "[SHIFT-ALT-M]";
- keys[239] = 0x24700l;
- keynames[239] = "[SHIFT-HOME]";
- keys[240] = 0x24800l;
- keynames[240] = "[SHIFT-ARROW-UP]";
- keys[241] = 0x24900l;
- keynames[241] = "[SHIFT-PAGE-UP]";
- keys[242] = 0x24B00l;
- keynames[242] = "[SHIFT-ARROW-LEFT]";
- keys[243] = 0x24D00l;
- keynames[243] = "[SHIFT-ARROW-RIGHT]";
- keys[244] = 0x24F00l;
- keynames[244] = "[SHIFT-END]";
- keys[245] = 0x25000l;
- keynames[245] = "[SHIFT-ARROW-DOWN]";
- keys[246] = 0x25100l;
- keynames[246] = "[SHIFT-PAGE-DOWN]";
- keys[247] = 0x25200l;
- keynames[247] = "[SHIFT-INSERT]";
- keys[248] = 0x25300l;
- keynames[248] = "[SHIFT-DELETE]";
- keys[249] = 0x25400l;
- keynames[249] = "[SHIFT-F1]";
- keys[250] = 0x25500l;
- keynames[250] = "[SHIFT-F2]";
- keys[251] = 0x25600l;
- keynames[251] = "[SHIFT-F3]";
- keys[252] = 0x25700l;
- keynames[252] = "[SHIFT-F4]";
- keys[253] = 0x25800l;
- keynames[253] = "[SHIFT-F5]";
- keys[254] = 0x25900l;
- keynames[254] = "[SHIFT-F6]";
- keys[255] = 0x25A00l;
- keynames[255] = "[SHIFT-F7]";
- keys[256] = 0x25B00l;
- keynames[256] = "[SHIFT-F8]";
- keys[257] = 0x25C00l;
- keynames[257] = "[SHIFT-F9]";
- keys[258] = 0x25D00l;
- keynames[258] = "[SHIFT-F10]";
- keys[259] = 0x27800l;
- keynames[259] = "[SHIFT-ALT-1]";
- keys[260] = 0x27900l;
- keynames[260] = "[SHIFT-ALT-2]";
- keys[261] = 0x27A00l;
- keynames[261] = "[SHIFT-ALT-3]";
- keys[262] = 0x27B00l;
- keynames[262] = "[SHIFT-ALT-4]";
- keys[263] = 0x27C00l;
- keynames[263] = "[SHIFT-ALT-5]";
- keys[264] = 0x27D00l;
- keynames[264] = "[SHIFT-ALT-6]";
- keys[265] = 0x27E00l;
- keynames[265] = "[SHIFT-ALT-7]";
- keys[266] = 0x27F00l;
- keynames[266] = "[SHIFT-ALT-8]";
-
- keys[267] = 0x28000l;
- keynames[267] = "[ALT-9]";
- keys[268] = 0x28100l;
- keynames[268] = "[ALT-0]";
- keys[269] = 0x28200l;
- keynames[269] = "[ALT-MINUS]";
- keys[270] = 0x28300l;
- keynames[270] = "[ALT-EQUAL]";
- keys[271] = 0x28400l;
- keynames[271] = "[CTRL-PAGE-UP]";
-
-
- };
-
- /* BOXTEXT OFFSETS */
- #define BOX_X 3+1
- #define BOX_Y 3+1
-
- /* HOW BIG OF A BOX DOES BOXTEXT NEED TO MAKE ? */
- #define boxsizex(data) textwidth(data)+BOX_X+BOX_X
- #define boxsizey(data) textheight(data)+BOX_Y+BOX_Y
-
-
- /* routine to print a text in a box
- The text will have BOX_X-1 pixels between it and the horiz. walls.
- The text will have BOX_Y-1 pixels between it and the vert. walls.
- The text will be white pixels on a black background.
- */
- void boxtext(int x, int y, char *data)
-
- {
- int sx, sy;
-
- sx = boxsizex(data);
- sy = boxsizey(data);
-
- /* clear area for text */
- setfillstyle(0,0);
- bar(x, y,
- x+sx, y+sy);
-
- /* put a box at edge of cleared area */
- setcolor(15);
- rectangle(x, y,
- x+sx, y+sy);
-
- outtextxy(x+BOX_X,y+BOX_Y,data);
- };
-
-
-
- /* routine to do a function for each line in a string
- the lines are delimeted by '\n'
-
- this fn is not used yet.
- */
- void doeach_line(int x, int y, char *data, fn funct)
- {
- char part[180];
- int i =0;
- int tot;
-
- tot = strlen(data);
- accumx=0;
- accumy=0;
-
- loop:
- while (data[i] >=' ') part[i] = data[i++];
- part[i]='\0';
-
- funct(x,y,part);
- if (i<=tot) goto loop;
-
- };
-
-
- struct submenu {
- /* how the user describes this submenu entry */
- unsigned char direction;/* HORIZONTAL, VERTICAL, INVISIBLE */
- long int choicekey; /* simple key to activate this submenu */
- int lastchoice; /* offset of last submenu of this menu that was used */
- char *shortname; /* name of this menu/function */
- char *longname; /* title line for submenu (or blank or zero) */
- fn *funct;
- int style; /* background style */
-
- /* relationship to other submenu entries */
- struct submenu *next; /* right pointer */
- struct submenu *prev; /* left pointer */
- struct submenu *sub; /* down pointer */
- struct submenu *esc; /* up pointer */
-
- /* screen stuff */
- int startx, starty; /* where shortname starts at (on the screen) */
- int belowx, belowy; /* where longname would be put for submenu */
- int sizex, sizey; /* graphics size of shortname */
- };
-
-
- extern long int the_key=0; /* function key value */
- long int keystack[900];
- extern int keys_ptr=0;
-
-
-
- void undo_macro(struct submenu *one);
- void mk_macro();
-
- void savescr();
- void restorescr();
- int indexof(long int lkey);
- void get_stack_key();
- void doeach_entry(struct submenu *it, fn funct);
- void def_submenu(char choice, char *shortname, char *longname);
- void endef_submenu(char *matchshort); /* repeat shortname to match & debug */
- void def_entry(char choice, char *shortname, fn funct );
- void menu_fn(fn funct );
- void menu_horizontal();
- void menu_invisible();
-
-
- void nofn() {}; /* default function does nothing */
-
- #define MAXKEYS 500
- #define NUM_MYKEYS 8
- char *fkeynames[MAXKEYS+NUM_MYKEYS+2] = {0};
- fn *hotkeyfn[MAXKEYS+NUM_MYKEYS+2] = {nofn};
- int enable_hotkeys = 1;
-
- void prep_submenu(struct submenu *it);
- void dump_submenu(int x, int y, struct submenu *it);
- int key_submenu(struct submenu *it);
- void update_submenu(struct submenu *it);
-
- int find_fnindex(fn *thisfn);
- void padtext(int x, int y, char *data, int style);
-
-
-
-
- #define KEY_RIGHT MAXKEYS+1
- #define KEY_LEFT MAXKEYS+2
- #define KEY_SUB MAXKEYS+3
- #define KEY_ESC MAXKEYS+4
- #define KEY_TOTAL_ESC MAXKEYS+5
- #define KEY_DOWN MAXKEYS+6
- #define KEY_UP MAXKEYS+7
-
-
-
- /* This routine allows the user to define a function-key.
- The keynum is "made up" by the user.
- It is a value between 1 and MAXKEYS and is used to match a keyboard entry
- to the key.
-
- The keyboard entry assigned to this function key is passed as an ASCII name.
- The name for this keyboard entry is passed as keyname.
- Any value may be entered and the fkey may be
- re-defined later and saved in a config. file.
-
- From now on, whenever keyname is typed on the keyboard, fkey will be
- returned as a value. The name of fkey is fkeyname.
- */
- int def_fkey(int fkey, char *keyname, char *fkeyname);
- void user_menus(); /* this is defined by the user */
- void menu_run(); /* how to run the menu system */
-
-
- void read_config();
- void write_config();
-
-
- long int lkeyof(char ch);
-
-
-
-
- void init_fkeys()
- {
- def_fkey(KEY_RIGHT, "[ARROW-RIGHT]", "<KEY-RIGHT>" );
- def_fkey(KEY_LEFT, "[ARROW-LEFT]", "<KEY-LEFT>" );
- def_fkey(KEY_SUB, "[ENTER]", "<KEY-SUB>" );
- def_fkey(KEY_ESC, "[ESCAPE]", "<KEY-ESC>" );
- def_fkey(KEY_TOTAL_ESC, "[ALT-X]", "<KEY-TOTAL-ESC>" );
- def_fkey(KEY_DOWN, "[ARROW-DOWN]", "<KEY-DOWN>" );
- def_fkey(KEY_UP, "[ARROW-UP]", "<KEY-UP>" );
- };
-
-
-
-
-
- /* define a user defined key as being a 'hot' key.
- Whenever the key is encountered by the decoding routine, the
- given function will be executed.
- */
- void hot_key(int keynum, fn funct)
- {
- if( (keynum>0) && (keynum <= MAXKEYS) ){
- hotkeyfn[keynum] = funct;
- };
- };
-
-
-
-
-
- #define VERTICAL 1 /* default is vertical (after first level or horiz.) */
- #define HORIZONTAL 2
- #define INVISIBLE 3 /* the root and the subroots are place holders */
-
-
-
- /* close down the graphics system
- print an error message
- stop the program.
- */
- void g_failure(char *text)
- {
- closegraph();
- fprintf(stderr,"%s\n",text);
- exit(256);
- };
-
-
- /* get memory
- if we can't then abort
- entry: assume we will be in graphics mode
- */
- void *g_malloc(int siz)
-
- {
- void *mem;
-
- mem = malloc(siz+3);
- if (mem==NULL) {
- g_failure("Out of memory\n");
- };
- return(mem);
- };
-
-
-
- struct submenu example;
-
- extern struct submenu *rootmenu=0;
- struct submenu *curmenu;
-
- struct submenu *newmenu(fn *nofn)
- {
- struct submenu *it;
-
- it = g_malloc(sizeof(example));
- it->direction = VERTICAL;
- it->choicekey = 0; /* how to choose this menu by letter from "above" */
- it->lastchoice = 0; /* which entry "below" here was chosen last time */
- it->shortname = "unknown";
- it->longname = "unknown title line";
- it->funct = nofn;
- it->style = 9;
-
-
- it->next = 0;
- it->prev = 0;
- it->sub = 0;
- it->esc = 0;
-
- it->startx = 0;
- it->starty = 0;
- it->belowx = 0;
- it->belowy = 0;
- it->sizex = 0;
- it->sizey = 0;
-
- return(it);
- };
-
-
-
-
-
-
-
- int convert_case = 1; /* 0=don't convert lower to upper 1=do */
-
-
-
-
-
- void def_submenu(char choice, char *sname, char *lname)
- {
- struct submenu *it, *sub1;
-
-
- it = newmenu(nofn);
-
- it->choicekey = lkeyof(choice); /* how this sub-menu is activated */
- /* funct defaults to nothing */
- it->shortname = sname;
- it->sizex = boxsizex(sname);
- it->sizey = boxsizey(sname);
- it->longname = lname;
-
-
- curmenu->next = it;
- it->prev = curmenu;
- it->next = 0;
- it->esc = curmenu->esc;
-
-
- sub1 = newmenu(nofn);
- it->sub = sub1;
- /* make a root for the submenu so that we don't need to make a flag
- which would determine whether the next 'newmenu' is supposed to
- attach to the 'next' or to the 'sub'. Since we have this dummy
- root, everything attaches to the 'next' and this root attaches to
- the 'sub'. */
- sub1->esc = it;
- sub1->direction = INVISIBLE;
-
-
- /* how do we define sub1, other than as a root? */
-
-
-
- curmenu = sub1; /* curmenu=curmenu->next; curmenu=curmenu->sub; */
-
-
- #ifdef DEBUG
- fprintf(dbout,"def_submenu %s\n",sname);
- #endif
- };
-
-
-
-
- void new_fn(fn thisfn)
- {
- int i;
- char fnname1[20], *fnname = fnname1;
-
- i = find_fnindex(thisfn);
- if (i==0) {
- for(i=MAXKEYS-1;i>1;i--){
- if( (hotkeyfn[i] == nofn) || (hotkeyfn[i]==0) ){
- goto add;
- };
- };
- padtext(50,150,"Ran out of room in hotkey table",8);
- i = MAXKEYS-1;
-
- add:
- sprintf(fnname,"<0x%8.8lX>",thisfn);
- fkeynames[i] = strcpy( g_malloc(strlen(fnname)),fnname);
- hot_key(i,thisfn);
-
- };
- };
-
-
-
-
-
- void def_entry(char choice, char *sname, fn userfunct)
- {
- struct submenu *it;
-
- it = newmenu(nofn);
-
- it->choicekey = lkeyof(choice); /* how this sub-menu is activated */
- new_fn(userfunct);
- it->funct = userfunct;
- it->shortname = sname;
- it->sizex = boxsizex(sname);
- it->sizey = boxsizey(sname);
- it->longname = sname;
-
- curmenu->next = it;
- it->prev = curmenu;
-
-
- it->esc = curmenu->esc;
- /*it->sub is undefined*/
-
- curmenu = it;
- #ifdef DEBUG
- fprintf(dbout,"def_entry %s\n",sname);
- #endif
- };
-
-
-
- void menu_fn(fn funct)
- {
- /*
- Attach the function to the last completed menu or entry.
- */
- curmenu->funct = funct;
- new_fn(funct);
- };
-
-
-
- /* define function and/or direction after endef_submenu is called.
- */
- void menu_horizontal()
- {
- curmenu->direction = HORIZONTAL;
- };
-
- void menu_style(int i)
- {
- curmenu->style = i;
- };
-
-
- void menu_invisible()
- {
- curmenu->direction = INVISIBLE;
- };
-
-
-
- void endef_submenu(char *match)
- {
- char data[80];
-
- if( strcmp(match,curmenu->esc->shortname)!=0 ) {
- sprintf(data,
- "End of menu '%s' doesn't match '%s'\n",
- match,curmenu->esc->shortname);
- g_failure(data);
- };
-
- curmenu = curmenu->esc;
- #ifdef DEBUG
- fprintf(dbout,"endef_submenu %s\n",sname);
- #endif
- };
-
-
- #ifdef DEBUG
- void debug_submenu (struct submenu *it)
- {
- if (it!=0){
- fprintf(stdprn,"'%s' of '%s' at %8.8lX\n",it->shortname,it->esc->shortname,it);
- fprintf(stdprn," below=(%d,%d), size=(%d,%d)\n",
- it->belowx,it->belowy,it->sizex,it->sizey);
- fprintf(stdprn,"next ");
- debug_submenu(it->next);
- fprintf(stdprn,"sub ");
- debug_submenu(it->sub);
- fprintf(stdprn,"\n");
- };
- };
- #endif DEBUG
-
-
- fn *donefun = nofn; /* function that the user requested with the menus */
- struct submenu *donecur;/* cursor to pass to donefun() */
- static int quitflag=0; /* flag for total_esc feature */
-
-
-
- /* footpad OFFSETS -- this defines how much space to leave around the
- requested area for a background.
- */
- #define PAD_X 10
- #define PAD_Y 6
-
- /* Routine to make a background for a menu or isolated boxtext.
- Returns a pointer to the saved graphics "below" the footpad
- which is suitable to pass to the undo_footpad routine.
- */
- void *make_footpad(int x, int y, int accumx, int accumy, int style)
- {
- int menuside = 1;
- void *mem;
- int lowx, lowy;
-
- lowx = x-PAD_X;
- if (lowx<0) lowx=0;
-
- lowy = y-PAD_Y;
- if (lowy<0) lowy=0;
-
- /* save the menu area from being modified (allocate mem) */
- mem = g_malloc( imagesize(
- lowx, lowy,
- x+accumx+PAD_X, y+accumy+PAD_Y
- ) );
- getimage(lowx, lowy,
- x+accumx+PAD_X, y+accumy+PAD_Y,
- mem);
-
-
-
- /* clear area for menu */
- /* yes, i know this is one pixel smaller than the saved area in
- both the horizontal and vertical. But turboc graphics seems
- to have a 1 pixel vertical bug somewhere and the horizontal
- is for symmetry.
- */
- setfillstyle(style,style); /* manual is ambiguous where to put style */
- bar(lowx,lowy,x+accumx+PAD_X-1,y+accumy+PAD_Y-1);
-
-
-
- if (style==1) {
- setcolor(0);
- }else{
- setcolor(15); /* our box is going to be white */
- };
-
-
- /* IF BACKGROUND IS EMPTY (BLACK), THEN INCREASE menuside
- if (style==0) menuside++;
- */
- rectangle(lowx+menuside, lowy+menuside,
- x+PAD_X+accumx-menuside, y+PAD_Y+accumy-menuside);
-
-
- return(mem);
- };
-
-
-
- /* routine to undo the make_footpad() routine by restoreing the saved data
- */
- void undo_footpad(int x, int y, void *mem)
- {
- int lowx, lowy;
-
- lowx = x-PAD_X;
- if (lowx<0) lowx=0;
-
- lowy = y-PAD_Y;
- if (lowy<0) lowy=0;
-
- if (mem) {
- putimage(lowx,lowy,mem,0);
- free(mem);
- };
-
- };
-
-
- /* function to make a footpad and put a message there
- wait for a key, then remove the message
- */
- void padtext(int x, int y, char *data, int style)
- {
- int dx, dy;
- void *mem;
-
- dx = boxsizex(data);
- dy = boxsizey(data);
-
- if(x+dx+PAD_X+1>getmaxx()) x=PAD_X;
- if(y+dy+PAD_Y+1>getmaxy()) y=PAD_Y;
- if ( (x+dx+PAD_X+1>getmaxx()) || (y+dy+PAD_Y+1>getmaxy()) ) {
- g_failure("data given to padtext is too large for screen");
- };
-
- mem = make_footpad(x,y,dx,dy,style);
- boxtext(x,y,data);
- if (style) {
- get_stack_key();
- }else{ /* style 0 is for big errors only */
- the_key = get_key();
- };
- undo_footpad(x,y,mem);
- };
-
-
- int find_fnindex(fn *thisfn)
- {
- int i;
-
- for(i=1;i<MAXKEYS+NUM_MYKEYS;i++){
- if (hotkeyfn[i] == thisfn) {
- return(i);
- };
- };
- return(0);
- };
-
-
-
-
- void meta_hotkey(struct submenu *here)
- {
- int x,y;
- fn *thisfn;
- char data[80];
- int ikey;
-
- int i;
- char fnname1[40], *fnname=fnname1;
-
-
- x = here->belowx; y = here->belowy;
- thisfn = here->funct;
-
- new_fn(thisfn);
-
- i = find_fnindex(thisfn);
- if (i) {
- fnname = fkeynames[i];
- }else{
- g_failure("Not enough room in hot key table.");
- };
-
-
- add:
- padtext(x,y,"Press the key you wish to assign this function to.",0);
- /* get_stack_key(); padtext gets key for us */
- ikey = indexof(the_key);
- def_fkey(i,keynames[ikey],fnname);
- sprintf(data,"key %s assigned function %s",keynames[ikey],fnname);
- padtext(x,y,data,1);
-
-
- quit:
- ;
- };
-
-
-
-
- void mk_invisible(struct submenu *one)
- {
- one->direction = INVISIBLE;
- };
- void mk_horiz(struct submenu *one)
- {
- one->direction = HORIZONTAL;
- };
- void mk_vert(struct submenu *one)
- {
- one->direction = VERTICAL;
- };
- void delta_style(struct submenu *one)
- {
- one->style--;
- if (one->style<0) one->style=14;
- };
-
- void mk_visible(struct submenu *one)
- {
- struct submenu *each = one->esc->sub;
-
- while (each != 0) {
- each->direction = VERTICAL;
- each = each->next;
- };
- };
-
- void asgn_escape(struct submenu *one)
- {
- int ikey;
-
- padtext(one->belowx,one->belowy,"Which key should become <ESCAPE>?",0);
-
- ikey = indexof(the_key);
- padtext(50,50,keynames[ikey],1);
- def_fkey(KEY_ESC, keynames[ikey], "<KEY-ESC>" );
- };
-
-
- void g_system(char *text)
- {
- int i;
- savescr();
- i = system(text);
- (void) get_key();
- restorescr();
- if (i) padtext(50,50,"DOS error",5);
- };
-
- void short_dir()
- {
- g_system("dir /w");
- };
-
- void long_dir()
- {
- g_system("dir");
- };
-
- void alpha_dir()
- {
- g_system("ds ne");
- };
-
-
- int keyready()
- {
- return ( (bioskey(1)) || (keys_ptr!=0) );
- };
-
- static void *memory=0; /* last value of 'memory' variable */
- static int glob_x,glob_y;
-
- void MM_right(struct submenu *one)
- {
- undo_footpad(glob_x,glob_y,memory);
- one->esc->sub->startx++;
-
- if (!keyready()) {
- update_submenu(one->esc->sub);
- }else{
- memory = 0;
- };
- };
-
- void MM_left(struct submenu *one)
- {
- undo_footpad(glob_x,glob_y,memory);
- one->esc->sub->startx--;
-
- if (!keyready()) {
- update_submenu(one->esc->sub);
- }else{
- memory = 0;
- };
- };
- void MM_up(struct submenu *one)
- {
- undo_footpad(glob_x,glob_y,memory);
- one->esc->sub->starty--;
-
- if (!keyready()) {
- update_submenu(one->esc->sub);
- }else{
- memory = 0;
- };
- };
- void MM_down(struct submenu *one)
- {
- undo_footpad(glob_x,glob_y,memory);
- one->esc->sub->starty++;
-
- if (!keyready()) {
- update_submenu(one->esc->sub);
- }else{
- memory = 0;
- };
- };
-
- void DOSshell()
- {
- g_system("");
- };
-
-
- /* this must be called before anything else may be called.
- initgr() should be called before this.
- */
- void menu_init()
- {
- rootmenu = newmenu(nofn);
- curmenu = rootmenu;
- rootmenu->direction = INVISIBLE;
- rootmenu->shortname = "rootmenu";
- rootmenu->longname = "";
- rootmenu->esc = rootmenu;
- rootmenu->sub = rootmenu;
- rootmenu->belowx = 0;
- rootmenu->belowy = 0;
-
- init_keys();
- init_fkeys();
-
- menu_horizontal(); /* default is vertical */
- user_menus();
- def_submenu('U',"Utilities","--- utilities ---");
- def_submenu('K',"Keys"," -- key utilities -- ");
- def_entry('H',"assign Hotkey to menu entry's function",meta_hotkey);
- def_entry('E',"assign Escape key",asgn_escape);
- def_entry('M',"define key Macro",mk_macro);
- def_entry('U',"Undefine macro",undo_macro);
-
- /*
- do this just like assign escape key, but let them pick
- which key will be assigned
- def_entry('F',"define a function key",nofn);
-
- If a keyboard lkey or a hotkey function has the wrong name
- or no name at all, then these features will allow the user
- to correct that.
- def_entry('N',"Give an ASCII name to a keyboard key",nofn);
- def_entry('n',"Give an ASCII name to a hotkey function",nofn);
- */
- endef_submenu("Keys");
-
- def_submenu('M',"Menus"," -- hotkey menu utilities -- ");
- def_entry('C',"Change background color",delta_style);
- def_entry('H',"Make menu horizontal",mk_horiz);
- def_entry('V',"Make menu vertical",mk_vert);
- def_entry('I',"Make menu entry invisible",mk_invisible);
- def_entry('V',"Make entries visible in this menu",mk_visible);
- def_submenu('M',"Move menu","moving menus on the screen");
- def_entry('R',"to the Right",MM_right);
- def_entry('L',"to the Left",MM_left);
- def_entry('U',"Upward",MM_up);
- def_entry('D',"Downward",MM_down);
- endef_submenu("Move menu");
- /*
- def_entry('P',"Prune menu entry",nofn);
- def_entry('G',"Graft menu entry",nofn);
- */
- endef_submenu("Menus");
- def_submenu('D',"Disk"," -- disk stuff -- ");
- /*
- def_entry('C',"Change subdirectory",nofn);
- */
- def_entry('L',"show Long directory",long_dir);
- def_entry('S',"show Short directory",short_dir);
- def_entry('A',"Alphabetize directory",alpha_dir);
- def_entry('D',"DOS shell",DOSshell);
- def_entry('W',"Write configuration to disk",write_config);
- def_entry('R',"Read configuration from disk",read_config);
-
- endef_submenu("Disk");
- endef_submenu("Utilities");
- };
-
-
-
-
-
- /* size and print a menu on the display using a backdrop and boxes.
- (save old contents of area)
- */
- void update_submenu(struct submenu *it)
- {
- int ax, ay;
- int maxx, maxy;
-
-
- maxx = getmaxx();
- maxy = getmaxy();
-
-
-
-
- /* check to see if the menu has an starting point */
- ax = (it->esc->sub->startx);
- ay = (it->esc->sub->starty);
- if( (ax!=0) || (ay!=0) ) {
- glob_x = ax;
- glob_y = ay;
- }else{ /* if not, use default */
- glob_x = it->esc->belowx+PAD_X;
- glob_y = it->esc->belowy+PAD_Y;
- };
-
-
- /* this sets up the accumx and accumy locations */
- prep_submenu(it); /* measure size of menu */
-
-
- if (glob_x+PAD_X+accumx+1>maxx) glob_x=PAD_X;
- if (glob_y+PAD_Y+accumy+1>maxy) glob_y=PAD_Y;
-
- if( (glob_x+PAD_X+accumx+1>maxx) || (glob_y+PAD_Y+accumy+1>maxy) ) {
- g_failure("Menu doesn't fit on screen\n");
- };
-
- /* whatever the starting point for the menu turns out to be
- SAVE IT FOR LATER
- */
- it->esc->sub->startx = glob_x;
- it->esc->sub->starty = glob_y;
-
-
- /* make an area for the menu */
- memory = make_footpad(glob_x,glob_y,accumx,accumy,it->esc->style);
-
- /* dump menu in glob_x,glob_y footpad */
- dump_submenu(glob_x,glob_y,it);
- };
-
-
-
- /* print the menu, get the action, remove the menu
- */
- int run_submenu(struct submenu *it)
- {
- int retval;
-
- if (it==0) return(0);
- it->funct(it);
-
-
- /* this makes glob_x and glob_y,
- saves the background,
- and puts the menu on the screen
- */
- update_submenu(it);
-
-
- /* use the menu */
- retval = key_submenu(it);
-
-
- /* restore area that was saved (release memory) */
- undo_footpad(glob_x,glob_y,memory);
- memory = 0;
-
- return(retval);
- };
-
-
-
-
- int subrun_submenu(struct submenu *it)
- {
- void *savemem;
- int savex, savey;
-
- if (it==0) return(quitflag);
-
-
- /* if submenu doesn't exist, then just execute the function */
- if( (it->sub==0) || (it == it->sub) ) {
- donefun = it->funct;
- donecur = it;
- quitflag = 1;
-
- /* totally quit this menu so we can run the 'donefun' function */
- return(quitflag);
- };
-
-
- /* here we save the global variable 'memory' so that it remains a global
- and can be accessed globally, and yet it is local to the level of the
- menu that we are on and is not destroyed.
- */
- savemem = memory;
- savex = glob_x;
- savey = glob_y;
- quitflag = run_submenu(it->sub);
- glob_x = savex;
- glob_y = savey;
- memory = savemem;
-
-
- return(quitflag);
- };
-
-
-
-
-
-
-
- /* find the index for a keyboard key given it's name
- */
- int indexofname(char *name)
- {
- int i;
-
- for(i=0;i<LASTKEY;i++){
- if( strcmp(keynames[i],name)==0 ){
- return(i);
- };
- };
- return(0);
- };
-
-
-
-
- /* find the long word that the keyboard will give for a character
- find it given that we know the character's ASCII value
- */
- long int lkeyof(char ch)
- {
- char d0[10], *data=d0;
-
- switch (ch) {
- case '\t' :
- data = "[TAB]";
- case '\n' :
- data = "[ENTER]";
- default :
- data[0] = '[';
- data[1] = ch;
- data[2] = ']';
- data[3] = '\0';
- };
-
- return( keys[ indexofname(data) ] );
- };
-
-
-
-
- /* find the index of a keyboard key given the keyboard long word
- */
- int indexof(long int lkey)
- {
- int i;
-
- for (i=0;i<LASTKEY;i++){
- if ( lkey == keys[i] ) return(i);
- };
- return(0);
- };
-
-
-
- /* find the last entry of the macro
- */
- struct mac *lastof(struct mac *mac)
- {
- struct mac *amac = mac;
-
- if (amac==0) return(amac);
-
- top:
- if (amac->next==0) return(amac);
- amac = amac->next;
- goto top;
- };
-
-
- /* get the next key off the stack
- or get another key from the keyboard if the stack is empty
- if the keyboard key is a macro, then expand it and put it on the stack.
- */
- void get_stack_key()
- {
- /*int fkey; * function key value */
- int ikey; /* index into key table */
- struct mac *amacro;
-
- if (keys_ptr) {
- the_key = keystack[--keys_ptr];
- }else{
-
- the_key = get_key();
- ikey = indexof(the_key);
- if (ikey) {
- amacro = lastof(mac[ikey]);
- if (amacro) {
- while (amacro){
- keystack[keys_ptr++] = amacro->fkey;
- amacro = amacro->prev;
- };
- the_key = keystack[--keys_ptr];
- };
- };
-
- };
- };
-
-
-
-
- /* this puts a cursor around the submenu item
- we want to change this [;] to invert the area of the screen.
- */
- void cursdo(struct submenu *it)
- {
-
- if (it->prev != 0) {
- #define CURSMARG 2
- rectangle(it->startx+CURSMARG,
- it->starty+CURSMARG,
- it->startx+it->sizex-CURSMARG,
- it->starty+it->sizey-CURSMARG
- );
- };
- };
-
- void curson(struct submenu *it)
- {
- setcolor(15);
- cursdo(it);
- };
- void cursoff(struct submenu *it)
- {
- setcolor(00);
- cursdo(it);
- };
-
-
-
-
-
- /* Get a key from the stack.
- Check to see if it is a hot key, if so do it's routine.
- Save key value in global location.
- */
- void call_for_key(struct submenu *cursor)
- {
- int i;
-
- get_stack_key();
-
- /* now call function assigned to the fkey
- */
- if( (the_key>0) && (the_key <= MAXKEYS+NUM_MYKEYS) ){
- i = (int) the_key;
- if (hotkeyfn[i]) if (enable_hotkeys) {
- cursoff(cursor);
- hotkeyfn[i](cursor);
- curson(cursor);
- };
- };
- };
-
-
-
-
-
-
-
- struct mac *new_mac()
- {
- struct mac *it;
-
- it = g_malloc( sizeof(*it) );
- return (it);
- /*
- it->next=0;
- it->prev=0;
- it->fkey=0;
- */
- };
-
-
-
- void macs_free(struct mac *start)
- {
- struct mac *nxt, *it=start;
-
- while (it!=0) {
- nxt = it->next;
- free(it);
- it = nxt;
- };
- };
-
-
- /* find the name of a keyname or function
- */
- char last_kname1[40], *last_kname = last_kname1;
- char *find_keyname(long int lkey)
- {
- int ikey;
-
- ikey = indexof(lkey);
- if (ikey) {
- sprintf(last_kname,"%s",keynames[ikey]);
- }else{
- if( (lkey>0) && (lkey <= MAXKEYS+NUM_MYKEYS) ){
- ikey = (int) lkey;
- sprintf(last_kname,"%s",fkeynames[ikey]);
- }else{
- sprintf(last_kname,"[%8.8lX]",lkey);
- };
- };
-
- return(last_kname);
- };
-
-
-
- struct mac *get_macs()
- {
- struct mac *last, *amac, *first;
-
-
- last = new_mac();
- last->next = 0;
- last->prev = 0;
- last->fkey = 0; /* make a token/spacer node which we will delete later */
-
- first = last;
-
- top:
- get_stack_key();
-
- if( (the_key == KEY_ESC) && (keys_ptr==0) ){
- amac = first->next;
- free(first);
- amac->prev=0; /* don't forget this -- it'll take you hours to fix */
- return(amac);
- };
-
- printf("%s",find_keyname(the_key));
-
- amac = new_mac();
- amac->fkey = the_key;
- amac->prev = last;
- amac->next = 0;
-
- last->next = amac;
- last = last->next;
- goto top;
-
-
- };
-
-
-
- /* function to initialize the graphics system for whatever hardware
- the user's computer happens to have.
- Used by restorescr() to 'undo' the effect of closegraph() from savescr();
- Something like this should be called by the user before menu_init() to turn
- on the graphics system.
- */
- void initgr()
- {
- int gd=DETECT;
- int gm=HERCMONOHI;
- char *pth = "D:\\TC";
-
-
- initgraph(&gd, &gm, pth);
- if (gd<0) {
- closegraph();
- fprintf(stderr,"fail %d",gd);
- exit(256);
- };
- /* graphdefaults(); */
-
- };
-
-
-
- /* function (nonrecursive) to save the screen and jump to text
- so that processing may occur in text mode (disk i/o and such)
- savescr must be called before restorescr can be called.
- */
- static void *scrdata=0;
- static fn *old_wait_key=nofn;
- void savescr()
- {
- if (scrdata==0) scrdata = g_malloc( imagesize(0,0,getmaxx(),getmaxy()) );
- getimage(0,0,getmaxx(),getmaxy(),scrdata);
- closegraph();
-
- old_wait_key = the_wait_key;
- the_wait_key = my_wait_key;
-
- enable_hotkeys=0;
- };
-
- /* function (nonrecursive) to restore the screen and jump back to graphics.
- This is the opposite of savescr();
- savescr must be called first.
- */
- void restorescr()
- {
- initgr(); /* init graphics */
- if (scrdata) putimage(0,0,scrdata,0);
-
- the_wait_key = old_wait_key;
- old_wait_key = nofn;
-
- enable_hotkeys=1; /* hope it wasn't 0 on call to savescr */
- };
-
-
-
-
-
- void undo_macro(struct submenu *one)
- {
- int ikey;
- int x,y;
-
- x = one->belowx;
- y = one->belowy;
- padtext(x,y,"Press the key from which you wish to UNASSIGN a macro.",0);
-
- /* lkey = get_key(); */
- ikey = indexof(the_key);
- if (ikey) {
- if (mac[ikey]) macs_free(mac[ikey]);
- mac[ikey] = 0;
- }else{
- padtext(x,y,"Internal problem.",8);
- };
-
- };
-
-
-
- void mk_macro()
- {
- long int lkey;
- int ikey;
- struct mac *new;
-
- savescr();
-
- printf("\
- --- Macro facility --- \n\
- \n\
- This utility allows you to define which keys will be pressed for you whenever\n\
- you press a given key. So, for example, you can assign F9 to go into the menus\n\
- and enter this utility.\n\
- \n\
- Press the key to which you wish to assign a macro: ");
-
-
-
- lkey = get_key();
- ikey = indexof(lkey);
- printf("%s\n",keynames[ikey]);
-
- if ( mac[ikey] ) {
- printf("\n\
- ----->>>>> warning: macro already exists.\n\
- Press the macro key to see it's expansion.\n\n");
- };
-
- printf("\
- Now type the keys that the macro key will expand as.\n\
- Press the <ESCAPE> function when you are done.\n");
-
- new = get_macs();
- if (mac[ikey]) macs_free(mac[ikey]);
- mac[ikey] = new;
-
-
- restorescr();
-
- };
-
-
-
-
-
- void menu_run() /* how to run the menu system */
- {
- if (debug1) boxtext(100,150,"menu_run");
-
- do {
- (void) run_submenu(rootmenu); /* 1=TOTAL_ESC, 0=ESC */
-
- memory = 0;
- donefun(donecur); /* execute the requested function */
- donefun = nofn; /* cancel any previous menu function executed */
- donecur = NULL;
- /* turn off menu from hotkey
- this fixes the bug of 'what if the menu move is executed from the
- menu instead of from a hot key? Then the menus are turned off
- (quitflag and donefun) and the function cannot move the menu!
- So we use 'memory' to keep track of these things...
- */
- if (memory) {
- undo_footpad(glob_x,glob_y,memory);
- memory = 0;
- };
-
- quitflag = 0;
-
- } while (keys_ptr);
-
- };
-
-
-
-
- void doeach_entry(struct submenu *it, void funct(struct submenu *q) )
- {
- struct submenu *each = it->next;
-
- if (debug2) {
- boxtext(100,110,"doeach_entry");
- boxtext(100,122,it->shortname);
- boxtext(100,134,each->next->shortname);
- };
-
- while (each != 0) {
- if( (each->direction != INVISIBLE) || (debug2) ){
- funct(each);
- };
- each = each->next;
- };
- };
-
-
-
- int maxof(int a, int b)
- {
- if (a<=b) return(b);
- return(a);
- };
-
-
-
- void accum_size(struct submenu *one)
- {
-
- if (debug2) boxtext(50,250,"accum_size");
-
- if (one->esc->direction == HORIZONTAL) {
- accumx = accumx + one->sizex;
- accumy = maxof(accumy,one->sizey);
- }else{
- accumx = maxof(accumx,one->sizex);
- accumy = accumy + one->sizey;
- };
-
- };
-
-
- /* size up a menu for a box */
- void prep_submenu(struct submenu *it)
- {
-
- if (debug1) boxtext(0,170,"prep_submenu");
-
- /* don't matter whether we are horiz or vert */
- accumx = 0;
- accumy = 0;
-
- if (it->esc->longname) {
- if (strlen(it->esc->longname)) {
- accumx = boxsizex(it->esc->longname);
- accumy = boxsizey(it->esc->longname);
- };
- };
- doeach_entry(it,accum_size);
-
-
- if (debug1) boxtext(130,170,"prep done");
- };
-
-
-
-
- void dump_text(struct submenu *one)
- {
- #ifdef DEBUG
- char d1[80],*data=d1;
- if (debug2) {
- boxtext(250,120,"dump_text");
- boxtext(250,131,one->shortname);
- sprintf(data,"(%d,%d)",accumx,accumy);
- boxtext(250,142,data);
- };
- #endif
-
-
- one->startx = accumx;
- one->starty = accumy;
- boxtext(accumx,accumy,one->shortname);
- if (one->esc->direction == HORIZONTAL) {
- one->belowx = accumx;
- one->belowy = accumy + one->sizey;
- accumx += one->sizex; /* boxsizex(one->shortname); */
- }else{
- one->belowx = accumx + one->sizex;
- one->belowy = accumy;
- accumy += one->sizey; /* boxsizey(one->shortname); */
- };
-
- };
-
-
-
- void dump_submenu(int x, int y, struct submenu *it)
- {
- if (debug1) boxtext(0,130,"dump_submenu");
-
- accumx = x;
- accumy = y;
-
- if (it->esc->longname) {
- if (strlen(it->esc->longname)) {
-
- boxtext(accumx,accumy,it->esc->longname);
- if (it->esc->direction == HORIZONTAL) {
- accumx += boxsizex(it->esc->longname);
- }else{
- accumy += boxsizey(it->esc->longname);
- };
-
- };
- };
-
-
- doeach_entry(it,dump_text);
-
- if (debug1) boxtext(100,130,"dump done");
- };
-
-
-
-
-
- void matchkey(struct submenu *one)
- {
- /* note that if we don't check the quitflag here, then
- if we are nested in several submenus
- and the same key is used on different levels
- then when the key is pressed, it could be taken to mean 2 functions
- so by checking the quitflag, we take it to mean only 1 function.
- We could have cleared 'the_key' instead, but that would be logical.
- */
- if (!quitflag) {
- if (the_key == one->choicekey) {
- quitflag = subrun_submenu(one);
- };
-
- /* Here we convert lower case letters to upper case and try again to match.
- I don't see any point in making the convert_case variable local to each
- menu.
- We rely on the fact that the long word keyboard alphabet is linear in
- both the upper and lower case sequences.
- */
- if (convert_case) {
- if( (lkeyof('a')<= the_key) && (lkeyof('z')>= the_key) ){
- if ( (the_key-lkeyof('a')+lkeyof('A')) == one->choicekey) {
- quitflag = subrun_submenu(one);
- };
- };
- };
-
- };
- };
-
-
-
-
-
-
- /* here we go to next item, skipping any invisible items */
- struct submenu *cur_next(struct submenu *oldcursor)
- {
- struct submenu *cursor = oldcursor;
-
- cursoff(cursor);
- if (cursor->next) {
- cursor = cursor->next;
- while( (cursor->direction==INVISIBLE) && (cursor->next != 0) ) {
- cursor = cursor->next;
- };
- if (cursor->direction==INVISIBLE) cursor = oldcursor;
- };
- curson(cursor);
- return(cursor);
- };
-
-
- /* here we go to previous item, skipping any invisible items */
- struct submenu *cur_prev(struct submenu *oldcursor)
- {
- struct submenu *cursor = oldcursor;
-
- cursoff(cursor);
- if (cursor->prev) {
- cursor = cursor->prev;
- while( (cursor->direction==INVISIBLE) && (cursor->prev != 0) ) {
- cursor = cursor->prev;
- };
- /* if (cursor->direction==INVISIBLE) cursor = oldcursor; */
- };
- curson(cursor);
- return(cursor);
- };
-
-
- /* do all key processing for this menu
- return 0 for normal termination or 1 for TOTAL_QUIT
- */
- int key_submenu(struct submenu *it)
- {
- struct submenu *cursor = it;
-
- if (debug1) boxtext(0,140,"key_submenu");
-
- top:
- curson(cursor);
- call_for_key(cursor); /* needs cursor for hotkey function calling */
-
- if (debug1) boxtext(50,140,"got key");
-
- if (the_key == KEY_ESC) {
- cursoff(cursor);
- return(0);
- };
- if (the_key == KEY_TOTAL_ESC) {
- cursoff(cursor);
- return(1);
- };
-
- /* cursor movement */
- if (the_key == KEY_RIGHT) {
- cursor = cur_next(cursor);
- };
- if (the_key == KEY_LEFT) {
- cursor = cur_prev(cursor);
- };
-
- if (the_key == KEY_DOWN) {
- if (it->esc->direction == HORIZONTAL) {
- quitflag = subrun_submenu(cursor);
- }else{
- cursor = cur_next(cursor);
- };
- };
-
- if (the_key == KEY_UP) {
- if (it->esc->direction == HORIZONTAL) {
- cursoff(cursor);
- return(0);
- }else{
- cursor = cur_prev(cursor);
- };
- };
-
-
- if (the_key == KEY_SUB) {
- quitflag = subrun_submenu(cursor);
- };
-
- if (debug1) boxtext(120,140,"almost");
-
- cursoff(cursor);
- doeach_entry(it,matchkey);
- if (quitflag) {
- return(quitflag);
- };
-
- curson(cursor);
- goto top;
- };
-
-
-
-
- int def_fkey(int fkey, char *keyname, char *fkeyn)
- {
- int ikey;
- char *data;
-
- ikey = indexofname(keyname);
- if (ikey) {
- if (mac[ikey]) macs_free(mac[ikey]);
- mac[ikey] = new_mac();
- mac[ikey]->fkey = fkey;
- mac[ikey]->next = 0;
- mac[ikey]->prev = 0;
-
- if (!fkeynames[fkey]) goto over;
- if (strcmp(fkeyn,fkeynames[fkey])!=0) {
- over:
- data = (char *) g_malloc(strlen(fkeyn));
- strcpy(data,fkeyn);
- fkeynames[fkey] = data;
- };
-
- return(1);
- };
- return(0);
- };
-
-
-
-
- #define configfile "MENU.TMP"
- /* the default name of the file where the config data is written */
-
-
-
- FILE *Fconfig;
-
-
- /* this routine writes out the config data to the default file.
- if the file cannot be written, the user is prompted for a name.
- */
- void write_config()
- {
- int i;
- struct mac *amac;
-
- Fconfig = fopen(configfile,"w");
- fprintf(Fconfig,"%s\n","__TIME__ __DATE__");
-
-
-
- fprintf(Fconfig,"%d\n",lastkey);
- for(i=0;i<lastkey;i++){
- fprintf(Fconfig,"%8.8lX\n%s\n",keys[i],keynames[i]);
- };
-
- for(i=1;i<=MAXKEYS+NUM_MYKEYS;i++){
- if( (hotkeyfn[i]!=0) || (fkeynames[i]!=0) ){
- if (fkeynames[i]==0) fkeynames[i] = "unknown";
- fprintf(Fconfig,"%d\n",i);
- /*
- fprintf(Fconfig,"%X\n",hotkeyfn[i]);
- */
- fprintf(Fconfig,"%s\n",fkeynames[i]);
- };
- };
- fprintf(Fconfig,"%d\n",0);
-
-
- for (i=0;i<lastkey;i++){
- if (mac[i]) {
- amac = mac[i];
- fprintf(Fconfig,"%s\n",keynames[i]);
- while (amac !=0) {
- fprintf(Fconfig,"%s\n",find_keyname(amac->fkey));
- amac = amac->next;
- };
- fprintf(Fconfig,"\n");
- };
- };
- fprintf(Fconfig,"endofmacros\n");
-
- /*
- dump rootmenu
- */
-
-
-
-
- fclose(Fconfig);
- };
-
-
-
-
-
-
-
-
- char *readstr(char *data)
- {
- int len;
-
- fgets(data,70,Fconfig);
- len = strlen(data);
- data[len-1]='\0';
- return( strcpy(g_malloc(len-1),data) );
- };
-
-
-
- long int lkeyofname(char *name)
- {
- int i;
-
- i = indexofname(name);
- if (i==0) {
- for(i=1;i<=MAXKEYS+NUM_MYKEYS;i++){
- if(strcmp(fkeynames[i],name)==0) {
- return(i);
- };
- };
- return(0);
- }else{
- return(keys[i]);
- };
- };
-
-
- void read_config()
- {
- char data[80];
- int i;
- char ch;
- char *answ;
- struct mac *amac, *first;
- fn *rou;
-
-
- Fconfig = fopen(configfile,"r");
-
- answ = readstr(data);
- /*
- if (strcmp(answ,"__TIME__ __DATE__")!=0) {
- padtext(50,50,answ,3);
- };
- */
-
-
-
- fscanf(Fconfig,"%d%c",&lastkey,&ch);
-
- for(i=0;i<lastkey;i++){
- fscanf(Fconfig,"%lx%c",&keys[i],&ch);
- keynames[i] = readstr(data);
- };
-
- while (i) {
- fscanf(Fconfig,"%d%c",&i,&ch);
- if (i) {
- /*
- fscanf(Fconfig,"%x",&rou);
- hotkeyfn[i] = rou;
- fscanf(Fconfig,"%c",&ch);
- */
- fkeynames[i] = readstr(data);
- };
- };
-
-
-
-
- answ = readstr(data);
- while (strcmp(answ,"endofmacros")!=0) {
- i = indexofname(answ);
- first = new_mac();
- first->prev=0;
- amac = first;
-
- answ = readstr(data);
- while (strlen(answ)) {
- amac->fkey = lkeyofname(answ);
- amac->next = new_mac();
- amac->next->prev = amac;
- amac->next->next = 0;
- amac = amac->next;
- answ = readstr(data);
- };
-
- mac[i] = first;
- amac->prev->next =0;
- free(amac);
-
- answ = readstr(data);
- };
-
-
-
- fclose(Fconfig);
- };
-