2 * Menu selection window
4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/menu.c,v 1.8 2017/12/02 02:07:29 tg Exp $");
25 static void mconfig(MENU *);
27 static void menufllw(MENU *m)
29 if (m->cursor < m->top)
30 m->top = m->cursor - m->cursor % m->perline;
31 else if (m->cursor >= m->top+m->perline*m->h)
32 m->top = m->cursor - m->cursor % m->perline - m->perline*(m->h-1);
35 static void menudisp(MENU *m)
40 int *s = m->t->t->scrn + m->x + m->y * m->t->t->co;
41 int *a = m->t->t->attr + m->x + m->y * m->t->t->co;
46 if (m->t->t->co != m->saved_co)
49 for (y = 0; y != m->h; ++y) {
51 for (x = 0; x != m->perline && y*m->perline+x+m->top<m->nitems; ++x) {
54 if (x + y*m->perline + m->top == m->cursor)
69 m->list[x + y*m->perline + m->top],
70 strlen((char *)m->list[x + y*m->perline + m->top]),
78 /* Space between columns */
80 outatr(locale_map, m->t->t, s + col, a + col, m->x + col, m->y+y, ' ', 0);
84 /* Clear to end of line */
86 eraeol(m->t->t, m->x + col, m->y + y);
90 m->parent->cury = (m->cursor - m->top) / (m->perline ? m->perline : 1);
91 col = txtwidth(m->list[m->cursor],strlen((char *)m->list[m->cursor]));
92 m->parent->curx = ((m->cursor - m->top) % (m->perline ? m->perline : 1)) *
93 (m->width + 1) + (col < m->width ? col : m->width);
96 static void menumove(MENU *m, int x, int y)
102 static void menuresz(MENU *m, int wi, int he)
108 static int mlines(unsigned char **s, int w)
116 for (x = 0, width = 0; s[x]; ++x) {
117 int d = txtwidth(s[x],strlen((char *)(s[x])));
124 perline = w / (width + 1);
126 lines = (nitems + perline - 1) / perline;
131 static void mconfig(MENU *m)
133 /* Configure menu display parameters */
139 for (x = 0, m->width = 0; m->list[x]; ++x) {
140 int d = txtwidth(m->list[x],strlen((char *)(m->list[x])));
147 m->perline = m->w / (m->width + 1);
149 /* lines = (m->nitems + m->perline - 1) / m->perline; */
151 m->saved_co = m->t->t->co;
157 m->cursor -= m->cursor % m->perline;
170 m->cursor = m->nitems - 1;
176 m->cursor -= m->cursor % m->perline;
178 if (m->cursor+m->perline-1 >= m->nitems)
179 m->cursor = m->nitems - 1;
181 m->cursor += m->perline - 1;
188 if (m->cursor + 1 < m->nitems) {
197 if (m->cursor + 1 >= m->nitems)
215 if (m->cursor >= m->perline) {
216 m->cursor -= m->perline;
224 int col = m->cursor % m->perline;
228 if (m->cursor + m->perline < m->nitems) {
229 m->cursor += m->perline;
230 if (m->cursor + col >= m->nitems)
232 m->cursor = m->nitems - 1;
246 int amnt = (m->h+1)/2;
247 if (m->top >= amnt*m->perline) {
248 m->top -= amnt*m->perline;
249 m->cursor -= amnt*m->perline;
255 } else if (m->cursor >= m->perline) {
256 m->cursor = m->cursor % m->perline;
264 int amnt = (m->h+1)/2;
265 int col = m->cursor % m->perline;
266 int y = m->cursor / m->perline;
267 int h = (m->nitems + m->perline - 1) / m->perline;
268 int t = m->top / m->perline;
271 if (t + m->h + amnt <= h) {
272 m->top += amnt*m->perline;
273 m->cursor += amnt*m->perline;
274 if (m->cursor + col >= m->nitems)
276 m->cursor = m->nitems - 1;
282 } else if (t + m->h < h) {
283 amnt = h - (t + m->h);
284 m->top += amnt*m->perline;
285 m->cursor += amnt*m->perline;
286 if (m->cursor + col >= m->nitems)
288 m->cursor = m->nitems - 1;
295 m->cursor = (h-1)*m->perline;
296 if (m->cursor + col >= m->nitems)
298 m->cursor = m->nitems - 1;
311 static int umrtn(MENU *m)
315 return m->func(m, m->cursor, m->object, 0);
323 return m->backs(m, m->cursor, m->object);
328 static int umkey(MENU *m, int c)
335 return m->func(m, m->cursor, m->object, -1);
341 return m->func(m, m->cursor, m->object, 1);
345 if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))))
348 for (x = 0; x != m->nitems; ++x)
349 if ((m->list[x][0] & 0x1F) == c)
354 for (x = 0; x != m->nitems; ++x)
355 if ((m->list[x][0] & 0x1F) == c) {
361 if (m->cursor == m->nitems)
363 } while ((m->list[m->cursor][0] & 0x1F) != c);
368 static int menuabort(MENU *m)
371 int (*func) () = m->abrt;
372 void *object = m->object;
378 return func(win->object, x, object);
397 void ldmenu(MENU *m, unsigned char **s, int cursor)
404 MENU *mkmenu(W *w, unsigned char **s, int (*func) (/* ??? */), int (*abrt) (/* ??? */), int (*backs) (/* ??? */), int cursor, void *object, int *notify)
409 int h = (w->main->h*40) / 100; /* 40% of window size */
414 lines = mlines(s,w->t->w-1);
419 new = wcreate(w->t, &watommenu, w, w, w->main, h, NULL, notify);
427 new->object = (void *) (m = (MENU *) joe_malloc(sizeof(MENU)));
440 ldmenu(m, s, cursor);
445 static unsigned char *cull(unsigned char *a, unsigned char *b)
449 for (x = 0; a[x] && b[x] && a[x] == b[x]; ++x) ;
450 return vstrunc(a, x);
453 unsigned char *find_longest(unsigned char **lst)
458 if (!lst || !aLEN(lst))
459 return vstrunc(NULL, 0);
460 com = vsncpy(NULL, 0, sv(lst[0]));
461 for (x = 1; x != aLEN(lst); ++x)
462 com = cull(com, lst[x]);
466 unsigned char *mcomplete(MENU *m)
472 return vstrunc(NULL, 0);
473 com = vsncpy(NULL, 0, sz(m->list[0]));
474 for (x = 1; x != m->nitems; ++x)
475 com = cull(com, m->list[x]);