btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * $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);
}