/* * $Id: coolmenu.c,v 1.1 2005/06/13 20:50:49 murrayma Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1996 Markus Stenberg * All rights reserved * * Created: Mon Sep 16 20:38:36 1996 fingon * Last modified: Wed Jun 24 22:41:40 1998 fingon * */ #include <stdio.h> #include <string.h> #include "db.h" void KillText(char **mapt); void ShowText(char **mapt, dbref player); /* Simple menu system for cool menus ;-) */ #include "db.h" #include "coolmenu.h" #include "create.h" #ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) #endif #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif int BOUNDED(int, int, int); int number_of_entries(coolmenu * c) { if (c->flags & CM_ONE) return 1; if (c->flags & CM_TWO) return 2; if (c->flags & CM_THREE) return 3; if (c->flags & CM_FOUR) return 4; return 1; } int count_following_with(coolmenu * c, int num) { int count = 0; for (; c && number_of_entries(c) >= num && count < num; c = c->next) count++; return count; } void display_line(char **c, int *len, coolmenu * m) { char *ch = *c; int i; sprintf(ch, "%%cm"); ch += strlen(ch); for (i = 0; i < *len; i++) *(ch++) = '-'; sprintf(ch, "%%c"); ch += strlen(ch); *len = 0; *c = ch; } static int compute_length(char *s) { int l = strlen(s); char *c; for (c = s; *c; c++) { if (*c == '%') if (*(c + 1) == 'c') { if (isalpha(*(c + 2))) { c += 2; l -= 3; } else { c += 1; l -= 2; } } } return l; } void display_string(char **c, int *len, coolmenu * m) { int l = strlen(m->text), lo; int p, e; int i; if (m->flags & CM_NOCUT) { *len = 1; strcpy(*c, m->text); *c += strlen(*c); return; } if (m->flags & CM_CENTER) { p = MAX(*len / 2 - l / 2, 0); e = MIN(*len - 1, p + l); for (i = 0; i < p; i++) (*c)[i] = ' '; *c += p; sprintf(*c, "%%ch%%cm"); *c += strlen(*c); strncpy(*c, m->text, (e - p) + 1); *c += (e - p); sprintf(*c, "%%c"); *c += strlen(*c); **c = 0; *len -= e; } else { lo = l - compute_length(m->text); l = MIN(*len - 1 + lo, l); strncpy(*c, m->text, l); (*c)[l] = 0; *len -= l - lo; *c = &((*c)[l]); } } void display_toggle_end(char **c, coolmenu * m) { if (m->value) sprintf(*c, " %s<%%cbX%%c%%ch>%%c", !(m->flags & CM_NO_HILITE) ? "%ch" : ""); else sprintf(*c, " < >"); *c += strlen(*c); } /* Turn value into equivalent with kilo, mega, giga, tera, peta, exa, zetta or yotta postfix. */ char *stringified_value(int v) { char foo[] = "KMGTPEZY"; int i = -1; static char buf[5]; if (v > 999) { do { i++; v /= 1000; } while (v > 999 && foo[i]); if (!foo[i]) i--; sprintf(buf, "%d%c", BOUNDED(0, v, 999), foo[i]); } else sprintf(buf, "%d", BOUNDED(0, v, 999)); return buf; } void display_number_end(char **c, coolmenu * m) { if (m->value >= 0) { sprintf(*c, " %%cg%s%4s%%c", (m->value > 0 && !(m->flags & CM_NO_HILITE)) ? "%ch" : "", stringified_value(m->value)); } else sprintf(*c, " ____"); *c += strlen(*c); } char *display_entry(char *ch, int maxlen, coolmenu * c) { int i, j = 0, t = 0; /* returns: number of characters to forward the main pointer with. basically: strlen(ouradditions) */ if ((c->flags & (LETTERFIRST)) && !(c->flags & CM_NOTOG)) { if (c->flags & CM_NUMBER) maxlen -= 5; else maxlen -= 4; t = ((c->flags & (CM_TOGGLE | CM_NUMBER)) && c->value); sprintf(ch, "%s[%c]%s ", (t && !(c->flags & CM_NO_HILITE)) ? "%ch%cr" : "%cr", t ? (c->letter + 'A' - 'a') : c->letter, "%c"); ch += strlen(ch); } if (c->flags & (RIGHTEDGES) && !(c->flags & CM_NORIGHT)) { if (c->flags & CM_NUMBER) maxlen -= 6; else maxlen -= 5; j = 1; } if (t && !(c->flags & (CM_NO_HILITE))) { sprintf(ch, "%%ch"); ch += strlen(ch); } if (c->flags & CM_LINE) display_line(&ch, &maxlen, c); else display_string(&ch, &maxlen, c); if (t && !(c->flags & (CM_NO_HILITE))) { sprintf(ch, "%%c"); ch += strlen(ch); } if (maxlen > 0 && !(c->flags & CM_NOCUT)) { for (i = 0; i < maxlen; i++) *(ch++) = ' '; } if (j) { if (c->flags & CM_TOGGLE) display_toggle_end(&ch, c); else if (c->flags & CM_NUMBER) display_number_end(&ch, c); *(ch++) = ' '; } *ch = 0; return ch; } void display_entries(coolmenu * c, int wnum, int num, char *text) { int i; char *ch = text; int single_length = (MENU_CHAR_WIDTH / wnum); for (i = 0; i < num; i++) { ch = display_entry(ch, single_length, c); c = c->next; } } char **MakeCoolMenuText(coolmenu * c) { char **m; int pos = 0; int n, rn; Create(m, char *, MAX_MENU_LENGTH + 1); /* Whole whopping menu is ready to be written at.. */ while (c) if ((n = number_of_entries(c))) if ((rn = count_following_with(c, n))) { Create(m[pos], char, MAX_MENU_WIDTH); /* display_entries(c,rn,m[pos++]); */ display_entries(c, n, rn, m[pos++]); while (rn > 0 && c) { rn--; c = c->next; } } return m; } void CreateMenuEntry_Killer(coolmenu ** c, char *text, int flag, int id, int value, int maxvalue) { coolmenu *d, *e; char first = 'a'; if (!*c) { Create(*c, coolmenu, 1); d = *c; } else { for (d = *c; d->next; d = d->next); Create(d->next, coolmenu, 1); d = d->next; } if (text) d->text = strdup(text); d->flags = flag; if ((flag & LETTERFIRST) && !(flag & CM_NOTOG)) { /* gasp, s'pose we need a letter for this thingy */ for (e = *c; e; e = e->next) if (e->letter) if (e->letter >= first) first = e->letter + 1; d->letter = first; } d->id = id; d->value = value; d->maxvalue = maxvalue; } void KillCoolMenu(coolmenu * c) { coolmenu *d; for (; c; c = d) { d = c->next; if (c->text) free((void *) c->text); free((void *) c); } } void ShowCoolMenu(dbref player, coolmenu * c) { char **ch; ch = MakeCoolMenuText(c); ShowText(ch, player); KillText(ch); } int CoolMenu_FPWBit(int number, int maxlen) { if (number <= maxlen) return CM_ONE; if (number <= (maxlen * 2)) return CM_TWO; if (number <= (maxlen * 3)) return CM_THREE; return CM_FOUR; } coolmenu *SelCol_Menu(int columns, char *heading, char **strings, int type, int max) { coolmenu *c = NULL; int i, co = 0; char buf[LBUF_SIZE]; strcpy(buf, heading); buf[0] = toupper(buf[0]); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); CreateMenuEntry_Simple(&c, buf, CM_ONE | CM_CENTER); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); for (co = 0; strings[co]; co++); if (columns < 0) columns = CoolMenu_FPWBit(co, 18); for (i = 0; i < co; i++) CreateMenuEntry_Normal(&c, strings[i], columns | type, i + 1, max); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); return c; } coolmenu *SelCol_FunStringMenuK(int columns, char *heading, char *(*fun) (), int last) { coolmenu *c = NULL; int i; char buf[LBUF_SIZE]; int sick = 0; strcpy(buf, heading); buf[0] = toupper(buf[0]); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); CreateMenuEntry_Simple(&c, buf, CM_ONE | CM_CENTER); if (fun(0)[0] == '%') { CreateMenuEntry_Normal(&c, fun(0), columns, 1, 0); sick = 1; } CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); if (columns < 0) columns = CoolMenu_FPWBit(last, 18); for (i = sick; i < last; i++) CreateMenuEntry_Normal(&c, fun(i), columns, i + 1 - sick, 0); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); return c; } coolmenu *SelCol_FunStringMenu(int columns, char *heading, char *(*fun) ()) { int co; for (co = 0; fun(co); co++); return SelCol_FunStringMenuK(columns, heading, fun, co); }