1 /*--------------------------------------------------------------------
2 menu module.
3
4 Copyright (c) 1998,1999,2000 SASAKI Shunsuke.
5 All rights reserved.
6 --------------------------------------------------------------------*/
7 #include "ed.h"
8 #include "sh.h"
9 #include <ctype.h>
10 #include <stdarg.h>
11
12
13 dspfmt_t *dspreg_menu(void *vp,int y,int sizex,int sizey);
14
menu_iteminit(menu_t * mnp)15 void menu_iteminit(menu_t *mnp)
16 {
17 mnp->nums =0;
18
19 mnp->sy =0;
20 mnp->cy =0;
21
22 mnp->title="";
23 mnp->drp =dsp_reginit();
24 mnp->drp->func =dspreg_menu;
25 mnp->drp->vp =(void *)mnp;
26
27 mnp->drp->y +=1;
28 mnp->drp->sizey-=1;
29
30 mnp->df=FALSE;
31 }
32
menu_itemfin(menu_t * mnp)33 void menu_itemfin(menu_t *mnp)
34 {
35 if (mnp->nums>0)
36 {
37 int i;
38
39 term_color(AC_normal);
40 for (i=mnp->drp->y; i<mnp->drp->y+mnp->drp->sizey; ++i)
41 {
42 term_locate(i, mnp->drp->x);
43 widthputs("", mnp->drp->sizex);
44 }
45
46 free(mnp->mitem);
47 mnp->nums=0;
48 }
49 }
50
menu_itemmake(menu_t * mnp,void func (int,mitem_t *,void *),size_t nums,void * vp)51 void menu_itemmake(menu_t *mnp,void func(int,mitem_t *,void *),size_t nums,void *vp)
52 {
53 int i;
54 int ln;
55
56 menu_itemfin(mnp);
57
58 mnp->mitem=mem_alloc(sizeof(mitem_t) * nums);
59
60 ln=0;
61 for (i=0;i<nums;++i)
62 {
63 mnp->mitem[i].cc= sysinfo.c_menuc;
64 mnp->mitem[i].nc= sysinfo.c_menun;
65 mnp->mitem[i].mf=FALSE;
66
67 func(i, mnp->mitem+i, vp);
68 ln=max(ln,strlen(mnp->mitem[i].str));
69 ++mnp->nums;
70 }
71
72 dsp_regresize(mnp->drp, ln+4, min(mnp->nums+2, dspall.sizey-2));
73 dsp_regadd(mnp->drp);
74 }
75
76
77 typedef struct
78 {
79 size_t width;
80 size_t num;
81 char *s;
82 } itemstr_t;
83
makelists_proc(int a,mitem_t * mip,void * vp)84 void makelists_proc(int a,mitem_t *mip,void *vp)
85 {
86 itemstr_t *isp;
87
88 isp=vp;
89 strcpy(mip->str, isp->s +isp->width*a);
90 }
91
menu_itemmakelists(menu_t * mnp,size_t width,size_t num,char * s)92 void menu_itemmakelists(menu_t *mnp,size_t width,size_t num,char *s)
93 {
94 itemstr_t is;
95
96 is.num=num;
97 is.width=width;
98 is.s=s;
99
100 menu_itemmake(mnp, makelists_proc, num, &is);
101 }
102
makev_proc(int a,mitem_t * mip,void * vp)103 void makev_proc(int a, mitem_t *mip, void *vp)
104 {
105 va_list args;
106 char *p;
107
108 va_copy(args, *(va_list *)vp);
109
110 p=va_arg(args, char *);
111 if (p==NULL)
112 strcpy(mip->str,"null"); else
113 strcpy(mip->str,p);
114
115 va_copy(*(va_list *)vp, args);
116 }
117
118
menu_vselect(int x,int y,size_t num,...)119 int menu_vselect(int x, int y, size_t num, ...)
120 {
121 menu_t menu;
122 va_list args;
123
124 menu_iteminit(&menu);
125 if (x!=-1)
126 menu.drp->x=x;
127 if (y!=-1)
128 menu.drp->y=y;
129
130 va_start(args,num);
131 menu_itemmake(&menu, makev_proc, num, &args);
132 va_end(args);
133
134 return menu_select(&menu);
135 }
136
menu_dview(menu_t * mnp)137 void menu_dview(menu_t *mnp)
138 {
139 int i;
140
141 for (i=0;i<mnp->nums;++i)
142 fprintf(stderr,"%2d:%s\n",i,mnp->mitem[i].str);
143 }
144
menu_csrmove(menu_t * mnp,int ly)145 void menu_csrmove(menu_t *mnp,int ly)
146 {
147 int ly_b;
148
149 ly_b=mnp->cy+mnp->sy;
150
151 ly=max(ly,0);
152 ly=min(ly,mnp->nums-1);
153
154 if (ly_b==ly)
155 return;
156
157 if (ly_b-ly>mnp->cy)
158 {
159 ly_b-=mnp->cy;
160 mnp->cy=0;
161 mnp->sy-=ly_b-ly;
162
163 return;
164 }
165
166 if (ly-ly_b>mnp->drp->sizey- 2 -mnp->cy -1)
167 {
168 ly-=mnp->drp->sizey- 2 -mnp->cy-1;
169 mnp->cy=mnp->drp->sizey-2 -1;
170 mnp->sy+= ly-ly_b;
171
172 return;
173 }
174
175 mnp->cy+=ly-ly_b;
176 }
177
menu_csrnext(menu_t * mnp,char c)178 void menu_csrnext(menu_t *mnp,char c)
179 {
180 int n,m;
181
182 m=n=mnp->cy+mnp->sy;
183 for (;;)
184 {
185 ++n;
186 if (n>=mnp->nums)
187 n=0;
188 if (n==m)
189 return;
190 if (toupper(*mnp->mitem[n].str)==toupper(c))
191 {
192 menu_csrmove(mnp,n);
193 return;
194 }
195 }
196 }
197
198
dspreg_menu(void * vp,int y,int sizex,int sizey)199 dspfmt_t *dspreg_menu(void *vp,int y,int sizex,int sizey)
200 {
201 dspfmt_t *dfp,*dfpb;
202 char buf[LN_dspbuf+1];
203 menu_t *mnp;
204
205 mnp=(menu_t *)vp;
206
207 if (y==0)
208 {
209 int a;
210
211 if (*mnp->title=='\0')
212 y=sizey-1; else
213 {
214 a= min(strlen(mnp->title), sizex-3 -3);
215
216 strcpy(buf, "+- ");
217 strjfcpy(buf+3, mnp->title, LN_dspbuf-3, a);
218 buf[a+3]=' ';
219 if (sizex-a-5>0)
220 memset(buf+4+a, '-', sizex-a-5);
221 }
222 }
223
224 if (y==sizey-1)
225 {
226 *buf='+';
227 memset(buf+1, '-', sizex-2);
228 }
229
230 if (y==0|| y==sizey-1)
231 {
232 buf[sizex-1]='+';
233 buf[sizex]='\0';
234
235 dfp=dsp_fmtinit(buf, NULL);
236 return dfp;
237 }
238
239 --y;
240
241
242 buf[0]='|';
243 buf[1]=mnp->mitem[mnp->sy+y].mf? '*': ' ';
244 buf[2]='\0';
245 dfpb=dfp=dsp_fmtinit(buf, NULL);
246
247 strjfcpy(buf, mnp->mitem[mnp->sy+y].str, LN_dspbuf, sizex-4);
248 dfp=dsp_fmtinit(buf, dfp);
249 if (mnp->cy==y &&!mnp->df)
250 dfp->col= mnp->mitem[mnp->sy+y].cc; else
251 dfp->col= mnp->mitem[mnp->sy+y].nc;
252
253 dfp=dsp_fmtinit(" |", dfp);
254
255 return dfpb;
256 }
257
menu_select(menu_t * mnp)258 int menu_select(menu_t *mnp)
259 {
260 int c;
261
262 for (;;)
263 {
264 dsp_allview();
265 term_csrh();
266 c=get_keyf(1);
267 switch(c)
268 {
269 case -1:
270 continue;
271
272 default:
273 if (c&0xff00)
274 menu_csrnext(mnp,c&0x00ff);
275 continue;
276 case KF_SysCursorup:
277 menu_csrmove(mnp,mnp->cy +mnp->sy -1);
278 continue;
279 case KF_SysCursordown:
280 menu_csrmove(mnp,mnp->cy +mnp->sy +1);
281 continue;
282 case KF_SysScrolldown:
283 menu_csrmove(mnp,mnp->cy +mnp->sy -mnp->drp->sizey -2);
284 continue;
285 case KF_SysScrollup:
286 menu_csrmove(mnp,mnp->cy +mnp->sy +mnp->drp->sizey -2);
287 continue;
288 case KF_SysCursortopside:
289 menu_csrmove(mnp,0);
290 continue;
291 case KF_SysCursorendside:
292 menu_csrmove(mnp,mnp->nums-1);
293 continue;
294
295 case KF_SysReturn:
296 c=mnp->cy+mnp->sy;
297 break;
298 case KF_SysEscape:
299 c=-1;
300 break;
301 }
302 break;
303 }
304
305
306 menu_itemfin(mnp);
307 dsp_regfin(mnp->drp);
308 return c;
309 }
310
311