/* * Menu selection window * Copyright * (C) 1992 Joseph H. Allen * * This file is part of JOE (Joe's Own Editor) */ #include "config.h" #include "types.h" #include #include "scrn.h" #include "utils.h" #include "vs.h" #include "w.h" extern int dostaupd; static void menufllw(MENU *m) { m->top = m->cursor - m->cursor % m->perline; } static void menudisp(MENU *m) { int col; int x; int *s = m->t->t->scrn + m->x + m->y * m->t->t->co; col = 0; for (x = 0; x != m->perline && m->list[x + m->top]; ++x) { int atr, z; atr = 0; /* if (x + m->top == m->cursor) atr = INVERSE; else atr = 0; */ if (col == m->w) break; for (z = 0; m->list[x + m->top][z]; ++z) { if (col == m->w) break; outatr(m->t->t, s + col, m->x + col, m->y, m->list[x + m->top][z], atr); ++col; } while (z < m->width) { if (col == m->w) break; outatr(m->t->t, s + col, m->x + col, m->y, ' ', 0); ++col; ++z; } if (col != m->w) { outatr(m->t->t, s + col, m->x + col, m->y, ' ', 0); ++col; } } if (col != m->w) eraeol(m->t->t, m->x + col, m->y); m->parent->cury = 0; m->parent->curx = (m->cursor - m->top) * (m->width + 1); } static void menumove(MENU *m, int x, int y) { m->x = x; m->y = y; } static void menuresz(MENU *m, int wi, int he) { m->w = wi; m->h = he; } static void mconfig(MENU *m) { /* Configure menu display parameters */ if (m->list) { int x; m->top = 0; for (x = 0, m->width = 0; m->list[x]; ++x) if (strlen(m->list[x]) > m->width) m->width = strlen(m->list[x]); m->nitems = x; if (m->width > m->w) m->width = m->w - 1; m->perline = m->w / (m->width + 1); } } int umbol(MENU *m) { m->cursor = m->top; return 0; } int umbof(MENU *m) { m->cursor = 0; return 0; } int umeof(MENU *m) { if (m->nitems) m->cursor = m->nitems - 1; return 0; } int umeol(MENU *m) { if (m->top + m->perline < m->nitems) m->cursor = m->top + m->perline - 1; else umeof(m); return 0; } int umrtarw(MENU *m) { if (m->cursor + 1 < m->nitems) { ++m->cursor; return 0; } else return -1; } int umltarw(MENU *m) { if (m->cursor) { --m->cursor; return 0; } else return -1; } int umuparw(MENU *m) { if (m->cursor >= m->perline) { m->cursor -= m->perline; return 0; } else return -1; } int umdnarw(MENU *m) { if (m->cursor + m->perline < m->nitems) { m->cursor += m->perline; return 0; } else if (m->top + m->perline < m->nitems) return umeof(m); else return -1; } static int umrtn(MENU *m) { dostaupd = 1; if (m->func) return m->func(m, m->cursor, m->object, 0); else return -1; } int umbacks(MENU *m) { if (m->backs) return m->backs(m, m->cursor, m->object); else return -1; } static int umkey(MENU *m, int c) { int x; int n = 0; if (c == '0') { if (m->func) return m->func(m, m->cursor, m->object, -1); else return -1; } if (c == '1') { if (m->func) return m->func(m, m->cursor, m->object, 1); else return -1; } c &= 0x1F; for (x = 0; x != m->nitems; ++x) if ((m->list[x][0] & 0x1F) == c) ++n; if (!n) return -1; if (n == 1) for (x = 0; x != m->nitems; ++x) if ((m->list[x][0] & 0x1F) == c) { m->cursor = x; return umrtn(m); } do { ++m->cursor; if (m->cursor == m->nitems) m->cursor = 0; } while ((m->list[m->cursor][0] & 0x1F) != c); return -1; } static int menuabort(MENU *m) { W *w = m->parent; int (*func) () = m->abrt; void *object = m->object; int x = m->cursor; W *win = w->win; joe_free(m); if (func) return func(win->object, x, object); else return -1; } WATOM watommenu = { "menu", menudisp, menufllw, menuabort, umrtn, umkey, menuresz, menumove, NULL, NULL, TYPEMENU }; void ldmenu(MENU *m, char **s, int cursor) { m->list = s; m->cursor = cursor; mconfig(m); } MENU *mkmenu(W *w, char **s, int (*func) (/* ??? */), int (*abrt) (/* ??? */), int (*backs) (/* ??? */), int cursor, void *object, int *notify) { W *new = wcreate(w->t, &watommenu, w, w, w->main, 1, NULL, notify); MENU *m; if (!new) { if (notify) *notify = 1; return NULL; } wfit(new->t); new->object = (void *) (m = (MENU *) joe_malloc(sizeof(MENU))); m->parent = new; m->func = func; m->abrt = abrt; m->backs = backs; m->object = object; m->t = w->t; m->h = new->h; m->w = new->w; m->x = new->x; m->y = new->y; ldmenu(m, s, cursor); w->t->curwin = new; return m; } static char *cull(char *a, char *b) { int x; for (x = 0; a[x] && b[x] && a[x] == b[x]; ++x) ; return vstrunc(a, x); } char *mcomplete(MENU *m) { char *com; int x; if (!m->nitems) return vstrunc(NULL, 0); com = vsncpy(NULL, 0, sz(m->list[0])); for (x = 1; x != m->nitems; ++x) com = cull(com, m->list[x]); return com; }