btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $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);
}