1 #include "deco.h"
2 #include "scr.h"
3 #include "menu.h"
4
5 static void drawhead (int nm);
6 static void clrmenu (struct menu *m);
7 static void drawmenu (struct menu *m);
8 static void upmenu (struct menu *m);
9 static int hotkey (int c, struct menu *m);
10
initmenu()11 static void initmenu ()
12 {
13 register struct menu *m;
14 register struct submenu *sm;
15 int col, w;
16
17 col = 3;
18 for (m=menu; m->name; ++m) {
19 m->len = 4 + strlen (m->name);
20 m->col = col;
21 col += m->len;
22 m->hgh = 0;
23 m->wid = 0;
24 for (sm=m->submenu; sm->name; ++sm) {
25 sm->row = m->hgh;
26 w = 4 + strlen (sm->name);
27 if (w > m->wid)
28 m->wid = w;
29 ++m->hgh;
30 }
31 }
32 }
33
getboxes()34 static void getboxes ()
35 {
36 register struct menu *m;
37
38 for (m=menu; m->name; ++m) {
39 if (m->box)
40 VFreeBox (m->box);
41 m->box = VGetBox (1, m->col-1, m->hgh+3, m->wid+4);
42 }
43 }
44
getmenu()45 int getmenu ()
46 {
47 if (! menu[0].len)
48 initmenu ();
49
50 getboxes ();
51 VMPutString (LINES-1, 0, "\0011\16 \17 2\16 \17 3\16 \17 4\16 \17 5\16 \17 6\16 \17 7\16 \17 8\16 \17 9\16 \01710\16Quit \17\2");
52 for (;;) {
53 drawhead (nmenu);
54 for (;;) {
55 int c, k;
56
57 drawmenu (&menu[nmenu]);
58 hidecursor ();
59 VSync ();
60 c = KeyGet ();
61 switch (c) {
62 default:
63 k = hotkey (c, &menu[nmenu]);
64 if (k) {
65 clrmenu (&menu[nmenu]);
66 return (k);
67 }
68 VBeep ();
69 continue;
70 case cntrl (']'): /* redraw screen */
71 VRedraw ();
72 continue;
73 case cntrl ('M'):
74 clrmenu (&menu[nmenu]);
75 return (1);
76 case cntrl ('J'):
77 clrmenu (&menu[nmenu]);
78 return (2);
79 case cntrl ('C'):
80 case cntrl ('['):
81 case meta ('J'): /* f0 */
82 clrmenu (&menu[nmenu]);
83 return (0);
84 case meta ('r'): /* right */
85 clrmenu (&menu[nmenu]);
86 if (! menu[++nmenu].name)
87 nmenu = 0;
88 break;
89 case meta ('l'): /* left */
90 clrmenu (&menu[nmenu]);
91 if (--nmenu < 0) {
92 for (nmenu=0; menu[nmenu].name; ++nmenu);
93 --nmenu;
94 }
95 break;
96 case meta ('u'): /* up */
97 upmenu (&menu[nmenu]);
98 continue;
99 case meta ('d'): /* down */
100 downmenu (&menu[nmenu]);
101 continue;
102 }
103 break;
104 }
105 }
106 }
107
drawhead(int nm)108 static void drawhead (int nm)
109 {
110 register i, reverse;
111
112 VSetDim ();
113 reverse = VStandOut ();
114 VMove (0, 0);
115 for (i=0; i<80; ++i)
116 VPutChar (' ');
117 VMove (0, 2);
118 for (i=0; menu[i].name; ++i) {
119 if (i == nm) {
120 VStandEnd ();
121 VSetBold ();
122 }
123 VPutChar (' ');
124 VPutChar (i==nm && !reverse ? '[' : ' ');
125 VPutString (menu[i].name);
126 VPutChar (i==nm && !reverse ? ']' : ' ');
127 VPutChar (' ');
128 if (i == nm) {
129 VStandOut ();
130 VSetDim ();
131 }
132 }
133 VSetNormal ();
134 VStandEnd ();
135 }
136
clrmenu(struct menu * m)137 static void clrmenu (struct menu *m)
138 {
139 VUngetBox (m->box);
140 }
141
drawmenu(struct menu * m)142 static void drawmenu (struct menu *m)
143 {
144 register i, reverse;
145
146 VClearBox (1, m->col-1, m->hgh+3, m->wid+4);
147 VSetBold ();
148 VDrawBox (1, m->col, m->hgh+2, m->wid+2);
149 VSetDim ();
150 for (i=0; m->submenu[i].name; ++i)
151 if (! m->submenu[i].name[0])
152 VHorLine (i+2, m->col+2, m->wid-2);
153 VSetNormal ();
154 for (i=0; m->submenu[i].name; ++i) {
155 if (! m->submenu[i].name[0])
156 continue;
157 reverse = 0;
158 if (i == m->nsm)
159 reverse = VStandOut ();
160 else if (! m->submenu[i].active)
161 VSetDim ();
162 VMove (2+i, m->col+1);
163 VPutChar (i==m->nsm && !reverse ? '[' : ' ');
164 VPrint ("%c %-*s", m->submenu[i].tag ? '*' : ' ',
165 m->wid-4, m->submenu[i].name);
166 VPutChar (i==m->nsm && !reverse ? ']' : ' ');
167 if (i == m->nsm)
168 VStandEnd ();
169 else if (! m->submenu[i].active)
170 VSetNormal ();
171 }
172 }
173
upmenu(struct menu * m)174 static void upmenu (struct menu *m)
175 {
176 for (;;) {
177 if (--m->nsm < 0) {
178 for (m->nsm=0; m->submenu[m->nsm].name; ++m->nsm);
179 --m->nsm;
180 }
181 if (m->submenu[m->nsm].active)
182 break;
183 }
184 }
185
downmenu(struct menu * m)186 void downmenu (struct menu *m)
187 {
188 for (;;) {
189 if (! m->submenu[++m->nsm].name)
190 m->nsm = 0;
191 if (m->submenu[m->nsm].active)
192 break;
193 }
194 }
195
hotkey(int c,struct menu * m)196 static int hotkey (int c, struct menu *m)
197 {
198 register nsm, ret;
199
200 if (c>='A' && c<='Z') {
201 c += 'a' - 'A';
202 ret = 2;
203 } else
204 ret = 1;
205 for (nsm=0; m->submenu[nsm].name; ++nsm)
206 if (c == m->submenu[nsm].key && m->submenu[nsm].active) {
207 m->nsm = nsm;
208 return (ret);
209 }
210 return (0);
211 }
212