shithub: fc

Download patch

ref: de871ed7ecaed3a301b4007f1f49b3320abfe64d
parent: ef1c78b3ad619f48c4835f1684cf23393d704b3b
author: glenda <glenda@krsna>
date: Mon Aug 18 19:10:00 EDT 2025

more-config-emojis

--- a/fc.c
+++ b/fc.c
@@ -28,16 +28,14 @@
 #define DEFAULT_MAX_RECALC_PASSES 			10
 #define DEFAULT_FORMULA_PRECISION 			2
 #define DEFAULT_PARAGRAPH_W 				256
-#define DEFAULT_PARAGRAPH_H 				128
+#define DEFAULT_PARAGRAPH_H 				256
+#define DEFAULT_BOXWIDTH 					128
+#define DEFAULT_BOXHEIGHT 					32
+#define DEFAULT_MAXFORMULA 					256
+#define DEFAULT_MAXCONTENT 					512
+#define DEFAULT_MAXBOXES 					300
 
-/* Constants */
-#define MAXBOXES 300
-#define BOXWIDTH 128
-#define BOXHEIGHT 32
-#define MAXFORMULA 256
-#define MAXCONTENT 256
 
-
 enum {
 	T_TEXT = 0,
 	T_NUMBER,
@@ -103,6 +101,8 @@
 	int box_label_offset_y;
 	int box_text_margin;
 	int formula_indicator_offset;
+	int box_width;
+	int box_height;
 	int dialog_width;
 	int dialog_height;
 	int dialog_padding;
@@ -115,6 +115,9 @@
 	int redraw_interval;
 	int gridsnap;
 	int gridsize;
+	int max_boxes;
+	int max_formula;
+	int max_content;
 	int max_eval_depth;
 	int max_recalc_passes;
 	int formula_precision;
@@ -121,6 +124,7 @@
 	int show_formula_indicator;
 	char ctl_file[256];
 	char default_save_path[256];
+	char formula_format[32];
 	ulong color_bg;
 	ulong color_fg;
 	ulong color_box_bg;
@@ -129,7 +133,6 @@
 	ulong color_grid;
 	ulong color_label;
 	ulong color_formula;
-	char formula_format[32];
 };
 
 typedef struct Box Box;
@@ -136,8 +139,8 @@
 struct Box {
 	Point		pos;
 	Rectangle	r;
-	char		content[MAXCONTENT];
-	char		formula[MAXFORMULA];
+	char		content[DEFAULT_MAXCONTENT];
+	char		formula[DEFAULT_MAXFORMULA];
 	char		label[32];
 	int			type;
 	double		value;
@@ -149,11 +152,11 @@
 
 typedef struct Sheet Sheet;
 struct Sheet {
-	Box		boxes[MAXBOXES];
+	Box		boxes[DEFAULT_MAXBOXES];
 	int		nboxes;
 	int		selected;
 	int		editing;
-	char	editbuf[MAXCONTENT];
+	char	editbuf[DEFAULT_MAXCONTENT];
 	int		editpos;
 	int		editing_label;
 	char	labelbuf[32];
@@ -193,7 +196,7 @@
 		} range;
 		int		op;
 		int		func;
-		char	str[MAXCONTENT];
+		char	str[DEFAULT_MAXCONTENT];
 	};
 };
 
@@ -244,8 +247,8 @@
 	int  condition;
 };
 
-typedef struct CommandHandler CommandHandler;
-struct CommandHandler {
+typedef struct CtlHandler CtlHandler;
+struct CtlHandler {
 	char	*name;
 	int		minargs;
 	void	(*execute)(char **args, int nargs);
@@ -363,6 +366,8 @@
 	{"box_label_offset_y",			CFG_INT,	&config.box_label_offset_y,			0,	nil},
 	{"box_text_margin",				CFG_INT,	&config.box_text_margin,			0,	nil},
 	{"formula_indicator_offset",	CFG_INT,	&config.formula_indicator_offset,	0,	nil},
+	{"box_width",					CFG_INT,	&config.box_width,					0,	nil},
+	{"box_height",					CFG_INT,	&config.box_height,					0,	nil},
 	{"dialog_width",				CFG_INT,	&config.dialog_width,				0,	nil},
 	{"dialog_height",				CFG_INT,	&config.dialog_height,				0,	nil},
 	{"dialog_padding",				CFG_INT,	&config.dialog_padding,				0,	nil},
@@ -373,15 +378,15 @@
 	{"emoji_frame_delay",			CFG_INT,	&config.emoji_frame_delay,			0,	nil},
 	{"ctl_check_interval",			CFG_INT,	&config.ctl_check_interval,			0,	nil},
 	{"redraw_interval",				CFG_INT,	&config.redraw_interval,			0,	nil},
-
 	{"gridsize",					CFG_INT,	&config.gridsize,					0,	nil},
 	{"gridsnap",					CFG_BOOL,	&config.gridsnap,					0,	nil},
-
+	{"max_boxes",					CFG_INT,	&config.max_boxes,					0,	nil},
+	{"max_formula",					CFG_INT,	&config.max_formula,				0,	nil},
+	{"max_content",					CFG_INT,	&config.max_content,				0,	nil},
 	{"max_eval_depth",				CFG_INT,	&config.max_eval_depth,				0,	nil},
 	{"max_recalc_passes",			CFG_INT,	&config.max_recalc_passes,			0,	nil},
 	{"formula_precision",			CFG_INT,	&config.formula_precision,			0,	update_formula_format},
 	{"show_formula_indicator",		CFG_BOOL,	&config.show_formula_indicator,		0,	nil},
-
 	{"ctl_file",					CFG_STRING,	config.ctl_file,					256, nil},
 	{"default_save",				CFG_STRING,	config.default_save_path,			256, nil},
 	{"color_bg",					CFG_COLOR,	&config.color_bg,					0, nil},
@@ -396,37 +401,61 @@
 };
 
 BoxType boxtypes[] = {
-	[T_TEXT]	= {"text",	parse_text,	eval_text,	draw_box_generic},
-	[T_NUMBER]  = {"number",  parse_number,  eval_number,  draw_box_generic},
-	[T_FORMULA] = {"formula", parse_formula, eval_formula, draw_box_generic},
-	[T_LABEL]   = {"label",   parse_text,	eval_text,	draw_box_generic},
-	[T_PARAGRAPH] = {"paragraph", parse_paragraph, eval_paragraph, draw_box_paragraph},
+	[T_TEXT]	= {"text", 			parse_text,		eval_text,			draw_box_generic},
+	[T_NUMBER]  = {"number",		parse_number,	eval_number,		draw_box_generic},
+	[T_FORMULA] = {"formula",		parse_formula,	eval_formula,		draw_box_generic},
+	[T_LABEL]   = {"label",			parse_text,		eval_text,			draw_box_generic},
+	[T_PARAGRAPH] = {"paragraph",	parse_paragraph, eval_paragraph, 	draw_box_paragraph},
 };
 
 Function functions[MAXFUNCS] = {
-	[FN_SUM]	= {"SUM",	1, 100, fn_sum},
-	[FN_AVG]	= {"AVG",	1, 100, fn_avg},
-	[FN_MIN]	= {"MIN",	1, 100, fn_min},
-	[FN_MAX]	= {"MAX",	1, 100, fn_max},
-	[FN_COUNT]  = {"COUNT",  1, 100, fn_count},
-	[FN_ABS]	= {"ABS",	1, 1,   fn_abs},
-	[FN_SQRT]   = {"SQRT",   1, 1,   fn_sqrt},
-	[FN_POW]	= {"POW",	2, 2,   fn_pow},
-	[FN_ROUND]  = {"ROUND",  1, 2,   fn_round},
-	[FN_FLOOR]  = {"FLOOR",  1, 1,   fn_floor},
-	[FN_CEIL]   = {"CEIL",   1, 1,   fn_ceil},
-	[FN_IF]	 = {"IF",	 3, 3,   fn_if},
-	[FN_AND]	= {"AND",	2, 100, fn_and},
-	[FN_OR]	 = {"OR",	 2, 100, fn_or},
-	[FN_NOT]	= {"NOT",	1, 1,   fn_not},
-	[FN_LOOKUP] = {"LOOKUP", 2, 3,   fn_lookup},
+	[FN_SUM]	= {"SUM",		1, 100, fn_sum},
+	[FN_AVG]	= {"AVG",		1, 100, fn_avg},
+	[FN_MIN]	= {"MIN",		1, 100, fn_min},
+	[FN_MAX]	= {"MAX",		1, 100, fn_max},
+	[FN_COUNT]  = {"COUNT",  	1, 100, fn_count},
+	[FN_ABS]	= {"ABS",		1, 1,   fn_abs},
+	[FN_SQRT]   = {"SQRT",   	1, 1,   fn_sqrt},
+	[FN_POW]	= {"POW",		2, 2,   fn_pow},
+	[FN_ROUND]  = {"ROUND",  	1, 2,   fn_round},
+	[FN_FLOOR]  = {"FLOOR",  	1, 1,   fn_floor},
+	[FN_CEIL]   = {"CEIL",   	1, 1,   fn_ceil},
+	[FN_IF]	 	= {"IF",	 	3, 3,   fn_if},
+	[FN_AND]	= {"AND",		2, 100, fn_and},
+	[FN_OR]	 	= {"OR",	 	2, 100, fn_or},
+	[FN_NOT]	= {"NOT",		1, 1,   fn_not},
+	[FN_LOOKUP] = {"LOOKUP", 	2, 3,   fn_lookup},
 };
 
 InputMode input_modes[] = {
-	[0] = {"normal",	handle_normal_mode,	handle_normal_mouse,	draw_normal_overlay,	"E:moji  e:cycle  S:ave  O:pen  l:abel  g:rid  r:eload-cfg "},
-	[1] = {"edit",	  handle_cell_edit,	  handle_edit_mouse,	  draw_cell_edit_overlay, "Enter:save  Esc:cancel"},
-	[2] = {"label",	 handle_label_edit,	 handle_label_mouse,	 draw_label_edit_overlay,"Enter:save  Esc:cancel"},
-	[3] = {"filename",  handle_filename_input, handle_filename_mouse,  draw_filename_overlay,  "Tab:.spr  Enter:confirm  Esc:cancel"},
+	[0] = {
+			"normal",
+			handle_normal_mode,	
+			handle_normal_mouse,	
+			draw_normal_overlay,	
+			"E:moji  e:cycle  S:ave  O:pen  l:abel  g:rid  r:eload-cfg "
+		},
+	[1] = {
+			"edit",	  
+			handle_cell_edit,
+			handle_edit_mouse,
+			draw_cell_edit_overlay,
+			"Enter:save  Esc:cancel"
+		},
+	[2] = {
+			"label",
+			handle_label_edit,
+			handle_label_mouse,
+			draw_label_edit_overlay,
+			"Enter:save  Esc:cancel"
+		},
+	[3] = {
+			"filename",
+			handle_filename_input,
+			handle_filename_mouse,
+			draw_filename_overlay,
+			"Tab:.spr  Enter:confirm  Esc:cancel"
+		},
 };
 
 Command commands[] = {
@@ -461,7 +490,7 @@
 	{nil, 0}
 };
 
-CommandHandler cmd_handlers[] = {
+CtlHandler ctl_handlers[] = {
 	{"addbox", 2, ctl_addbox},
 	{"load",   1, ctl_load},
 	{"save",   1, ctl_save},
@@ -518,6 +547,335 @@
 	"~\\_(^.^)_/~"
 };
 
+char *classic_emotions[] = {
+    ":-)",
+    ":-D",
+    ";-)",
+    ":-P"
+};
+
+char *bear_moods[] = {
+    "(o.o)",
+    "(^.^)",
+    "(*.*)",
+    "(-.-)zzz"
+};
+
+char *bunny_hop[] = {
+    "(\\(\\",
+    "( -.-)(",
+    "o(\")(\")o",
+    "(\")_(\")"
+};
+
+char *robot_faces[] = {
+    "[o_o]",
+    "[O_O]",
+    "[^_^]",
+    "[x_x]"
+};
+
+char *owl_looks[] = {
+    "(O,O)",
+    "(o,o)",
+    "(0,0)",
+    "(@,@)"
+};
+
+char *fish_swim[] = {
+    "><>",
+    "<><",
+    "><(((o>",
+    "<o)))><"
+};
+
+char *music_notes[] = {
+    "d(^_^)b",
+    "q(^_^)p",
+    "b(^_^)d",
+    "p(^_^)q"
+};
+
+char *wizard_cast[] = {
+    "(o)===*",
+    "*(===o)",
+    "~(o)~===*",
+    "*===~(o)~"
+};
+
+char *table_flip[] = {
+    "(o_o)",
+    "(o_O)",
+    "(O_O)",
+    "(x_x)===___"
+};
+
+char *love_hearts[] = {
+    "<3",
+    "</3",
+    "<3<3<3",
+    "~<3~"
+};
+
+char *stick_figure[] = {
+    "o/",
+    "\\o",
+    "|o|",
+    "_o_"
+};
+
+char *cool_shades[] = {
+    "B-)",
+    "8-)",
+    "B-D",
+    "8-D"
+};
+
+char *space_invaders[] = {
+    "/o\\",
+    "\\o/",
+    "|o|",
+    "-o-"
+};
+
+char *bat_fly[] = {
+    "^v^",
+    "vVv",
+    "^V^",
+    "VvV"
+};
+
+char *spider_crawl[] = {
+    "//\\\\(oo)//\\\\",
+    "//\\\\(  )//\\\\",
+    "\\\\//(..)\\\\//",
+    "\\\\//()\\\\//",
+};
+
+char *boxing[] = {
+    "(o_o)-Q",
+    "Q-(o_o)",
+    "Q-(>_<)-Q",
+    "(^o^)9"
+};
+
+char *flex_arms[] = {
+    "o==[]::::::>",
+    "@==[]::::::>",
+    "O==[]::::::>",
+    "*==[]::::::>"
+};
+
+char *crab_walk[] = {
+    "V(o_o)V",
+    "V(._.)V",
+    "V(^_^)V",
+    "V(*_*)V"
+};
+
+char *penguin[] = {
+    "<(^_^)>",
+    "<('_')>",
+    "<(o_o)>",
+    "<(._.)>"
+};
+
+char *excited[] = {
+    "\\(^o^)/",
+    "~(^o^)~",
+    "*(^o^)*",
+    "/(^o^)\\"
+};
+
+char *ghosts[] = {
+    "~(o.o)~",
+    "~(O.O)~",
+    "~(x.x)~",
+    "~(-.-)~"
+};
+
+char *zombies[] = {
+    "[x_x]",
+    "[X_X]",
+    "]x_x[",
+    "]X_X["
+};
+
+char *snails[] = {
+    "@__)",
+    "(__@",
+    "@__]",
+    "[__@"
+};
+
+char *ufo[] = {
+    "<o>",
+    "=<o>=",
+    "==<o>==",
+    "=<o>="
+};
+
+char *rockets[] = {
+    "=>",
+    "==>",
+    "===>",
+    "===>"
+};
+
+char *weather[] = {
+    "* * *",
+    "' ' '",
+    ". . .",
+    "~ ~ ~"
+};
+
+char *math_dance[] = {
+    "+(^_^)+",
+    "-(^_^)-",
+    "*(^_^)*",
+    "/(^_^)/"
+};
+
+char *pacman[] = {
+    "C",
+    "c",
+    "<",
+    "("
+};
+
+char *dice[] = {
+    "[1]",
+    "[2]",
+    "[3]",
+    "[4]"
+};
+
+char *stars[] = {
+    "*",
+    "+",
+    "x",
+    "."
+};
+
+char *arrows[] = {
+    "->",
+    "-->",
+    "--->",
+    "---->"
+};
+
+char *code_brackets[] = {
+    "{^_^}",
+    "[^_^]",
+    "(^_^)",
+    "<^_^>"
+};
+
+char *swords[] = {
+    "o==|::::>",
+    "<::::|==o",
+    "o==|::::>",
+    "<::::|==o"
+};
+
+char *dragon[] = {
+    ">=<>",
+    ">==<>",
+    ">===<>",
+    ">====<>"
+};
+
+char *butterfly[] = {
+    "}i{",
+    "}I{",
+    "}!{",
+    "}|{"
+};
+
+char *skulls[] = {
+    "8-X",
+    "8-(",
+    "X-X",
+    "x-x"
+};
+
+char *money[] = {
+    "[$]",
+    "[$$]",
+    "[$$$]",
+    "[$$$$]"
+};
+
+char *flower[] = {
+    "@}->--",
+    "@}>---",
+    "@}>----",
+    "@}>-----"
+};
+
+char *chess[] = {
+    "|\\*",
+    "|\\#",
+    "|\\+",
+    "|\\@"
+};
+
+char *lenny[] = {
+    "( *_*)",  
+    "( o_o)",    
+    "( ^_^)",
+    "( >_>)"
+};
+
+char *minimal[] = {
+    "._.",
+    "o_o",
+    "^_^",
+    "-_-"
+};
+
+char *surprised[] = {
+    "o.o",
+    "O.O",
+    "0.0",
+    "@.@"
+};
+
+char *winking[] = {
+    ";)",
+    ";]",
+    ";D",
+    ";P"
+};
+
+char *nyan[] = {
+    "=^.^=",
+    "=^.o=",
+    "=o.^=",
+    "=o.o="
+};
+
+char *keyboard_smash[] = {
+    "asdf",
+    "jkl;",
+    "qwer",
+    "zxcv"
+};
+
+char *binary[] = {
+    "0101",
+    "1010",
+    "1100",
+    "0011"
+};
+
+char *waves[] = {
+    "~~~~~",
+    "^^^^^",
+    "vvvvv",
+    "~v~v~"
+};
+
 void
 save_spr(char *file)
 {
@@ -592,26 +950,23 @@
 		if(line[0] == '#' || line[0] == '\0')
 			continue;
 
-		// Check for formula with spaces (don't tokenize these lines)
 		if(strncmp(line, "  formula ", 10) == 0){
 			if(sheet.nboxes > 0){
 				Box *box = &sheet.boxes[sheet.nboxes-1];
 				char *content = line + 10;
 				
-				// If we have a length, use it; otherwise just copy what's there
-				if(formula_len > 0 && formula_len < MAXFORMULA){
+				if(formula_len > 0 && formula_len < config.max_formula){
 					strncpy(box->formula, content, formula_len);
 					box->formula[formula_len] = '\0';
 					formula_len = 0;
 				} else {
-					strncpy(box->formula, content, MAXFORMULA-1);
-					box->formula[MAXFORMULA-1] = '\0';
+					strncpy(box->formula, content, config.max_formula-1);
+					box->formula[config.max_formula-1] = '\0';
 				}
 			}
 			continue;
 		}
 		
-		// Check for label with spaces
 		if(strncmp(line, "  label ", 8) == 0){
 			if(sheet.nboxes > 0){
 				Box *box = &sheet.boxes[sheet.nboxes-1];
@@ -629,14 +984,13 @@
 			continue;
 		}
 
-		// For other lines, use tokenize as before
 		nf = tokenize(line, fields, nelem(fields));
 
 		if(nf >= 2 && strcmp(fields[0], "box") == 0){
-			if(sheet.nboxes < MAXBOXES){
+			if(sheet.nboxes < config.max_boxes){
 				Box *box = &sheet.boxes[sheet.nboxes];
 				memset(box, 0, sizeof(Box));
-				box->r = Rect(0, 0, BOXWIDTH, BOXHEIGHT);
+				box->r = Rect(0, 0, config.box_width, config.box_height);
 				sheet.nboxes++;
 			}
 		} else if(nf >= 3 && strcmp(fields[0], "pos") == 0){
@@ -644,7 +998,7 @@
 			box->pos.x = atoi(fields[1]);
 			box->pos.y = atoi(fields[2]);
 			box->r = Rect(box->pos.x, box->pos.y,
-				box->pos.x + BOXWIDTH, box->pos.y + BOXHEIGHT);
+				box->pos.x + config.box_width, box->pos.y + config.box_height);
 		} else if(nf >= 2 && strcmp(fields[0], "type") == 0){
 			int type = atoi(fields[1]);
 			if (type >= 0 && type < MAXBOXTYPES) {
@@ -696,37 +1050,35 @@
 	
 	b = Bfdopen(fd, OWRITE);
 	
-	Bprint(b, "# fc.conf auto-gen\n");
-	
+	Bprint(b, "# auto-gen fc.conf $\n");	
 	Bprint(b, "banner_height %d\n", config.banner_height);
 	Bprint(b, "status_height %d\n", config.status_height);
 	Bprint(b, "box_label_offset_y %d\n", config.box_label_offset_y);
 	Bprint(b, "box_text_margin %d\n", config.box_text_margin);
 	Bprint(b, "formula_indicator_offset %d\n", config.formula_indicator_offset);
-	
+	Bprint(b, "box_width %d\n", config.box_width);
+	Bprint(b, "box_height %d\n", config.box_height);	
 	Bprint(b, "dialog_width %d\n", config.dialog_width);
 	Bprint(b, "dialog_height %d\n", config.dialog_height);
 	Bprint(b, "dialog_padding %d\n", config.dialog_padding);
 	Bprint(b, "paragraph_height %d\n", config.paragraph_height);
-	Bprint(b, "paragraph_width %d\n", config.paragraph_width);
-	
+	Bprint(b, "paragraph_width %d\n", config.paragraph_width);	
 	Bprint(b, "emoji_enabled %d\n", config.emoji_enabled);
 	Bprint(b, "emoji_speed %d\n", config.emoji_speed);
 	Bprint(b, "emoji_frame_delay %d\n", config.emoji_frame_delay);
 	Bprint(b, "ctl_check_interval %d\n", config.ctl_check_interval);
-	Bprint(b, "redraw_interval %d\n", config.redraw_interval);
-	
+	Bprint(b, "redraw_interval %d\n", config.redraw_interval);	
 	Bprint(b, "gridsize %d\n", config.gridsize);
 	Bprint(b, "gridsnap %d\n", config.gridsnap);
-	
+	Bprint(b, "max_boxes %d\n", config.max_boxes);
+	Bprint(b, "max_formula %d\n", config.max_formula);
+	Bprint(b, "max_content %d\n", config.max_content);
 	Bprint(b, "max_eval_depth %d\n", config.max_eval_depth);
 	Bprint(b, "max_recalc_passes %d\n", config.max_recalc_passes);
 	Bprint(b, "formula_precision %d\n", config.formula_precision);
 	Bprint(b, "show_formula_indicator %d\n", config.show_formula_indicator);
-	
 	Bprint(b, "ctl_file %s\n", config.ctl_file);
 	Bprint(b, "default_save %s\n", config.default_save_path);
-	
 	Bprint(b, "color_bg %08lux\n", config.color_bg);
 	Bprint(b, "color_fg %08lux\n", config.color_fg);
 	Bprint(b, "color_box_bg %08lux\n", config.color_box_bg);
@@ -749,30 +1101,29 @@
 	config.box_label_offset_y = DEFAULT_BOX_LABEL_OFFSET_Y;
 	config.box_text_margin = DEFAULT_BOX_TEXT_MARGIN;
 	config.formula_indicator_offset = DEFAULT_FORMULA_INDICATOR_OFFSET;
-
+	config.box_width = DEFAULT_BOXWIDTH;
+	config.box_height = DEFAULT_BOXHEIGHT;
 	config.dialog_width = DEFAULT_DIALOG_WIDTH;
 	config.dialog_height = DEFAULT_DIALOG_HEIGHT;
 	config.dialog_padding = DEFAULT_DIALOG_PADDING;
 	config.paragraph_height = DEFAULT_PARAGRAPH_H;
 	config.paragraph_width = DEFAULT_PARAGRAPH_W;
-
 	config.emoji_enabled = 1;
 	config.emoji_speed = DEFAULT_EMOJI_SPEED;
 	config.emoji_frame_delay = DEFAULT_EMOJI_FRAME_DELAY;
 	config.ctl_check_interval = DEFAULT_CTL_CHECK_INTERVAL;
 	config.redraw_interval = DEFAULT_REDRAW_INTERVAL;
-
 	config.gridsnap = 1;
 	config.gridsize = 32;
-
+	config.max_boxes = DEFAULT_MAXBOXES;
+	config.max_formula = DEFAULT_MAXFORMULA;
+	config.max_content = DEFAULT_MAXCONTENT;
 	config.max_eval_depth = DEFAULT_MAX_EVAL_DEPTH;
 	config.max_recalc_passes = DEFAULT_MAX_RECALC_PASSES;
 	config.formula_precision = DEFAULT_FORMULA_PRECISION;
 	config.show_formula_indicator = 1;
-
 	strcpy(config.ctl_file, DEFAULT_CTL_FILE);
 	strcpy(config.default_save_path, DEFAULT_SAVE_PATH);
-
 	config.color_bg = 0xEEEEEEFF;
 	config.color_fg = 0x000000FF;
 	config.color_box_bg = 0xFFFFFFFF;
@@ -781,7 +1132,6 @@
 	config.color_grid = 0xCCCCCCFF;
 	config.color_label = 0xFF4444FF;
 	config.color_formula = 0x4444FFFF;
-
 	update_formula_format();
 }
 
@@ -873,7 +1223,13 @@
 	
 	if(config.formula_indicator_offset < 0) config.formula_indicator_offset = 0;
 	if(config.formula_indicator_offset > 30) config.formula_indicator_offset = 30;
+
+	if(config.box_width < 32) config.box_width = 32;
+	if(config.box_width > 512) config.box_width = 512;
 	
+	if(config.box_height < 32) config.box_height = 32;
+	if(config.box_height > 512) config.box_height = 512;
+	
 	if(config.dialog_width < 100) config.dialog_width = 100;
 	if(config.dialog_width > 800) config.dialog_width = 800;
 	
@@ -906,6 +1262,15 @@
 	
 	if(config.formula_precision < 0) config.formula_precision = 0;
 	if(config.formula_precision > 10) config.formula_precision = 10;
+
+	if(config.max_boxes < 3) config.max_boxes = 3;
+	if(config.max_boxes > 1000) config.max_boxes = 1000;
+
+	if(config.max_formula < 256) config.max_formula = 256;
+	if(config.max_formula > 512) config.max_formula = 512;
+
+	if(config.max_content < 32) config.max_content = 32;
+	if(config.max_content > 1024) config.max_content = 1024;
 	
 	if(config.max_eval_depth < 1) config.max_eval_depth = 1;
 	if(config.max_eval_depth > 100) config.max_eval_depth = 100;
@@ -1135,7 +1500,7 @@
 		if(*p == '"') {
 			p++;
 			i = 0;
-			while(*p && *p != '"' && i < MAXCONTENT-1)
+			while(*p && *p != '"' && i < config.max_content-1)
 				t->str[i++] = *p++;
 			t->str[i] = '\0';
 			if(*p == '"')
@@ -1625,10 +1990,10 @@
 		if(*endp == '\0') {
 			b->type = T_NUMBER;
 			b->value = val;
-			snprint(b->content, MAXCONTENT, config.formula_format, val);
+			snprint(b->content, config.max_content, config.formula_format, val);
 		} else {
 			b->type = T_TEXT;
-			strncpy(b->content, b->formula, MAXCONTENT);
+			strncpy(b->content, b->formula, config.max_content);
 		}
 		return;
 	}
@@ -1639,7 +2004,7 @@
 	e.depth = 0;
 	e.pos = 0;
 	e.ntokens = tokenize_formula(b->formula, e.tokens, nelem(e.tokens));
-	strncpy(b->content, b->formula, MAXCONTENT);
+	strncpy(b->content, b->formula, config.max_content);
 	b->dirty = 1;
 
 	b->nrefs = 0;
@@ -1672,11 +2037,11 @@
 	b->value = eval_expr(&e);
 
 	if(b->formula[0] == '=' && b->formula[1] == '"') {
-		strncpy(b->content, b->formula + 2, MAXCONTENT);
+		strncpy(b->content, b->formula + 2, config.max_content);
 		char *p = strchr(b->content, '"');
 		if(p) *p = '\0';
 	} else {
-		snprint(b->content, MAXCONTENT, config.formula_format, b->value);
+		snprint(b->content, config.max_content, config.formula_format, b->value);
 	}
 
 	b->dirty = 0;
@@ -1738,7 +2103,7 @@
 {
 	Box *b;
 
-	if(sheet.nboxes >= MAXBOXES)
+	if(sheet.nboxes >= config.max_boxes)
 		return -1;
 
 	b = &sheet.boxes[sheet.nboxes];
@@ -1750,7 +2115,7 @@
 	}
 
 	b->pos = p;
-	b->r = Rect(p.x, p.y, p.x + BOXWIDTH, p.y + BOXHEIGHT);
+	b->r = Rect(p.x, p.y, p.x + config.box_width, p.y + config.box_height);
 	b->type = T_TEXT;
 	strcpy(b->content, "");
 
@@ -1783,17 +2148,17 @@
 parse_paragraph(Box *b)
 {
 	if(b->formula[0] == '"'){
-		strncpy(b->content, b->formula + 1, MAXCONTENT - 1);
+		strncpy(b->content, b->formula + 1, config.max_content - 1);
 	} else {
-		strncpy(b->content, b->formula, MAXCONTENT - 1);
+		strncpy(b->content, b->formula, config.max_content - 1);
 	}
-	b->content[MAXCONTENT-1] = '\0';
+	b->content[config.max_content-1] = '\0';
 }
 
 void
 parse_text(Box *b)
 {
-	strncpy(b->content, b->formula, MAXCONTENT);
+	strncpy(b->content, b->formula, config.max_content);
 }
 
 void
@@ -1801,7 +2166,7 @@
 {
 	char *endp;
 	b->value = strtod(b->formula, &endp);
-	snprint(b->content, MAXCONTENT, config.formula_format, b->value);
+	snprint(b->content, config.max_content, config.formula_format, b->value);
 }
 
 void
@@ -2053,7 +2418,7 @@
 
 	char *text = text_to_draw;
 	char *line_start = text;
-	char line_buffer[MAXCONTENT];
+	char line_buffer[DEFAULT_MAXCONTENT];
 
 	while (*line_start) {
 		char *word_ptr = line_start;
@@ -2065,7 +2430,7 @@
 				word_ptr++;
 			
 			int word_len = word_ptr - line_start;
-			if(word_len >= MAXCONTENT) break;
+			if(word_len >= config.max_content) break;
 
 			strncpy(line_buffer, line_start, word_len);
 			line_buffer[word_len] = '\0';
@@ -2166,42 +2531,219 @@
 void
 cmd_cycle_emoji(void)
 {
-	static int emoji_set = 0;
-	int i;
+    static int emoji_set = 0;
+    int i;
+    
+    emoji_set = (emoji_set + 1) % 51;  /* 45 total emoji sets */
+    
+    switch(emoji_set) {
+    case 0:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = rcc_style[i];
+        break;
+    case 1:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = kirby_dance[i];
+        break;
+    case 2:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = lambda_dance[i];
+        break;
+    case 3:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = dancing_guy[i];
+        break;
+    case 4:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = happy_faces[i];
+        break;
+    case 5:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = classic_emotions[i];
+        break;
+    case 6:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = bear_moods[i];
+        break;
+    case 7:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = bunny_hop[i];
+        break;
+    case 8:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = robot_faces[i];
+        break;
+    case 9:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = owl_looks[i];
+        break;
+    case 10:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = fish_swim[i];
+        break;
+    case 11:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = music_notes[i];
+        break;
+    case 12:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = wizard_cast[i];
+        break;
+    case 13:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = table_flip[i];
+        break;
+    case 14:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = love_hearts[i];
+        break;
+    case 15:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = stick_figure[i];
+        break;
+    case 16:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = cool_shades[i];
+        break;
+    case 17:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = space_invaders[i];
+        break;
+    case 18:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = bat_fly[i];
+        break;
+    case 19:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = spider_crawl[i];
+        break;
+    case 20:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = boxing[i];
+        break;
+    case 21:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = flex_arms[i];
+        break;
+    case 22:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = crab_walk[i];
+        break;
+    case 23:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = penguin[i];
+        break;
+    case 24:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = excited[i];
+        break;
+    case 25:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = ghosts[i];
+        break;
+    case 26:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = zombies[i];
+        break;
+    case 27:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = snails[i];
+        break;
+    case 28:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = ufo[i];
+        break;
+    case 29:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = rockets[i];
+        break;
+    case 30:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = weather[i];
+        break;
+    case 31:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = math_dance[i];
+        break;
+    case 32:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = pacman[i];
+        break;
+    case 33:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = dice[i];
+        break;
+    case 34:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = stars[i];
+        break;
+    case 35:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = arrows[i];
+        break;
+    case 36:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = code_brackets[i];
+        break;
+    case 37:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = swords[i];
+        break;
+    case 38:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = dragon[i];
+        break;
+    case 39:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = butterfly[i];
+        break;
+    case 40:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = skulls[i];
+        break;
+    case 41:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = money[i];
+        break;
+    case 42:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = flower[i];
+        break;
+    case 43:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = chess[i];
+        break;
+    case 44:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = minimal[i];
+        break;
+    case 45:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = surprised[i];
+        break;
+    case 46:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = winking[i];
+        break;
+    case 47:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = nyan[i];
+        break;
+    case 48:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = keyboard_smash[i];
+        break;
+    case 49:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = binary[i];
+        break;
+    case 50:
+        for(i = 0; i < 4; i++)
+            sheet.emoji_frames[i] = waves[i];
+        break;
+    }
 
-	emoji_set = (emoji_set + 1) % 7; /* +1 each case */
-
-	switch(emoji_set) {
-	case 0:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = rcc_style[i];
-		break;
-	case 1:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = kirby_dance[i];
-		break;
-	case 2:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = lambda_dance[i];
-		break;
-	case 3:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = dancing_guy[i];
-		break;
-	case 4:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = happy_faces[i];
-		break;
-	case 5:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = cat_faces[i];
-		break;
-	case 6:
-		for(i = 0; i < 4; i++)
-			sheet.emoji_frames[i] = shrug_guys[i];
-		break;
-	}
-	sheet.needredraw = 1;
+    sheet.needredraw = 1;
 }
 
 void
@@ -2367,7 +2909,7 @@
 			sheet.editbuf[sheet.editpos] = '\0';
 			sheet.needredraw = 1;
 		}
-	} else if(key >= 32 && key < 127 && sheet.editpos < MAXCONTENT-1) {
+	} else if(key >= 32 && key < 127 && sheet.editpos < config.max_content-1) {
 		sheet.editbuf[sheet.editpos++] = key;
 		sheet.editbuf[sheet.editpos] = '\0';
 		sheet.needredraw = 1;
@@ -2454,13 +2996,13 @@
 			sheet.selected = i;
 
 			while(m.buttons & 1){
-				sheet.boxes[i].pos = subpt(m.xy, Pt(BOXWIDTH/2, BOXHEIGHT/2));
+				sheet.boxes[i].pos = subpt(m.xy, Pt(config.box_width/2, config.box_height/2));
 				if(sheet.gridsnap){
 					sheet.boxes[i].pos.x = (sheet.boxes[i].pos.x / sheet.gridsize) * sheet.gridsize;
 					sheet.boxes[i].pos.y = (sheet.boxes[i].pos.y / sheet.gridsize) * sheet.gridsize;
 				}
 				sheet.boxes[i].r = Rect(sheet.boxes[i].pos.x, sheet.boxes[i].pos.y,
-					sheet.boxes[i].pos.x + BOXWIDTH, sheet.boxes[i].pos.y + BOXHEIGHT);
+					sheet.boxes[i].pos.x + config.box_width, sheet.boxes[i].pos.y + config.box_height);
 				redraw();
 				m = emouse();
 			}
@@ -2550,8 +3092,8 @@
 	int idx = addbox(p);
 
 	if(idx >= 0 && nargs > 2) {
-		strncpy(sheet.boxes[idx].formula, args[2], MAXFORMULA-1);
-		sheet.boxes[idx].formula[MAXFORMULA-1] = '\0';
+		strncpy(sheet.boxes[idx].formula, args[2], config.max_formula-1);
+		sheet.boxes[idx].formula[config.max_formula-1] = '\0';
 
 		BoxType *bt = &boxtypes[sheet.boxes[idx].type];
 		if(bt->parse) bt->parse(&sheet.boxes[idx]);
@@ -2614,8 +3156,8 @@
 		nt = tokenize(line, tokens, nelem(tokens));
 		if(nt == 0) continue;
 
-		CommandHandler *h;
-		for(h = cmd_handlers; h->name; h++) {
+		CtlHandler *h;
+		for(h = ctl_handlers; h->name; h++) {
 			if(strcmp(tokens[0], h->name) == 0) {
 				if(nt-1 < h->minargs) {
 					fprint(2, "%s: needs %d arguments\n",
--