1 /******************************************************************************
2 *   This file is part of TinTin++                                             *
3 *                                                                             *
4 *   Copyright 2004-2020 Igor van den Hoven                                    *
5 *                                                                             *
6 *   TinTin++ is free software; you can redistribute it and/or modify          *
7 *   it under the terms of the GNU General Public License as published by      *
8 *   the Free Software Foundation; either version 3 of the License, or         *
9 *   (at your option) any later version.                                       *
10 *                                                                             *
11 *   This program is distributed in the hope that it will be useful,           *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
14 *   GNU General Public License for more details.                              *
15 *                                                                             *
16 *   You should have received a copy of the GNU General Public License         *
17 *   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
18 ******************************************************************************/
19 
20 /******************************************************************************
21 *                               T I N T I N + +                               *
22 *                                                                             *
23 *                      coded by Igor van den Hoven 2019                       *
24 ******************************************************************************/
25 
26 static char draw_buf[100][10];
27 static int  draw_cnt;
28 
29 #include "tintin.h"
30 
31 #define DRAW_FLAG_NONE                   0
32 #define DRAW_FLAG_ASCII               BV01
33 #define DRAW_FLAG_BLANKED             BV02
34 #define DRAW_FLAG_BOT                 BV03
35 #define DRAW_FLAG_BOXED               BV04
36 #define DRAW_FLAG_BUMP                BV05
37 #define DRAW_FLAG_CIRCLED             BV06
38 #define DRAW_FLAG_COLOR1              BV07
39 #define DRAW_FLAG_COLOR2              BV08
40 #define DRAW_FLAG_CONVERT             BV09
41 #define DRAW_FLAG_CORNERED            BV10
42 #define DRAW_FLAG_CROSSED             BV11
43 #define DRAW_FLAG_FILLED              BV12
44 #define DRAW_FLAG_FOREGROUND          BV13
45 #define DRAW_FLAG_GRID                BV14
46 #define DRAW_FLAG_HOR                 BV15
47 #define DRAW_FLAG_HUGE                BV16
48 #define DRAW_FLAG_JEWELED             BV17
49 #define DRAW_FLAG_LEFT                BV18
50 //#define DRAW_FLAG_LINED               BV19 unused / obsolete
51 #define DRAW_FLAG_NUMBERED            BV20
52 #define DRAW_FLAG_PRUNED              BV21
53 #define DRAW_FLAG_RIGHT               BV22
54 #define DRAW_FLAG_ROUNDED             BV23
55 #define DRAW_FLAG_SCALED              BV24
56 #define DRAW_FLAG_SCROLL              BV25
57 #define DRAW_FLAG_SHADOWED            BV26
58 #define DRAW_FLAG_TEED                BV27
59 #define DRAW_FLAG_TOP                 BV28
60 #define DRAW_FLAG_TRACED              BV29
61 #define DRAW_FLAG_TUBED               BV30
62 #define DRAW_FLAG_UTF8                BV31
63 #define DRAW_FLAG_VER                 BV32
64 
65 #define DRAW_FLAG_CURSIVE             BV33
66 #define DRAW_FLAG_FAT                 BV34
67 #define DRAW_FLAG_SANSSERIF           BV35
68 #define DRAW_FLAG_CALIGN              BV36
69 #define DRAW_FLAG_LALIGN              BV37
70 #define DRAW_FLAG_RALIGN              BV38
71 #define DRAW_FLAG_TALIGN              BV39
72 #define DRAW_FLAG_UALIGN              BV40
73 #define DRAW_FLAG_BALIGN              BV41
74 
75 #define DRAW_FLAG_APPENDIX            DRAW_FLAG_CIRCLED|DRAW_FLAG_CORNERED|DRAW_FLAG_CROSSED|DRAW_FLAG_JEWELED|DRAW_FLAG_PRUNED|DRAW_FLAG_ROUNDED|DRAW_FLAG_TEED
76 
77 
78 
79 #define DO_DRAW(draw) void draw (struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *box_color, char *txt_color, char *arg, char *arg1, char *arg2, char *arg3)
80 
81 extern DO_DRAW(draw_blank);
82 extern DO_DRAW(draw_bot_side);
83 //extern DO_DRAW(draw_arg);
84 extern DO_DRAW(draw_box);
85 extern DO_DRAW(draw_buffer);
86 extern DO_DRAW(draw_corner);
87 extern DO_DRAW(draw_horizontal_line);
88 extern DO_DRAW(draw_left_side);
89 extern DO_DRAW(draw_line);
90 extern DO_DRAW(draw_map);
91 extern DO_DRAW(draw_right_side);
92 extern DO_DRAW(draw_side);
93 extern DO_DRAW(draw_square);
94 extern DO_DRAW(draw_rain);
95 extern DO_DRAW(draw_hbar);
96 extern DO_DRAW(draw_table_grid);
97 extern DO_DRAW(draw_text);
98 extern DO_DRAW(draw_top_side);
99 extern DO_DRAW(draw_vertical_lines);
100 
101 typedef void DRAW(struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *box_color, char *txt_color, char *arg, char *arg1, char *arg2, char *arg3);
102 
103 struct draw_type
104 {
105 	char                  * name;
106 	char                  * desc;
107 	int                     flags;
108 	DRAW                  * fun;
109 };
110 
111 struct draw_type draw_table[] =
112 {
113 	{       "BAR",       "Draw a bar.",                       DRAW_FLAG_NONE, draw_hbar },
114 	{       "BOX",       "Draw four sides of a box.",         DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT, draw_box },
115 	{       "BUFFER",    "Draw the scrollback buffer.",       DRAW_FLAG_NONE, draw_buffer },
116 	{       "CORNER",    "Draw a corner",                     DRAW_FLAG_CORNERED, draw_corner },
117 	{       "LINE",      "Draw a line.",                      DRAW_FLAG_NONE, draw_line },
118 	{       "MAP",       "Draw the map.",                     DRAW_FLAG_NONE, draw_map },
119 	{       "RAIN",      "Draw digital rain.",                DRAW_FLAG_NONE, draw_rain },
120 	{       "SIDE",      "Draw a line with corners.",         DRAW_FLAG_CORNERED, draw_side },
121 	{       "TABLE",     "Draw a table.",                     DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT, draw_table_grid },
122 	{       "TILE",      "Draw a tile.",                      DRAW_FLAG_NONE, draw_square },
123 	{       "",          "",                                  DRAW_FLAG_NONE, NULL }
124 };
125 
126 
127 void scale_drawing(struct session *ses, int *top_row, int *top_col, int *bot_row, int *bot_col, int *rows, int *cols, int index, long long flags, char *arg);
128 
DO_COMMAND(do_draw)129 DO_COMMAND(do_draw)
130 {
131 	char *box_color, *txt_color, *code1, *code2, *input;
132 	long long flags;
133 	int index, top_row, top_col, bot_row, bot_col, rows, cols;
134 
135 	input = str_alloc_stack(0);
136 
137 	substitute(ses, arg, input, SUB_VAR|SUB_FUN);
138 
139 	arg = input;
140 
141 	draw_cnt = 0;
142 
143 	if (*arg == 0)
144 	{
145 		tintin_header(ses, 80, " DRAW OPTIONS ");
146 
147 		for (index = 0 ; *draw_table[index].fun ; index++)
148 		{
149 			if (*draw_table[index].name)
150 			{
151 				tintin_printf2(ses, "  [%-24s] %s", draw_table[index].name, draw_table[index].desc);
152 			}
153 		}
154 		tintin_header(ses, 80, "");
155 
156 		return ses;
157 	}
158 
159 	box_color = str_alloc_stack(0);
160 	txt_color = str_alloc_stack(0);
161 
162 	code1 = str_alloc_stack(0);
163 	code2 = str_alloc_stack(0);
164 
165 	flags = HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) ? DRAW_FLAG_UTF8 : 0;
166 
167 	while (*arg)
168 	{
169 		arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
170 
171 		if (!HAS_BIT(flags, DRAW_FLAG_COLOR1) && translate_color_names(ses, arg1, code1))
172 		{
173 			get_color_names(ses, arg1, box_color);
174 
175 			SET_BIT(flags, DRAW_FLAG_COLOR1);
176 
177 			continue;
178 		}
179 
180 		if (!HAS_BIT(flags, DRAW_FLAG_COLOR2) && translate_color_names(ses, arg1, code2))
181 		{
182 			get_color_names(ses, arg1, txt_color);
183 
184 			SET_BIT(flags, DRAW_FLAG_COLOR2);
185 
186 			continue;
187 		}
188 
189 		switch (*arg1 % 32)
190 		{
191 			case CTRL_A:
192 				if (is_abbrev(arg1, "ASCII"))
193 				{
194 					DEL_BIT(flags, DRAW_FLAG_UTF8);
195 				}
196 				else
197 				{
198 					goto option;
199 				}
200 				continue;
201 			case CTRL_B:
202 				if (is_abbrev(arg1, "BALIGN"))
203 				{
204 					SET_BIT(flags, DRAW_FLAG_BALIGN);
205 				}
206 				else if (is_abbrev(arg1, "BLANKED"))
207 				{
208 					SET_BIT(flags, DRAW_FLAG_BLANKED);
209 				}
210 				else if (is_abbrev(arg1, "BOTTOM"))
211 				{
212 					SET_BIT(flags, DRAW_FLAG_BOT);
213 				}
214 				else if (!strcasecmp(arg1, "BOXED"))
215 				{
216 					SET_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT);
217 				}
218 				else if (is_abbrev(arg1, "BUMPED"))
219 				{
220 					SET_BIT(flags, DRAW_FLAG_BUMP);
221 				}
222 				else
223 				{
224 					goto option;
225 				}
226 				continue;
227 			case CTRL_C:
228 				if (is_abbrev(arg1, "CALIGN"))
229 				{
230 					SET_BIT(flags, DRAW_FLAG_CALIGN);
231 				}
232 				else if (is_abbrev(arg1, "CIRCLED"))
233 				{
234 					SET_BIT(flags, DRAW_FLAG_CIRCLED);
235 				}
236 				else if (is_abbrev(arg1, "CONVERT"))
237 				{
238 					SET_BIT(flags, DRAW_FLAG_CONVERT);
239 				}
240 				else if (is_abbrev(arg1, "CROSSED"))
241 				{
242 					SET_BIT(flags, DRAW_FLAG_CROSSED);
243 				}
244 				else if (is_abbrev(arg1, "CURSIVE"))
245 				{
246 					SET_BIT(flags, DRAW_FLAG_CURSIVE);
247 				}
248 				else
249 				{
250 					goto option;
251 				}
252 				continue;
253 			case CTRL_F:
254 				if (is_abbrev(arg1, "FAT"))
255 				{
256 					SET_BIT(flags, DRAW_FLAG_FAT);
257 				}
258 				else if (is_abbrev(arg1, "FILLED"))
259 				{
260 					SET_BIT(flags, DRAW_FLAG_FILLED);
261 				}
262 				else if (is_abbrev(arg1, "FOREGROUND"))
263 				{
264 					SET_BIT(flags, DRAW_FLAG_FOREGROUND);
265 				}
266 				else
267 				{
268 					goto option;
269 				}
270 				continue;
271 			case CTRL_G:
272 				if (is_abbrev(arg1, "GRID"))
273 				{
274 					SET_BIT(flags, DRAW_FLAG_GRID);
275 				}
276 				else
277 				{
278 					goto option;
279 				}
280 				continue;
281 			case CTRL_H:
282 				if (is_abbrev(arg1, "HORIZONTAL"))
283 				{
284 					SET_BIT(flags, DRAW_FLAG_HOR);
285 				}
286 				else if (is_abbrev(arg1, "HUGE"))
287 				{
288 					SET_BIT(flags, DRAW_FLAG_HUGE);
289 				}
290 				else
291 				{
292 					goto option;
293 				}
294 				continue;
295 			case CTRL_J:
296 				if (is_abbrev(arg1, "JEWELED"))
297 				{
298 					SET_BIT(flags, DRAW_FLAG_JEWELED);
299 				}
300 				else if (is_abbrev(arg1, "JOINTED"))
301 				{
302 					SET_BIT(flags, DRAW_FLAG_CORNERED);
303 				}
304 				else
305 				{
306 					goto option;
307 				}
308 				continue;
309 			case CTRL_L:
310 				if (is_abbrev(arg1, "LALIGN"))
311 				{
312 					SET_BIT(flags, DRAW_FLAG_LALIGN);
313 				}
314 				else if (is_abbrev(arg1, "LEFT"))
315 				{
316 					SET_BIT(flags, DRAW_FLAG_LEFT);
317 				}
318 				else
319 				{
320 					goto option;
321 				}
322 				continue;
323 
324 			case CTRL_N:
325 				if (is_abbrev(arg1, "NUMBERED"))
326 				{
327 					SET_BIT(flags, DRAW_FLAG_NUMBERED);
328 				}
329 				else
330 				{
331 					goto option;
332 				}
333 				continue;
334 			case CTRL_P:
335 				if (is_abbrev(arg1, "PRUNED"))
336 				{
337 					SET_BIT(flags, DRAW_FLAG_PRUNED);
338 				}
339 				else
340 				{
341 					goto option;
342 				}
343 				continue;
344 			case CTRL_R:
345 				if (is_abbrev(arg1, "RALIGN"))
346 				{
347 					SET_BIT(flags, DRAW_FLAG_RALIGN);
348 				}
349 				else if (is_abbrev(arg1, "RIGHT"))
350 				{
351 					SET_BIT(flags, DRAW_FLAG_RIGHT);
352 				}
353 				else if (is_abbrev(arg1, "ROUNDED"))
354 				{
355 					SET_BIT(flags, DRAW_FLAG_ROUNDED);
356 				}
357 				else
358 				{
359 					goto option;
360 				}
361 				continue;
362 			case CTRL_S:
363 				if (is_abbrev(arg1, "SANSSERIF"))
364 				{
365 					SET_BIT(flags, DRAW_FLAG_SANSSERIF);
366 				}
367 				else if (is_abbrev(arg1, "SCALED"))
368 				{
369 					SET_BIT(flags, DRAW_FLAG_SCALED);
370 				}
371 				else if (is_abbrev(arg1, "SCROLL"))
372 				{
373 					SET_BIT(flags, DRAW_FLAG_SCROLL);
374 				}
375 				else if (is_abbrev(arg1, "SHADOWED"))
376 				{
377 					SET_BIT(flags, DRAW_FLAG_SHADOWED);
378 				}
379 				else
380 				{
381 					goto option;
382 				}
383 				continue;
384 			case CTRL_T:
385 				if (is_abbrev(arg1, "TALIGN"))
386 				{
387 					SET_BIT(flags, DRAW_FLAG_TALIGN);
388 				}
389 				else if (is_abbrev(arg1, "TEED"))
390 				{
391 					SET_BIT(flags, DRAW_FLAG_TEED);
392 				}
393 				else if (is_abbrev(arg1, "TOP"))
394 				{
395 					SET_BIT(flags, DRAW_FLAG_TOP);
396 				}
397 				else if (is_abbrev(arg1, "TRACED"))
398 				{
399 					SET_BIT(flags, DRAW_FLAG_TRACED);
400 				}
401 				else if (is_abbrev(arg1, "TUBED"))
402 				{
403 					SET_BIT(flags, DRAW_FLAG_TUBED);
404 				}
405 				else
406 				{
407 					goto option;
408 				}
409 				continue;
410 			case CTRL_U:
411 				if (is_abbrev(arg1, "UALIGN"))
412 				{
413 					SET_BIT(flags, DRAW_FLAG_UALIGN);
414 				}
415 				else if (is_abbrev(arg1, "UNICODE"))
416 				{
417 					SET_BIT(flags, DRAW_FLAG_UTF8);
418 				}
419 				else
420 				{
421 					goto option;
422 				}
423 				continue;
424 			case CTRL_V:
425 				if (is_abbrev(arg1, "VERTICAL"))
426 				{
427 					SET_BIT(flags, DRAW_FLAG_VER);
428 				}
429 				else
430 				{
431 					break;
432 				}
433 				continue;
434 
435 			default:
436 				goto option;
437 				continue;
438 		}
439 	}
440 
441 	option:
442 
443 	for (index = 0 ; *draw_table[index].name ; index++)
444 	{
445 		if (is_abbrev(arg1, draw_table[index].name))
446 		{
447 			arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
448 			arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
449 //			arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
450 //			arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
451 
452 			top_row = get_row_index_arg(ses, arg1);
453 			top_col = get_col_index_arg(ses, arg2);
454 
455 			arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
456 			arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
457 
458 			bot_row = get_row_index_arg(ses, arg1);
459 			bot_col = get_col_index_arg(ses, arg2);
460 
461 			if (top_row == 0 && top_col == 0)
462 			{
463 				show_error(ses, LIST_COMMAND, "#SYNTAX: #DRAW [COLOR] [OPTIONS] {%s} <TOP_ROW> <TOP_COL> <BOT_ROW> <BOT_COL> [TEXT]", draw_table[index].name);
464 
465 				return ses;
466 			}
467 
468 			if (top_row == 0)
469 			{
470 				top_row = 1;
471 
472 				SET_BIT(flags, DRAW_FLAG_SCROLL);
473 			}
474 			else
475 			{
476 				if (!HAS_BIT(flags, DRAW_FLAG_SCROLL) && !HAS_BIT(flags, DRAW_FLAG_FOREGROUND) && ses != gtd->ses)
477 				{
478 					show_message(ses, LIST_COMMAND, "#WARNING: #DRAW %s %d %d %d %d: SESSION IS IN THE BACKGROUND.", draw_table[index].name, top_row, top_col, bot_row, bot_col);
479 
480 					return ses;
481 				}
482 			}
483 
484 			if (top_col == 0)
485 			{
486 				top_col = 1;
487 			}
488 
489 			if (bot_row == 0)
490 			{
491 				bot_row = 1;
492 			}
493 
494 			if (bot_col == 0)
495 			{
496 				bot_col = 1;
497 			}
498 
499 			if (top_row > bot_row || top_col > bot_col)
500 			{
501 				show_error(ses, LIST_COMMAND, "#ERROR: #DRAW INVALID SQUARE: %s {%d %d %d %d} ROWS: %d COLS: %d", draw_table[index].name, top_row, top_col, bot_row, bot_col, 1 + bot_row - top_row, 1 + bot_col - top_col);
502 
503 				return ses;
504 			}
505 
506 			rows = URANGE(1, 1 + bot_row - top_row, gtd->screen->rows);
507 			cols = URANGE(1, 1 + bot_col - top_col, gtd->screen->cols);
508 
509 			if (HAS_BIT(flags, DRAW_FLAG_SCALED))
510 			{
511 				scale_drawing(ses, &top_row, &top_col, &bot_row, &bot_col, &rows, &cols, index, draw_table[index].flags | flags, arg);
512 			}
513 
514 			*arg1 = 0;
515 			*arg2 = 0;
516 			*arg3 = 0;
517 //			*arg4 = 0;
518 
519 			// forgot why I did this originally
520 /*
521 			if (*arg == 0)
522 			{
523 				arg = arg4;
524 			}
525 */
526 			save_pos(ses);
527 
528 			if (HAS_BIT(flags, DRAW_FLAG_BUMP))
529 			{
530 				tintin_printf2(ses, "");
531 			}
532 
533 			str_cpy(&arg2, code1);
534 			str_cpy(&arg3, code2);
535 
536 			draw_table[index].fun(ses, top_row, top_col, bot_row, bot_col, rows, cols, draw_table[index].flags | flags, box_color, txt_color, arg, arg1, arg2, arg3);
537 
538 			print_stdout(0, 0, "\e[0m");
539 
540 			restore_pos(ses);
541 
542 			return ses;
543 		}
544 	}
545 	show_error(ses, LIST_COMMAND, "#ERROR: #DRAW {%s} IS NOT A VALID OPTION.", capitalize(arg1));
546 
547 	return ses;
548 }
549 
550 // utilities
551 
scale_drawing(struct session * ses,int * top_row,int * top_col,int * bot_row,int * bot_col,int * rows,int * cols,int index,long long flags,char * arg)552 void scale_drawing(struct session *ses, int *top_row, int *top_col, int *bot_row, int *bot_col, int *rows, int *cols, int index, long long flags, char *arg)
553 {
554 	char *buf, *out, *tmp;
555 	int inside;
556 	int height, bor_height, tot_height, max_height;
557 	int width, bor_width, tot_width, max_width;
558 
559 	if (*arg == 0)
560 	{
561 		return;
562 	}
563 
564 	push_call("scale_drawing(%p,%p,%p,%p,%p,%p,%p,%p,%d,%lld,%p",ses,top_row,top_col,bot_row,bot_col,rows,cols,index,flags,arg);
565 
566 	buf = str_alloc_stack(0);
567 	out = str_alloc_stack(0);
568 	tmp = str_alloc_stack(0);
569 
570 	height = bor_height = tot_height = max_height = 0;
571 	width = bor_width = tot_width = max_width = 0;
572 
573 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
574 	{
575 		inside = TRUE;
576 	}
577 	else
578 	{
579 		inside = inside_scroll_region(ses, *top_row, *top_col);
580 	}
581 
582 	if (inside)
583 	{
584 		max_height = 0 + ses->split->bot_row - ses->split->top_row;
585 		max_width  = 1 + ses->split->bot_col - ses->split->top_col;
586 	}
587 	else
588 	{
589 		max_height = gtd->screen->rows;
590 		max_width  = gtd->screen->cols;
591 	}
592 
593 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
594 	{
595 		max_height = gtd->screen->rows * 10;
596 	}
597 
598 	bor_height += HAS_BIT(flags, DRAW_FLAG_TOP) ? 1 : 0;
599 	bor_height += HAS_BIT(flags, DRAW_FLAG_BOT) ? 1 : 0;
600 
601 	bor_width += HAS_BIT(flags, DRAW_FLAG_LEFT)  ? 1 : 0;
602 	bor_width += HAS_BIT(flags, DRAW_FLAG_RIGHT) ? 1 : 0;
603 
604 	if (HAS_BIT(flags, DRAW_FLAG_UALIGN))
605 	{
606 		ualign(ses, arg, tmp, max_width - bor_width);
607 
608 		arg = tmp;
609 	}
610 
611 	while (*arg)
612 	{
613 		arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN|SUB_COL|SUB_LIT|SUB_ESC);
614 
615 		word_wrap_split(ses, buf, out, max_width - bor_width, 0, 0, WRAP_FLAG_NONE, &height, &width);
616 
617 		tot_width = UMAX(tot_width, width);
618 		tot_height += height;
619 
620 		if (*arg == COMMAND_SEPARATOR)
621 		{
622 			arg++;
623 		}
624 	}
625 
626 	tot_height += bor_height;
627 	tot_width += bor_width;
628 
629 	if (tot_height > max_height)
630 	{
631 		tot_height = max_height;
632 	}
633 
634 	if (tot_height > *rows)
635 	{
636 		*bot_row = get_row_index(ses, *top_row + tot_height - 1);
637 
638 		if (inside)
639 		{
640 			if (*bot_row > ses->split->bot_row - 1)
641 			{
642 				*bot_row = ses->split->bot_row - 1;
643 			}
644 		}
645 		*rows = URANGE(1, 1 + *bot_row - *top_row, gtd->screen->rows);
646 	}
647 
648 	while (tot_height > *rows)
649 	{
650 		(*top_row)--;
651 
652 		*rows = 1 + *bot_row - *top_row;
653 	}
654 //	tintin_printf2(ses, "debug4: rows %d top_row: %d bot_row %d", *rows, *top_row, *bot_row);
655 
656 	if (tot_width > max_width)
657 	{
658 		tot_width = max_width;
659 	}
660 
661 	if (tot_width > *cols)
662 	{
663 		*bot_col = get_col_index(ses, *top_col + tot_width - 1);
664 
665 		if (inside)
666 		{
667 			if (*bot_col > ses->split->bot_col)
668 			{
669 				*bot_col = ses->split->bot_col;
670 			}
671 		}
672 		*cols = URANGE(1, 1 + *bot_col - *top_col, gtd->screen->cols);
673 	}
674 
675 	while (tot_width > *cols)
676 	{
677 		(*top_col)--;
678 
679 		*cols = 1 + *bot_col - *top_col;
680 	}
681 //	tintin_printf2(ses, "debug4: cols %d top_col: %d bot_col %d", *cols, *top_col, *bot_col);
682 
683 	pop_call();
684 	return;
685 }
686 
687 char *alnum_normal[] =
688 {
689 	"\x00",   "\x01",   "\x02",   "\x03",   "\x04",   "\x05",   "\x06",   "\x07",   "\x08",   "\x09",   "\x10",   "\x11",   "\x12",   "\x13",   "\x14",   "\x15",   "\x16",   "\x17",   "\x18",   "\x19",   "\x20",   "\x21",   "\x22",   "\x23",   "\x24",   "\x25",   "\x26",   "\x27",   "\x28",   "\x29",   "\x30",   "\x31",
690 	" ",      "!",      "\"",     "#",      "$",      "%",      "&",      "'",      "(",      ")",      "*",      "+",      ",",      "-",      ".",      "/",      "0",      "1",      "2",      "3",      "4",      "5",      "6",      "7",      "8",      "9",      ":",      ";",      "<",      "=",      ">",      "?",
691 	"@",      "A",      "B",      "C",      "D",      "E",      "F",      "G",      "H",      "I",      "J",      "K",      "L",      "M",      "N",      "O",      "P",      "Q",      "R",      "S",      "T",      "U",      "V",      "W",      "X",      "Y",      "Z",      "[",      "\\",     "]",      "^",      "_",
692 	"`",      "a",      "b",      "c",      "d",      "e",      "f",      "g",      "h",      "i",      "j",      "k",      "l",      "m",      "n",      "o",      "p",      "q",      "r",      "s",      "t",      "u",      "v",      "w",      "x",      "y",      "z",      "{",      "|",      "}",      "~",      "\x7F"
693 };
694 
695 char *alnum_normal_fat[] =
696 {
697 	"\x00",   "\x01",   "\x02",   "\x03",   "\x04",   "\x05",   "\x06",   "\x07",   "\x08",   "\x09",   "\x10",   "\x11",   "\x12",   "\x13",   "\x14",   "\x15",   "\x16",   "\x17",   "\x18",   "\x19",   "\x20",   "\x21",   "\x22",   "\x23",   "\x24",   "\x25",   "\x26",   "\x27",   "\x28",   "\x29",   "\x30",   "\x31",
698 	" ",      "!",      "\"",     "#",      "$",      "%",      "&",      "'",      "(",      ")",      "*",      "+",      ",",      "-",      ".",      "/",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      ":",      ";",      "<",      "=",      ">",      "?",
699 	"@",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "Z",      "��",      "\\",     "]",      "^",      "_",
700 	"`",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "{",      "|",      "}",      "~",      "\x7F"
701 };
702 
703 char *alnum_cursive[] =
704 {
705 	"\x00",   "\x01",   "\x02",   "\x03",   "\x04",   "\x05",   "\x06",   "\x07",   "\x08",   "\x09",   "\x10",   "\x11",   "\x12",   "\x13",   "\x14",   "\x15",   "\x16",   "\x17",   "\x18",   "\x19",   "\x20",   "\x21",   "\x22",   "\x23",   "\x24",   "\x25",   "\x26",   "\x27",   "\x28",   "\x29",   "\x30",   "\x31",
706 	" ",      "!",      "\"",     "#",      "$",      "%",      "&",      "'",      "(",      ")",      "*",      "+",      ",",      "-",      ".",      "/",      "0",      "1",      "2",      "3",      "4",      "5",      "6",      "7",      "8",      "9",      ":",      ";",      "<",      "=",      ">",      "?",
707 	"@",      "��",      "ℬ",      "��",      "��",      "ℰ",      "ℱ",      "��",      "ℋ",      "ℐ",      "��",      "��",      "ℒ",      "ℳ",      "��",      "��",      "��",      "��",      "ℛ",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "[",      "\\",     "]",      "^",      "_",
708 	"`",      "��",      "��",      "��",      "��",      "ℯ",      "��",      "ℊ",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "ℴ",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "{",      "|",      "}",      "~",      "\x7F"
709 };
710 
711 char *alnum_sansserif[] =
712 {
713 	"\x00",   "\x01",   "\x02",   "\x03",   "\x04",   "\x05",   "\x06",   "\x07",   "\x08",   "\x09",   "\x10",   "\x11",   "\x12",   "\x13",   "\x14",   "\x15",   "\x16",   "\x17",   "\x18",   "\x19",   "\x20",   "\x21",   "\x22",   "\x23",   "\x24",   "\x25",   "\x26",   "\x27",   "\x28",   "\x29",   "\x30",   "\x31",
714 	" ",      "!",      "\"",     "#",      "$",      "%",      "&",      "'",      "(",      ")",      "*",      "+",      ",",      "-",      ".",      "/",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      ":",      ";",      "<",      "=",      ">",      "?",
715 	"@",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "[",      "\\",     "]",      "^",      "_",
716 	"`",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "��",      "{",      "|",      "}",      "~",      "\x7F"
717 };
718 
string_to_font(struct session * ses,long long flags,char * in,char * out)719 void string_to_font(struct session *ses, long long flags, char *in, char *out)
720 {
721 	char buf[BUFFER_SIZE];
722 	char *pti, *pto;
723 	int skip;
724 
725 	push_call("string_to_font(%p,%d,%p,%p)",ses,flags,in,out);
726 
727 	// DRAW_FLAG_FAT, DRAW_FLAG_ITALIC, DRAW_FLAG_SERIF, DRAW_FLAG_CURSIVE, DRAW_FLAG_GOTHIC, DRAW_FLAG_TRACED, DRAW_FLAG_MONO
728 
729 	strcpy(buf, in);
730 
731 	pti = buf;
732 	pto = out;
733 
734 	while (*pti)
735 	{
736 		skip = skip_vt102_codes(pti);
737 
738 		if (skip)
739 		{
740 			pto += sprintf(pto, "%.*s", skip, pti);
741 
742 			pti += skip;
743 
744 			continue;
745 		}
746 
747 		if (*pti >= 32)
748 		{
749 			switch (HAS_BIT(flags, DRAW_FLAG_FAT|DRAW_FLAG_CURSIVE|DRAW_FLAG_SANSSERIF))
750 			{
751 				case DRAW_FLAG_CURSIVE:
752 					pto += sprintf(pto, "%s", alnum_cursive[(int) *pti]);
753 					break;
754 
755 				case DRAW_FLAG_FAT:
756 					pto += sprintf(pto, "%s", alnum_normal_fat[(int) *pti]);
757 					break;
758 
759 				case DRAW_FLAG_SANSSERIF:
760 					pto += sprintf(pto, "%s", alnum_sansserif[(int) *pti]);
761 					break;
762 
763 				default:
764 					*pto++ = *pti;
765 					break;
766 			}
767 			pti++;
768 		}
769 		else
770 		{
771 			*pto++ = *pti++;
772 		}
773 	}
774 	*pto++ = 0;
775 
776 	pop_call();
777 	return;
778 }
779 
find_stamp(char * in,char * out)780 int find_stamp(char *in, char *out)
781 {
782 	int cnt;
783 
784 	for (cnt = 0 ; huge_stamp_table[cnt].name != NULL ; cnt++)
785 	{
786 		if (!strcmp(in, huge_stamp_table[cnt].name))
787 		{
788 			strcpy(out, huge_stamp_table[cnt].desc);
789 
790 			return huge_stamp_table[cnt].length;
791 		}
792 	}
793 	tintin_printf2(gtd->ses, "debug: didn't find stamp {%s}", in);
794 
795 	return 0;
796 }
797 
stamp_cat(char * color,long long flags,char * str,char * cat,char * out)798 void stamp_cat(char *color, long long flags, char *str, char *cat, char *out)
799 {
800 	char *pts = str;
801 	char *ptc = cat;
802 	char *pto = out;
803 
804 	while (*pts || *ptc)
805 	{
806 		while (*pts && *pts != '\n')
807 		{
808 			*pto++ = *pts++;
809 		}
810 
811 		pto += sprintf(pto, "%s", color);
812 
813 		while (*ptc && *ptc != '\n')
814 		{
815 			if (HAS_BIT(flags, DRAW_FLAG_SHADOWED))
816 			{
817 				*pto++ = *ptc++;
818 			}
819 			else if (HAS_BIT(flags, DRAW_FLAG_TRACED))
820 			{
821 				if (!strncmp(ptc, "╗", 3))
822 				{
823 					pto += sprintf(pto, "┐");
824 					ptc += strlen("╗");
825 				}
826 				else if (!strncmp(ptc, "║", 3))
827 				{
828 					pto += sprintf(pto, "│");
829 					ptc += strlen("║");
830 				}
831 				else if (!strncmp(ptc, "╝", 3))
832 				{
833 					pto += sprintf(pto, "┘");
834 					ptc += strlen("╝");
835 				}
836 				else if (!strncmp(ptc, "╚", 3))
837 				{
838 					pto += sprintf(pto, "└");
839 					ptc += strlen("╚");
840 				}
841 				else if (!strncmp(ptc, "╔", 3))
842 				{
843 					pto += sprintf(pto, "┌");
844 					ptc += strlen("╔");
845 				}
846 				else if (!strncmp(ptc, "═", 3))
847 				{
848 					pto += sprintf(pto, "─");
849 					ptc += strlen("═");
850 				}
851 				else
852 				{
853 					*pto++ = *ptc++;
854 				}
855 			}
856 			else
857 			{
858 				if (!strncmp(ptc, "╗", 3))
859 				{
860 					pto += sprintf(pto, " ");
861 					ptc += strlen("╗");
862 				}
863 				else if (!strncmp(ptc, "║", 3))
864 				{
865 					pto += sprintf(pto, " ");
866 					ptc += strlen("║");
867 				}
868 				else if (!strncmp(ptc, "╝", 3))
869 				{
870 					pto += sprintf(pto, " ");
871 					ptc += strlen("╝");
872 				}
873 				else if (!strncmp(ptc, "╚", 3))
874 				{
875 					pto += sprintf(pto, " ");
876 					ptc += strlen("╚");
877 				}
878 				else if (!strncmp(ptc, "╔", 3))
879 				{
880 					pto += sprintf(pto, " ");
881 					ptc += strlen("╔");
882 				}
883 				else if (!strncmp(ptc, "═", 3))
884 				{
885 					pto += sprintf(pto, " ");
886 					ptc += strlen("═");
887 				}
888 				else
889 				{
890 					*pto++ = *ptc++;
891 				}
892 			}
893 		}
894 
895 		if (*pts == '\n' && *ptc == '\n')
896 		{
897 			*pto++ = *pts++;
898 			ptc++;
899 		}
900 		else if (*ptc == '\n')
901 		{
902 			*pto++ = *ptc++;
903 		}
904 	}
905 	*pto = 0;
906 }
907 
string_to_stamp(struct session * ses,long long flags,char * in,char * out)908 void string_to_stamp(struct session *ses, long long flags, char *in, char *out)
909 {
910 	char *pti, *buf1, *buf2, *buf3, chr1[CHAR_SIZE], color[COLOR_SIZE] = { 0 };
911 	int skip;
912 
913 	push_call("string_to_stamp(%p,%d,%p,%p)",ses,flags,in,out);
914 
915 	buf1 = str_alloc_stack(0);
916 	buf2 = str_alloc_stack(0);
917 	buf3 = str_alloc_stack(0);
918 
919 	sub_arg_in_braces(ses, in, buf1, GET_ALL, SUB_COL|SUB_LIT|SUB_ESC);
920 
921 	pti = buf1;
922 
923 	buf3[0] = 0;
924 
925 	while (*pti)
926 	{
927 		skip = skip_vt102_codes(pti);
928 
929 		if (skip)
930 		{
931 			get_color_codes(color, pti, color, GET_ONE);
932 
933 			pti += skip;
934 
935 			continue;
936 		}
937 		pti = get_char(ses, pti, chr1);
938 
939 		find_stamp(chr1, buf2);
940 
941 		stamp_cat(color, flags, buf3, buf2, out);
942 
943 		strcpy(buf3, out);
944 	}
945 	strcat(out, "\n");
946 
947 	pop_call();
948 	return;
949 }
950 
get_draw_corner(long long flags,char * str)951 char *get_draw_corner(long long flags, char *str)
952 {
953 	draw_cnt = (draw_cnt + 1) % 100;
954 
955 	if (HAS_BIT(flags, DRAW_FLAG_BLANKED))
956 	{
957 		strcpy(draw_buf[draw_cnt], " ");
958 	}
959 	else if (HAS_BIT(flags, DRAW_FLAG_NUMBERED))
960 	{
961 		sprintf(draw_buf[draw_cnt], "%d", draw_cnt % 10);
962 	}
963 	else if (HAS_BIT(flags, DRAW_FLAG_UTF8))
964 	{
965 		if (HAS_BIT(flags, DRAW_FLAG_PRUNED))
966 		{
967 			if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
968 			{
969 				strcpy(draw_buf[draw_cnt], " ");
970 			}
971 			else
972 			{
973 				strcpy(draw_buf[draw_cnt], "\e[C");
974 			}
975 		}
976 		else if (HAS_BIT(flags, DRAW_FLAG_CIRCLED))
977 		{
978 			if (HAS_BIT(flags, DRAW_FLAG_CROSSED))
979 			{
980 				strcpy(draw_buf[draw_cnt], "ϴ");
981 			}
982 			else if (HAS_BIT(flags, DRAW_FLAG_FILLED))
983 			{
984 				strcpy(draw_buf[draw_cnt], "⬤");
985 			}
986 			else if (HAS_BIT(flags, DRAW_FLAG_VER))
987 			{
988 				strcpy(draw_buf[draw_cnt], "O");
989 			}
990 			else
991 			{
992 				strcpy(draw_buf[draw_cnt], "○");
993 			}
994 		}
995 		else if (HAS_BIT(flags, DRAW_FLAG_CROSSED))
996 		{
997 			if (HAS_BIT(flags, DRAW_FLAG_TUBED))
998 			{
999 				strcpy(draw_buf[draw_cnt], "╬");
1000 			}
1001 			else
1002 			{
1003 				strcpy(draw_buf[draw_cnt], "┼");
1004 			}
1005 		}
1006 		else if (HAS_BIT(flags, DRAW_FLAG_JEWELED))
1007 		{
1008 			if (HAS_BIT(flags, DRAW_FLAG_FILLED))
1009 			{
1010 				strcpy(draw_buf[draw_cnt], "⧫");
1011 			}
1012 			else
1013 			{
1014 				strcpy(draw_buf[draw_cnt], "◊");
1015 			}
1016 		}
1017 		else if (HAS_BIT(flags, DRAW_FLAG_TEED))
1018 		{
1019 			if (HAS_BIT(flags, DRAW_FLAG_HOR))
1020 			{
1021 				if (HAS_BIT(flags, DRAW_FLAG_LEFT))
1022 				{
1023 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1024 					{
1025 						strcpy(draw_buf[draw_cnt], "╠");
1026 					}
1027 					else
1028 					{
1029 						strcpy(draw_buf[draw_cnt], "├");
1030 					}
1031 				}
1032 				else
1033 				{
1034 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1035 					{
1036 						strcpy(draw_buf[draw_cnt], "╣");
1037 					}
1038 					else
1039 					{
1040 						strcpy(draw_buf[draw_cnt], "┤");
1041 					}
1042 				}
1043 			}
1044 			else
1045 			{
1046 				if (HAS_BIT(flags, DRAW_FLAG_TOP))
1047 				{
1048 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1049 					{
1050 						strcpy(draw_buf[draw_cnt], "╦");
1051 					}
1052 					else
1053 					{
1054 						strcpy(draw_buf[draw_cnt], "┬");
1055 					}
1056 				}
1057 				else
1058 				{
1059 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1060 					{
1061 						strcpy(draw_buf[draw_cnt], "╩");
1062 					}
1063 					else
1064 					{
1065 						strcpy(draw_buf[draw_cnt], "┴");
1066 					}
1067 				}
1068 			}
1069 		}
1070 		else if (HAS_BIT(flags, DRAW_FLAG_BOXED) || HAS_BIT(flags, DRAW_FLAG_CORNERED))
1071 		{
1072 			if (HAS_BIT(flags, DRAW_FLAG_LEFT))
1073 			{
1074 				if (HAS_BIT(flags, DRAW_FLAG_TOP))
1075 				{
1076 					if (HAS_BIT(flags, DRAW_FLAG_ROUNDED))
1077 					{
1078 						strcpy(draw_buf[draw_cnt], "╭");
1079 					}
1080 					else
1081 					{
1082 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1083 						{
1084 							strcpy(draw_buf[draw_cnt], "╔");
1085 						}
1086 						else
1087 						{
1088 							strcpy(draw_buf[draw_cnt], "┌");
1089 						}
1090 					}
1091 				}
1092 				else if (HAS_BIT(flags, DRAW_FLAG_BOT))
1093 				{
1094 					if (HAS_BIT(flags, DRAW_FLAG_ROUNDED))
1095 					{
1096 						strcpy(draw_buf[draw_cnt], "╰");
1097 					}
1098 					else
1099 					{
1100 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1101 						{
1102 							strcpy(draw_buf[draw_cnt], "╚");
1103 						}
1104 						else
1105 						{
1106 							strcpy(draw_buf[draw_cnt], "└");
1107 						}
1108 					}
1109 				}
1110 				else
1111 				{
1112 					if (HAS_BIT(flags, DRAW_FLAG_HOR))
1113 					{
1114 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1115 						{
1116 							strcpy(draw_buf[draw_cnt], "═");
1117 						}
1118 						else
1119 						{
1120 							strcpy(draw_buf[draw_cnt], "─");
1121 						}
1122 					}
1123 					else
1124 					{
1125 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1126 						{
1127 							strcpy(draw_buf[draw_cnt], "║");
1128 						}
1129 						else
1130 						{
1131 							strcpy(draw_buf[draw_cnt], "│");
1132 						}
1133 					}
1134 				}
1135 			}
1136 			else if (HAS_BIT(flags, DRAW_FLAG_RIGHT))
1137 			{
1138 				if (HAS_BIT(flags, DRAW_FLAG_TOP))
1139 				{
1140 					if (HAS_BIT(flags, DRAW_FLAG_ROUNDED))
1141 					{
1142 						strcpy(draw_buf[draw_cnt], "╮");
1143 					}
1144 					else
1145 					{
1146 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1147 						{
1148 							strcpy(draw_buf[draw_cnt], "╗");
1149 						}
1150 						else
1151 						{
1152 							strcpy(draw_buf[draw_cnt], "┐");
1153 						}
1154 					}
1155 				}
1156 				else if (HAS_BIT(flags, DRAW_FLAG_BOT))
1157 				{
1158 					if (HAS_BIT(flags, DRAW_FLAG_ROUNDED))
1159 					{
1160 						strcpy(draw_buf[draw_cnt], "╯");
1161 					}
1162 					else
1163 					{
1164 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1165 						{
1166 							strcpy(draw_buf[draw_cnt], "╝");
1167 						}
1168 						else
1169 						{
1170 							strcpy(draw_buf[draw_cnt], "┘");
1171 						}
1172 					}
1173 				}
1174 				else
1175 				{
1176 					if (HAS_BIT(flags, DRAW_FLAG_HOR))
1177 					{
1178 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1179 						{
1180 							strcpy(draw_buf[draw_cnt], "═");
1181 						}
1182 						else
1183 						{
1184 							strcpy(draw_buf[draw_cnt], "─");
1185 						}
1186 					}
1187 					else
1188 					{
1189 						if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1190 						{
1191 							strcpy(draw_buf[draw_cnt], "║");
1192 						}
1193 						else
1194 						{
1195 							strcpy(draw_buf[draw_cnt], "│");
1196 						}
1197 					}
1198 				}
1199 			}
1200 			else
1201 			{
1202 				if (HAS_BIT(flags, DRAW_FLAG_HOR))
1203 				{
1204 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1205 					{
1206 						strcpy(draw_buf[draw_cnt], "═");
1207 					}
1208 					else
1209 					{
1210 						strcpy(draw_buf[draw_cnt], "─");
1211 					}
1212 				}
1213 				else
1214 				{
1215 					if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1216 					{
1217 						strcpy(draw_buf[draw_cnt], "║");
1218 					}
1219 					else
1220 					{
1221 						strcpy(draw_buf[draw_cnt], "│");
1222 					}
1223 				}
1224 			}
1225 		}
1226 		else
1227 		{
1228 			if (HAS_BIT(flags, DRAW_FLAG_HOR))
1229 			{
1230 				if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1231 				{
1232 					strcpy(draw_buf[draw_cnt], "═");
1233 				}
1234 				else
1235 				{
1236 					strcpy(draw_buf[draw_cnt], "─");
1237 				}
1238 			}
1239 			else if (HAS_BIT(flags, DRAW_FLAG_VER))
1240 			{
1241 				if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1242 				{
1243 					strcpy(draw_buf[draw_cnt], "║");
1244 				}
1245 				else
1246 				{
1247 					strcpy(draw_buf[draw_cnt], "│");
1248 				}
1249 			}
1250 			else
1251 			{
1252 				strcpy(draw_buf[draw_cnt], "?");
1253 			}
1254 		}
1255 	}
1256 	else
1257 	{
1258 		if (HAS_BIT(flags, DRAW_FLAG_PRUNED))
1259 		{
1260 			strcpy(draw_buf[draw_cnt], "\e[C");
1261 		}
1262 		else if (HAS_BIT(flags, DRAW_FLAG_CIRCLED) || HAS_BIT(flags, DRAW_FLAG_ROUNDED))
1263 		{
1264 			strcpy(draw_buf[draw_cnt], "o");
1265 		}
1266 		else if (HAS_BIT(flags, DRAW_FLAG_CROSSED))
1267 		{
1268 			strcpy(draw_buf[draw_cnt], "+");
1269 		}
1270 		else
1271 		{
1272 			strcpy(draw_buf[draw_cnt], "+");
1273 		}
1274 	}
1275 	return draw_buf[draw_cnt];
1276 }
1277 
draw_horizontal(long long flags,char * str)1278 char *draw_horizontal(long long flags, char *str)
1279 {
1280 	draw_cnt = (draw_cnt + 1) % 100;
1281 
1282 	if (HAS_BIT(flags, DRAW_FLAG_BLANKED))
1283 	{
1284 		strcpy(draw_buf[draw_cnt], " ");
1285 	}
1286 	else if (HAS_BIT(flags, DRAW_FLAG_NUMBERED))
1287 	{
1288 		sprintf(draw_buf[draw_cnt], "%d", draw_cnt % 10);
1289 	}
1290 	else if (HAS_BIT(flags, DRAW_FLAG_UTF8))
1291 	{
1292 		if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1293 		{
1294 			strcpy(draw_buf[draw_cnt], "═");
1295 		}
1296 		else
1297 		{
1298 			strcpy(draw_buf[draw_cnt], "─");
1299 		}
1300 	}
1301 	else
1302 	{
1303 		strcpy(draw_buf[draw_cnt], "-");
1304 	}
1305 	return draw_buf[draw_cnt];
1306 }
1307 
draw_vertical(long long flags,char * str)1308 char *draw_vertical(long long flags, char *str)
1309 {
1310 	draw_cnt = (draw_cnt + 1) % 100;
1311 
1312 	if (HAS_BIT(flags, DRAW_FLAG_BLANKED))
1313 	{
1314 		strcpy(draw_buf[draw_cnt], " ");
1315 	}
1316 	else if (HAS_BIT(flags, DRAW_FLAG_NUMBERED))
1317 	{
1318 		sprintf(draw_buf[draw_cnt], "%d", draw_cnt % 10);
1319 	}
1320 	else if (HAS_BIT(flags, DRAW_FLAG_UTF8))
1321 	{
1322 		if (HAS_BIT(flags, DRAW_FLAG_TUBED))
1323 		{
1324 			strcpy(draw_buf[draw_cnt], "║");
1325 		}
1326 		else
1327 		{
1328 			strcpy(draw_buf[draw_cnt], "│");
1329 		}
1330 	}
1331 	else
1332 	{
1333 		strcpy(draw_buf[draw_cnt], "|");
1334 	}
1335 	return draw_buf[draw_cnt];
1336 }
1337 
1338 // options
1339 
DO_DRAW(draw_bot_side)1340 DO_DRAW(draw_bot_side)
1341 {
1342 	int col, corner;
1343 
1344 	if (!HAS_BIT(flags, DRAW_FLAG_LEFT) && !HAS_BIT(flags, DRAW_FLAG_RIGHT) && !HAS_BIT(flags, DRAW_FLAG_BOT))
1345 	{
1346 		return;
1347 	}
1348 
1349 	SET_BIT(flags, HAS_BIT(flags, DRAW_FLAG_VER) ? DRAW_FLAG_VER : DRAW_FLAG_HOR);
1350 
1351 	corner = flags;
1352 
1353 	DEL_BIT(corner, DRAW_FLAG_RIGHT|DRAW_FLAG_TOP);
1354 
1355 	arg = arg1;
1356 
1357 	if (HAS_BIT(flags, DRAW_FLAG_LEFT) || HAS_BIT(flags, DRAW_FLAG_BOT))
1358 	{
1359 		SET_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_BOT);
1360 
1361 		arg1 += sprintf(arg1, "%s%s", box_color, get_draw_corner(corner, "└"));
1362 	}
1363 
1364 	if (cols - 2 >= 0)
1365 	{
1366 		if (HAS_BIT(flags, DRAW_FLAG_BOT))
1367 		{
1368 			for (col = top_col + 1 ; col < bot_col ; col++)
1369 			{
1370 				arg1 += sprintf(arg1, "%s", draw_horizontal(flags, "─"));
1371 			}
1372 		}
1373 		else if (HAS_BIT(flags, DRAW_FLAG_RIGHT) && cols - 2 > 0)
1374 		{
1375 			arg1 += sprintf(arg1, "\e[%dC", cols - 2);
1376 		}
1377 
1378 		corner = flags;
1379 
1380 		DEL_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_TOP);
1381 
1382 		if (HAS_BIT(flags, DRAW_FLAG_RIGHT) || HAS_BIT(flags, DRAW_FLAG_BOT))
1383 		{
1384 			arg1 += sprintf(arg1, "%s", get_draw_corner(corner, "┘"));
1385 		}
1386 	}
1387 
1388 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
1389 	{
1390 
1391 		tintin_printf2(ses, "%s%s", indent_one(top_col - 1), arg);
1392 	}
1393 	else
1394 	{
1395 		goto_pos(ses, bot_row, top_col);
1396 
1397 		print_stdout(bot_row, top_col, "%s", arg);
1398 	}
1399 }
1400 
1401 /*
1402 DO_DRAW(draw_arg)
1403 {
1404 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1405 	top_row = get_row_index_arg(ses, arg1);
1406 
1407 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1408 	top_col = get_col_index_arg(ses, arg1);
1409 
1410 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1411 	bot_row = get_row_index_arg(ses, arg1);
1412 
1413 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1414 	bot_col = get_col_index_arg(ses, arg1);
1415 
1416 	rows = URANGE(1, 1 + bot_row - top_row, gtd->screen->rows);
1417 	cols = URANGE(1, 1 + bot_col - top_col, gtd->screen->cols);
1418 
1419 	save_pos(ses);
1420 
1421 	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, arg2, arg1, arg, arg3);
1422 
1423 	restore_pos(ses);
1424 }
1425 */
1426 
DO_DRAW(draw_box)1427 DO_DRAW(draw_box)
1428 {
1429 	if (HAS_BIT(flags, DRAW_FLAG_TOP))
1430 	{
1431 		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1432 	}
1433 
1434 	draw_vertical_lines(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1435 
1436 	if (HAS_BIT(flags, DRAW_FLAG_BOT))
1437 	{
1438 		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1439 	}
1440 }
1441 
DO_DRAW(draw_buffer)1442 DO_DRAW(draw_buffer)
1443 {
1444 	char *buf;
1445 	int cnt, line;
1446 
1447 	push_call("draw_buffer(%p,...)",ses);
1448 
1449 	buf = str_alloc_stack(0);
1450 
1451 	if (ses->scroll->line == -1)
1452 	{
1453 		line = ses->scroll->used - 1;
1454 	}
1455 	else
1456 	{
1457 		line = ses->scroll->line;
1458 	}
1459 
1460 	for (cnt = rows ; cnt >= 0 && line - cnt >= 0 ; cnt--)
1461 	{
1462 		str_cat_printf(&buf, "{%s}", ses->scroll->buffer[line - cnt]->str);
1463 	}
1464 
1465 	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, buf, arg1, arg2, arg3);
1466 
1467 	pop_call();
1468 	return;
1469 }
1470 
DO_DRAW(draw_corner)1471 DO_DRAW(draw_corner)
1472 {
1473 	if (*arg)
1474 	{
1475 		strcpy(arg1, arg);
1476 	}
1477 	else
1478 	{
1479 		strcpy(arg1, get_draw_corner(flags, " "));
1480 	}
1481 
1482 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
1483 	{
1484 		tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), box_color, arg1);
1485 	}
1486 	else
1487 	{
1488 		goto_pos(ses, top_row, top_col);
1489 
1490 		print_stdout(top_row, top_col, "%s%s", box_color, arg1);
1491 	}
1492 }
1493 
DO_DRAW(draw_line_horizontal)1494 DO_DRAW(draw_line_horizontal)
1495 {
1496 	int col, corner;
1497 
1498 	if (!HAS_BIT(flags, DRAW_FLAG_VER))
1499 	{
1500 		SET_BIT(flags, DRAW_FLAG_HOR);
1501 	}
1502 
1503 	if (HAS_BIT(flags, DRAW_FLAG_APPENDIX))
1504 	{
1505 		if (!HAS_BIT(flags, DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT))
1506 		{
1507 			SET_BIT(flags, DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT);
1508 		}
1509 	}
1510 
1511 	corner = flags;
1512 
1513 	arg = arg1;
1514 
1515 	if (HAS_BIT(flags, DRAW_FLAG_LEFT))
1516 	{
1517 		DEL_BIT(corner, DRAW_FLAG_RIGHT);
1518 
1519 		arg1 += sprintf(arg1, "%s", get_draw_corner(corner, "┌"));
1520 	}
1521 	else
1522 	{
1523 		arg1 += sprintf(arg1, "%s", draw_horizontal(flags, "─"));
1524 	}
1525 
1526 	if (cols - 2 > 0)
1527 	{
1528 		for (col = top_col + 1 ; col < bot_col ; col++)
1529 		{
1530 			arg1 += sprintf(arg1, "%s", draw_horizontal(flags, "─"));
1531 		}
1532 	}
1533 
1534 	if (HAS_BIT(flags, DRAW_FLAG_RIGHT) && cols - 2 > 0)
1535 	{
1536 		SET_BIT(corner, DRAW_FLAG_RIGHT);
1537 		DEL_BIT(corner, DRAW_FLAG_LEFT);
1538 
1539 		arg1 += sprintf(arg1, "%s", get_draw_corner(corner, "┐"));
1540 	}
1541 	else
1542 	{
1543 		arg1 += sprintf(arg1, "%s", draw_horizontal(flags, "─"));
1544 	}
1545 
1546 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
1547 	{
1548 		tintin_printf2(ses, "%*s%s%s", top_col - 1, "", box_color, arg);
1549 	}
1550 	else
1551 	{
1552 		goto_pos(ses, top_row, top_col);
1553 
1554 		print_stdout(top_row, top_col, "%s%s", box_color, arg);
1555 	}
1556 }
1557 
DO_DRAW(draw_line_vertical)1558 DO_DRAW(draw_line_vertical)
1559 {
1560 	int row, corner;
1561 
1562 	if (!HAS_BIT(flags, DRAW_FLAG_HOR))
1563 	{
1564 		SET_BIT(flags, DRAW_FLAG_VER);
1565 	}
1566 
1567 	if (HAS_BIT(flags, DRAW_FLAG_APPENDIX))
1568 	{
1569 		if (!HAS_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT))
1570 		{
1571 			SET_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT);
1572 		}
1573 	}
1574 
1575 	corner = flags;
1576 
1577 	arg = arg1;
1578 
1579 	if (HAS_BIT(flags, DRAW_FLAG_TOP))
1580 	{
1581 		DEL_BIT(corner, DRAW_FLAG_BOT);
1582 
1583 		arg1 += sprintf(arg1, "{%s}", get_draw_corner(corner, "┬"));
1584 	}
1585 	else
1586 	{
1587 		arg1 += sprintf(arg1, "{%s}", draw_vertical(flags, "│"));
1588 	}
1589 
1590 	if (rows - 2 > 0)
1591 	{
1592 		for (row = top_row + 1 ; row < bot_row ; row++)
1593 		{
1594 			arg1 += sprintf(arg1, "{%s}", draw_vertical(flags, "│"));
1595 		}
1596 	}
1597 
1598 	if (HAS_BIT(flags, DRAW_FLAG_BOT))
1599 	{
1600 		SET_BIT(corner, DRAW_FLAG_BOT);
1601 		DEL_BIT(corner, DRAW_FLAG_TOP);
1602 
1603 		arg1 += sprintf(arg1, "{%s}", get_draw_corner(corner, "┴"));
1604 	}
1605 	else
1606 	{
1607 		arg1 += sprintf(arg1, "{%s}", draw_vertical(flags, "│"));
1608 	}
1609 
1610 	row = top_row;
1611 
1612 	while (*arg)
1613 	{
1614 		arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
1615 
1616 		if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
1617 		{
1618 			tintin_printf2(ses, "%*s%s%s", top_col - 1, "", box_color, arg2);
1619 		}
1620 		else
1621 		{
1622 			goto_pos(ses, row, top_col);
1623 
1624 			print_stdout(row, top_col, "%s%s", box_color, arg2);
1625 		}
1626 		row++;
1627 	}
1628 	return;
1629 }
1630 
DO_DRAW(draw_line)1631 DO_DRAW(draw_line)
1632 {
1633 	if (top_row == bot_row)
1634 	{
1635 		draw_line_horizontal(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1636 
1637 		return;
1638 	}
1639 
1640 	if (top_col == bot_col)
1641 	{
1642 		draw_line_vertical(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1643 
1644 		return;
1645 	}
1646 
1647 	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
1648 }
1649 
DO_DRAW(draw_map)1650 DO_DRAW(draw_map)
1651 {
1652 	int map_rows = rows;
1653 	int map_cols = cols;
1654 
1655 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_TOP|DRAW_FLAG_PRUNED))
1656 	{
1657 		map_rows--;
1658 	}
1659 
1660 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_BOT|DRAW_FLAG_PRUNED))
1661 	{
1662 		map_rows--;
1663 	}
1664 
1665 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_PRUNED))
1666 	{
1667 		map_cols--;
1668 	}
1669 
1670 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_RIGHT|DRAW_FLAG_PRUNED))
1671 	{
1672 		map_cols--;
1673 	}
1674 
1675 	if (ses->map && ses->map->in_room)
1676 	{
1677 		sprintf(arg, "{%d} {%d} {SAVE}", map_rows, map_cols);
1678 
1679 		map_map(ses, arg, arg1, arg2);
1680 	}
1681 	else
1682 	{
1683 		str_cpy(&gtd->buf, "{}");
1684 	}
1685 
1686 	if (HAS_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT))
1687 	{
1688 		draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
1689 	}
1690 	else
1691 	{
1692 		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
1693 	}
1694 }
1695 
1696 // ideas
1697 // 0 use color gradients
1698 // 1 use inverse color so text can be added to solid blocks.
1699 // 2 use ralign for raligned bar
1700 // 3 use calign for centered bar
1701 // 4 use box drawing modifiers if no box is specified.
1702 // 4.1 rounded = (###)
1703 // 4.2 teed    = [---]
1704 // 4.3 jeweled = <###>
1705 // 4.4 crossed = +++++
1706 // 4.5 circled = OOOOO
1707 // 4.6 pruned  = no rounding
1708 
1709 // hpbar <square> {val;max;color}
1710 
DO_DRAW(draw_hbar)1711 DO_DRAW(draw_hbar)
1712 {
1713 	char *nest, *buf, *ptb, *col1;
1714 	int cnt, val, bar;
1715 	long double min, max;
1716 
1717 	bar = cols;
1718 
1719 	bar -= HAS_BIT(flags, DRAW_FLAG_LEFT) ? 1 : 0;
1720 	bar -= HAS_BIT(flags, DRAW_FLAG_RIGHT) ? 1 : 0;
1721 
1722 	if (bar <= 0)
1723 	{
1724 		show_error(ses, LIST_COMMAND, "#DRAW BAR %d %d %d %d: DRAWING WIDTH (%d) MUST BE GREATER THAN 0.", top_row, top_col, bot_row, bot_col, bar);
1725 
1726 		return;
1727 	}
1728 
1729 	buf  = str_alloc_stack(0);
1730 	col1 = str_alloc_stack(0);
1731 
1732 	str_cpy(&gtd->buf, "");
1733 
1734 	bar *= 8;
1735 
1736 	start:
1737 
1738 	arg = get_arg_in_braces(ses, arg, buf, GET_ALL);
1739 
1740 	nest = buf;
1741 	nest = get_arg_in_braces(ses, nest, arg1, GET_ALL);
1742 	if (*nest == COMMAND_SEPARATOR)
1743 		nest++;
1744 	nest = get_arg_in_braces(ses, nest, arg2, GET_ALL);
1745 	if (*nest == COMMAND_SEPARATOR)
1746 		nest++;
1747 	nest = get_arg_in_braces(ses, nest, arg3, GET_ALL);
1748 
1749 	min = get_number(ses, arg1);
1750 	max = get_number(ses, arg2);
1751 
1752 	if (max <= 0)
1753 	{
1754 		show_error(ses, LIST_COMMAND, "#DRAW BAR {%s;%s;%s}: MAX (%Lg) MUST BE GREATER THAN 0.", arg1, arg2, arg3, max);
1755 
1756 		return;
1757 	}
1758 
1759 	if (min > max)
1760 	{
1761 		min = max;
1762 	}
1763 
1764 	color_gradient(arg3, min, max);
1765 
1766 	translate_color_names(ses, arg3, col1);
1767 
1768 //	printf("debug: min %d max %d bar %d\n", (int) min, (int) max, bar);
1769 
1770 	ptb = buf;
1771 
1772 	ptb += sprintf(ptb, "{%s", col1);
1773 
1774 	val = bar * min / max;
1775 
1776 	for (cnt = 8 ; cnt <= bar + 8 ; cnt += 8)
1777 	{
1778 //		printf("debug: cnt %3d - val = %3d\n", cnt, val);
1779 
1780 		if (cnt > val)
1781 		{
1782 			break;
1783 		}
1784 		ptb += sprintf(ptb, "█");
1785 	}
1786 
1787 //	printf("debug: val - lst = %d - %d\n", val, lst);
1788 
1789 	if (cnt <= bar)
1790 	{
1791 		switch (val + 8 - cnt)
1792 		{
1793 			case 0: ptb += sprintf(ptb, " "); break;
1794 			case 1: ptb += sprintf(ptb, "▏"); break;
1795 			case 2: ptb += sprintf(ptb, "▎"); break;
1796 			case 3: ptb += sprintf(ptb, "▍"); break;
1797 			case 4: ptb += sprintf(ptb, "▌"); break;
1798 			case 5: ptb += sprintf(ptb, "▋"); break;
1799 			case 6: ptb += sprintf(ptb, "▊"); break;
1800 			case 7: ptb += sprintf(ptb, "▉"); break;
1801 			case 8: ptb += sprintf(ptb, "█"); break;
1802 		}
1803 		ptb += sprintf(ptb, "%*s%s}", (bar - cnt) / 8, "", box_color);
1804 	}
1805 	else
1806 	{
1807 		ptb += sprintf(ptb, "%s}", box_color);
1808 	}
1809 
1810 	str_cat(&gtd->buf, buf);
1811 
1812 //	printf("debug (%s) bar: %d cnt %d val %d\n", gtd->buf, bar, cnt, val);
1813 
1814 	if (*arg)
1815 	{
1816 		goto start;
1817 	}
1818 
1819 	*arg1 = 0;
1820 	*arg2 = 0;
1821 	*arg3 = 0;
1822 
1823 	if (HAS_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT))
1824 	{
1825 		draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
1826 	}
1827 	else
1828 	{
1829 		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
1830 	}
1831 }
1832 
1833 char *rain_symbols = "ロヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ01SԐ45789Z=*+-¦|_ʺ╌";
1834 char *braille_symbols = "⠁⠂⠃⠄⠅⠆⠇⠈⠊⠌⠎⠐⠑⠔⠕⠘⠜⠠⠡⠢⠣⠨⠪⠰⠱⠸⡀⡁⡂⡃⡄⡅⡆⡇⡈⡊⡌⡎⡐⡑⡔⡕⡘⡜⡠⡡⡢⡣⡨⡪⡰⡱⡸⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢌⢎⢐⢑⢔⢕⢘⢜⢠⢡⢢⢣⢨⢪⢰⢱";
1835 
DO_DRAW(draw_rain)1836 DO_DRAW(draw_rain)
1837 {
1838 	char code[BUFFER_SIZE], arg4[BUFFER_SIZE], *rain[400];
1839 	struct listnode *node;
1840 	int row, col, len, rand, cnt, size, max, utfs[400];
1841 	long double density, fade;
1842 
1843 	strcpy(code, arg2);
1844 
1845 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1846 
1847 
1848 	if (!valid_variable(ses, arg1))
1849 	{
1850 		show_error(ses, LIST_COMMAND, "#SYNTAX: #DRAW {<COLOR>} RAIN %d %d %d %d {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}.", top_row, top_col, bot_row, bot_col);
1851 
1852 		return;
1853 	}
1854 
1855 	node = search_nest_node_ses(ses, arg1);
1856 
1857 	if (node == NULL || node->root == NULL)
1858 	{
1859 		node = set_nest_node(ses->list[LIST_VARIABLE], arg1, "{0}{}");
1860 	}
1861 
1862 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1863 
1864 	if (*arg1 == 0)
1865 	{
1866 		density = 1;
1867 	}
1868 	else
1869 	{
1870 		density = URANGE(0.01, get_number(ses, arg1), 100);
1871 	}
1872 
1873 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
1874 
1875 	if (*arg1 == 0)
1876 	{
1877 		fade = 10;
1878 	}
1879 	else
1880 	{
1881 		fade = URANGE(1, get_number(ses, arg1), 100);
1882 	}
1883 
1884 	arg = get_arg_in_braces(ses, arg, arg4, GET_ONE);
1885 
1886 	if (*arg4 == 0)
1887 	{
1888 		if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER))
1889 		{
1890 			for (max = len = 0 ; braille_symbols[len] ; max++)
1891 			{
1892 				rain[max] = &braille_symbols[len];
1893 				utfs[max] = get_utf8_size(&braille_symbols[len]);
1894 				len += utfs[max];
1895 			}
1896 		}
1897 		else
1898 		{
1899 			for (max = len = 0 ; rain_symbols[len] ; max++)
1900 			{
1901 				rain[max] = &rain_symbols[len];
1902 				utfs[max] = get_utf8_size(&rain_symbols[len]);
1903 				len += utfs[max];
1904 			}
1905 		}
1906 	}
1907 	else
1908 	{
1909 		for (max = len = 0 ; arg4[len] && max < 400 ; max++)
1910 		{
1911 			rain[max] = &arg4[len];
1912 			utfs[max] = get_utf8_size(&arg4[len]);
1913 			len += utfs[max];
1914 		}
1915 	}
1916 
1917 //	tintin_printf2(ses, "debug: [%s] (%s) <%s>", code, fuzzy_color_code(ses, code), dim_color_code(ses, code, 20));
1918 
1919 	for (col = 0 ; col < 1 + bot_col - top_col ; col++)
1920 	{
1921 		if (node->root->used <= col)
1922 		{
1923 			set_nest_node(node->root, ntos(col), "");
1924 		}
1925 
1926 		if (node->root->list[col]->val16[0] == 0)
1927 		{
1928 			if (generate_rand(ses) % 10000 / (long double) 100 < density)
1929 			{
1930 				rand = generate_rand(ses) % rows;
1931 
1932 				node->root->list[col]->val16[0] = 1;
1933 				node->root->list[col]->val16[1] = rand;
1934 				node->root->list[col]->val16[2] = rand < rows / 2 ? 2 : 0;
1935 				node->root->list[col]->val16[3] = 0;
1936 
1937 				str_cpy_printf(&node->root->list[col]->arg2, "%*s", rand, "");
1938 			}
1939 			continue;
1940 		}
1941 		else if (node->root->list[col]->val16[0] == 1)
1942 		{
1943 			if (node->root->list[col]->val16[2])
1944 			{
1945 				node->root->list[col]->val16[3]++;
1946 
1947 				if (node->root->list[col]->val16[3] % 2)
1948 				{
1949 					rand = generate_rand(ses) % max;
1950 
1951 					sprintf(arg2, "%s%.*s", lit_color_code(ses, code, 10), utfs[rand], rain[rand]);
1952 
1953 					substitute(ses, arg2, arg3, SUB_COL);
1954 
1955 					goto_pos(ses, top_row + node->root->list[col]->val16[1], top_col + col);
1956 
1957 					print_stdout(0, 0, "%s", arg3);
1958 
1959 					continue;
1960 				}
1961 			}
1962 
1963 			rand = generate_rand(ses) % max;
1964 
1965 			str_cat_printf(&node->root->list[col]->arg2, "%.*s", utfs[rand], rain[rand]);
1966 
1967 			node->root->list[col]->val16[1]++;
1968 
1969 			if (generate_rand(ses) % 10000 / (long double) 100 < fade)
1970 			{
1971 				node->root->list[col]->val16[0] = 2;
1972 			}
1973 			else if (node->root->list[col]->val16[1] > rows - generate_rand(ses) % 8)
1974 			{
1975 				node->root->list[col]->val16[0] = 2;
1976 			}
1977 		}
1978 		else
1979 		{
1980 			node->root->list[col]->val16[0]++;
1981 		}
1982 
1983 		len = str_len(node->root->list[col]->arg2);
1984 
1985 		row = 0;
1986 		cnt = 0;
1987 
1988 		if (node->root->list[col]->val16[0] == 1)
1989 		{
1990 			while (row < len)
1991 			{
1992 				if (node->root->list[col]->arg2[row] == ' ')
1993 				{
1994 					cnt++;
1995 					row++;
1996 
1997 					continue;
1998 				}
1999 				goto_pos(ses, top_row + cnt, top_col + col);
2000 
2001 				cnt++;
2002 
2003 				size = get_utf8_size(&node->root->list[col]->arg2[row]);
2004 
2005 				if (cnt == node->root->list[col]->val16[1])
2006 				{
2007 					sprintf(arg2, "%s%.*s", lit_color_code(ses, code, 5), size, &node->root->list[col]->arg2[row]);
2008 				}
2009 				else
2010 				{
2011 					if (node->root->list[col]->val16[1] % 2 == 0)
2012 					{
2013 						row += size;
2014 
2015 						continue;
2016 					}
2017 
2018 					sprintf(arg2, "%s%.*s", fuzzy_color_code(ses, code), size, &node->root->list[col]->arg2[row]);
2019 				}
2020 
2021 				substitute(ses, arg2, arg3, SUB_COL);
2022 
2023 				print_stdout(0, 0, "%s", arg3);
2024 
2025 				row += size;
2026 			}
2027 		}
2028 		else if (node->root->list[col]->val16[0] > 1)
2029 		{
2030 			while (row < len)
2031 			{
2032 				if (node->root->list[col]->arg2[row] == ' ')
2033 				{
2034 					cnt++;
2035 					row++;
2036 					continue;
2037 				}
2038 
2039 				goto_pos(ses, top_row + cnt, top_col + col);
2040 
2041 				cnt++;
2042 
2043 				size = get_utf8_size(&node->root->list[col]->arg2[row]);
2044 
2045 				if (node->root->list[col]->val16[0] - cnt > 15)
2046 				{
2047 					sprintf(arg2, "%s ", dim_color_code(ses, code, node->root->list[col]->val16[0] - cnt));
2048 					substitute(ses, arg2, arg3, SUB_COL);
2049 					print_stdout(0, 0, "%s", arg3);
2050 
2051 					print_stdout(0, 0, " ");
2052 				}
2053 				else if (node->root->list[col]->val16[0] - cnt < 0)
2054 				{
2055 					sprintf(arg2, "%s%.*s", fuzzy_color_code(ses, code), size, &node->root->list[col]->arg2[row]);
2056 					substitute(ses, arg2, arg3, SUB_COL);
2057 					print_stdout(0, 0, "%s", arg3);
2058 				}
2059 				else
2060 				{
2061 					sprintf(arg2, "%s%.*s", dim_color_code(ses, code, node->root->list[col]->val16[0] - cnt), size, &node->root->list[col]->arg2[row]);
2062 					substitute(ses, arg2, arg3, SUB_COL);
2063 					print_stdout(0, 0, "%s", arg3);
2064 				}
2065 
2066 				row += size;
2067 			}
2068 
2069 			if (node->root->list[col]->val16[0] - cnt > 16)
2070 			{
2071 				node->root->list[col]->val16[0] = 0;
2072 				node->root->list[col]->val16[1] = 0;
2073 
2074 				str_cpy(&node->root->list[col]->arg2, "");
2075 			}
2076 		}
2077 		else
2078 		{
2079 			tintin_printf2(ses, "debug: problemo");
2080 		}
2081 	}
2082 }
2083 
DO_DRAW(draw_side)2084 DO_DRAW(draw_side)
2085 {
2086 	push_call("draw_side()");
2087 
2088 	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
2089 
2090 	pop_call();
2091 	return;
2092 }
2093 
DO_DRAW(draw_square)2094 DO_DRAW(draw_square)
2095 {
2096 	if (HAS_BIT(flags, DRAW_FLAG_TOP))
2097 	{
2098 		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
2099 	}
2100 
2101 	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
2102 
2103 	if (HAS_BIT(flags, DRAW_FLAG_BOT))
2104 	{
2105 		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
2106 	}
2107 }
2108 
2109 
DO_DRAW(draw_table_grid)2110 DO_DRAW(draw_table_grid)
2111 {
2112 	char buf1[BUFFER_SIZE], *str, buf2[BUFFER_SIZE], buf3[BUFFER_SIZE], row_color[COLOR_SIZE];
2113 	int corner, blank, row, col, max_r, max_c, r, c, top_r, top_c, bot_r, bot_c, tot_r, tot_c;
2114 
2115 	row = cnt_arg_all(ses, arg, GET_ALL);
2116 
2117 	row = URANGE(0, row, (rows - 1) / 2);
2118 
2119 	get_arg_in_braces(ses, arg, buf1, GET_ALL);
2120 
2121 	col = cnt_arg_all(ses, buf1, GET_ALL);
2122 
2123 	if (row == 0 || col == 0)
2124 	{
2125 		tintin_printf2(ses, "#ERROR: #DRAW TABLE: NEED AT LEAST 1 ROW AND 1 COLUMN.");
2126 
2127 		return;
2128 	}
2129 
2130 	if (*arg3)
2131 	{
2132 		substitute(ses, arg3, row_color, SUB_COL|SUB_LIT|SUB_ESC);
2133 	}
2134 	else
2135 	{
2136 		row_color[0] = 0;
2137 	}
2138 
2139 	corner = flags;
2140 
2141 	DEL_BIT(corner, DRAW_FLAG_LEFT | DRAW_FLAG_RIGHT | DRAW_FLAG_TOP | DRAW_FLAG_BOT);
2142 
2143 	if (HAS_BIT(flags, DRAW_FLAG_GRID))
2144 	{
2145 		max_r = (rows - 1) / row;
2146 		max_c = (cols - 1) / col;
2147 
2148 		tot_r = 1 + max_r * row;
2149 		tot_c = 1 + max_c * col;
2150 
2151 		if (max_r <= 0)
2152 		{
2153 			tintin_printf2(ses, "#ERROR: #DRAW TABLE: ROW SIZE TOO SMALL.");
2154 			return;
2155 		}
2156 
2157 		if (max_c <= 0)
2158 		{
2159 			tintin_printf2(ses, "#ERROR: #DRAW TABLE: COLUMN SIZE TOO SMALL.");
2160 			return;
2161 		}
2162 
2163 
2164 		for (r = 0 ; r < tot_r ; r++)
2165 		{
2166 			buf3[0] = 0;
2167 
2168 			if (r % max_r == 0)
2169 			{
2170 				arg = get_arg_in_braces(ses, arg, buf1, GET_ALL);
2171 				str = buf1;
2172 
2173 				if (*arg == COMMAND_SEPARATOR)
2174 				{
2175 					arg++;
2176 				}
2177 			}
2178 			else
2179 			{
2180 				str = buf1;
2181 			}
2182 
2183 			for (c = 0 ; c < tot_c ; c++)
2184 			{
2185 				if (r == 0)
2186 				{
2187 					if (c == 0)
2188 					{
2189 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_LEFT | DRAW_FLAG_TOP, "┌"));
2190 					}
2191 					else if (c == tot_c - 1)
2192 					{
2193 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_RIGHT | DRAW_FLAG_TOP, "┐"));
2194 					}
2195 					else if (c % max_c == 0)
2196 					{
2197 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_TEED | DRAW_FLAG_TOP, "┬"));
2198 					}
2199 					else
2200 					{
2201 						strcat(buf3, draw_horizontal(flags, "?"));
2202 					}
2203 				}
2204 				else if (r == tot_r - 1)
2205 				{
2206 					if (c == 0)
2207 					{
2208 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_LEFT | DRAW_FLAG_BOT, "?"));
2209 					}
2210 					else if (c == tot_c - 1)
2211 					{
2212 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_RIGHT | DRAW_FLAG_BOT, "?"));
2213 					}
2214 					else if (c % max_c == 0)
2215 					{
2216 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_TEED | DRAW_FLAG_BOT, "┬"));
2217 					}
2218 					else
2219 					{
2220 						strcat(buf3, draw_horizontal(flags, "?"));
2221 					}
2222 				}
2223 				else if (r % max_r == 0)
2224 				{
2225 					if (c == 0)
2226 					{
2227 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_TEED | DRAW_FLAG_HOR | DRAW_FLAG_LEFT, "?"));
2228 					}
2229 					else if (c == tot_c - 1)
2230 					{
2231 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_TEED | DRAW_FLAG_HOR | DRAW_FLAG_RIGHT, "?"));
2232 					}
2233 					else if (c % max_c == 0)
2234 					{
2235 						strcat(buf3, get_draw_corner(corner | DRAW_FLAG_CROSSED, "?"));
2236 					}
2237 					else
2238 					{
2239 						strcat(buf3, draw_horizontal(flags, "?"));
2240 					}
2241 				}
2242 				else if (r % max_r == 1)
2243 				{
2244 					if (c == tot_c - 1)
2245 					{
2246 						if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2247 						{
2248 							cat_sprintf(buf3, "%s", draw_vertical(flags, "│"));
2249 						}
2250 						else
2251 						{
2252 							goto_pos(ses, top_row + r, top_col + c);
2253 
2254 							print_stdout(top_row + r, top_col + c, "%s%s", box_color, draw_vertical(flags, "│"));
2255 						}
2256 					}
2257 					else if (c == 0 || c % max_c == 0)
2258 					{
2259 						strcpy(buf2, row_color);
2260 
2261 						str = sub_arg_in_braces(ses, str, buf2 + strlen(buf2), GET_ALL, SUB_VAR|SUB_FUN|SUB_LIT|SUB_ESC|SUB_COL);
2262 
2263 						get_color_codes(row_color, buf2, row_color, GET_ALL);
2264 
2265 						top_r = top_row + r - 1;
2266 						top_c = top_col + c;
2267 						bot_r = top_row + r - 1 + max_r;
2268 						bot_c = top_col + c + max_c;
2269 
2270 						draw_vertical_lines(ses, top_r, top_c, top_r, bot_c, 1 + max_r, 1 + max_c, corner | DRAW_FLAG_LEFT, box_color, txt_color, buf2, arg1, arg2, arg3);
2271 
2272 						if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2273 						{
2274 							strcat(buf3, arg2);
2275 						}
2276 
2277 						if (*str == COMMAND_SEPARATOR)
2278 						{
2279 							str++;
2280 						}
2281 					}
2282 				}
2283 				else
2284 				{
2285 					if (c == tot_c - 1)
2286 					{
2287 						if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2288 						{
2289 							cat_sprintf(buf3, "%s", draw_vertical(flags, "│"));
2290 						}
2291 						else
2292 						{
2293 							goto_pos(ses, top_row + r, top_col + c);
2294 
2295 							print_stdout(top_row + r, top_col + c, "%s%s", box_color, draw_vertical(flags, "│"));
2296 						}
2297 					}
2298 				}
2299 			}
2300 
2301 			if (*buf3)
2302 			{
2303 				if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2304 				{
2305 					tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), box_color, buf3);
2306 				}
2307 				else
2308 				{
2309 					goto_pos(ses, top_row + r, top_col);
2310 
2311 					print_stdout(top_row + r, top_col, "%s%s", box_color, buf3);
2312 				}
2313 			}
2314 
2315 		}
2316 		return;
2317 	}
2318 
2319 	blank = flags;
2320 
2321 	DEL_BIT(blank, DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT);
2322 
2323 	max_r = rows / row;
2324 	max_c = cols / col;
2325 
2326 	for (r = 0 ; r < row ; r++)
2327 	{
2328 		top_r = top_row + r * max_r;
2329 		bot_r = top_row + r * max_r + max_r - 1;
2330 
2331 		arg = get_arg_in_braces(ses, arg, buf1, GET_ALL);
2332 
2333 		str = buf1;
2334 
2335 		for (c = 0 ; c < col ; c++)
2336 		{
2337 			str = get_arg_in_braces(ses, str, buf2, GET_ALL);
2338 
2339 			top_c = top_col + c * max_c;
2340 			bot_c = top_col + c * max_c + max_c - 1;
2341 
2342 			draw_box(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, flags, box_color, txt_color, buf2, arg1, arg2, arg3);
2343 
2344 //			tintin_printf2(ses, "#draw box %d %d %d %d %s", top_row + r * max_r, top_col + c * max_c, top_row + r * max_r + max_r, top_col + c * max_c + max_c, buf1);
2345 
2346 			if (*str == COMMAND_SEPARATOR)
2347 			{
2348 				str++;
2349 			}
2350 		}
2351 
2352 		if (cols > max_c * col)
2353 		{
2354 			top_c = top_col + c * max_c;
2355 			bot_c = bot_col;
2356 
2357 			draw_text(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, blank, box_color, txt_color, "", arg1, arg2, arg3);
2358 		}
2359 
2360 		if (*arg == COMMAND_SEPARATOR)
2361 		{
2362 			arg++;
2363 		}
2364 	}
2365 }
2366 
DO_DRAW(draw_text)2367 DO_DRAW(draw_text)
2368 {
2369 	char *txt, *buf1, *buf2, *buf3, side1[100], side2[100];
2370 	int row, col, height, width;
2371 
2372 	push_call("draw_text(%p,%d,%p,%p,%p)",ses,flags,arg,arg1,arg2);
2373 
2374 	buf1 = str_alloc_stack(0);
2375 	buf2 = str_alloc_stack(0);
2376 	buf3 = str_alloc_stack(0);
2377 
2378 	side1[0] = side2[0] = arg2[0] = 0;
2379 
2380 	txt = buf2;
2381 
2382 	substitute(ses, arg, buf3, SUB_VAR|SUB_FUN);
2383 
2384 	arg = buf3;
2385 
2386 	if (*arg3)
2387 	{
2388 		txt += substitute(ses, arg3, txt, SUB_COL|SUB_LIT|SUB_ESC);
2389 	}
2390 
2391 	if (HAS_BIT(flags, DRAW_FLAG_HUGE))
2392 	{
2393 		string_to_stamp(ses, flags, arg, txt);
2394 	}
2395 	else
2396 	{
2397 		while (*arg)
2398 		{
2399 			arg = sub_arg_in_braces(ses, arg, buf1, GET_ALL, SUB_COL|SUB_LIT|SUB_ESC|SUB_VAR|SUB_FUN);
2400 
2401 			txt += sprintf(txt, "%s\n", buf1);
2402 
2403 			if (*arg == COMMAND_SEPARATOR)
2404 			{
2405 				arg++;
2406 			}
2407 		}
2408 		string_to_font(ses, flags, buf2, buf2);
2409 	}
2410 
2411 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_TOP|DRAW_FLAG_PRUNED))
2412 	{
2413 		top_row++;
2414 		rows--;
2415 	}
2416 
2417 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_BOT|DRAW_FLAG_PRUNED))
2418 	{
2419 		bot_row--;
2420 		rows--;
2421 	}
2422 
2423 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_PRUNED))
2424 	{
2425 		strcpy(side1, " ");
2426 		cols--;
2427 	}
2428 
2429 	if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_RIGHT|DRAW_FLAG_PRUNED))
2430 	{
2431 		if (!HAS_BIT(flags, DRAW_FLAG_GRID) || HAS_BIT(flags, DRAW_FLAG_RIGHT))
2432 		{
2433 			strcpy(side2, " ");
2434 		}
2435 		cols--;
2436 	}
2437 
2438 	if (HAS_BIT(flags, DRAW_FLAG_UALIGN))
2439 	{
2440 		ualign(ses, buf2, buf3, cols);
2441 
2442 		word_wrap_split(ses, buf3, buf1, cols, 0, 0, FLAG_NONE, &height, &width);
2443 	}
2444 	else
2445 	{
2446 		word_wrap_split(ses, buf2, buf1, cols, 0, 0, FLAG_NONE, &height, &width);
2447 	}
2448 
2449 	height--;
2450 
2451 	txt = buf1;
2452 
2453 	if (HAS_BIT(flags, DRAW_FLAG_BALIGN))
2454 	{
2455 		str_fix(buf1);
2456 
2457 		while (height < rows)
2458 		{
2459 			str_ins(&buf1, 0, "\n");
2460 			height++;
2461 		}
2462 	}
2463 
2464 	if (HAS_BIT(flags, DRAW_FLAG_TALIGN))
2465 	{
2466 		height = 0;
2467 
2468 		while (*txt && height < rows)
2469 		{
2470 			txt = strchr(txt, '\n');
2471 			txt++;
2472 			height++;
2473 		}
2474 		*txt = 0;
2475 		txt = buf1;
2476 	}
2477 	else
2478 	{
2479 		while (*txt && height > rows)
2480 		{
2481 			txt = strchr(txt, '\n');
2482 			txt++;
2483 			height--;
2484 		}
2485 	}
2486 
2487 	if (HAS_BIT(flags, DRAW_FLAG_LEFT))
2488 	{
2489 		strcpy(side1, draw_vertical(flags, "│"));
2490 	}
2491 
2492 	if (HAS_BIT(flags, DRAW_FLAG_RIGHT))
2493 	{
2494 		strcpy(side2, draw_vertical(flags, "│"));
2495 	}
2496 
2497 	row = top_row;
2498 	col = top_col;
2499 
2500 	arg = txt;
2501 
2502 	while (*arg)
2503 	{
2504 		arg = strchr(arg, '\n');
2505 
2506 		if (arg)
2507 		{
2508 			*arg++ = 0;
2509 		}
2510 		else
2511 		{
2512 			break;
2513 		}
2514 
2515 		if (HAS_BIT(flags, DRAW_FLAG_CONVERT))
2516 		{
2517 			convert_meta(txt, buf3, FALSE);
2518 
2519 			justify_string(ses, buf3, buf2, 0 - cols, cols);
2520 		}
2521 		else if (HAS_BIT(flags, DRAW_FLAG_CALIGN|DRAW_FLAG_LALIGN|DRAW_FLAG_RALIGN))
2522 		{
2523 			if (HAS_BIT(flags, DRAW_FLAG_CALIGN))
2524 			{
2525 				calign(ses, txt, buf3, cols);
2526 			}
2527 			else if (HAS_BIT(flags, DRAW_FLAG_LALIGN))
2528 			{
2529 				lalign(ses, txt, buf3, cols);
2530 			}
2531 			else
2532 			{
2533 				ralign(ses, txt, buf3, cols);
2534 			}
2535 			justify_string(ses, buf3, buf2, 0 - cols, cols);
2536 		}
2537 		else
2538 		{
2539 			justify_string(ses, txt, buf2, 0 - cols, cols);
2540 		}
2541 
2542 		if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2543 		{
2544 			if (HAS_BIT(flags, DRAW_FLAG_GRID))
2545 			{
2546 				cat_sprintf(arg2, "%s%s%s%s%s", box_color, side1, buf2, box_color, side2);
2547 			}
2548 			else
2549 			{
2550 				tintin_printf2(ses, "%s%s%s%s%s%s", indent_one(top_col - 1), box_color, side1, buf2, box_color, side2);
2551 			}
2552 		}
2553 		else
2554 		{
2555 			goto_pos(ses, row, col);
2556 
2557 			print_stdout(row, col, "%s%s%s%s%s", box_color, side1, buf2, box_color, side2);
2558 		}
2559 		row++;
2560 
2561 		txt = arg;
2562 	}
2563 
2564 	while (height < rows)
2565 	{
2566 		if (HAS_BIT(flags, DRAW_FLAG_LEFT))
2567 		{
2568 			strcpy(side1, draw_vertical(flags, "│"));
2569 		}
2570 
2571 		if (HAS_BIT(flags, DRAW_FLAG_RIGHT))
2572 		{
2573 			strcpy(side2, draw_vertical(flags, "│"));
2574 		}
2575 
2576 		if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2577 		{
2578 			if (HAS_BIT(flags, DRAW_FLAG_GRID))
2579 			{
2580 				cat_sprintf(arg2, "%s%s%*s%s%s", box_color, side1, cols, "", box_color, side2);
2581 			}
2582 			else
2583 			{
2584 				tintin_printf2(ses, "%s%s%s%-*s%s%s", indent_one(top_col - 1), box_color, side1, cols, "", box_color, side2);
2585 			}
2586 		}
2587 		else
2588 		{
2589 			goto_pos(ses, row, col);
2590 
2591 			print_stdout(row, col, "%s%s%*s%s%s", box_color, side1, cols, "", box_color, side2);
2592 
2593 			row++;
2594 		}
2595 		height++;
2596 	}
2597 	pop_call();
2598 	return;
2599 }
2600 
DO_DRAW(draw_top_side)2601 DO_DRAW(draw_top_side)
2602 {
2603 	int col, corner;
2604 
2605 	SET_BIT(flags, HAS_BIT(flags, DRAW_FLAG_VER) ? DRAW_FLAG_VER : DRAW_FLAG_HOR);
2606 
2607 	corner = flags;
2608 
2609 	DEL_BIT(corner, DRAW_FLAG_RIGHT|DRAW_FLAG_BOT);
2610 
2611 	arg = arg1;
2612 
2613 	if (HAS_BIT(flags, DRAW_FLAG_LEFT) || HAS_BIT(flags, DRAW_FLAG_TOP))
2614 	{
2615 		SET_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT);
2616 
2617 		arg1 += sprintf(arg1, "%s%s", box_color, get_draw_corner(corner, "┌"));
2618 	}
2619 
2620 	if (cols - 2 >= 0)
2621 	{
2622 		if (HAS_BIT(flags, DRAW_FLAG_TOP))
2623 		{
2624 			for (col = top_col + 1 ; col < bot_col ; col++)
2625 			{
2626 				arg1 += sprintf(arg1, "%s", draw_horizontal(flags, "─"));
2627 			}
2628 		}
2629 		else if (HAS_BIT(flags, DRAW_FLAG_RIGHT) && cols - 2 > 0)
2630 		{
2631 			arg1 += sprintf(arg1, "\e[%dC", cols - 2);
2632 		}
2633 
2634 		corner = flags;
2635 
2636 		DEL_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_BOT);
2637 
2638 		if (HAS_BIT(flags, DRAW_FLAG_TOP) || HAS_BIT(flags, DRAW_FLAG_RIGHT))
2639 		{
2640 			SET_BIT(corner, DRAW_FLAG_RIGHT|DRAW_FLAG_TOP);
2641 
2642 			arg1 += sprintf(arg1, "%s", get_draw_corner(corner, "┐"));
2643 		}
2644 	}
2645 
2646 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
2647 	{
2648 		tintin_printf2(ses, "%*s%s", top_col - 1, "", arg);
2649 	}
2650 	else
2651 	{
2652 		goto_pos(ses, top_row, top_col);
2653 
2654 		print_stdout(top_row, top_col, "%s", arg);
2655 	}
2656 }
2657 
DO_DRAW(draw_vertical_lines)2658 DO_DRAW(draw_vertical_lines)
2659 {
2660 	int row;
2661 
2662 	push_call("draw_vertical_lines(%p,%d,%p,%p,%p)",ses,flags,arg,arg1,arg2);
2663 
2664 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL) || *arg)
2665 	{
2666 		draw_text(ses, top_row, top_col, bot_row, top_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
2667 
2668 		pop_call();
2669 		return;
2670 	}
2671 
2672 	arg1[0] = arg2[0] = 0;
2673 
2674 	if (HAS_BIT(flags, DRAW_FLAG_BOXED) || HAS_BIT(flags, DRAW_FLAG_TOP))
2675 	{
2676 		top_row++;
2677 		rows--;
2678 	}
2679 
2680 	if (HAS_BIT(flags, DRAW_FLAG_BOXED) || HAS_BIT(flags, DRAW_FLAG_BOT))
2681 	{
2682 		bot_row--;
2683 		rows--;
2684 	}
2685 
2686 	if (HAS_BIT(flags, DRAW_FLAG_LEFT))
2687 	{
2688 		strcpy(arg1, draw_vertical(flags, "│"));
2689 
2690 		cols--;
2691 	}
2692 
2693 	if (HAS_BIT(flags, DRAW_FLAG_RIGHT))
2694 	{
2695 		strcpy(arg2, draw_vertical(flags, "│"));
2696 
2697 		cols--;
2698 	}
2699 
2700 //	tintin_printf2(ses, "debug: rows = %d", rows);
2701 
2702 	if (*arg1)
2703 	{
2704 		row = top_row;
2705 
2706 		while (row <= bot_row)
2707 		{
2708 			goto_pos(ses, row, top_col);
2709 
2710 			print_stdout(row, top_col, "%s%s", box_color, arg1);
2711 
2712 			row++;
2713 		}
2714 	}
2715 
2716 	if (*arg2)
2717 	{
2718 		row = top_row;
2719 
2720 		while (row <= bot_row)
2721 		{
2722 			goto_pos(ses, row, bot_col);
2723 
2724 			print_stdout(row, bot_col, "%s%s", box_color, arg2);
2725 
2726 			row++;
2727 		}
2728 	}
2729 
2730 	pop_call();
2731 	return;
2732 }
2733