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