1 /* Copyleft John McCutchan 2000 */
2 
3 /*
4  * this file is distributed in the hope that it will be useful, but
5  * WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
6  * to anyone for the consequences of using it or for whether it serves any
7  * particular purpose or works at all, unless he says so in writing.  Refer
8  * to the GNU General Public License for full details.
9  *
10  * Everyone is granted permission to copy, modify and redistribute
11  * this file, but only under the conditions described in the GNU
12  * General Public License.  A copy of this license is supposed to have been
13  * given to you along with this file so you can know your rights and
14  * responsibilities.  It should be in a file named COPYING.  Among other
15  * things, the copyright notice and this notice must be preserved on all
16  * copies.
17  * */
18 
19 
20 
21 
22 #include <ncurses.h>
23 #include <menu.h>
24 #include <ctype.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdlib.h>
28 #include <dirent.h>
29 #include <unistd.h>
30 #include <time.h>
31 
32 #include "internal.h"
33 #include "types.h"
34 #include "colours.h"
35 #include "global.h"
36 
37 #include "editor.h"
38 #include "interface.h"
39 #include "term.h"
40 #include "save.h"
41 #include "block.h"
42 #include "keys.h"
43 #include "network.h"
44 #include "sauce.h"
45 #include "multidraw.h"
46 #include "tetradraw.h"
47 #include "options_io.h"
48 
49 #include "art/statusbar.h"
50 #include "art/colour_selection.h"
51 #include "art/file_loader.h"
52 #include "art/quick_palette.h"
53 #include "art/multidraw_connect.h"
54 #include "art/multidraw_chat.h"
55 #include "art/tv_file_loader.h"
56 #include "art/help.h"
57 #include "art/options.h"
58 #include "art/character_select.h"
59 #include "art/start_logo.h"
60 #include "art/tetradraw_logo2.h"
61 #include "art/exit_logo.h"
62 
63 
64 /* this function draws the main editor screen */
draw_editor(canvas * page)65 void draw_editor(canvas *page) {
66 
67 	if(!page) return;
68 
69 	undraw_cursor(page);
70 	undraw_r_cursor(page);
71 	clear_screen();
72 	draw_statusbar(page);
73 	draw_page(page);
74 	draw_r_cursor(page);
75 	draw_cursor(page);
76 }
77 
78 /* this function undraws the local cursor */
undraw_cursor(canvas * page)79 void undraw_cursor(canvas *page) {
80 	hide_cursor();
81 }
82 
83 /* this function draws the local cursor */
draw_cursor(canvas * page)84 void draw_cursor(canvas *page) {
85 	int offset = 0;
86 
87 	if(!page) return;
88 
89 	if(options.sb_top) offset = 1;
90 
91 	move(offset+L_Y(page), L_X(page));
92 
93 	if(options.soft_cursor) {
94 		if((page->buffer[L_RY(page)][L_X(page)] & 0xff) == ' ')
95 			mvaddch(L_Y(page)+offset, L_X(page), (('�' & 0xff) | A_ALTCHARSET |
96 						opp_attrib(page->buffer[L_RY(page)][L_X(page)])));
97 		else
98 			mvaddch(L_Y(page)+offset, L_X(page),
99 					(page->buffer[L_RY(page)][L_X(page)] & 0xFF) |
100 					opp_attrib(page->buffer[L_RY(page)][L_X(page)]));
101 	} else
102 		show_cursor();
103 }
104 
105 
106 /* this undraws the remote cursor */
undraw_r_cursor(canvas * page)107 void undraw_r_cursor(canvas *page) {
108 	int offset = 0;
109 	if(!page||!remote) return;
110 
111 	if(options.sb_top) offset = 1;
112 	return;
113 }
114 
115 /* this draws the remote cursor */
draw_r_cursor(canvas * page)116 void draw_r_cursor(canvas *page) {
117 	int offset = 0;
118 
119 	if(!page||!remote) return;
120 
121 	if(options.sb_top) offset = 1;
122 
123 	/* is the remote cursor visible on the local screen at the moment ? */
124 	if(R_RY(page) <= L_OY(page)+td_maxy &&
125 			R_RY(page) >= L_OY(page))
126 
127 		mvaddch((R_RY(page) - L_OY(page))+offset, R_X(page), 'M' | colour_attribute(
128 				COLOUR_GREEN, COLOUR_YELLOW, FALSE, TRUE));
129 }
130 
131 
132 /* this draws the status bar */
draw_statusbar(canvas * page)133 void draw_statusbar(canvas *page) {
134 	int count = 0;
135 	int offset = 24;
136 	attribute clr = colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE);
137 
138 	if(!page) return;
139 
140 	if(options.sb_top) offset = 0;
141 
142 	move(offset,0);
143 	for(; count < 80; count++)
144 		mvaddch(offset, count, ansi_sb[SB_EDITOR][count]);
145 
146 	mvaddch(offset, 1, ('0' + ((L_X(page) % 100) / 10)) | clr);
147 	mvaddch(offset, 2, ('0' + ((L_X(page) % 100) % 10)) | clr);
148 
149 	mvaddch(offset, 4, ('0' + (L_RY(page) / 1000)) | clr);
150 	mvaddch(offset, 5, ('0' + ((L_RY(page) % 1000) / 100)) | clr);
151 	mvaddch(offset, 6, ('0' + (((L_RY(page) % 1000) % 100) / 10)) | clr);
152 	mvaddch(offset, 7, ('0' + (((L_RY(page) % 1000) % 100) % 10)) | clr);
153 
154 	if(L_INSERT(page)) {
155 		mvaddch(offset, 13, ' ' | clr);
156 		mvaddch(offset, 14, 'o' | clr);
157 		mvaddch(offset, 15, 'N' | clr);
158 	} else {
159 		mvaddch(offset, 13, 'o' | clr);
160 		mvaddch(offset, 14, 'F' | clr);
161 		mvaddch(offset, 15, 'F' | clr);
162 	}
163 
164 	mvaddch(offset, 18, 'c' | l_colour(page));
165 	mvaddch(offset, 19, 'L' | l_colour(page));
166 	mvaddch(offset, 20, 'R' | l_colour(page));
167 
168 
169 	mvaddch(offset, 25, ('0' + pagecnt) | clr);
170 
171 	mvaddch(offset, 25, ('0' + (CS(page) / 10)) | clr);
172 	mvaddch(offset, 26, ('0' + (CS(page) % 10)) | clr);
173 
174 	/* character set */
175 	for(count = 0; count < 10; count++)
176 		if(!isprint(options.highascii[CS(page)][count] & 0xff))
177 			mvaddch(offset, 31 + (count * 3), (options.highascii[CS(page)][count] & 0xff) | A_ALTCHARSET | clr);
178 		else
179 			mvaddch(offset, 31 + (count * 3), (options.highascii[CS(page)][count] & 0xff) | clr);
180 
181 	if(remote) {
182 		for(count = 0; count < 9; count++)
183 			mvaddch(offset, 62 + count, remotehandle[count] | clr);
184 
185 
186 		if(L_X(page) > R_X(page)) {
187 			mvaddch(offset, 74, ('' & 0xff) | A_ALTCHARSET | colour_attribute(COLOUR_GREEN,
188 						COLOUR_BLACK, FALSE, FALSE));
189 		} else if (L_X(page) == R_X(page)) {
190 			mvaddch(offset, 74, ('�' & 0xff) | colour_attribute(COLOUR_GREEN,
191 						COLOUR_BLACK, FALSE, FALSE));
192 		} else {
193 			mvaddch(offset, 74, ('' & 0xff) | A_ALTCHARSET | colour_attribute(COLOUR_GREEN,
194 						COLOUR_BLACK, FALSE, FALSE));
195 		}
196 
197 		if(L_RY(page) > R_RY(page)) {
198 			mvaddch(offset, 76, ('' & 0xff) | A_ALTCHARSET | colour_attribute(COLOUR_GREEN,
199 						COLOUR_BLACK, FALSE, FALSE));
200 		} else if (L_RY(page) == R_RY(page)) {
201 			mvaddch(offset, 76, ('�' & 0xff) | colour_attribute(COLOUR_GREEN,
202 						COLOUR_BLACK, FALSE, FALSE));
203 		} else {
204 			mvaddch(offset, 76, ('' & 0xff) | A_ALTCHARSET | colour_attribute(COLOUR_GREEN,
205 						COLOUR_BLACK, FALSE, FALSE));
206 		}
207 	}
208 	return;
209 }
210 
211 /* this draws the canvas */
draw_page(canvas * page)212 void draw_page(canvas *page) {
213 	coordinate x = 0;
214 	coordinate y = 0;
215 
216 	if(!page) return;
217 
218 
219 	if(options.sb_top) {
220 		for(y = 0; y < td_maxy && (page->l_oy + y) < (page->ly); y++)
221 			for(x = 0; x < td_maxx; x++)
222 				mvaddch(y+1, x, page->buffer[page->l_oy + y][x]);
223 	} else {
224 		for(y = 0; y < td_maxy && (page->l_oy + y) < (page->ly); y++)
225 			for(x = 0; x < td_maxx; x++)
226 				mvaddch(y, x, page->buffer[page->l_oy + y][x]);
227 	}
228 	return;
229 }
230 
231 
232 /* this draws the clipboard */
draw_clipboard(canvas * page,canvas * clipboard,int x,int y,int layer)233 void draw_clipboard(canvas *page, canvas *clipboard, int x, int y,
234 		int layer) {
235 
236 	coordinate yoffset = options.sb_top;
237 	coordinate ycount = 0;
238 	coordinate xcount = 0;
239 
240 	if(!page||!clipboard) return;
241 
242 	hide_cursor();
243 	switch (layer) {
244 
245 		case -1:
246 			for(ycount = y; ycount <= td_maxy && ycount-y <= HY(clipboard) &&
247 					(ycount + L_OY(page)) < LY(page); ycount++)
248 				for(xcount = x; xcount < 80; xcount++)
249 					if(clipboard->buffer[ycount-y][xcount-x] != -1 &&
250 							is_transparent(page->buffer[ycount + L_OY(page)][xcount]))
251 						mvaddch(ycount+yoffset, xcount,
252 								clipboard->buffer[ycount-y][xcount-x]);
253 			break;
254 		case 0:
255 			for(ycount = y; ycount <= td_maxy && ycount-y <= HY(clipboard); ycount++)
256 				for(xcount = x; xcount < 80; xcount++)
257 					if(clipboard->buffer[ycount-y][xcount-x] != -1)
258 						mvaddch(ycount+yoffset, xcount,
259 								clipboard->buffer[ycount-y][xcount-x]);
260 			break;
261 		case 1:
262 			for(ycount = y; ycount <= td_maxy && ycount-y <= HY(clipboard); ycount++)
263 				for(xcount = x; xcount < 80; xcount++)
264 					if(clipboard->buffer[ycount-y][xcount-x] != -1 &&
265 							!is_transparent(clipboard->buffer[ycount-y][xcount-x]))
266 						mvaddch(ycount+yoffset, xcount,
267 								clipboard->buffer[ycount-y][xcount-x]);
268 			break;
269 
270 	}
271 }
272 
273 /* this function just checks if a character is transparent
274  * transparent: its a space and has a black background */
is_transparent(character ch)275 int is_transparent(character ch) {
276 	if((ch) == (' ' | colour_attribute(COLOUR_WHITE, COLOUR_BLACK, FALSE, FALSE)))
277 			return 1;
278 	return 0;
279 }
280 
281 /* this draws the block select */
draw_block(canvas * page,int x1,int y1,int x2,int y2)282 void draw_block(canvas *page, int x1, int y1, int x2, int y2) {
283 	coordinate yoffset = options.sb_top;
284 	coordinate hx = 0;
285 	coordinate hy = 0;
286 	coordinate lx = 0;
287 	coordinate ly = 0;
288 
289 	coordinate y = 0;
290 	coordinate x = 0;
291 
292 	if(!page) return;
293 
294 	hide_cursor();
295 
296 	hx = (x1 > x2) ? x1 : x2;
297 	hy = (y1 > y2) ? y1 : y2;
298 
299 	lx = (x1 > x2) ? x2 : x1;
300 	ly = (y1 > y2) ? y2 : y1;
301 
302 	for(y = 0; y <= td_maxy; y++)
303 		if((L_OY(page) + y) >= ly && hy >= (L_OY(page) + y))
304 			for(x = 0; x < td_maxx; x++)
305 				if(x <= hx && x >= lx)
306 				mvaddch(y+yoffset, x, ((page->buffer[L_OY(page) + y][x] & 0xff) |
307 						opp_attrib(page->buffer[L_OY(page) + y][x])) & ~A_BLINK) ;
308 
309 	return;
310 }
311 
312 /* this draws the statusbar when you are in the block mode */
draw_block_statusbar(int p)313 void draw_block_statusbar(int p) {
314 	int count = 0;
315 	int offset = 24;
316 
317 	if(options.sb_top) offset = 0;
318 
319 	for(; count < 80; count++)
320 		mvaddch(offset, count, ansi_sb[p][count]);
321 }
322 
323 /* this is the main block command */
block_command(canvas * page)324 void block_command(canvas *page) {
325 	coordinate x1 = 0;
326 	coordinate y1 = 0;
327 
328 	coordinate x2 = 0;
329 	coordinate y2 = 0;
330 
331 	character ch = 0;
332 
333 	colour fg = COLOUR_WHITE;
334 	colour bg = COLOUR_BLACK;
335 	flag bold = FALSE;
336 	flag blink = FALSE;
337 
338 	colour newfg = COLOUR_WHITE;
339 	colour newbg = COLOUR_BLACK;
340 	flag newbold = FALSE;
341 	flag newblink = FALSE;
342 
343 	character chr = 0;
344 	character chf = 0;
345 
346 	canvas *clipboard = (canvas *)NULL;
347 
348 	int state = SB_BLOCK;
349 
350 	int layer = 0;
351 
352 	if(!page) return;
353 
354 	x1 = L_X(page);
355 	y1 = L_RY(page);
356 
357 	x2 = L_X(page);
358 	y2 = L_RY(page);
359 
360 	draw_editor(page);
361 	draw_block_statusbar(SB_BLOCK);
362 	draw_block(page, x1, y1, x2, y2);
363 	refresh();
364 	while(state == SB_BLOCK) {
365 			ch = n_getch();
366 			switch(ch) {
367 			case TD_KEY_ESCAPE:
368 				return;
369 			case 'C':
370 			case 'c':
371 				clipboard = block_copy(page, x1, y1, x2, y2);
372 				state = SB_BLOCK_PASTE;
373 				break;
374 			case 'M':
375 			case 'm':
376 				clipboard = block_cut(page, x1, y1, x2, y2);
377 				state = SB_BLOCK_PASTE;
378 				break;
379 			case 'E':
380 			case 'e':
381 				clipboard = block_cut(page, x1, y1, x2, y2);
382 				block_destroy(clipboard);
383 				return;
384 			case 'F':
385 			case 'f':
386 				clipboard = block_copy(page, x1, y1, x2, y2);
387 				state = SB_BLOCK_FILL;
388 				break;
389 			case 'R':
390 			case 'r':
391 				clipboard = block_copy(page, x1, y1, x2, y2);
392 				state = SB_BLOCK_REPLACE;
393 				break;
394 			case KEY_DOWN:
395 				move_down(page, 1);
396 				break;
397 			case KEY_UP:
398 				move_up(page, 1);
399 				break;
400 			case KEY_RIGHT:
401 				move_right(page, 1);
402 				break;
403 			case KEY_LEFT:
404 				move_left(page, 1);
405 				break;
406 			case TD_KEY_PAGEUP:
407 				if(L_Y(page) == 23) {
408 					move_up(page, 46);
409 				} else move_up(page, 23);
410 				break;
411 			case TD_KEY_PAGEDOWN:
412 				if(L_Y(page) == 0) {
413 					move_down(page, 46);
414 				} else move_down(page, 23);
415 				break;
416 			case TD_KEY_HOME:
417 				move_left(page, td_maxx);
418 				break;
419 			case TD_KEY_END:
420 				move_right(page, td_maxx);
421 				break;
422 		}
423 		x2 = L_X(page);
424 		y2 = L_RY(page);
425 		draw_editor(page);
426 		draw_block_statusbar(SB_BLOCK);
427 		draw_block(page, x1, y1, x2, y2);
428 		refresh();
429 
430 	}
431 
432 	if(x1 > x2) move_right(page, x1 - x2);
433 	else move_left(page, x2 - x1);
434 
435 	if(y1 > y2) move_down(page, y1 - y2);
436 	else move_up(page, y2 - y1);
437 
438 	draw_editor(page);
439 	draw_block_statusbar(state);
440 	draw_clipboard(page, clipboard, L_X(page), L_Y(page), layer);
441 	refresh();
442 	while(state != SB_BLOCK) {
443 		ch = n_getch();
444 		switch(state) {
445 			case SB_BLOCK_PASTE:
446 				switch(ch) {
447 					case TD_KEY_ESCAPE:
448 						state = SB_BLOCK;
449 						break;
450 					case 'S':
451 					case 's':
452 							block_paste(page, clipboard, L_X(page), L_RY(page), layer);
453 							break;
454 					case 'X':
455 					case 'x':
456 							clipboard = flip_x(clipboard);
457 							break;
458 					case 'Y':
459 					case 'y':
460 							clipboard = flip_y(clipboard);
461 							break;
462 					case 'R':
463 					case 'r':
464 							if(layer < 1) layer++;
465 							break;
466 					case 'L':
467 					case 'l':
468 							if(layer > -1) layer--;
469 							break;
470 							break;
471 					case KEY_UP:
472 							move_up(page, 1);
473 							break;
474 					case KEY_DOWN:
475 							move_down(page, 1);
476 							break;
477 					case KEY_LEFT:
478 							move_left(page, 1);
479 							break;
480 					case KEY_RIGHT:
481 							move_right(page, 1);
482 						break;
483 					case TD_KEY_HOME:
484 							move_left(page, td_maxx);
485 						break;
486 					case TD_KEY_END:
487 							move_right(page, td_maxx);
488 						break;
489 					case TD_KEY_PAGEUP:
490 							if(L_Y(page) == 23) {
491 								move_up(page, 46);
492 							} else move_up(page, 23);
493 						break;
494 					case TD_KEY_PAGEDOWN:
495 							if(L_Y(page) == 23) {
496 								move_down(page, 46);
497 							} else move_down(page, 23);
498 						break;
499 				}
500 			break;
501 			case SB_BLOCK_FILL:
502 				switch(ch) {
503 					case TD_KEY_ESCAPE:
504 						state = SB_BLOCK;
505 						break;
506 					case 'F':
507 					case 'f':
508 						if(fg_selection(&fg, &bold, &blink)) {
509 							state = SB_BLOCK;
510 							break;
511 						}
512 						fill_fg(clipboard, fg, bold, blink);
513 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
514 						state = SB_BLOCK;
515 						break;
516 					case 'B':
517 					case 'b':
518 						if(bg_selection(&bg)) {
519 							state = SB_BLOCK;
520 							break;
521 						}
522 						fill_bg(clipboard, bg);
523 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
524 						state = SB_BLOCK;
525 						break;
526 					case 'C':
527 					case 'c':
528 						chf = chselect();
529 						fill_ch(clipboard, (chf & 0xff));
530 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
531 						state = SB_BLOCK;
532 						break;
533 				}
534 			break;
535 			case SB_BLOCK_REPLACE:
536 				switch(ch) {
537 					case TD_KEY_ESCAPE:
538 						state = SB_BLOCK;
539 						break;
540 					case 'F':
541 					case 'f':
542 						if(fg_selection(&fg, &bold, &blink)) {
543 							state = SB_BLOCK;
544 							break;
545 						}
546 						if(fg_selection(&newfg, &newbold, &newblink)) {
547 							state = SB_BLOCK;
548 							break;
549 						}
550 						replace_fg(clipboard, fg, bold, blink, newfg, newbold, newblink);
551 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
552 						state = SB_BLOCK;
553 						break;
554 					case 'B':
555 					case 'b':
556 						if(bg_selection(&bg)) {
557 							state = SB_BLOCK;
558 							break;
559 						}
560 						if(bg_selection(&newbg)) {
561 							state = SB_BLOCK;
562 							break;
563 						}
564 						replace_bg(clipboard, bg, newbg);
565 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
566 						state = SB_BLOCK;
567 						break;
568 					case 'C':
569 					case 'c':
570 						chf = chselect();
571 						chr = chselect();
572 						replace_ch(clipboard, (chf & 0xff), (chr & 0xff));
573 						block_paste(page, clipboard, L_X(page), L_RY(page), layer);
574 						state = SB_BLOCK;
575 						break;
576 				}
577 			break;
578 		}
579 		draw_editor(page);
580 		draw_block_statusbar(state);
581 		draw_clipboard(page, clipboard, L_X(page), L_Y(page), layer);
582 		refresh();
583 	}
584 	block_destroy(clipboard);
585 }
586 
587 /* this is the foreground attribute selection screen */
fg_selection(colour * fg,flag * bold,flag * blink)588 int fg_selection(colour *fg, flag *bold, flag *blink) {
589 	int y = 0;
590 	int x = 0;
591 
592 	char input[2];
593 	int i_offset = 0;
594 
595 	int done = 0;
596 	character ch = 0;
597 	int i_fg = -1;
598 
599 	hide_cursor();
600 	input[0] = ' ';
601 	input[1] = ' ';
602 
603 	for(y = 0; y < 25; y++)
604 		for(x = 0; x < 80; x++)
605 			mvaddch(y, x, ansi_cselect[y][x]);
606 
607 	mvprintw(19, 66, "Foreground: ");
608 	refresh();
609 	while(!done) {
610 		ch = n_getch();
611 		switch(ch) {
612 			case TD_KEY_ESCAPE:
613 				return 1;
614 				break;
615 			case KEY_BACKSPACE:
616 				input[i_offset] = ' ';
617 				if(i_offset > 0) i_offset--;
618 				break;
619 			case 13:
620 				done = 1;
621 				break;
622 			default:
623 				if(isdigit(ch & 0xff)) {
624 					input[i_offset] = (ch & 0xff);
625 					if(i_offset+1 < 2) i_offset++;
626 				}
627 				break;
628 		}
629 		mvaddch(19, 77, input[0]);
630 		mvaddch(19, 78, input[1]);
631 		refresh();
632 	}
633 	if(isdigit(input[0]) || isdigit(input[1])) {
634 		i_fg = 0;
635 		if(isdigit(input[0]))
636 			i_fg = input[0] - '0';
637 		if(isdigit(input[1])) {
638 			i_fg *= 10;
639 			i_fg += input[1] - '0';
640 		}
641 	}
642 	if(i_fg >= 0 && i_fg <= 31) {
643 		if(i_fg > 15) {
644 			*blink = TRUE;
645 			if(i_fg > 23) {
646 				*bold = TRUE;
647 				i_fg -= 24;
648 			} else {
649 				*bold = FALSE;
650 				i_fg -= 16;
651 			}
652 		} else {
653 			*bold = FALSE;
654 			if(i_fg > 7) {
655 				*bold = TRUE;
656 				i_fg -= 8;
657 			}
658 			*blink = FALSE;
659 		}
660 		*fg = i_fg;
661 	} else return 1;
662 	return 0;
663 }
664 
665 /* this is the background attribute selection screen */
bg_selection(colour * bg)666 int bg_selection(colour *bg) {
667 	int y = 0;
668 	int x = 0;
669 
670 	char input[2];
671 	int i_offset = 0;
672 
673 	int done = 0;
674 	character ch = 0;
675 	int i_bg = 0;
676 
677 	hide_cursor();
678 	input[0] = ' ';
679 	input[1] = ' ';
680 
681 	for(y = 0; y < 25; y++)
682 		for(x = 0; x < 80; x++)
683 			mvaddch(y, x, ansi_cselect[y][x]);
684 
685 	mvprintw(19, 66, "Background: ");
686 	refresh();
687 	while(!done) {
688 		ch = n_getch();
689 		switch(ch) {
690 			case TD_KEY_ESCAPE:
691 				return 1;
692 				break;
693 			case KEY_BACKSPACE:
694 				input[i_offset] = ' ';
695 				if(i_offset > 0) i_offset--;
696 				break;
697 			case 13:
698 				done = 1;
699 				break;
700 			default:
701 				if(isdigit(ch & 0xff)) {
702 					input[i_offset] = (ch & 0xff);
703 					if(i_offset+1 < 2) i_offset++;
704 				}
705 				break;
706 		}
707 		mvaddch(19, 77, input[0]);
708 		mvaddch(19, 78, input[1]);
709 		refresh();
710 	}
711 	if(isdigit(input[0]) || isdigit(input[1])) {
712 		i_bg = 0;
713 		if(isdigit(input[0]))
714 			i_bg = input[0] - '0';
715 		if(isdigit(input[1])) {
716 			i_bg *= 10;
717 			i_bg += input[1] - '0';
718 		}
719 	}
720 	if(i_bg >= 0 && i_bg <= 7) {
721 		*bg = i_bg;
722 	} else return 1;
723 	return 0;
724 }
725 
726 /* this function just makes sure that the stuff in the menu listing
727  * is all characters that are printable */
make_printable(char * str)728 void make_printable(char *str) {
729 	char *ostr = str;
730 	if(!str) return;
731 
732 	while(*str) {
733 		*str = (isprint(*str)) ? *str : '?';
734 		str++;
735 	}
736 
737 	if(strlen(ostr) > 33) {
738 		ostr[30] = '.';
739 		ostr[31] = '.';
740 		ostr[32] = '.';
741 		ostr[33] = '\0';
742 	}
743 }
744 
745 /* this function builds a array of t_filerecords of all the
746  * files in your current working directory */
new_filelist(const char * cwd)747 t_filerecord **new_filelist(const char *cwd) {
748 	DIR *dir = (DIR *)NULL;
749 
750 	struct dirent *dire = (struct dirent *)NULL;
751 
752 	t_filerecord **files = (t_filerecord **)NULL;
753 
754 	int numfiles = 0;
755 	int count = 0;
756 	struct stat statbuf;
757 
758 	dir = opendir(cwd);
759 	if(!dir) return NULL;
760 
761 	while((dire = readdir(dir))) {
762 		if(strcmp("..", dire->d_name))
763 			if(!options.dot_files&&dire->d_name[0] == '.')
764 					continue;
765 		numfiles++;
766 	}
767 
768 	rewinddir(dir);
769 
770 	numfiles++;
771 
772 	files = m_malloc(numfiles * sizeof(t_filerecord *));
773 
774 	/* do directories first */
775 	while((dire = readdir(dir))) {
776 		if(strcmp("..", dire->d_name))
777 			if(!options.dot_files&&dire->d_name[0] == '.')
778 					continue;
779 
780 		stat(dire->d_name, &statbuf);
781 		if(S_ISDIR(statbuf.st_mode)) {
782 			files[count] = m_malloc(sizeof(t_filerecord));
783 			files[count]->fname = m_malloc(strlen(dire->d_name) + 1);
784 			strcpy(files[count]->fname, dire->d_name);
785 			files[count]->mname = m_malloc(strlen(dire->d_name) + 2);
786 			sprintf(files[count]->mname, "%s/", dire->d_name);
787 			make_printable(files[count]->mname);
788 			count++;
789 		}
790 	}
791 
792 	rewinddir(dir);
793 
794 	while((dire = readdir(dir))) {
795 		if(strcmp("..", dire->d_name))
796 			if(!options.dot_files&&dire->d_name[0] == '.')
797 					continue;
798 
799 		stat(dire->d_name, &statbuf);
800 		if(!S_ISDIR(statbuf.st_mode)) {
801 			files[count] = m_malloc(sizeof(t_filerecord));
802 			files[count]->fname = m_malloc(strlen(dire->d_name) + 1);
803 			strcpy(files[count]->fname, dire->d_name);
804 			files[count]->mname = m_malloc(strlen(dire->d_name) + 1);
805 			strcpy(files[count]->mname, dire->d_name);
806 			make_printable(files[count]->mname);
807 			count++;
808 		}
809 	}
810 
811 
812 	closedir(dir);
813 
814 	files[count] = NULL;
815 
816 	return files;
817 }
818 
819 /* this frees the array built from the above function */
free_filelist(t_filerecord ** files)820 t_filerecord **free_filelist(t_filerecord **files) {
821 	int count = 0;
822 
823 	if(!files) return NULL;
824 
825 	while(files[count]) {
826 		files[count]->fname = m_free(files[count]->fname);
827 		files[count]->mname = m_free(files[count]->mname);
828 		files[count] = m_free(files[count]);
829 		count++;
830 	}
831 
832 	files = m_free(files);
833 
834 	return NULL;
835 }
836 
837 /* this builds a new list of ITEMS suitable for use with a MENU */
new_items(t_filerecord ** files)838 ITEM **new_items(t_filerecord **files) {
839 	ITEM **items = (ITEM **)NULL;
840 	int numitems = 0;
841 	int count = 0;
842 
843 	if(!files) return NULL;
844 
845 	while(files[numitems]) numitems++;
846 
847 	numitems++;
848 	items = m_malloc(sizeof(ITEM *) * numitems);
849 
850 	while(files[count]) {
851 		items[count] = new_item(files[count]->mname, NULL);
852 		count++;
853 	}
854 	items[count] = NULL;
855 
856 	return items;
857 }
858 
859 /* this frees the array of ITEM *'s from the above function */
free_items(ITEM ** items)860 ITEM **free_items(ITEM **items) {
861 	int count = 0;
862 
863 	while(items[count]) {
864 		free_item(items[count]);
865 		items[count] = NULL;
866 		count++;
867 	}
868 	items = m_free(items);
869 	return NULL;
870 }
871 
872 /* this funtction makes a new menu */
menu_new(ITEM ** items,WINDOW * mw)873 MENU *menu_new(ITEM **items, WINDOW *mw) {
874 	MENU *menu = (MENU *)NULL;
875 
876 	menu = new_menu(NULL);
877 	set_menu_fore(menu, colour_attribute(COLOUR_WHITE, COLOUR_BLUE, TRUE, FALSE));
878 	set_menu_back(menu, colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
879 	set_menu_mark(menu, NULL);
880 	set_menu_items(menu, items);
881 	set_menu_format(menu, 14, 1);
882 	set_menu_win(menu, mw);
883 	set_menu_sub(menu, mw);
884 
885 	return menu;
886 }
887 
888 /* this function draws the sauce information from a file in the file
889  * selection widget */
draw_sauce(char * sauce_author,char * sauce_group,char * sauce_title)890 void draw_sauce(char *sauce_author, char *sauce_group, char *sauce_title) {
891 	int count = 0;
892 
893 	for(count = 0; count < 20 && sauce_author[count]; count++)
894 		mvaddch(2, 11 + count, sauce_author[count]);
895 	for(; count < 20; count++)
896 		mvaddch(2, 11 + count, ' ');
897 
898 	for(count = 0; count < 20 && sauce_group[count]; count++)
899 		mvaddch(3, 11 + count, sauce_group[count]);
900 	for(; count < 20; count++)
901 		mvaddch(3, 11 + count, ' ');
902 
903 	for(count = 0; count < 26 && sauce_title[count]; count++)
904 		mvaddch(4, 11 + count, sauce_title[count]);
905 	for(; count < 26; count++)
906 		mvaddch(4, 11 + count, ' ');
907 }
908 
909 /* this function draws the current path in the file selection widget */
draw_path(char * cwd,char * file)910 void draw_path(char *cwd, char *file) {
911 	char *full = (char *)NULL;
912 	int count = 0;
913 	int offset = 0;
914 
915 	if(!cwd||!file) return;
916 
917 	if(!strcmp("/", cwd)) {
918 		full = m_malloc(1 + strlen(cwd) + strlen(file));
919 		sprintf(full, "%s%s", cwd, file);
920 	} else {
921 		full = m_malloc(2 + strlen(cwd) + strlen(file));
922 		sprintf(full, "%s/%s", cwd, file);
923 	}
924 
925 	offset = strlen(full);
926 	if(offset>34) offset -= 34;
927 	else offset -= offset;
928 
929 	for(count = 0; count < 34; count++)
930 		mvaddch(8, 3 + count, ' ');
931 
932 	for(count = 0; count < 34 && full[offset + count]; count++)
933 		if(full[count + offset] == '/')
934 			mvaddch(8, 3 + count, full[count + offset] |
935 					colour_attribute(COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
936 		else
937 			mvaddch(8, 3 + count, full[count + offset]);
938 
939 	full = m_free(full);
940 }
941 
942 /* this function builds a menu text from the filename
943  * author, group and title this is used in tetraview */
build_mname(char * buffer,char * filename,char * author,char * group,char * title)944 void build_mname(char *buffer, char *filename, char *author, char *group, char *title) {
945 
946 	char *str = buffer;
947 	int count = 0;
948 	struct stat statbuf;
949 
950 	if(!buffer) return;
951 
952 	for(count = 0; count < 13 && filename[count];count++)
953 		buffer[count] = filename[count];
954 	stat(filename, &statbuf);
955 	if(S_ISDIR(statbuf.st_mode)) {
956 		buffer[count] = '/';
957 		count++;
958 	}
959 
960 	for(; count < 15; count++)
961 		buffer[count] = ' ';
962 
963 	for(; count < 47 && title[count-15]; count++)
964 		buffer[count] = title[count-15];
965 
966 	for(; count < 47; count++)
967 		buffer[count] = ' ';
968 
969 	for(; count < 63 && author[count-47]; count++)
970 		buffer[count] = author[count-47];
971 
972 	for(; count < 63;count++)
973 		buffer[count] = ' ';
974 
975 	buffer[60] = '\0';
976 
977 	while (*(str)) {
978 		*(str) = isprint(*str) ? *str : '?';
979 		str++;
980 	}
981 
982 	return;
983 }
984 
985 /* this builds all of the sauce information into the t_filerecord array */
sauce_list(t_filerecord ** files)986 void sauce_list(t_filerecord **files) {
987 	char sauce_author[20];
988 	char sauce_group[20];
989 	char sauce_title[35];
990 	int count = 0;
991 
992 	if(!files) return;
993 
994 	while(files[count]) {
995 		files[count]->mname = m_free(files[count]->mname);
996 		memset(&sauce_title, 0, sizeof(sauce_title));
997 		memset(&sauce_group, 0, sizeof(sauce_group));
998 		memset(&sauce_author, 0, sizeof(sauce_author));
999 		sauce_load(files[count]->fname, sauce_author, sauce_group, sauce_title);
1000 		files[count]->mname = m_malloc(64);
1001 		build_mname(files[count]->mname, files[count]->fname, sauce_author, sauce_group, sauce_title);
1002 		count++;
1003 	}
1004 	return;
1005 }
1006 
1007 /* this is the tetraview file selection screen */
tv_file_select(int next)1008 char *tv_file_select(int next) {
1009 	coordinate y = 0;
1010 	coordinate x = 0;
1011 
1012 	character ch = 0;
1013 
1014 	char *fname = (char *)NULL;
1015 
1016 	t_filerecord **files = (t_filerecord **)NULL;
1017 
1018 	ITEM **items = (ITEM **)NULL;
1019 	ITEM *current = (ITEM *)NULL;
1020 	MENU *menu = (MENU *)NULL;
1021 
1022 	WINDOW *wf = (WINDOW *)NULL;
1023 
1024 	char cwd[256];
1025 	struct stat statbuf;
1026 	static int index = 0;
1027 
1028 	char input[1024];
1029 	int i_offset = 0;
1030 
1031 	memset(&input, 0, sizeof(input));
1032 	i_offset = 0;
1033 
1034 		for(y = 0; y < 25; y++)
1035 			for(x = 0; x < 80; x++)
1036 				mvaddch(y, x, ansi_tv_fload[y][x]);
1037 
1038 	if(!next)
1039 		refresh();
1040 	wf = newwin(6, 61, 11, 9);
1041 
1042 	while(1) {
1043 		getcwd(cwd, 256);
1044 		files = new_filelist(cwd);
1045 		sauce_list(files);
1046 		items = new_items(files);
1047 		menu = menu_new(items, wf);
1048 		set_menu_format(menu, 6, 1);
1049 		post_menu(menu);
1050 
1051 		for(y = 0; items[y]; y++)
1052 			if(items[y]->index != index) menu_driver(menu, REQ_DOWN_ITEM);
1053 			else break;
1054 
1055 		if(next) {
1056 			if(menu_driver(menu, REQ_DOWN_ITEM) != E_REQUEST_DENIED)
1057 				goto hugehack;
1058 			else refresh();
1059 		}
1060 
1061 		current = current_item(menu);
1062 		index = current->index;
1063 		wrefresh(wf);
1064 		while((ch = getch()) != 13) {
1065 			switch(ch) {
1066 				case TD_KEY_REDRAW:
1067 					/* FIXME doesnt redraw correctly ! */
1068 					for(y = 0; y < 25; y++)
1069 						for(x = 0; x < 80; x++)
1070 							mvaddch(y, x, ansi_fload[y][x]);
1071 					break;
1072 				case KEY_UP:
1073 						menu_driver(menu, REQ_UP_ITEM);
1074 					break;
1075 				case TD_KEY_PAGEUP:
1076 					for(y = 0; y < 6; y++)
1077 						menu_driver(menu, REQ_UP_ITEM);
1078 					break;
1079 				case KEY_DOWN:
1080 						menu_driver(menu, REQ_DOWN_ITEM);
1081 					break;
1082 				case TD_KEY_PAGEDOWN:
1083 					for(y = 0; y < 6; y++)
1084 						menu_driver(menu, REQ_DOWN_ITEM);
1085 					break;
1086 				case TD_KEY_HOME:
1087 					while(menu_driver(menu, REQ_UP_ITEM) != E_REQUEST_DENIED);
1088 					break;
1089 				case TD_KEY_END:
1090 					while(menu_driver(menu, REQ_DOWN_ITEM) != E_REQUEST_DENIED);
1091 					break;
1092 				case TD_KEY_ESCAPE:
1093 					current = current_item(menu);
1094 					index = current->index;
1095 
1096 					unpost_menu(menu);
1097 					free_menu(menu);
1098 					free_items(items);
1099 					free_filelist(files);
1100 
1101 					delwin(wf);
1102 
1103 					return NULL;
1104 					break;
1105 				case KEY_BACKSPACE:
1106 					input[i_offset] = '\0';
1107 					if(i_offset > 0) i_offset--;
1108 
1109 					input[i_offset] = '\0';
1110 					break;
1111 				default:
1112 					if(isprint(ch)) {
1113 						input[i_offset] = ch & 0xff;
1114 						if(i_offset+1 < 1024) i_offset++;
1115 						input[i_offset] = '\0';
1116 					}
1117 			}
1118 			current = current_item(menu);
1119 			index = current->index;
1120 			wrefresh(wf);
1121 		}
1122 		if(strcmp("", input)) {
1123 			fname = m_malloc(strlen(input) + 1);
1124 			sprintf(fname, "%s", input);
1125 			return fname;
1126 		} else {
1127 hugehack:
1128 			current = current_item(menu);
1129 			index = current->index;
1130 			unpost_menu(menu);
1131 			free_menu(menu);
1132 			free_items(items);
1133 			stat(files[index]->fname, &statbuf);
1134 			if(!S_ISDIR(statbuf.st_mode)) {
1135 				fname = m_malloc(strlen(files[index]->fname) + 1);
1136 				strcpy(fname, files[index]->fname);
1137 				free_filelist(files);
1138 				delwin(wf);
1139 				return fname;
1140 			}
1141 			chdir(files[index]->fname);
1142 			index = 0;
1143 			free_filelist(files);
1144 		}
1145 	}
1146 	return NULL;
1147 }
1148 
1149 /* this is the tetradraw file selection screen */
file_select()1150 char *file_select() {
1151 	coordinate y = 0;
1152 	coordinate x = 0;
1153 
1154 	character ch = 0;
1155 
1156 	char *fname = (char *)NULL;
1157 
1158 	t_filerecord **files = (t_filerecord **)NULL;
1159 
1160 	ITEM **items = (ITEM **)NULL;
1161 	ITEM *current = (ITEM *)NULL;
1162 	MENU *menu = (MENU *)NULL;
1163 
1164 	WINDOW *wf = (WINDOW *)NULL;
1165 
1166 	char cwd[256];
1167 	struct stat statbuf;
1168 	static int index = 0;
1169 
1170 	char sauce_title[35];
1171 	char sauce_author[20];
1172 	char sauce_group[20];
1173 
1174 	char input[1024];
1175 	int i_offset = 0;
1176 
1177 	memset(&sauce_title, 0, sizeof(sauce_title));
1178 	memset(&sauce_group, 0, sizeof(sauce_group));
1179 	memset(&sauce_author, 0, sizeof(sauce_author));
1180 
1181 	memset(&input, 0, sizeof(input));
1182 	i_offset = 0;
1183 
1184 	for(y = 0; y < 25; y++)
1185 		for(x = 0; x < 80; x++)
1186 			mvaddch(y, x, ansi_fload[y][x]);
1187 
1188 	refresh();
1189 
1190 	wf = newwin(14, 34, 10, 3);
1191 
1192 	while(1) {
1193 		getcwd(cwd, 256);
1194 		files = new_filelist(cwd);
1195 		items = new_items(files);
1196 		menu = menu_new(items, wf);
1197 		post_menu(menu);
1198 
1199 		for(y = 0; items[y]; y++)
1200 			if(items[y]->index != index) menu_driver(menu, REQ_DOWN_ITEM);
1201 			else break;
1202 
1203 		current = current_item(menu);
1204 		index = current->index;
1205 		memset(&sauce_title, 0, sizeof(sauce_title));
1206 		memset(&sauce_group, 0, sizeof(sauce_group));
1207 		memset(&sauce_author, 0, sizeof(sauce_author));
1208 		sauce_load(files[index]->fname, sauce_author, sauce_group, sauce_title);
1209 		draw_sauce(sauce_author, sauce_group, sauce_title);
1210 		draw_path(cwd, input);
1211 		wrefresh(wf);
1212 		while((ch = getch()) != 13) {
1213 			switch(ch) {
1214 				case TD_KEY_REDRAW:
1215 					/* FIXME doesnt redraw correctly ! */
1216 					for(y = 0; y < 25; y++)
1217 						for(x = 0; x < 80; x++)
1218 							mvaddch(y, x, ansi_fload[y][x]);
1219 					break;
1220 				case KEY_UP:
1221 						menu_driver(menu, REQ_UP_ITEM);
1222 					break;
1223 				case TD_KEY_PAGEUP:
1224 					for(y = 0; y < 14; y++)
1225 						menu_driver(menu, REQ_UP_ITEM);
1226 					break;
1227 				case KEY_DOWN:
1228 						menu_driver(menu, REQ_DOWN_ITEM);
1229 					break;
1230 				case TD_KEY_PAGEDOWN:
1231 					for(y = 0; y < 14; y++)
1232 						menu_driver(menu, REQ_DOWN_ITEM);
1233 					break;
1234 				case TD_KEY_HOME:
1235 					while(menu_driver(menu, REQ_UP_ITEM) != E_REQUEST_DENIED);
1236 					break;
1237 				case TD_KEY_END:
1238 					while(menu_driver(menu, REQ_DOWN_ITEM) != E_REQUEST_DENIED);
1239 					break;
1240 				case TD_KEY_ESCAPE:
1241 					current = current_item(menu);
1242 					index = current->index;
1243 
1244 					unpost_menu(menu);
1245 					free_menu(menu);
1246 					free_items(items);
1247 					free_filelist(files);
1248 
1249 					delwin(wf);
1250 
1251 					return NULL;
1252 					break;
1253 				case KEY_BACKSPACE:
1254 					input[i_offset] = '\0';
1255 					if(i_offset > 0) i_offset--;
1256 
1257 					input[i_offset] = '\0';
1258 					break;
1259 				default:
1260 					if(isprint(ch)) {
1261 						input[i_offset] = ch & 0xff;
1262 						if(i_offset+1 < 1024) i_offset++;
1263 						input[i_offset] = '\0';
1264 					}
1265 			}
1266 			current = current_item(menu);
1267 			index = current->index;
1268 			memset(&sauce_title, 0, sizeof(sauce_title));
1269 			memset(&sauce_group, 0, sizeof(sauce_group));
1270 			memset(&sauce_author, 0, sizeof(sauce_author));
1271 			sauce_load(files[index]->fname, sauce_author, sauce_group, sauce_title);
1272 			draw_sauce(sauce_author, sauce_group, sauce_title);
1273 			draw_path(cwd, input);
1274 			wrefresh(wf);
1275 		}
1276 		if(strcmp("", input)) {
1277 			fname = m_malloc(strlen(input) + 1);
1278 			sprintf(fname, "%s", input);
1279 			return fname;
1280 		} else {
1281 			current = current_item(menu);
1282 			index = current->index;
1283 			unpost_menu(menu);
1284 			free_menu(menu);
1285 			free_items(items);
1286 			stat(files[index]->fname, &statbuf);
1287 			if(!S_ISDIR(statbuf.st_mode)) {
1288 				fname = m_malloc(strlen(files[index]->fname) + 1);
1289 				strcpy(fname, files[index]->fname);
1290 				free_filelist(files);
1291 				delwin(wf);
1292 				return fname;
1293 			}
1294 			chdir(files[index]->fname);
1295 			index = 0;
1296 			free_filelist(files);
1297 		}
1298 	}
1299 	return NULL;
1300 }
1301 
1302 /* prints the foreground colour in the quick palette */
print_fg(colour fg)1303 void print_fg(colour fg) {
1304 	const char *fg_description[16] = {
1305 		"black", "red", "green", "brown", "blue", "magenta", "cyan", "grey",
1306 		"dark grey", "light red", "light green", "yellow", "light blue",
1307 		"light magenta", "light cyan", "white"
1308 	};
1309 	int x = 0;
1310 
1311 
1312 	for(x = 0; fg_description[fg][x]; x++)
1313 		mvaddch(12, 25 + x, fg_description[fg][x]);
1314 	for(; x < 20; x++)
1315 		mvaddch(12, 25 + x, ' ');
1316 }
1317 
1318 /* prints the background colour in the quick palette */
print_bg(colour bg)1319 void print_bg(colour bg) {
1320 	const char *bg_description[8] = {
1321 		"black", "red", "green", "brown", "blue", "magenta", "cyan", "grey"
1322 	};
1323 	int x = 0;
1324 
1325 	for(x = 0; bg_description[bg][x]; x++)
1326 		mvaddch(12, 60 + x, bg_description[bg][x]);
1327 	for(; x < 10; x++)
1328 		mvaddch(12, 60 + x, ' ');
1329 }
1330 
1331 /* this is the quick palette */
quick_palette(canvas * page)1332 void quick_palette(canvas *page) {
1333 	int y = 0;
1334 	int x = 0;
1335 	colour fg = COLOUR_WHITE;
1336 	colour bg = COLOUR_BLACK;
1337 	flag bold = FALSE;
1338 
1339 	int wfg = 0;
1340 	int wbg = 0;
1341 
1342 	int done = 0;
1343 
1344 	character ch = 0;
1345 
1346 	attribute clr = colour_attribute(COLOUR_CYAN, COLOUR_BLACK, FALSE, FALSE);
1347 	attribute hclr = colour_attribute(COLOUR_CYAN, COLOUR_BLACK, TRUE, FALSE);
1348 
1349 	if(!page) return;
1350 
1351 	fg = L_FG(page);
1352 	bg = L_BG(page);
1353 	bold = L_BOLD(page);
1354 
1355 	wfg = (8 * bold) + fg;
1356 	wbg = bg;
1357 
1358 	hide_cursor();
1359 
1360 	for(y = 0; y < 13; y++)
1361 		for(x = 0; x < 80; x++)
1362 			mvaddch(y+5, x, ansi_qpalette[y][x]);
1363 	refresh();
1364 
1365 	mvaddch(9, 48 + (wbg * 2), ('' | A_ALTCHARSET | hclr));
1366 	mvaddch(9, 49 + (wbg * 2), ('' | A_ALTCHARSET | hclr));
1367 	mvaddch(9, 13 + (wfg * 2), ('' | A_ALTCHARSET | hclr));
1368 	mvaddch(9, 14 + (wfg * 2), ('' | A_ALTCHARSET | hclr));
1369 	print_fg(wfg);
1370 	print_bg(wbg);
1371 	refresh();
1372 	while(!done) {
1373 		ch = n_getch();
1374 		switch(ch) {
1375 			case TD_KEY_ESCAPE:
1376 			case 13:
1377 				done = 1;
1378 				break;
1379 			case KEY_UP:
1380 				mvaddch(9, 48 + (wbg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1381 				mvaddch(9, 49 + (wbg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1382 				if(wbg+1 < 8) wbg++;
1383 				refresh();
1384 				break;
1385 			case KEY_DOWN:
1386 				mvaddch(9, 48 + (wbg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1387 				mvaddch(9, 49 + (wbg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1388 				if(wbg > 0) wbg--;
1389 				refresh();
1390 				break;
1391 			case KEY_RIGHT:
1392 				mvaddch(9, 13 + (wfg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1393 				mvaddch(9, 14 + (wfg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1394 				if(wfg+1 < 16) wfg++;
1395 				refresh();
1396 				break;
1397 			case KEY_LEFT:
1398 				mvaddch(9, 13 + (wfg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1399 				mvaddch(9, 14 + (wfg * 2), (ACS_HLINE | A_ALTCHARSET | clr));
1400 				if(wfg > 0) wfg--;
1401 				refresh();
1402 				break;
1403 		}
1404 		mvaddch(9, 48 + (wbg * 2), ('' | A_ALTCHARSET | hclr));
1405 		mvaddch(9, 49 + (wbg * 2), ('' | A_ALTCHARSET | hclr));
1406 		mvaddch(9, 13 + (wfg * 2), ('' | A_ALTCHARSET | hclr));
1407 		mvaddch(9, 14 + (wfg * 2), ('' | A_ALTCHARSET | hclr));
1408 		print_fg(wfg);
1409 		print_bg(wbg);
1410 		refresh();
1411 	}
1412 	if(wfg > 7) {
1413 		setbold(page, TRUE);
1414 		wfg -= 8;
1415 	} else
1416 		setbold(page, FALSE);
1417 	setfg(page, wfg);
1418 	setbg(page, wbg);
1419 }
1420 
1421 /* this asks the user which file format it wants to save */
savei_filetype()1422 int savei_filetype() {
1423 	int x = 0;
1424 	int offset = 24;
1425 	character ch = 0;
1426 
1427 	if(options.sb_top) offset = 0;
1428 
1429 	for(; x < 80; x++)
1430 		mvaddch(offset, x, ansi_sb[SB_FILE_TYPE][x]);
1431 
1432 	refresh();
1433 
1434 	while(1) {
1435 		ch = n_getch();
1436 		switch(ch & 0xff) {
1437 			case TD_KEY_ESCAPE:
1438 				return 0;
1439 				break;
1440 			case 'a':
1441 			case 'A':
1442 				return 1;
1443 				break;
1444 			case 'i':
1445 			case 'I':
1446 				return 2;
1447 				break;
1448 			case 'c':
1449 			case 'C':
1450 				return 3;
1451 				break;
1452 			case 'b':
1453 			case 'B':
1454 				return 4;
1455 				break;
1456 		}
1457 	}
1458 	return 0;
1459 }
1460 
1461 /* this function asks the user if they want to clear the screen before the
1462  * ansi */
savei_clearscreen()1463 int savei_clearscreen() {
1464 	int x = 0;
1465 	int offset = 24;
1466 	character ch = 0;
1467 
1468 	if(options.sb_top) offset = 0;
1469 
1470 	for(; x < 80; x++)
1471 		mvaddch(offset, x, ansi_sb[SB_CLEAR_SCREEN][x]);
1472 
1473 	refresh();
1474 
1475 	while(1) {
1476 		ch = n_getch();
1477 		switch(ch & 0xff) {
1478 			case TD_KEY_ESCAPE:
1479 				return 0;
1480 				break;
1481 			case 'y':
1482 			case 'Y':
1483 				return 1;
1484 				break;
1485 			case 'n':
1486 			case 'N':
1487 				return 0;
1488 				break;
1489 		}
1490 	}
1491 	return 0;
1492 }
1493 
1494 /* this function gets the sauce information from the user */
savei_sauce(char * author,char * group,char * title)1495 int savei_sauce(char *author, char *group, char *title) {
1496 	int x = 0;
1497 	character ch = 0;
1498 	int offset = 24;
1499 	int done = 0;
1500 	int i_offset = 0;
1501 
1502 	if(options.sb_top) offset = 0;
1503 
1504 	hide_cursor();
1505 
1506 	for(x = 0; x < 80; x++)
1507 		mvaddch(offset, x, ansi_sb[SB_SAVE_SAUCE][x]);
1508 	refresh();
1509 
1510 	while(!done) {
1511 		ch = n_getch();
1512 		switch(ch & 0xff) {
1513 			case 'n':
1514 			case 'N':
1515 			case TD_KEY_ESCAPE:
1516 				return 0;
1517 				break;
1518 			case 'y':
1519 			case 'Y':
1520 				done = 1;
1521 				break;
1522 		}
1523 	}
1524 
1525 
1526 	done = 0;
1527 	i_offset = 0;
1528 
1529 	for(x = 0; x < 80; x++)
1530 		mvaddch(offset, x, ansi_sb[SB_SAUCE_AUTHOR][x]);
1531 
1532 	for(x = 0; x < 20; x++)
1533 		author[x] = ' ';
1534 
1535 	for(x = 0; x < 20; x++)
1536 		mvaddch(offset, 19 + x, author[x]);
1537 
1538 	refresh();
1539 
1540 	while(!done) {
1541 		ch = n_getch();
1542 		switch(ch) {
1543 			case KEY_BACKSPACE:
1544 				author[i_offset] = ' ';
1545 				if(i_offset > 0) i_offset--;
1546 				author[i_offset] = ' ';
1547 				break;
1548 			case 13:
1549 				done = 1;
1550 				break;
1551 			default:
1552 				if(isprint(ch)) {
1553 					author[i_offset] = ch;
1554 					if((i_offset+1) < 20) i_offset++;
1555 				}
1556 				break;
1557 		}
1558 		for(x = 0; x < 20; x++)
1559 			mvaddch(offset, 19 + x, author[x]);
1560 		refresh();
1561 	}
1562 
1563 	done = 0;
1564 	i_offset = 0;
1565 
1566 	for(x = 0; x < 80; x++)
1567 		mvaddch(offset, x, ansi_sb[SB_SAUCE_GROUP][x]);
1568 
1569 	for(x = 0; x < 20; x++)
1570 		group[x] = ' ';
1571 
1572 	for(x = 0; x < 20; x++)
1573 		mvaddch(offset, 19 + x, group[x]);
1574 
1575 	refresh();
1576 
1577 	while(!done) {
1578 		ch = n_getch();
1579 		switch(ch) {
1580 			case KEY_BACKSPACE:
1581 				group[i_offset] = ' ';
1582 				if(i_offset > 0) i_offset--;
1583 				group[i_offset] = ' ';
1584 				break;
1585 			case 13:
1586 				done = 1;
1587 				break;
1588 			default:
1589 				if(isprint(ch)) {
1590 					group[i_offset] = ch;
1591 					if((i_offset+1) < 20) i_offset++;
1592 				}
1593 				break;
1594 		}
1595 		for(x = 0; x < 20; x++)
1596 			mvaddch(offset, 18 + x, group[x]);
1597 
1598 		refresh();
1599 	}
1600 
1601 	done = 0;
1602 	i_offset = 0;
1603 
1604 	for(x = 0; x < 80; x++)
1605 		mvaddch(offset, x, ansi_sb[SB_SAUCE_TITLE][x]);
1606 
1607 	for(x = 0; x < 35; x++)
1608 		title[x] = ' ';
1609 
1610 	for(x = 0; x < 35; x++)
1611 		mvaddch(offset, 18 + x, title[x]);
1612 
1613 	refresh();
1614 
1615 	while(!done) {
1616 		ch = n_getch();
1617 		switch(ch) {
1618 			case KEY_BACKSPACE:
1619 				title[i_offset] = ' ';
1620 				if(i_offset > 0) i_offset--;
1621 				title[i_offset] = ' ';
1622 				break;
1623 			case 13:
1624 				done = 1;
1625 				break;
1626 			default:
1627 				if(isprint(ch)) {
1628 					title[i_offset] = ch;
1629 					if((i_offset+1) < 35) i_offset++;
1630 				}
1631 				break;
1632 		}
1633 		for(x = 0; x < 35; x++)
1634 			mvaddch(offset, 18 + x, title[x]);
1635 
1636 		refresh();
1637 	}
1638 
1639 	return 1;
1640 }
1641 
1642 /* this either loads up the multidraw chat interface or the
1643  * multidraw connect interface */
multidraw_interface()1644 void multidraw_interface() {
1645 	if(remote)
1646 		multidraw_chat();
1647 	else
1648 		multidraw_connect();
1649 }
1650 
1651 /* this function draws whats in the input buffer in the multidraw
1652  * chat interface */
draw_md_chat_input(char input[1024])1653 void draw_md_chat_input(char input[1024]) {
1654 	int y = 0;
1655 	int x = 0;
1656 	int xoffset = 0;
1657 
1658 	if(strlen(input) >= 75)
1659 		xoffset = strlen(input) - 75;
1660 
1661 
1662 	y = 23;
1663 
1664 	for(x = 1; x <= 76; x++)
1665 		mvaddch(y, x, ' ');
1666 
1667 	for(x = 1; input[x+xoffset-1] && x <= 76; x++)
1668 		mvaddch(y, x, input[x+xoffset-1] |
1669 				colour_attribute(COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
1670 
1671 	return;
1672 }
1673 
1674 /* this function draws chat msgs */
draw_chat_msgs()1675 void draw_chat_msgs() {
1676 	int count = 0;
1677 	int x = 0;
1678 	int y = 7;
1679 
1680 	for(count = 0; count < 15; count++) {
1681 		for(x = 0; x < 60; x++)
1682 			mvaddch(y + count, x, ' ');
1683 
1684 		if(md_chat[count]) {
1685 			for(x = 0; md_chat[count][x] && x < 60; x++) {
1686 				if(x == 0 || x == 10) {
1687 					mvaddch(y + count, x, md_chat[count][x] |
1688 							colour_attribute(COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
1689 				} else if(x > 0 && x < 10) {
1690 					mvaddch(y + count, x, md_chat[count][x] |
1691 							colour_attribute(COLOUR_RED, COLOUR_BLACK, FALSE, FALSE));
1692 				} else {
1693 					mvaddch(y + count, x, md_chat[count][x]);
1694 				}
1695 			}
1696 		}
1697 
1698 	}
1699 }
1700 
1701 /* this is the multidraw chat interface */
multidraw_chat()1702 void multidraw_chat() {
1703 	int y = 0;
1704 	int x = 0;
1705 
1706 	char input[1024];
1707 	int i_offset = 0;
1708 
1709 	character ch = 0;
1710 
1711 	memset(input, 0, sizeof(input));
1712 
1713 	hide_cursor();
1714 	erase();
1715 	refresh();
1716 
1717 	for(y = 0; y < 25; y++)
1718 		for(x = 0; x < 80; x++)
1719 			mvaddch(y, x, ansi_mdchat[y][x]);
1720 
1721 	while(1&&remote) {
1722 		draw_chat_msgs();
1723 		refresh();
1724 		draw_md_chat_input(input);
1725 		refresh();
1726 		ch = n_getch();
1727 
1728 		switch(ch) {
1729 			case TD_KEY_ESCAPE:
1730 				return;
1731 				break;
1732 			case 13:
1733 				if(*input) {
1734 					md_sendcmd("%c %s", CMD_TALK, input);
1735 					md_chat_msgadd(localhandle, input);
1736 					memset(input, 0, sizeof(input));
1737 					i_offset = 0;
1738 				}
1739 				break;
1740 			case KEY_BACKSPACE:
1741 				input[i_offset] = '\0';
1742 				if(i_offset > 0) i_offset--;
1743 				input[i_offset] = '\0';
1744 				break;
1745 			default:
1746 				if(isprint(ch)) {
1747 					if(i_offset + 1 < 1024) {
1748 						input[i_offset] = ch & 0xff;
1749 						i_offset++;
1750 					}
1751 					input[i_offset] = '\0';
1752 				}
1753 				break;
1754 		}
1755 	}
1756 }
1757 
1758 /* this function connects the two clients
1759  * if HOSTNAME is null then we act as the server
1760  * if its not then we are the client */
md_connect(char handle[10],char * hostname,char sport[6])1761 int md_connect(char handle[10], char *hostname, char sport[6]) {
1762 	int port = 0;
1763 	int status = 0;
1764 	int count = 0;
1765 
1766 	port = atoi(sport);
1767 
1768 	status = n_connect(hostname, port);
1769 
1770 	if(status < 0) {
1771 		return status;
1772 	}
1773 
1774 	remote = status;
1775 
1776 	md_sendcmd("%c %c%c%c%c%c%c%c%c%c %d", CMD_HELO, handle[0], handle[1],
1777 			handle[2], handle[3], handle[4], handle[5], handle[6], handle[7],
1778 			handle[8], options.fix_flip);
1779 
1780 	for(count = 0; count < 9; count++)
1781 		localhandle[count] = handle[count];
1782 
1783 	localhandle[count] = '\0';
1784 
1785 	for(count = 0; count < 10; count++)
1786 		if(md_chat[count])
1787 			md_chat[count] = m_free(md_chat[count]);
1788 		else
1789 			md_chat[count] = NULL;
1790 
1791 	return 0;
1792 }
1793 
1794 /* this is the multidraw connect interface */
multidraw_connect()1795 void multidraw_connect() {
1796 	const char *menu_text[2] = { "        client        ",
1797 															 "        server        "};
1798 	const char *connect_errors[3] = { "could not lookup hostname",
1799 		"connection refused", "could not bind port", };
1800 
1801 	int y = 0;
1802 	int x = 0;
1803 	character ch = 0;
1804 
1805 	int done = 0;
1806 
1807 	int server = 1;
1808 
1809 	int status = 0;
1810 
1811 	char hostname[1024];
1812 	char handle[10];
1813 	char port[6];
1814 
1815 	MENU *menu = (MENU *)NULL;
1816 	ITEM *items[3];
1817 	ITEM *current = (ITEM *)NULL;
1818 	WINDOW *mw = (WINDOW *)NULL;
1819 
1820 
1821 	hostname[0] = '\0';
1822 	handle[9] = '\0';
1823 	port[5] = '\0';
1824 
1825 	hide_cursor();
1826 	for(y = 0; y < 25; y++)
1827 		for(x = 0; x < 80; x++)
1828 			mvaddch(y, x, ansi_mdconnect[y][x]);
1829 	refresh();
1830 
1831 	mw = newwin(3, 23, 8, 4);
1832 
1833 
1834 	items[0] = new_item(menu_text[0], NULL);
1835 	items[1] = new_item(menu_text[1], NULL);
1836 	items[2] = NULL;
1837 
1838 	menu = new_menu(NULL);
1839 
1840 	set_menu_fore(menu, colour_attribute(COLOUR_WHITE, COLOUR_BLUE, TRUE, FALSE));
1841 	set_menu_back(menu, colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
1842 	set_menu_mark(menu, NULL);
1843 	set_menu_items(menu, items);
1844 	set_menu_win(menu, mw);
1845 	set_menu_sub(menu, mw);
1846 	set_menu_format(menu, 4, 1);
1847 
1848 	post_menu(menu);
1849 
1850 	wrefresh(mw);
1851 
1852 	while(!done) {
1853 		ch = n_getch();
1854 		switch(ch) {
1855 			case -1:
1856 				break;
1857 			case KEY_UP:
1858 				menu_driver(menu, REQ_UP_ITEM);
1859 				break;
1860 			case KEY_DOWN:
1861 				menu_driver(menu, REQ_DOWN_ITEM);
1862 				break;
1863 			case 13:
1864 				current = current_item(menu);
1865 				if(item_index(current)==0)
1866 					server = 0;
1867 				done = 1;
1868 				break;
1869 			case TD_KEY_ESCAPE:
1870 				done = -1;
1871 				break;
1872 		}
1873 		wrefresh(mw);
1874 	}
1875 
1876 	unpost_menu(menu);
1877 	free_item(items[0]);
1878 	free_item(items[1]);
1879 	free_menu(menu);
1880 
1881 	delwin(mw);
1882 	refresh();
1883 
1884 	if(done < 0) return;
1885 
1886 	if(mdi_gethandle(handle)<0)
1887 		return;
1888 	if(mdi_getport(port)<0)
1889 			return;
1890 
1891 	if(server) {
1892 		mvprintw(14, 4, "Awaiting connection...");
1893 		refresh();
1894 		if ( (status = md_connect(handle, NULL, port)) < 0) {
1895 			switch(status) {
1896 				case -1:
1897 					mvprintw(15, 4, "%s", connect_errors[1]);
1898 					break;
1899 				case -2:
1900 					mvprintw(15, 4, "%s", connect_errors[0]);
1901 					break;
1902 				case -3:
1903 					mvprintw(15, 4, "%s", connect_errors[2]);
1904 					break;
1905 				default:
1906 					mvprintw(15, 4, "an unknown error occured");
1907 					break;
1908 			}
1909 			mvprintw(16, 4, "Press a key to continue");
1910 			refresh();
1911 			n_getch();
1912 		}
1913 		flushinp();
1914 		return;
1915 	}
1916 
1917 	if(mdi_gethostname(hostname)<0)
1918 		return;
1919 
1920 	if ( (status = md_connect(handle, hostname, port)) < 0 ) {
1921 		switch(status) {
1922 			case -1:
1923 				mvprintw(15, 4, "%s", connect_errors[1]);
1924 				break;
1925 			case -2:
1926 				mvprintw(15, 4, "%s", connect_errors[0]);
1927 				break;
1928 			case -3:
1929 				mvprintw(15, 4, "%s", connect_errors[2]);
1930 				break;
1931 			default:
1932 				mvprintw(15, 4, "an unknown error occured");
1933 				break;
1934 		}
1935 		mvprintw(16, 4, "Press a key to continue");
1936 		refresh();
1937 		n_getch();
1938 	}
1939 	flushinp();
1940 	return;
1941 }
1942 
1943 /* this gets the port from the user */
mdi_getport(char port[5])1944 int mdi_getport(char port[5]) {
1945 
1946 	int y = 12;
1947 	int x = 4;
1948 
1949 	int done = 0;
1950 	int i_offset = 0;
1951 
1952 	character ch = 0;
1953 
1954 	const char *prompt = "port";
1955 
1956 	for(x = 0; x < 5; x++)
1957 		port[x] = ' ';
1958 
1959 	for(x = 4; (x-4) < 4; x++)
1960 		mvaddch(y, x, prompt[x-4] | colour_attribute(COLOUR_BLUE, COLOUR_BLACK,
1961 					(x==4), FALSE));
1962 
1963 	mvaddch(y, x, ':' | colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
1964 
1965 	draw_port(port);
1966 	refresh();
1967 
1968 	while(!done) {
1969 		ch = n_getch();
1970 		switch(ch) {
1971 			case -1:
1972 				break;
1973 			case 13:
1974 				done = 1;
1975 				break;
1976 			case TD_KEY_ESCAPE:
1977 				done = -1;
1978 				break;
1979 			case KEY_BACKSPACE:
1980 				port[i_offset] = ' ';
1981 				if(i_offset > 0) i_offset--;
1982 				port[i_offset] = ' ';
1983 				break;
1984 			default:
1985 				if(isprint(ch)) {
1986 					port[i_offset] = ch & 0xff;
1987 					if((i_offset+1) < 5) i_offset++;
1988 				}
1989 		}
1990 		draw_port(port);
1991 		refresh();
1992 	}
1993 	return done;
1994 }
1995 
1996 /* this draws the port that the user is inputting */
draw_port(char port[5])1997 void draw_port(char port[5]) {
1998 	int y = 12;
1999 	int x = 4;
2000 
2001 	for(x = 12; (x-12) < 5; x++)
2002 		mvaddch(y, x, port[x-12] | colour_attribute(COLOUR_BLUE, COLOUR_BLACK,
2003 					(x==12), FALSE));
2004 }
2005 
2006 /* this function gets the hostname from the user */
mdi_gethostname(char hostname[1024])2007 int mdi_gethostname(char hostname[1024]) {
2008 	int y = 13;
2009 	int x = 12;
2010 
2011 	character ch = 0;
2012 
2013 	int i_offset = 0;
2014 	int done = 0;
2015 
2016 	const char *prompt = "hostname";
2017 
2018 	for(x = 4; (x-4) < 8; x++)
2019 		mvaddch(y, x, prompt[(x-4)] | colour_attribute(COLOUR_BLUE, COLOUR_BLACK,
2020 					(x==4), FALSE));
2021 
2022 	mvaddch(y,x, ':' | colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
2023 
2024 	for(x = 0; x < 1024; x++)
2025 		hostname[x] = '\0';
2026 
2027 	draw_hostname(hostname);
2028 	refresh();
2029 
2030 	while(!done) {
2031 		ch = n_getch();
2032 		switch(ch) {
2033 			case -1:
2034 				break;
2035 			case 13:
2036 				done = 1;
2037 				break;
2038 			case TD_KEY_ESCAPE:
2039 				done = -1;
2040 				break;
2041 			case KEY_BACKSPACE:
2042 				hostname[i_offset] = '\0';
2043 				if(i_offset > 0) i_offset--;
2044 				hostname[i_offset] = '\0';
2045 				break;
2046 			default:
2047 				if(isprint(ch)) {
2048 					hostname[i_offset] = ch & 0xff;
2049 					if((i_offset+1) < 1024) i_offset++;
2050 					hostname[i_offset] = '\0';
2051 				}
2052 		}
2053 		draw_hostname(hostname);
2054 		refresh();
2055 	}
2056 	return done;
2057 }
2058 
2059 /* this function draws the hostname that the user is inputting */
draw_hostname(char hostname[1024])2060 void draw_hostname(char hostname[1024]) {
2061 	int y = 13;
2062 	int x = 14;
2063 
2064 	int xoffset = 0;
2065 
2066 	int len = strlen(hostname);
2067 
2068 	if(len > 12)
2069 		xoffset = len - 12;
2070 
2071 	for(x = 14; (x-14) < 12 && hostname[xoffset+x-14]; x++)
2072 		if(hostname[xoffset+(x-14)]=='.')
2073 			mvaddch(y, x, hostname[xoffset+x-14] | colour_attribute(COLOUR_BLUE,
2074 						COLOUR_BLACK, TRUE, FALSE));
2075 		else
2076 			mvaddch(y, x, hostname[xoffset+x-14] | colour_attribute(COLOUR_BLUE,
2077 						COLOUR_BLACK, FALSE, FALSE));
2078 	for(; (x-14) < 12; x++)
2079 		mvaddch(y,x, ' ');
2080 }
2081 
2082 
2083 /*  this draws the handle that the user is inputting */
draw_handle(char handle[9])2084 void draw_handle(char handle[9]) {
2085 	int y = 11;
2086 	int x = 4;
2087 
2088 	for(x = 12; (x-12) < 9; x++)
2089 		mvaddch(y, x, handle[x-12] | colour_attribute(COLOUR_BLUE, COLOUR_BLACK,
2090 					(x==12), FALSE));
2091 }
2092 
2093 /* this function gets the users handle from the user */
mdi_gethandle(char handle[9])2094 int mdi_gethandle(char handle[9]) {
2095 
2096 	const char *prompt = "handle";
2097 
2098 	int y = 11;
2099 	int x = 4;
2100 
2101 	int i_offset = 0;
2102 	character ch = 0;
2103 
2104 	int done = 0;
2105 
2106 	for(x = 0; x < 9; x++)
2107 		handle[x] = ' ';
2108 
2109 	for(x = 4; (x-4) < 6; x++)
2110 		mvaddch(y, x, prompt[x-4] | colour_attribute(COLOUR_BLUE, COLOUR_BLACK, (x==4), FALSE));
2111 
2112 	mvaddch(y, x, ':' | colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
2113 
2114 	draw_handle(handle);
2115 	refresh();
2116 	while(!done) {
2117 		ch = n_getch();
2118 		switch(ch) {
2119 			case -1:
2120 				break;
2121 			case 13:
2122 				done = 1;
2123 				break;
2124 			case TD_KEY_ESCAPE:
2125 				done = -1;
2126 				break;
2127 			case KEY_BACKSPACE:
2128 				handle[i_offset] = ' ';
2129 				if(i_offset > 0) i_offset--;
2130 				handle[i_offset] = ' ';
2131 				break;
2132 			default:
2133 				if(isprint(ch)) {
2134 					handle[i_offset] = ch & 0xff;
2135 					if((i_offset+1) < 9) i_offset++;
2136 				}
2137 		}
2138 		draw_handle(handle);
2139 		refresh();
2140 	}
2141 	return done;
2142 }
2143 
2144 /* this function draws the help screen */
help_screen()2145 void help_screen() {
2146 	int y = 0;
2147 	int x = 0;
2148 
2149 	erase();
2150 	hide_cursor();
2151 	for(y = 0; y < 23; y++)
2152 		for(x = 0; x < 80; x++)
2153 			mvaddch(y, x, ansi_help[y][x]);
2154 	refresh();
2155 
2156 	while(n_getch()==-1) continue;
2157 }
2158 
2159 /* this function asks the user if it wants to quicksave the ansi */
quicksave_prompt()2160 int quicksave_prompt() {
2161 	int y = 0;
2162 	int x = 0;
2163 	character ch = 0;
2164 	const char *prompt = "Are you sure you want quicksave? (y/N)";
2165 	int len = strlen(prompt);
2166 
2167 	if(!options.sb_top) y = 24;
2168 
2169 	for(x = 0; x < 80; x++)
2170 		mvaddch(y, x, ' ');
2171 
2172 	for(x = 0; x < len; x++)
2173 		mvaddch(y, x, prompt[x]);
2174 
2175 	refresh();
2176 	while(1) {
2177 		ch = n_getch();
2178 
2179 		switch(ch) {
2180 			case TD_KEY_ESCAPE:
2181 			case 'n':
2182 			case 'N':
2183 			case 13:
2184 				return 0;
2185 				break;
2186 			case 'y':
2187 			case 'Y':
2188 				return 1;
2189 				break;
2190 		}
2191 	}
2192 }
2193 
2194 /* this function asks the user if it wants to clear the screen */
clear_prompt()2195 int clear_prompt() {
2196 	int y = 0;
2197 	int x = 0;
2198 
2199 	character ch = 0;
2200 	const char *prompt = "Are you sure you want clear the screen? (y/N)";
2201 	int len = strlen(prompt);
2202 
2203 	if(!options.sb_top) y = 24;
2204 
2205 	for(x = 0; x < 80; x++)
2206 		mvaddch(y, x, ' ');
2207 
2208 	for(x = 0; x < len; x++)
2209 		mvaddch(y, x, prompt[x]);
2210 
2211 	refresh();
2212 	while(1) {
2213 		ch = n_getch();
2214 
2215 		switch(ch) {
2216 			case TD_KEY_ESCAPE:
2217 			case 'n':
2218 			case 'N':
2219 			case 13:
2220 				return 0;
2221 				break;
2222 			case 'y':
2223 			case 'Y':
2224 				return 1;
2225 				break;
2226 		}
2227 	}
2228 
2229 }
2230 
2231 /* this function asks the user if it wants to quit tetradraw */
quit_prompt()2232 int quit_prompt() {
2233 	int y = 0;
2234 	int x = 0;
2235 	character ch = 0;
2236 	const char *prompt = "Are you sure you want to quit? (y/N)";
2237 	int len = strlen(prompt);
2238 
2239 	if(!options.sb_top) y = 24;
2240 
2241 	for(x = 0; x < 80; x++)
2242 		mvaddch(y, x, ' ');
2243 
2244 	for(x = 0; x < len; x++)
2245 		mvaddch(y, x, prompt[x]);
2246 
2247 	refresh();
2248 
2249 	while(1) {
2250 		ch = n_getch();
2251 
2252 		switch(ch) {
2253 			case TD_KEY_ESCAPE:
2254 			case 'n':
2255 			case 'N':
2256 			case 13:
2257 				return 0;
2258 				break;
2259 			case 'y':
2260 			case 'Y':
2261 				return 1;
2262 				break;
2263 		}
2264 	}
2265 }
2266 
2267 /* this is the colour selection screen */
colour_selection(canvas * page)2268 void colour_selection(canvas *page) {
2269 	int y = 0;
2270 	int x = 0;
2271 
2272 	char input[2];
2273 	int i_offset = 0;
2274 
2275 	int done = 0;
2276 	character ch = 0;
2277 	int i_fg = -1;
2278 	int i_bg = -1;
2279 
2280 	colour fg = 0;
2281 	colour bg = 0;
2282 	flag blink = 0;
2283 	flag bold = 0;
2284 
2285 
2286 	if(!page) return;
2287 
2288 
2289 
2290 	hide_cursor();
2291 
2292 	input[0] = ' ';
2293 	input[1] = ' ';
2294 
2295 	for(y = 0; y < 25; y++)
2296 		for(x = 0; x < 80; x++)
2297 			mvaddch(y, x, ansi_cselect[y][x]);
2298 
2299 	mvprintw(19, 66, "Foreground: ");
2300 	mvprintw(20, 66, "Background: ");
2301 	refresh();
2302 
2303 	while(!done) {
2304 		ch = n_getch();
2305 		switch(ch) {
2306 			case TD_KEY_ESCAPE:
2307 				return;
2308 				break;
2309 			case KEY_BACKSPACE:
2310 				input[i_offset] = ' ';
2311 				if(i_offset > 0) i_offset--;
2312 				break;
2313 			case 13:
2314 				done = 1;
2315 				break;
2316 			default:
2317 				if(isdigit(ch & 0xff)) {
2318 					input[i_offset] = (ch & 0xff);
2319 					if(i_offset+1 < 2) i_offset++;
2320 				}
2321 				break;
2322 		}
2323 		mvaddch(19, 77, input[0]);
2324 		mvaddch(19, 78, input[1]);
2325 		refresh();
2326 	}
2327 	if(isdigit(input[0]) || isdigit(input[1])) {
2328 		i_fg = 0;
2329 		if(isdigit(input[0]))
2330 			i_fg = input[0] - '0';
2331 		if(isdigit(input[1])) {
2332 			i_fg *= 10;
2333 			i_fg += input[1] - '0';
2334 		}
2335 	}
2336 	if(i_fg >= 0 && i_fg <= 31) {
2337 		if(i_fg > 15) {
2338 			blink = TRUE;
2339 			if(i_fg > 23) {
2340 				bold = TRUE;
2341 				i_fg -= 24;
2342 			} else {
2343 				bold = FALSE;
2344 				i_fg -= 16;
2345 			}
2346 		} else {
2347 			bold = FALSE;
2348 			if(i_fg > 7) {
2349 				bold = TRUE;
2350 				i_fg -= 8;
2351 			}
2352 			blink = FALSE;
2353 		}
2354 		fg = i_fg;
2355 	} else return;
2356 
2357 	i_offset = 0;
2358 	input[0] = ' ';
2359 	input[1] = ' ';
2360 	mvaddch(20, 77, input[0]);
2361 	mvaddch(20, 78, input[1]);
2362 	refresh();
2363 	done = 0;
2364 	while(!done) {
2365 		ch = n_getch();
2366 		switch(ch) {
2367 			case TD_KEY_ESCAPE:
2368 				return;
2369 				break;
2370 			case KEY_BACKSPACE:
2371 				input[i_offset] = ' ';
2372 				if(i_offset > 0) i_offset--;
2373 				break;
2374 			case 13:
2375 				done = 1;
2376 				break;
2377 			default:
2378 				if(isdigit(ch & 0xff)) {
2379 					input[i_offset] = (ch & 0xff);
2380 					if(i_offset+1 < 2) i_offset++;
2381 				}
2382 				break;
2383 		}
2384 		mvaddch(20, 77, input[0]);
2385 		mvaddch(20, 78, input[1]);
2386 		refresh();
2387 	}
2388 	if(isdigit(input[0]) || isdigit(input[1])) {
2389 		i_bg = 0;
2390 		if(isdigit(input[0]))
2391 			i_bg = input[0] - '0';
2392 		if(isdigit(input[1])) {
2393 			i_bg *= 10;
2394 			i_bg += input[1] - '0';
2395 		}
2396 	}
2397 	if(i_bg >= 0 && i_bg <= 7) {
2398 		bg = i_bg;
2399 	} else return;
2400 
2401 	setfg(page, fg);
2402 	setbg(page, bg);
2403 	setbold(page, bold);
2404 	setblink(page, blink);
2405 
2406 	return;
2407 }
2408 
2409 /* this function draws the tetraview statusbar */
draw_tv_sbar(canvas * page)2410 void draw_tv_sbar(canvas *page) {
2411 	int y = 24;
2412 	int x = 0;
2413 	int count = 0;
2414 
2415 	int percent = 0;
2416 	char *spercent = 0;
2417 	const char *prompt = "Percent Viewed: ";
2418 
2419 	if(!options.sb_top||!page) return;
2420 
2421 
2422 	for(x = 0; x < 80; x++)
2423 		mvaddch(y, x, ' ');
2424 
2425 	for(x = 0; prompt[x]; x++)
2426 		mvaddch(y, x, prompt[x]);
2427 
2428 	percent = (float)((float)((float)(L_OY(page) + 24) / (float)HY(page)) * 100);
2429 
2430 	/* handle overflow */
2431 	if(percent > 100) percent = 100;
2432 
2433 	spercent = m_malloc(5);
2434 
2435 	sprintf(spercent, "%d", percent);
2436 
2437 	for(; x < 80 && spercent[x-16]; x++)
2438 		mvaddch(y, x, spercent[x-16]);
2439 
2440 	mvaddch(y, x = 19, '%');
2441 
2442 	mvaddch(y, x += 1, ' ');
2443 
2444 	mvaddch(y, x += 1,'['|colour_attribute(COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
2445 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2446 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2447 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2448 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2449 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2450 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2451 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2452 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2453 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2454 	mvaddch(y, x += 1, ('�' & 0xff) | A_ALTCHARSET);
2455 	mvaddch(y, x += 1, ']'|colour_attribute(COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
2456 
2457 	x = 22;
2458 	for(count = 0; count < (percent / 10); count++)
2459 		mvaddch(y, x + count, ('�' & 0xff) | A_ALTCHARSET |
2460 				colour_attribute(COLOUR_BLUE, COLOUR_BLACK, FALSE, FALSE));
2461 	spercent = m_free(spercent);
2462 }
2463 
draw_num(int y,int x,int num)2464 void draw_num(int y, int x, int num) {
2465 	int count = 0;
2466 	char snum[100];
2467 	int len = 0;
2468 
2469 	snprintf(snum, 100, "%d", num);
2470 	if(!snum) return;
2471 	len = strlen(snum);
2472 
2473 	for(count = 0; snum[count] && count < len; count++)
2474 		mvaddch(y, x+count, snum[count] | colour_attribute(
2475 					COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2476 	for(; count < 5; count++)
2477 		mvaddch(y, x+count, ' ');
2478 }
2479 
2480 /* this function draws a yes no prompt */
draw_yesno(int y,int x,int tog)2481 void draw_yesno(int y, int x, int tog) {
2482 	int count = 0;
2483 	const char *yes = "yes";
2484 	const char *no = "no";
2485 
2486 	if(tog) {
2487 		for(count = 0; yes[count]; count++)
2488 			mvaddch(y, x+count, yes[count] |
2489 					colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2490 		for(count = 0; no[count]; count++)
2491 			mvaddch(y, x+count+4, no[count] |
2492 					colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2493 	} else {
2494 		for(count = 0; yes[count]; count++)
2495 			mvaddch(y, x+count, yes[count] |
2496 					colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2497 		for(count = 0; no[count]; count++)
2498 			mvaddch(y, x+count+4, no[count] |
2499 					colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2500 	}
2501 }
2502 
2503 /* this function draws the options */
draw_options(int stage)2504 void draw_options(int stage) {
2505 	int y = 0;
2506 	int x = 0;
2507 	const char *options_string[7] = {
2508 		"status bar on top",
2509 		"enable flip fixing",
2510 		"show dot files",
2511 		"show logo",
2512 		"default character set",
2513 		"auto save time",
2514 		"software cursor"
2515 	};
2516 
2517 	if(stage < 0 || stage > 6) return;
2518 
2519 	for(y = 0; y < 7; y++)
2520 		for(x = 0; options_string[y][x]; x++)
2521 			mvaddch(y+12, x+3, options_string[y][x] |
2522 					colour_attribute((y == stage) ? COLOUR_WHITE : COLOUR_BLACK, COLOUR_BLACK, TRUE, FALSE));
2523 
2524 	draw_yesno(12, 30, (options.sb_top));
2525 	draw_yesno(13, 30, (options.fix_flip));
2526 	draw_yesno(14, 30, (options.dot_files));
2527 	draw_yesno(15, 30, (options.show_logo));
2528 	draw_num(16, 30, options.default_cs);
2529 	draw_num(17, 30, options.autosave);
2530 	draw_yesno(18, 30, (options.soft_cursor));
2531 }
2532 
2533 /* this function draws yesno prompt*/
draw_get_yesno(int y,int x,int tog)2534 void draw_get_yesno(int y, int x,int tog) {
2535 	int count = 0;
2536 	const char *yes = "yes";
2537 	const char *no = "no";
2538 
2539 	if (tog) {
2540 		for(count = 0; yes[count]; count++)
2541 			mvaddch(y, x+count, yes[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2542 
2543 		for(count = 0; no[count]; count++)
2544 			mvaddch(y, x+count+4, no[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2545 
2546 	} else {
2547 		for(count = 0; yes[count]; count++)
2548 			mvaddch(y, x+count, yes[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2549 
2550 		for(count = 0; no[count]; count++)
2551 			mvaddch(y, x+count+4, no[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2552 	}
2553 
2554 	if (tog) {
2555 		for(count = 0; yes[count]; count++)
2556 			mvaddch(y, x+count, yes[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2557 
2558 		for(count = 0; no[count]; count++)
2559 			mvaddch(y, x+count+4, no[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2560 
2561 	} else {
2562 		for(count = 0; yes[count]; count++)
2563 			mvaddch(y, x+count, yes[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, FALSE, FALSE));
2564 
2565 		for(count = 0; no[count]; count++)
2566 			mvaddch(y, x+count+4, no[count] | colour_attribute(COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2567 	}
2568 }
2569 
2570 /* this function gets a yes no answer from the user */
get_yesno(int y,int x,flag * tog)2571 void get_yesno(int y, int x, flag *tog) {
2572 	character ch = 0;
2573 
2574 	if(!tog) return;
2575 
2576 
2577 	do {
2578 		draw_get_yesno(y, x, *tog);
2579 		refresh();
2580 		ch = n_getch();
2581 		switch(ch) {
2582 			case -1:
2583 				break;
2584 			case KEY_LEFT:
2585 				*tog = 1;
2586 				break;
2587 			case KEY_RIGHT:
2588 				*tog = 0;
2589 				break;
2590 			case 'y':
2591 			case 'Y':
2592 				*tog = 1;
2593 				return;
2594 				break;
2595 			case 'n':
2596 			case 'N':
2597 				*tog = 0;
2598 				return;
2599 				break;
2600 			case 13:
2601 				return;
2602 				break;
2603 		}
2604 	} while(1);
2605 
2606 	return;
2607 }
2608 
2609 /* this function draws the number that the user is inputting */
draw_get_num(int y,int x,int n,char * snum)2610 void draw_get_num(int y, int x, int n, char *snum) {
2611 	int count = 0;
2612 
2613 	for(; snum[count] && count < n; count++)
2614 		mvaddch(y, x+count, snum[count] | colour_attribute(
2615 					COLOUR_GREEN, COLOUR_BLACK, TRUE, FALSE));
2616 	for(; count < n; count++)
2617 		mvaddch(y, x+count, ' ');
2618 
2619 }
2620 
2621 /* this function gets a number from the user inbetween h(igh) and l(ow) */
get_num(int y,int x,int h,int l,int n,int * num)2622 void get_num(int y, int x, int h, int l, int n, int *num) {
2623 	char snum[100];
2624 	int i_offset = 0;
2625 	character ch = 0;
2626 	char prompt[1024];
2627 	int len = 0;
2628 
2629 
2630 	memset(&snum, 32, sizeof(n));
2631 
2632 	snprintf(snum, 100, "%d", *num);
2633 
2634 	snprintf(prompt, 1024, "range: %d to %d (inclusive)", l, h);
2635 
2636 	len = strlen(prompt);
2637 
2638 
2639 	for(i_offset = 0; i_offset < len; i_offset++)
2640 		mvaddch(24, i_offset, prompt[i_offset]);
2641 
2642 	if(!strcmp("0", snum))
2643 		i_offset = 0;
2644 	else
2645 		i_offset = strlen(snum);
2646 
2647 	do {
2648 		draw_get_num(y, x, n, snum);
2649 		refresh();
2650 		ch = n_getch();
2651 		switch(ch) {
2652 			case KEY_BACKSPACE:
2653 				if(i_offset > 0) i_offset--;
2654 				snum[i_offset] = '\0';
2655 				break;
2656 			case 13:
2657 				if(atoi(snum)<=h&&atoi(snum)>=l)
2658 					*num = atoi(snum);
2659 				return;
2660 			case TD_KEY_ESCAPE:
2661 				for(i_offset = 0; i_offset < 80; i_offset++)
2662 					mvaddch(24, i_offset, ' ');
2663 				return;
2664 				break;
2665 			default:
2666 				if(isdigit(ch)) {
2667 					snum[i_offset] = (ch & 0xff);
2668 					if(i_offset+1 < n) i_offset++;
2669 					snum[i_offset] = '\0';
2670 				}
2671 				break;
2672 		}
2673 	} while(1);
2674 
2675 }
2676 
2677 /* this function drives the options screen */
get_options(int stage)2678 void get_options(int stage) {
2679 	if(stage < 0 || stage > 6) return;
2680 	switch(stage) {
2681 		case 0:
2682 			get_yesno(12, 30, &options.sb_top);
2683 			break;
2684 		case 1:
2685 			get_yesno(13, 30, &options.fix_flip);
2686 			break;
2687 		case 2:
2688 			get_yesno(14, 30, &options.dot_files);
2689 			break;
2690 		case 3:
2691 			get_yesno(15, 30, &options.show_logo);
2692 			break;
2693 		case 4:
2694 			get_num(16, 30, 19, 0, 3, &options.default_cs);
2695 			break;
2696 		case 5:
2697 			get_num(17, 30, 999, 0, 4, &options.autosave);
2698 			break;
2699 		case 6:
2700 			get_yesno(18, 30, &options.soft_cursor);
2701 			break;
2702 	}
2703 }
2704 
2705 /* this function is the options interaface */
options_screen()2706 void options_screen() {
2707 	int y = 0;
2708 	int x = 0;
2709 	character ch = 0;
2710 	int stage = 0;
2711 
2712 	hide_cursor();
2713 	erase();
2714 	refresh();
2715 
2716 	for(y = 0; y < 10; y++)
2717 		for(x = 0; x < 80; x++)
2718 			mvaddch(y, x, ansi_options[y][x]);
2719 
2720 	draw_options(stage);
2721 	refresh();
2722 	while(1) {
2723 		ch = n_getch();
2724 
2725 		switch(ch) {
2726 			case -1:
2727 				break;
2728 			case TD_KEY_SAVE:
2729 				save_options();
2730 				break;
2731 			case TD_KEY_ESCAPE:
2732 				return;
2733 				break;
2734 			case KEY_UP:
2735 				if(stage > 0) stage--;
2736 				break;
2737 			case KEY_DOWN:
2738 				if(stage+1 < 7) stage++;
2739 				break;
2740 			case 13:
2741 			case 32:
2742 				get_options(stage);
2743 				break;
2744 		}
2745 		draw_options(stage);
2746 		refresh();
2747 	}
2748 }
2749 
2750 /* this function prompts the user to save the canvas before blasting it
2751  * away */
save_prompt()2752 int save_prompt() {
2753 	int y = 24;
2754 	int x = 0;
2755 	const char*prompt="Canvas has been modified do you want to save first? (Y/n)";
2756 
2757 	character ch = 0;
2758 
2759 	if(options.sb_top) y = 0;
2760 
2761 	for(x = 0; x < 80; x++)
2762 		mvaddch(y, x, ' ');
2763 
2764 	for(x = 0; prompt[x]; x++)
2765 		mvaddch(y, x, prompt[x]);
2766 	refresh();
2767 	while(1) {
2768 		ch = n_getch();
2769 
2770 		switch(ch) {
2771 			case -1:
2772 				break;
2773 			case 'n':
2774 			case 'N':
2775 			case TD_KEY_ESCAPE:
2776 				return 0;
2777 				break;
2778 			case 'y':
2779 			case 'Y':
2780 			case 13:
2781 				return 1;
2782 				break;
2783 		}
2784 	}
2785 }
2786 
2787 /* this function draws the percent bar while loading an ansi */
draw_percentbar(int fpos,int flen)2788 void draw_percentbar(int fpos, int flen) {
2789 	int count = 0;
2790 	int y = 6;
2791 	int x = 4;
2792 	int percent = (float)((float)fpos / (float)flen * 100);
2793 	char spercent[100];
2794 
2795 	hide_cursor();
2796 	if(percent < 0 || percent > 100) return;
2797 
2798 	snprintf(spercent,100, "%d", percent);
2799 	for(count = 0; spercent[count]; count++)
2800 		mvaddch(y, x + count, spercent[count] | colour_attribute(COLOUR_BLUE,
2801 					COLOUR_BLACK, FALSE, FALSE));
2802 	mvaddch(y, x+=4, '%' | colour_attribute(COLOUR_WHITE, COLOUR_BLACK,
2803 				FALSE, FALSE));
2804 	x += 2;
2805 	mvaddch(y, x+=1, '[' | colour_attribute(COLOUR_BLACK, COLOUR_BLACK,
2806 				TRUE, FALSE));
2807 	x += 1;
2808 	for(count = 0; count < 20; count++)
2809 		mvaddch(y, count + x, ('�' & 0xff) | A_ALTCHARSET);
2810 
2811 	mvaddch(y, count + x, ']' | colour_attribute(COLOUR_BLACK, COLOUR_BLACK,
2812 				TRUE, FALSE));
2813 
2814 
2815 	for(count = 0; count < (percent / 5); count++)
2816 		mvaddch(y, x + count, ('�' & 0xff) | A_ALTCHARSET |
2817 				colour_attribute(COLOUR_BLUE, COLOUR_BLACK, TRUE, FALSE));
2818 	refresh();
2819 
2820 	return;
2821 }
2822 
2823 #define VALID_CH(c) \
2824 	((c >= 1 && c <= 6) || \
2825 	(c >= 16 && c <=23) || \
2826 	(c == 25 || c == 28 || c == 29 || c == 30 || c == 31) || \
2827 	(c >= 32 && c < 256))
2828 
2829 	/* this function draws the character select screen */
draw_chselect(int page)2830 void draw_chselect(int page) {
2831 	int row = 0;
2832 	int column = 0;
2833 	attribute clr = colour_attribute(COLOUR_YELLOW, COLOUR_BLUE, TRUE, FALSE);
2834 	char sascii[100];
2835 	int count = 0;
2836 
2837 	for(row = 0; row < 2; row++) {
2838 		for(column = 1; column <= 10; column++) {
2839 			if((20*page)+(row*10)+column <= 256) {
2840 					snprintf(sascii, 100, "%3d", (20*page)+(row*10)+column);
2841 					for(count = 0; sascii[count]; count++)
2842 						mvaddch(column + 3, 40+(row*10)+count, sascii[count] | clr);
2843 
2844 					if(VALID_CH((20*page)+(row*10)+column))
2845 						mvaddch(column + 3, 45+(row*10),
2846 								((20*page)+(row*10)+column)
2847 								| A_ALTCHARSET);
2848 					else
2849 						mvaddch(column + 3, 45+(row*10), ' ');
2850 			} else for(count = 0; count < 6; count++)
2851 				mvaddch(column + 3, 40+(row*10)+count, ' ');
2852 		}
2853 	}
2854 }
2855 
2856 /* this function is the character selection screen */
chselect()2857 character chselect() {
2858 	int y = 0;
2859 	int x = 0;
2860 	character ch = 0;
2861 	int count = 0;
2862 	int page = 0;
2863 	char input[4];
2864 	int i_offset = 0;
2865 	attribute clr = colour_attribute(COLOUR_YELLOW, COLOUR_BLUE, TRUE, FALSE);
2866 	const char *prompt = "Ascii code: ";
2867 	int done = 0;
2868 
2869 	memset(&input, 32, sizeof(input));
2870 	input[3] = '\0';
2871 
2872 	for(y = 0; y < 14;y++)
2873 		for(x = 0; x < 80; x++)
2874 			mvaddch(y, x, ansi_chselect[y][x]);
2875 
2876 	draw_chselect(page);
2877 	do {
2878 		for(count = 0; count < 12; count++)
2879 			mvaddch(16, 27 + count, prompt[count]);
2880 		for(count = 0; count < 3; count++)
2881 			mvaddch(16, 40+count, (input[count]) ? input[count] | clr : ' ' | clr);
2882 		refresh();
2883 		ch = n_getch();
2884 		switch(ch) {
2885 			case 13:
2886 				done = 1;
2887 				break;
2888 			case TD_KEY_ESCAPE:
2889 				return -1;
2890 				break;
2891 			case TD_KEY_PAGEUP:
2892 				if(page > 0) {
2893 					page--;
2894 					draw_chselect(page);
2895 					refresh();
2896 				}
2897 				break;
2898 			case TD_KEY_PAGEDOWN:
2899 				if(page+1 < 13) {
2900 					page++;
2901 					draw_chselect(page);
2902 					refresh();
2903 				}
2904 				break;
2905 			case KEY_BACKSPACE:
2906 				input[i_offset] = '\0';
2907 				if(i_offset > 0) i_offset--;
2908 				break;
2909 			default:
2910 				if(isdigit(ch)) {
2911 					input[i_offset] = (ch);
2912 					if(i_offset+1 < 3) i_offset++;
2913 				}
2914 				break;
2915 		}
2916 	} while(!done);
2917 	if(atol(input) > 0 && atol(input) < 256) {
2918 		return atol(input);
2919 	} else return -1;
2920 }
2921 
2922 /* this function shows the startup logo */
start_logo()2923 void start_logo() {
2924 	int y = 0;
2925 	int x = 0;
2926 
2927 	srand(time(NULL));
2928 
2929 	if(rand()%2) {
2930 		for(y = 0; y < 25; y++)
2931 			for(x = 0; x < 80; x++)
2932 				mvaddch(y, x, ansi_slogo[y][x]);
2933 	} else {
2934 		for(y = 0; y < 24; y++)
2935 			for(x = 0; x < 80; x++)
2936 				mvaddch(y, x, ansi_slogo2[y][x]);
2937 	}
2938 }
2939 
2940 /* this function shows the exit logo */
exit_logo()2941 void exit_logo() {
2942 	int y = 0;
2943 	int x = 0;
2944 
2945 	for(y = 0; y < 19; y++)
2946 		for(x = 0; x < 80; x++)
2947 			mvaddch(y, x, ansi_elogo[y][x]);
2948 }
2949