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