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