src/hcode/coolmenu.c

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id: coolmenu.c,v 1.1 2005/06/13 20:50:49 murrayma Exp $
00004  *
00005  * Author: Markus Stenberg <fingon@iki.fi>
00006  *
00007  *  Copyright (c) 1996 Markus Stenberg
00008  *       All rights reserved
00009  *
00010  * Created: Mon Sep 16 20:38:36 1996 fingon
00011  * Last modified: Wed Jun 24 22:41:40 1998 fingon
00012  *
00013  */
00014 
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include "db.h"
00018 
00019 void KillText(char **mapt);
00020 void ShowText(char **mapt, dbref player);
00021 
00022 /* 
00023    Simple menu system for cool menus ;-)
00024    */
00025 #include "db.h"
00026 #include "coolmenu.h"
00027 #include "create.h"
00028 
00029 #ifndef MIN
00030 #define MIN(a,b) ((a)<(b)?(a):(b))
00031 #endif
00032 #ifndef MAX
00033 #define MAX(a,b) ((a)>(b)?(a):(b))
00034 #endif
00035 
00036 int BOUNDED(int, int, int);
00037 
00038 int number_of_entries(coolmenu * c)
00039 {
00040         if(c->flags & CM_ONE)
00041                 return 1;
00042         if(c->flags & CM_TWO)
00043                 return 2;
00044 
00045         if(c->flags & CM_THREE)
00046                 return 3;
00047         if(c->flags & CM_FOUR)
00048                 return 4;
00049         return 1;
00050 }
00051 
00052 int count_following_with(coolmenu * c, int num)
00053 {
00054         int count = 0;
00055 
00056         for(; c && number_of_entries(c) >= num && count < num; c = c->next)
00057                 count++;
00058         return count;
00059 }
00060 
00061 void display_line(char **c, int *len, coolmenu * m)
00062 {
00063         char *ch = *c;
00064         int i;
00065 
00066         sprintf(ch, "%%cb");
00067         ch += strlen(ch);
00068         for(i = 0; i < *len; i++)
00069                 *(ch++) = '-';
00070         sprintf(ch, "%%c");
00071         ch += strlen(ch);
00072         *len = 0;
00073         *c = ch;
00074 }
00075 
00076 static int compute_length(char *s)
00077 {
00078         int l = strlen(s);
00079         char *c;
00080 
00081         for(c = s; *c; c++) {
00082                 if(*c == '%')
00083                         if(*(c + 1) == 'c') {
00084                                 if(isalpha(*(c + 2))) {
00085                                         c += 2;
00086                                         l -= 3;
00087                                 } else {
00088                                         c += 1;
00089                                         l -= 2;
00090                                 }
00091                         }
00092         }
00093         return l;
00094 }
00095 
00096 void display_string(char **c, int *len, coolmenu * m)
00097 {
00098         int l = strlen(m->text), lo;
00099         int p, e;
00100         int i;
00101 
00102         if(m->flags & CM_NOCUT) {
00103                 *len = 1;
00104                 strcpy(*c, m->text);
00105                 *c += strlen(*c);
00106                 return;
00107         }
00108         if(m->flags & CM_CENTER) {
00109                 p = MAX(*len / 2 - l / 2, 0);
00110                 e = MIN(*len - 1, p + l);
00111                 for(i = 0; i < p; i++)
00112                         (*c)[i] = ' ';
00113                 *c += p;
00114                 sprintf(*c, "%%ch%%cb");
00115                 *c += strlen(*c);
00116                 strncpy(*c, m->text, (e - p) + 1);
00117                 *c += (e - p);
00118                 sprintf(*c, "%%c");
00119                 *c += strlen(*c);
00120                 **c = 0;
00121                 *len -= e;
00122         } else {
00123                 lo = l - compute_length(m->text);
00124                 l = MIN(*len - 1 + lo, l);
00125                 strncpy(*c, m->text, l);
00126                 (*c)[l] = 0;
00127                 *len -= l - lo;
00128                 *c = &((*c)[l]);
00129         }
00130 }
00131 
00132 void display_toggle_end(char **c, coolmenu * m)
00133 {
00134         if(m->value)
00135                 sprintf(*c, " %s<%%cbX%%c%%ch>%%c",
00136                                 !(m->flags & CM_NO_HILITE) ? "%ch" : "");
00137         else
00138                 sprintf(*c, " < >");
00139         *c += strlen(*c);
00140 }
00141 
00142 /* Turn value into equivalent with kilo, mega, giga, tera, peta, exa, zetta
00143    or yotta postfix. */
00144 char *stringified_value(int v)
00145 {
00146         char foo[] = "KMGTPEZY";
00147         int i = -1;
00148         static char buf[5];
00149 
00150         if(v > 999) {
00151                 do {
00152                         i++;
00153                         v /= 1000;
00154                 } while (v > 999 && foo[i]);
00155 
00156                 if(!foo[i])
00157                         i--;
00158                 sprintf(buf, "%d%c", BOUNDED(0, v, 999), foo[i]);
00159         } else
00160                 sprintf(buf, "%d", BOUNDED(0, v, 999));
00161         return buf;
00162 }
00163 
00164 void display_number_end(char **c, coolmenu * m)
00165 {
00166         if(m->value >= 0) {
00167                 sprintf(*c, " %%cg%s%4s%%c", (m->value > 0 &&
00168                                                                           !(m->
00169                                                                                 flags & CM_NO_HILITE)) ? "%ch" : "",
00170                                 stringified_value(m->value));
00171         } else
00172                 sprintf(*c, " ____");
00173         *c += strlen(*c);
00174 }
00175 
00176 char *display_entry(char *ch, int maxlen, coolmenu * c)
00177 {
00178         int i, j = 0, t = 0;
00179 
00180         /* returns: number of characters to forward the main pointer with.
00181            basically: strlen(ouradditions) */
00182         if((c->flags & (LETTERFIRST)) && !(c->flags & CM_NOTOG)) {
00183                 if(c->flags & CM_NUMBER)
00184                         maxlen -= 5;
00185                 else
00186                         maxlen -= 4;
00187                 t = ((c->flags & (CM_TOGGLE | CM_NUMBER)) && c->value);
00188                 sprintf(ch, "%s[%c]%s ", (t &&
00189                                                                   !(c->
00190                                                                         flags & CM_NO_HILITE)) ? "%ch%cr" : "%cr",
00191                                 t ? (c->letter + 'A' - 'a') : c->letter, "%c");
00192                 ch += strlen(ch);
00193         }
00194         if(c->flags & (RIGHTEDGES) && !(c->flags & CM_NORIGHT)) {
00195                 if(c->flags & CM_NUMBER)
00196                         maxlen -= 6;
00197                 else
00198                         maxlen -= 5;
00199                 j = 1;
00200         }
00201         if(t && !(c->flags & (CM_NO_HILITE))) {
00202                 sprintf(ch, "%%ch");
00203                 ch += strlen(ch);
00204         }
00205         if(c->flags & CM_LINE)
00206                 display_line(&ch, &maxlen, c);
00207         else
00208                 display_string(&ch, &maxlen, c);
00209         if(t && !(c->flags & (CM_NO_HILITE))) {
00210                 sprintf(ch, "%%c");
00211                 ch += strlen(ch);
00212         }
00213         if(maxlen > 0 && !(c->flags & CM_NOCUT)) {
00214                 for(i = 0; i < maxlen; i++)
00215                         *(ch++) = ' ';
00216         }
00217         if(j) {
00218                 if(c->flags & CM_TOGGLE)
00219                         display_toggle_end(&ch, c);
00220                 else if(c->flags & CM_NUMBER)
00221                         display_number_end(&ch, c);
00222                 *(ch++) = ' ';
00223         }
00224         *ch = 0;
00225         return ch;
00226 }
00227 
00228 void display_entries(coolmenu * c, int wnum, int num, char *text)
00229 {
00230         int i;
00231         char *ch = text;
00232         int single_length = (MENU_CHAR_WIDTH / wnum);
00233 
00234         for(i = 0; i < num; i++) {
00235                 ch = display_entry(ch, single_length, c);
00236                 c = c->next;
00237         }
00238 }
00239 
00240 char **MakeCoolMenuText(coolmenu * c)
00241 {
00242         char **m;
00243         int pos = 0;
00244         int n, rn;
00245 
00246         Create(m, char *, MAX_MENU_LENGTH + 1);
00247 
00248         /* Whole whopping menu is ready to be written at.. */
00249         while (c)
00250                 if((n = number_of_entries(c)))
00251                         if((rn = count_following_with(c, n))) {
00252                                 Create(m[pos], char, MAX_MENU_WIDTH);
00253 
00254 /*        display_entries(c,rn,m[pos++]); */
00255                                 display_entries(c, n, rn, m[pos++]);
00256                                 while (rn > 0 && c) {
00257                                         rn--;
00258                                         c = c->next;
00259                                 }
00260                         }
00261         return m;
00262 }
00263 
00264 void CreateMenuEntry_Killer(coolmenu ** c, char *text, int flag, int id,
00265                                                         int value, int maxvalue)
00266 {
00267         coolmenu *d, *e;
00268         char first = 'a';
00269 
00270         if(!*c) {
00271                 Create(*c, coolmenu, 1);
00272                 d = *c;
00273         } else {
00274                 for(d = *c; d->next; d = d->next);
00275                 Create(d->next, coolmenu, 1);
00276                 d = d->next;
00277         }
00278         if(text)
00279                 d->text = strdup(text);
00280         d->flags = flag;
00281         if((flag & LETTERFIRST) && !(flag & CM_NOTOG)) {
00282                 /* gasp, s'pose we need a letter for this thingy */
00283                 for(e = *c; e; e = e->next)
00284                         if(e->letter)
00285                                 if(e->letter >= first)
00286                                         first = e->letter + 1;
00287                 d->letter = first;
00288         }
00289         d->id = id;
00290         d->value = value;
00291         d->maxvalue = maxvalue;
00292 }
00293 
00294 void KillCoolMenu(coolmenu * c)
00295 {
00296         coolmenu *d;
00297 
00298         for(; c; c = d) {
00299                 d = c->next;
00300                 if(c->text)
00301                         free((void *) c->text);
00302                 free((void *) c);
00303         }
00304 }
00305 
00306 void ShowCoolMenu(dbref player, coolmenu * c)
00307 {
00308         char **ch;
00309 
00310         ch = MakeCoolMenuText(c);
00311         ShowText(ch, player);
00312         KillText(ch);
00313 }
00314 
00315 int CoolMenu_FPWBit(int number, int maxlen)
00316 {
00317         if(number <= maxlen)
00318                 return CM_ONE;
00319         if(number <= (maxlen * 2))
00320                 return CM_TWO;
00321         if(number <= (maxlen * 3))
00322                 return CM_THREE;
00323         return CM_FOUR;
00324 }
00325 
00326 coolmenu *SelCol_Menu(int columns, char *heading, char **strings, int type,
00327                                           int max)
00328 {
00329         coolmenu *c = NULL;
00330         int i, co = 0;
00331         char buf[LBUF_SIZE];
00332 
00333         strcpy(buf, heading);
00334         buf[0] = toupper(buf[0]);
00335         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00336         CreateMenuEntry_Simple(&c, buf, CM_ONE | CM_CENTER);
00337         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00338         for(co = 0; strings[co]; co++);
00339         if(columns < 0)
00340                 columns = CoolMenu_FPWBit(co, 18);
00341         for(i = 0; i < co; i++)
00342                 CreateMenuEntry_Normal(&c, strings[i], columns | type, i + 1, max);
00343         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00344         return c;
00345 }
00346 
00347 coolmenu *SelCol_FunStringMenuK(int columns, char *heading,
00348                                                                 char *(*fun) (), int last)
00349 {
00350         coolmenu *c = NULL;
00351         int i;
00352         char buf[LBUF_SIZE];
00353         int sick = 0;
00354 
00355         strcpy(buf, heading);
00356         buf[0] = toupper(buf[0]);
00357         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00358         CreateMenuEntry_Simple(&c, buf, CM_ONE | CM_CENTER);
00359         if(fun(0)[0] == '%') {
00360                 CreateMenuEntry_Normal(&c, fun(0), columns, 1, 0);
00361                 sick = 1;
00362         }
00363         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00364         if(columns < 0)
00365                 columns = CoolMenu_FPWBit(last, 18);
00366         for(i = sick; i < last; i++)
00367                 CreateMenuEntry_Normal(&c, fun(i), columns, i + 1 - sick, 0);
00368         CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE);
00369         return c;
00370 }
00371 
00372 coolmenu *SelCol_FunStringMenu(int columns, char *heading, char *(*fun) ())
00373 {
00374         int co;
00375 
00376         for(co = 0; fun(co); co++);
00377         return SelCol_FunStringMenuK(columns, heading, fun, co);
00378 }

Generated on Mon May 28 04:25:24 2007 for BattletechMUX by  doxygen 1.4.7