1 /*
2 * MSGED.C
3 *
4 * Written on 30-Jul-90 by jim nutt. Changes on 10-Jul-94 by John Dennis.
5 * Released to the public domain.
6 *
7 * Msged Mail Reader.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <time.h>
16
17 #ifndef UNIX
18 #include <process.h>
19 #endif
20
21 #include "addr.h"
22 #include "nedit.h"
23 #include "maintmsg.h"
24 #include "misc.h"
25 #include "keys.h"
26 #include "winsys.h"
27 #include "menu.h"
28 #include "main.h"
29 #include "dialogs.h"
30 #include "bmg.h"
31 #include "screen.h"
32 #include "memextra.h"
33 #include "strextra.h"
34 #include "areas.h"
35 #include "version.h"
36 #include "specch.h"
37 #include "dosmisc.h"
38 #include "config.h"
39 #include "list.h"
40 #include "help.h"
41 #include "getopts.h"
42 #include "keycode.h"
43 #include "helpcmp.h"
44 #include "helpinfo.h"
45 #include "system.h"
46 #include "msged.h"
47 #include "maincmds.h"
48 #include "readmail.h"
49 #include "makemsgn.h"
50 #include "nshow.h"
51 #include "charset.h"
52 #include "wrap.h"
53 #include "textfile.h"
54 #include "group.h"
55
56 #ifdef MSDOS
57 #ifdef USE_CRITICAL
58 #include "critical.h"
59 #endif
60 #if !defined(NODOSSWAP) && !defined(__FLAT__)
61 #include <dos.h> /* FP_OFF macro */
62 #include "spawn.h"
63 #endif
64 #endif
65
66 #ifdef USE_MSGAPI
67 #include "msg.h"
68 #endif
69
70 #ifndef randomize
71 #define randomize() srand((unsigned) time(NULL))
72 #endif
73
74 /* prototypes */
75
76 static void highest(void);
77 static void gotomsg(unsigned long i);
78 static void pm_next_area(void);
79
80 /* local/global variables */
81
82 int scan = 0; /* set scan = 1 to scan for new mail at startup */
83
84 static int endMain = 0;
85 static int errorlevel = 0;
86 int direction = RIGHT; /* travel direction in msgbase */
87 char *msgbuf = NULL; /* message buffer used for reading, size: BUFLEN */
88 int msgederr = 0; /* errno for msged */
89 int set_rcvd = 1; /* used to tell readmsg() not to set rcvd */
90
91 /* only used readmail between.c and msged.c */
92 static unsigned long root = 0; /* root message of a thread */
93 static unsigned long back = 0; /* Where you were before you said "go
94 * root" */
95 static unsigned long areastart = 0; /* msg number we started on in this
96 * area */
97 static unsigned long lastfound = 0; /* msg number last found */
98 static unsigned long oldmsg = 0;
99 static int command;
100
101 #if defined(MSDOS) && defined(__TURBOC__)
102 extern unsigned _stklen = 16384;
103 #endif
104
delete(void)105 static void delete(void)
106 {
107 deletemsg();
108 }
109
move(void)110 static void move(void)
111 {
112 if (message != NULL)
113 {
114 movemsg();
115 }
116 }
117
outtxt(void)118 static void outtxt(void)
119 {
120 if (message != NULL)
121 {
122 writetxt();
123 }
124 }
125
set(void)126 static void set(void)
127 {
128 set_switch();
129 }
130
chngaddr(void)131 static void chngaddr(void)
132 {
133 change_curr_addr();
134 }
135
chngname(void)136 static void chngname(void)
137 {
138 change_username();
139 }
140
chngnodel(void)141 static void chngnodel(void)
142 {
143 change_nodelist();
144 }
145
do_help(void)146 static void do_help(void)
147 {
148 show_help();
149 }
150
first(void)151 static void first(void)
152 {
153 CurArea.current = CurArea.first;
154 }
155
r_getbind(unsigned int key)156 char *r_getbind(unsigned int key)
157 {
158 unsigned int i = 0;
159 void (*action) (void);
160
161 if (key & 0xff)
162 {
163 action = mainckeys[key & 0xff];
164 }
165 else
166 {
167 action = mainakeys[(key >> 8) & 0xff];
168 }
169
170 while (maincmds[i].label != NULL && action != maincmds[i].action)
171 {
172 i++;
173 }
174
175 return maincmds[i].label;
176 }
177
r_getlabels(int i)178 char *r_getlabels(int i)
179 {
180 return maincmds[i].label;
181 }
182
r_assignkey(unsigned int key,char * label)183 void r_assignkey(unsigned int key, char *label)
184 {
185 unsigned int i = 0;
186
187 while ((maincmds[i].label != NULL) &&
188 (strncmp(maincmds[i].label, label, strlen(maincmds[i].label)) != 0))
189 {
190 i++;
191 }
192
193 if (maincmds[i].label != NULL)
194 {
195 if (key & 0xff)
196 {
197 mainckeys[key & 0xff] = maincmds[i].action;
198 }
199 else
200 {
201 mainakeys[(key >> 8) & 0xff] = maincmds[i].action;
202 }
203 }
204 }
205
dispose(msg * message)206 void dispose(msg * message)
207 {
208 if (message == NULL)
209 {
210 return;
211 }
212
213 if (message->text != NULL)
214 {
215 message->text = clearbuffer(message->text);
216 }
217
218 release(message->isto);
219 release(message->isfrom);
220 release(message->reply);
221 release(message->msgid);
222 release(message->subj);
223 release(message->to.domain);
224 release(message->from.domain);
225 release(message->replyarea);
226 release(message->charset_name);
227 release(message);
228 }
229
KillMsg(msg * m)230 msg *KillMsg(msg * m)
231 {
232 dispose(m);
233 return NULL;
234 }
235
236 /* edithdr - lets the user edit the header only */
237
edithdr(void)238 static void edithdr(void)
239 {
240 int q;
241
242 if (message == NULL)
243 {
244 return;
245 }
246
247 q = 0;
248 while (!q)
249 {
250 if (EditHeader(message) == Key_Esc)
251 {
252 if (confirm("Cancel?"))
253 {
254 message = KillMsg(message);
255 return;
256 }
257 }
258 else
259 {
260 q = 1;
261 }
262 }
263
264 /* TE 07/2000: We have to rewrite all the message, not just
265 the header, because of the @FLAGS kludge which is in the body
266 MsgWriteHeader(message, WR_HEADER); */
267 writemsg(message);
268
269 message = KillMsg(message);
270 }
271
272 /* cleanup - make sure you exit straight after calling this! */
273
cleanup(char * msg,...)274 void cleanup(char *msg,...)
275 {
276 AREA *a;
277
278 if (CurArea.status)
279 {
280 highest();
281 AreaSetLast(&CurArea);
282 MsgAreaClose();
283 }
284 setcwd(ST->home);
285 WndClose(hMnScr);
286 TTgotoxy(term.NRow - 1, 0);
287 TTclose();
288
289 for (a = &(arealist[SW->area = 0]); SW->area < SW->areas; a = &(arealist[++SW->area]))
290 {
291 errorlevel |= (a->netmail && a->new) ? 0x01 : 0;
292 errorlevel |= (a->echomail && a->new) ? 0x02 : 0;
293 errorlevel |= (a->uucp && a->new) ? 0x04 : 0;
294 errorlevel |= (a->news && a->new) ? 0x08 : 0;
295 errorlevel |= (a->local && a->new) ? 0x10 : 0;
296 }
297
298 if (msg)
299 {
300 va_list ap;
301 va_start(ap, msg);
302 putchar('\n');
303 vprintf(msg, ap);
304 va_end(ap);
305 }
306
307 group_destroy_arealist();
308 destroy_charset_maps();
309 DeinitMem();
310 #ifdef USE_MSGAPI
311 MsgApiTerm();
312 #endif
313 TTCurSet(1);
314 /*#ifdef UNIX
315 TTScolor(7);
316 #endif */
317
318 #ifdef USE_CRITICAL
319 remove24h();
320 #endif
321 }
322
quit(void)323 static void quit(void)
324 {
325 endMain = 1;
326 }
327
328 /* search - search header and message text for keyword */
329
search(void)330 static void search(void)
331 {
332 LINE *l = NULL;
333 static char prompt[256] = "";
334 static char patstr[256] = "";
335 char tempstr[60];
336 char totalmsg[12]; /* to allow for upto 4,294,967,295 msgs */
337 msg *m = NULL;
338 unsigned long tmp = 0;
339 int done = 0;
340 unsigned int boxwidth; /* boxwidth of search display */
341 unsigned int mlength;
342
343 if (!GetString(" Keyword Search (message header and text) ", "Search for:", prompt, 64))
344 {
345 return;
346 }
347
348 if (strlen(prompt) == 0)
349 {
350 return;
351 }
352
353 sprintf(tempstr, " Searching for \"%.30s\" ", prompt);
354
355 sprintf(totalmsg, "%ld", CurArea.messages);
356 mlength = (2 * strlen(totalmsg)) + 26;
357 if (mlength <= (strlen(tempstr) + 18))
358 {
359 boxwidth = (strlen(tempstr) + 18);
360 }
361 else
362 {
363 boxwidth = mlength;
364 }
365
366 if (!OpenMsgWnd(boxwidth, 6, tempstr, NULL, 0, 0))
367 {
368 return;
369 }
370
371 message = KillMsg(message);
372
373 /*
374 * We use this to ensure the rcvd bit doesn't get set. Possibly a
375 * mistake if the msg found is addressed to the user...
376 */
377
378 set_rcvd = 0;
379
380 SendMsgWnd("Press Esc to stop", 0);
381
382 if ((stricmp(prompt, patstr) == 0) && (lastfound == CurArea.current) &&
383 (CurArea.current < CurArea.messages))
384 {
385 if (direction == RIGHT)
386 {
387 tmp = CurArea.current + 1;
388 }
389 else
390 {
391 if (CurArea.current > 1)
392 {
393 tmp = CurArea.current - 1;
394 }
395 }
396 bmg_setsearch(prompt);
397 }
398 else
399 {
400 tmp = CurArea.current;
401 lastfound = 0;
402 strcpy(patstr, prompt);
403 bmg_setsearch(prompt);
404 }
405
406 for (;;)
407 {
408 if ((direction == RIGHT) && (tmp > CurArea.messages))
409 {
410 break;
411 }
412 else if (tmp == 0)
413 {
414 break;
415 }
416
417 /* check for event here */
418
419 if (done == TRUE || (KeyHit() && GetKey() == Key_Esc))
420 {
421 break;
422 }
423
424 l = NULL;
425
426 if ((m = readmsg(tmp)) != NULL)
427 {
428 sprintf(tempstr, "Reading message #%ld of #%ld", tmp, CurArea.messages);
429 SendMsgWnd(tempstr, 1);
430
431 if (bmg_search(m->isto) != NULL)
432 {
433 done = TRUE;
434 break;
435 }
436
437 if (bmg_search(m->isfrom) != NULL)
438 {
439 done = TRUE;
440 break;
441 }
442
443 if (bmg_search(m->subj) != NULL)
444 {
445 done = TRUE;
446 break;
447 }
448
449 l = m->text;
450
451 while ((l != NULL) && (done == FALSE))
452 {
453 if (l->text && (strlen(l->text) > 0))
454 {
455 if (bmg_search(l->text) != NULL)
456 {
457 done = TRUE;
458 break;
459 }
460 }
461 l = l->next;
462 }
463 if (done == TRUE)
464 {
465 break;
466 }
467
468 dispose(m);
469 m = NULL;
470 }
471
472 if (direction == RIGHT)
473 {
474 tmp++;
475 }
476 else
477 {
478 tmp--;
479 }
480 }
481
482 CloseMsgWnd();
483
484 set_rcvd = 1; /* readmsg() is now free to set it */
485
486 if (done)
487 {
488 CurArea.current = tmp;
489 lastfound = tmp;
490 oldmsg = tmp;
491 message = m;
492
493 TTBeginOutput();
494 ShowMsgHeader(message);
495
496 if (l != NULL)
497 {
498 l->block = TRUE;
499 RefreshMsg(l, 6);
500 }
501 else
502 {
503 RefreshMsg(message->text, 6);
504 }
505 TTEndOutput();
506 }
507 else
508 {
509 dispose(m);
510 }
511 }
512
513 /* hdrsearch - search header for keyword */
514
hdrsearch(void)515 static void hdrsearch(void)
516 {
517 LINE *l = NULL;
518 static char prompt[256] = "";
519 static char patstr[256] = "";
520 char tempstr[40];
521 char totalmsg[12]; /* to allow for upto 4,294,967,295 msgs */
522 msg *m = NULL;
523 unsigned long tmp = 0;
524 int done = 0;
525 unsigned int boxwidth; /* boxwidth of search display */
526 unsigned int mlength;
527
528 if (!GetString(" Keyword Search (message header) ", "Search for:", prompt, 64))
529 {
530 return;
531 }
532
533 if (strlen(prompt) == 0)
534 {
535 return;
536 }
537
538 sprintf(tempstr, " Searching for \"%.30s\" ", prompt);
539
540 sprintf(totalmsg, "%ld", CurArea.messages);
541 mlength = (2 * strlen(totalmsg)) + 26;
542 if (mlength <= (strlen(tempstr) + 18))
543 {
544 boxwidth = (strlen(tempstr) + 18);
545 }
546 else
547 {
548 boxwidth = mlength;
549 }
550
551 if (!OpenMsgWnd(boxwidth, 6, tempstr, NULL, 0, 0))
552 {
553 return;
554 }
555
556 message = KillMsg(message);
557
558 /*
559 * We use this to ensure the rcvd bit doesn't get set. Possibly a
560 * mistake if the msg found is addressed to the user...
561 */
562
563 set_rcvd = 0;
564
565 SendMsgWnd("Press Esc to stop", 0);
566
567 if ((stricmp(prompt, patstr) == 0) && (lastfound == CurArea.current) &&
568 (CurArea.current < CurArea.messages))
569 {
570 if (direction == RIGHT)
571 {
572 tmp = CurArea.current + 1;
573 }
574 else
575 {
576 if (CurArea.current > 1)
577 {
578 tmp = CurArea.current - 1;
579 }
580 }
581 bmg_setsearch(prompt);
582 }
583 else
584 {
585 tmp = CurArea.current;
586 lastfound = 0;
587 strcpy(patstr, prompt);
588 bmg_setsearch(prompt);
589 }
590
591 for (;;)
592 {
593 if ((direction == RIGHT) && (tmp > CurArea.messages))
594 {
595 break;
596 }
597 else if (tmp == 0)
598 {
599 break;
600 }
601
602 /* check for event here */
603
604 if (done == TRUE || (KeyHit() && GetKey() == Key_Esc))
605 {
606 break;
607 }
608
609 l = NULL;
610
611 if ((m = MsgReadHeader(tmp, RD_HEADER_BRIEF)) != NULL)
612 {
613 sprintf(tempstr, "Reading message #%ld of #%ld", tmp, CurArea.messages);
614 SendMsgWnd(tempstr, 1);
615
616 if (bmg_search(m->isto) != NULL)
617 {
618 done = TRUE;
619 break;
620 }
621
622 if (bmg_search(m->isfrom) != NULL)
623 {
624 done = TRUE;
625 break;
626 }
627
628 if (bmg_search(m->subj) != NULL)
629 {
630 done = TRUE;
631 break;
632 }
633
634 if (done == TRUE)
635 {
636 break;
637 }
638
639 dispose(m);
640 m = NULL;
641 }
642
643 if (direction == RIGHT)
644 {
645 tmp++;
646 }
647 else
648 {
649 tmp--;
650 }
651 }
652
653 CloseMsgWnd();
654
655 set_rcvd = 1; /* readmsg() is now free to set it */
656
657 if (done)
658 {
659 dispose(m);
660 m = readmsg(tmp);
661
662 message = m;
663 CurArea.current = tmp;
664 lastfound = tmp;
665 oldmsg = tmp;
666
667 TTBeginOutput();
668
669 ShowMsgHeader(message);
670
671 if (l != NULL)
672 {
673 l->block = TRUE;
674 RefreshMsg(l, 6);
675 }
676 else
677 {
678 RefreshMsg(message->text, 6);
679 }
680
681 TTEndOutput();
682 }
683 else
684 {
685 dispose(m);
686 }
687 }
688
689 /* spmail - searchs for personal mail in a single area */
690
spmail(void)691 static void spmail(void)
692 {
693 LINE *l = NULL;
694 static char prompt[256] = "";
695 static char patstr[256] = "";
696 char tempstr[40];
697 char totalmsg[12]; /* to allow for upto 4,294,967,295 msgs */
698 msg *m = NULL;
699 unsigned long tmp;
700 int done = 0;
701 int boxwidth; /* boxwidth for search display */
702 int mlength;
703
704 strcpy(prompt, ST->username);
705
706 if (strlen(prompt) == 0)
707 {
708 return;
709 }
710
711 sprintf(tempstr, " Searching for \"%.30s\" ", prompt);
712 sprintf(totalmsg, "%ld", CurArea.messages);
713 mlength = (2 * strlen(totalmsg)) + 26;
714
715 if (mlength <= (strlen(tempstr) + 18))
716 {
717 boxwidth = (strlen(tempstr) + 18);
718 }
719 else
720 {
721 boxwidth = mlength;
722 }
723
724 if (!OpenMsgWnd(boxwidth, 6, tempstr, NULL, 0, 0))
725 {
726 return;
727 }
728
729 message = KillMsg(message);
730
731 /*
732 * We use this to ensure the rcvd bit doesn't get set. Possibly a
733 * mistake if the msg found is addressed to the user...
734 */
735
736 set_rcvd = 0;
737
738 SendMsgWnd("Press Esc to stop", 0);
739
740 if ((stricmp(prompt, patstr) == 0) && (lastfound == CurArea.current))
741 {
742 tmp = CurArea.current + 1;
743 }
744 else
745 {
746 tmp = CurArea.current + 1;
747 lastfound = 0;
748 strcpy(patstr, prompt);
749 bmg_setsearch(prompt);
750 }
751
752 for (; tmp <= CurArea.messages; tmp++)
753 {
754 /* check for event here */
755
756 if (done == TRUE || (KeyHit() && (GetKey()) == Key_Esc))
757 {
758 break;
759 }
760
761 l = NULL;
762
763 if ((m = readmsg(tmp)) != NULL)
764 {
765 sprintf(tempstr, "Area: %s", CurArea.tag);
766 SendMsgWnd(tempstr, 1);
767 sprintf(tempstr, "Reading message #%ld of #%ld", tmp, CurArea.messages);
768 SendMsgWnd(tempstr, 2);
769
770 bmg_setsearch(ST->username);
771
772 if (bmg_search(m->isto) != NULL)
773 {
774 done = TRUE;
775 break;
776 }
777
778 if (done == TRUE)
779 {
780 break;
781 }
782
783 dispose(m);
784 m = NULL;
785 }
786 }
787
788 CloseMsgWnd();
789
790 set_rcvd = 1; /* readmsg() is now free to set it */
791
792 if (done)
793 {
794 CurArea.current = tmp;
795 lastfound = tmp;
796 oldmsg = tmp;
797 message = m;
798
799 TTBeginOutput();
800
801 ShowMsgHeader(message);
802
803 if (l != NULL)
804 {
805 l->block = TRUE;
806 RefreshMsg(l, 6);
807 }
808 else
809 {
810 RefreshMsg(message->text, 6);
811 }
812
813 TTEndOutput();
814 }
815 else
816 {
817 dispose(m);
818 }
819 }
820
821 /* pmail - personal mail scan */
822
823 static int x = -1;
824 static int firstarea = 0;
825
pmail(void)826 static void pmail(void)
827 {
828 LINE *l = NULL;
829 static char prompt[256] = "";
830 static char patstr[256] = "";
831 static char username[256] = "";
832 char tempstr[40];
833 char totalmsg[12]; /* to allow upto 4,294,967,295 msgs */
834 msg *m = NULL;
835 unsigned long tmp;
836 int done = 0;
837 int boxwidth; /* boxwidth for search display */
838 int mlength;
839 unsigned int chkkey = 0;
840 int again = 1;
841
842 while (again)
843 {
844 again = 0;
845 if (x == -1)
846 {
847 firstarea = SW->grouparea;
848 strcpy(username, ST->username);
849 }
850
851 x += 1;
852
853 strcpy(prompt, username);
854
855 if (strlen(prompt) == 0)
856 {
857 return;
858 }
859
860 sprintf(tempstr, " Searching for \"%.30s\" ", prompt);
861
862 sprintf(totalmsg, "%ld", CurArea.messages);
863 mlength = (2 * strlen(totalmsg)) + 26;
864 if (mlength <= (strlen(tempstr) + 18))
865 {
866 boxwidth = (strlen(tempstr) + 18);
867 }
868 else
869 {
870 boxwidth = mlength;
871 }
872
873 if ((long)arealist[SW->area].messages != (long)arealist[SW->area].lastread)
874 {
875 if (!OpenMsgWnd(boxwidth, 6, tempstr, NULL, 0, 0))
876 {
877 return;
878 }
879 }
880
881 message = KillMsg(message);
882
883 /*
884 * We use this to ensure the rcvd bit doesn't get set. Possibly a
885 * mistake if the msg found is addressed to the user...
886 */
887
888 set_rcvd = 0;
889
890 if ((long)arealist[SW->area].messages != (long)arealist[SW->area].lastread)
891 {
892 SendMsgWnd("Press Esc to stop", 0);
893 }
894
895 if (stricmp(prompt, patstr) == 0 && lastfound == CurArea.current)
896 {
897 tmp = CurArea.current + 1;
898 }
899 else
900 {
901 tmp = CurArea.current + 1;
902 lastfound = 0;
903 strcpy(patstr, prompt);
904 bmg_setsearch(prompt);
905 }
906
907 for (; tmp <= CurArea.messages; tmp++)
908 {
909 /* check for event here */
910
911 if (done == TRUE || (KeyHit() && (chkkey = GetKey()) == Key_Esc))
912 {
913 break;
914 }
915
916 l = NULL;
917
918 if ((m = readmsg(tmp)) != NULL)
919 {
920 sprintf(tempstr, "Area: %s", CurArea.tag);
921
922 if ((long)arealist[SW->area].messages != (long)arealist[SW->area].lastread)
923 {
924 SendMsgWnd(tempstr, 1);
925 }
926
927 sprintf(tempstr, "Reading message #%ld of #%ld", tmp, CurArea.messages);
928
929 if ((long)arealist[SW->area].messages != (long)arealist[SW->area].lastread)
930 {
931 SendMsgWnd(tempstr, 2);
932 }
933
934 bmg_setsearch(username);
935 if (bmg_search(m->isto) != NULL)
936 {
937 done = TRUE;
938 break;
939 }
940
941 if (done == TRUE)
942 {
943 break;
944 }
945
946 dispose(m);
947 m = NULL;
948 }
949 }
950
951 if ((long)arealist[SW->area].messages != (long)arealist[SW->area].lastread)
952 {
953 CloseMsgWnd();
954 }
955
956 set_rcvd = 1; /* readmsg() is now free to set it */
957
958 if (done)
959 {
960 CurArea.current = tmp;
961 lastfound = tmp;
962 oldmsg = tmp;
963 message = m;
964
965 ShowMsgHeader(message);
966
967 if (l != NULL)
968 {
969 l->block = TRUE;
970 RefreshMsg(l, 6);
971 }
972 else
973 {
974 RefreshMsg(message->text, 6);
975 }
976 }
977 else
978 {
979 dispose(m);
980 pm_next_area();
981 if (SW->grouparea != firstarea && chkkey != Key_Esc)
982 {
983 again = 1;
984 }
985 else
986 {
987 set_area(firstarea);
988 SetupArea();
989 firstarea = 0;
990 x = -1;
991 }
992 }
993 }
994 }
995
gotomsg0(void)996 static void gotomsg0(void)
997 {
998 gotomsg(0L);
999 }
1000
1001 /* confirm - Ask if the user is doing something on purpose (Never! :-) */
1002
confirm(char * option)1003 int confirm(char *option) /* Allows more meaningful confirm messages */
1004 {
1005 if (!SW->confirmations)
1006 {
1007 return TRUE;
1008 }
1009 return ChoiceBox("", option, "Yes", "No", NULL) == ID_ONE ? TRUE : FALSE;
1010 }
1011
1012 /* SetupArea - Sets up the operating vars for the current area */
1013
SetupArea(void)1014 void SetupArea(void)
1015 {
1016 lastfound = 0;
1017 direction = RIGHT;
1018 back = CurArea.current;
1019 root = CurArea.current;
1020 areastart = CurArea.current;
1021
1022 /*
1023 * Set this area up with it's info: The template, The username,
1024 * lastread (fido areas) name, useroffset (squish areas).
1025 */
1026
1027 if (SW->areadefinesuser)
1028 {
1029 release(ST->username);
1030 release(ST->template);
1031 release(ST->lastread);
1032
1033 ST->username = xstrdup(user_list[CurArea.username].name);
1034 SW->useroffset = user_list[CurArea.username].offset;
1035 ST->lastread = xstrdup(user_list[CurArea.username].lastread);
1036 }
1037
1038 if (templates != NULL)
1039 {
1040 ST->template = xstrdup(templates[CurArea.template]);
1041 }
1042 }
1043
1044
set_area_backend(int show_all,int newgrouparea,int newarea)1045 static void set_area_backend(int show_all, int newgrouparea, int newarea)
1046 {
1047 int done = 0;
1048 int ret;
1049 int temp;
1050
1051 if (CurArea.status) /* close current area, if open */
1052 {
1053 highest();
1054 AreaSetLast(&CurArea);
1055 MsgAreaClose();
1056 }
1057 message = KillMsg(message);
1058 SW->area = newarea;
1059 if (!show_all)
1060 {
1061 SW->grouparea = newgrouparea;
1062 }
1063
1064 while (!CurArea.status && !done)
1065 {
1066 CurArea.messages = MsgAreaOpen(&CurArea);
1067
1068 if (!CurArea.status)
1069 {
1070 ret = ChoiceBox(" Error ", "Error opening area;", "Retry",
1071 "New area", "Cancel");
1072
1073 switch (ret)
1074 {
1075 case ID_TWO: /* UH, OH, FIXME! */
1076 temp = SW->grouparea;
1077 temp = selectarea("Pic New Area", temp);
1078 SW->grouparea = temp;
1079 SW->area = group_getareano(temp);
1080 break;
1081
1082 case ID_THREE:
1083 done = TRUE;
1084 break;
1085
1086 default:
1087 break;
1088 }
1089 }
1090 else
1091 {
1092 done = TRUE;
1093 }
1094 }
1095 ShowNewArea(); /* display the new area */
1096 }
1097
1098
1099
1100 /* set_area - Opens a new area & sets all the vars */
1101
set_area(int newgrouparea)1102 void set_area(int newgrouparea)
1103 {
1104
1105 set_area_backend(0, newgrouparea, group_getareano(newgrouparea));
1106 }
1107
set_nongrouped_area(int newarea)1108 void set_nongrouped_area(int newarea)
1109 {
1110 set_area_backend(1, 0, newarea);
1111 }
1112
1113
1114 /*
1115 * Scans all the areas for new mail, calling scan_areas(), but is
1116 * callable from other modules.
1117 */
1118
area_scan(int all)1119 void area_scan(int all)
1120 {
1121 scan_areas(all);
1122 }
1123
1124 /*
1125 * Scans all the areas for new mail, calling al_scan_areas(), but is
1126 * callable from other modules. Calls from Arealist.
1127 */
1128
arealist_area_scan(int all)1129 void arealist_area_scan(int all)
1130 {
1131 al_scan_areas(all);
1132 }
1133
1134 /*
1135 * void ...(void) wrapper functions for void scan_areas(int)
1136 */
1137
scan_all_areas(void)1138 void scan_all_areas(void)
1139 {
1140 scan_areas(1);
1141 }
1142
scan_unscanned_areas(void)1143 void scan_unscanned_areas(void)
1144 {
1145 scan_areas(0);
1146 }
1147
1148 /*
1149 * Scans all the areas for new messages. Saves the current area and
1150 * returns to it.
1151 * Parameter: int all: =1: scan all areas, =0: scan unscanned areas
1152 */
1153
scan_areas(int all)1154 static void scan_areas(int all)
1155 {
1156 char line[255];
1157 char temp[20];
1158 int a, ga;
1159 int l;
1160 int x,y;
1161
1162 TTgetxy(&x,&y);
1163
1164 a = SW->area; ga = SW->grouparea;
1165 l = strlen(PROG) + strlen(VERNUM VERPATCH);
1166 if (!SW->dmore)
1167 {
1168 l += sprintf(temp, "%ld of %ld", CurArea.current, CurArea.messages);
1169 }
1170
1171 if (!SW->statbar)
1172 {
1173 if (!OpenMsgWnd(50, 6, " Scanning areas for new messages ", NULL, 0, 0))
1174 {
1175 return;
1176 }
1177 SendMsgWnd("Press Esc to stop", 0);
1178 }
1179
1180 if (CurArea.status)
1181 {
1182 highest();
1183 AreaSetLast(&CurArea);
1184 MsgAreaClose();
1185 }
1186
1187 if (all) /* reset the "scanned" flag of all areas */
1188 {
1189 for (SW->grouparea = 0; SW->grouparea < SW->groupareas;
1190 SW->grouparea++)
1191 {
1192 if (group_getareano(SW->grouparea) >= 0)
1193 arealist[group_getareano(SW->grouparea)].scanned = 0;
1194 }
1195 }
1196
1197
1198 for (SW->grouparea = 0; SW->grouparea < SW->groupareas; SW->grouparea++)
1199 {
1200 SW->area = group_getareano(SW->grouparea);
1201 if (SW->area < 0 || ((!all) && (arealist[SW->area].scanned)))
1202 {
1203 continue;
1204 }
1205
1206 if (SW->statbar)
1207 {
1208 TTBeginOutput();
1209 sprintf(line, "%.40s", CurArea.description);
1210 if (!SW->dmore)
1211 {
1212 line[maxx - l - 20] = '\0';
1213
1214 WndPutsn(l + 9, maxy - 1, maxx - l - 10, cm[CM_ITXT], "Scanning:");
1215 WndWriteStr(l + 19, maxy - 1, cm[CM_ITXT], line);
1216 }
1217 else
1218 {
1219 line[79 - strlen(PROG) -
1220 strlen(VERNUM VERPATCH) - 16] = '\0';
1221
1222 WndPutsn(l + 6, maxy - 1, maxx - l - 7, cm[CM_ITXT], "Scanning:");
1223 WndWriteStr(l + 16, maxy - 1, cm[CM_ITXT], line);
1224 }
1225 TTEndOutput();
1226 }
1227 else
1228 {
1229 sprintf(line, "%.40s", CurArea.description);
1230 SendMsgWnd(line, 1);
1231 }
1232
1233 if (KeyHit() && GetKey() == Key_Esc)
1234 {
1235 break;
1236 }
1237
1238 CurArea.messages = MsgAreaOpen(&CurArea);
1239
1240 if (CurArea.status)
1241 {
1242 MsgAreaClose();
1243 }
1244 }
1245
1246 TTBeginOutput();
1247
1248 if (!SW->statbar)
1249 {
1250 CloseMsgWnd();
1251 }
1252
1253 SW->area = a;
1254 SW->grouparea = ga;
1255 CurArea.messages = MsgAreaOpen(&CurArea);
1256 if (SW->statbar)
1257 {
1258 if (!SW->dmore)
1259 {
1260 WndPutsn(l + 9, maxy - 1, maxx - l - 10, cm[CM_ITXT], " ");
1261 }
1262 else
1263 {
1264 WndPutsn(l + 6, maxy - 1, maxx - l - 7, cm[CM_ITXT], " ");
1265 }
1266 }
1267
1268 #if defined(MSDOS) && !defined(__FLAT__)
1269 if (SW->statbar)
1270 {
1271 sprintf(line, "%c %3ldK ", SC7, (long)(corerem() / 1024));
1272 WndPutsn(maxx - 7, maxy - 1, 1, cm[CM_ITXT] | F_ALTERNATE, line + 1);
1273 WndPutsn(maxx - 6, maxy - 1, 6, cm[CM_ITXT], line + 1);
1274 }
1275 #endif
1276
1277 if (SW->statbar && !SW->dmore)
1278 {
1279 int l;
1280
1281 sprintf(line, "%ld of %ld %c", CurArea.current, CurArea.messages, SC7);
1282 l = strlen(line);
1283
1284 WndPutsn((strlen(PROG) + strlen(VERNUM VERPATCH) + 6),
1285 maxy - 1, l - 1, cm[CM_ITXT], line);
1286 WndPutsn((strlen(PROG) + strlen(VERNUM VERPATCH) + 6 + l - 1),
1287 maxy - 1, 18 - (l - 1), cm[CM_ITXT] | F_ALTERNATE,
1288 line + l - 1);
1289 }
1290 TTgotoxy(x,y);
1291
1292 TTEndOutput();
1293 }
1294
1295 /*
1296 * Scans all areas for new messages, from Arealist screen. Saves the
1297 * current area and returns to it.
1298 */
1299
al_scan_areas(int all)1300 static void al_scan_areas(int all)
1301 {
1302 char line[255];
1303 int a = SW->area;
1304 int ga = SW->grouparea;
1305
1306 if (!OpenMsgWnd(50, 6, " Scanning areas for new messages ", NULL, 0, 0))
1307 {
1308 return;
1309 }
1310
1311 SendMsgWnd("Press Esc to stop", 0);
1312
1313 if (CurArea.status)
1314 {
1315 highest();
1316 AreaSetLast(&CurArea);
1317 MsgAreaClose();
1318 }
1319
1320 if (all)
1321 {
1322 for (SW->grouparea = 0; SW->grouparea < SW->groupareas;
1323 SW->grouparea++)
1324 {
1325 if (group_getareano(SW->grouparea) >= 0)
1326 arealist[group_getareano(SW->grouparea)].scanned = 0;
1327 }
1328 }
1329
1330 for (SW->grouparea = 0; SW->grouparea < SW->groupareas; SW->grouparea++)
1331 {
1332 SW->area = group_getareano(SW->grouparea);
1333
1334 if (SW->area < 0 || ((!all) && arealist[SW->area].scanned))
1335 {
1336 continue;
1337 }
1338
1339 sprintf(line, "%.40s", CurArea.description);
1340 SendMsgWnd(line, 1);
1341
1342 if (KeyHit() && GetKey() == Key_Esc)
1343 {
1344 break;
1345 }
1346
1347
1348 CurArea.messages = MsgAreaOpen(&CurArea);
1349
1350 if (CurArea.status)
1351 {
1352 MsgAreaClose();
1353 }
1354
1355 }
1356 CloseMsgWnd();
1357 SW->area = a;
1358 SW->grouparea = ga;
1359 }
1360
1361 /* next_area - goes to the next area with unread messages */
1362
next_area(void)1363 static void next_area(void)
1364 {
1365 int NewArea;
1366 int OldArea;
1367
1368 if (SW->groupareas < 2)
1369 {
1370 return;
1371 }
1372
1373 OldArea = SW->grouparea;
1374
1375 do
1376 {
1377 NewArea = (SW->grouparea + 1) % SW->groupareas;
1378 } while (group_getareano(NewArea) < 0);
1379
1380 while (((long)arealist[group_getareano(NewArea)].messages <=
1381 (long)arealist[group_getareano(NewArea)].lastread) &&
1382 arealist[group_getareano(NewArea)].scanned)
1383 {
1384 NewArea = (NewArea + 1) % SW->groupareas;
1385 if (NewArea == OldArea)
1386 {
1387 ChoiceBox(" Notice ", "There are no more unread messages in this area", "Ok", NULL, NULL);
1388 break;
1389 }
1390 }
1391
1392 set_area(NewArea);
1393 SetupArea();
1394 }
1395
pm_next_area(void)1396 static void pm_next_area(void)
1397 {
1398 int NewArea;
1399
1400 if (SW->groupareas < 2)
1401 {
1402 return;
1403 }
1404
1405 NewArea = SW->grouparea;
1406 do
1407 {
1408 /* prevent group separators from being selected */
1409 NewArea = (NewArea + 1) % SW->groupareas;
1410 } while (group_getareano(NewArea) < 0);
1411 set_area(NewArea);
1412 SetupArea();
1413 }
1414
1415 /* prev_area - goes to the previous area with unread messages */
1416
prev_area(void)1417 static void prev_area(void)
1418 {
1419 int OldArea;
1420 int NewArea;
1421
1422 if (SW->groupareas < 2)
1423 {
1424 return;
1425 }
1426
1427 OldArea = SW->grouparea;
1428 NewArea = SW->grouparea;
1429
1430 do
1431 {
1432 NewArea--;
1433 NewArea = (NewArea < 0) ? SW->groupareas - 1 : NewArea;
1434 } while (group_getareano(NewArea)< 0);
1435
1436 while ((((long)arealist[group_getareano(NewArea)].messages -
1437 (long)arealist[group_getareano(NewArea)].lastread) <= 0) &&
1438 arealist[group_getareano(NewArea)].scanned)
1439 {
1440 NewArea--;
1441 NewArea = (NewArea < 0) ? SW->groupareas - 1 : NewArea;
1442 if (NewArea == OldArea)
1443 {
1444 NewArea--;
1445 NewArea = (NewArea < 0) ? SW->groupareas - 1 : NewArea;
1446 break;
1447 }
1448 }
1449
1450 set_area(NewArea);
1451 SetupArea();
1452 }
1453
1454 /* highest - sets the higest read message */
1455
highest(void)1456 static void highest(void)
1457 {
1458 CurArea.lastread = min(CurArea.current, CurArea.messages);
1459 root = CurArea.current;
1460 }
1461
1462 /* left - goes one message to the left */
1463
left(void)1464 static void left(void)
1465 {
1466 direction = LEFT;
1467 if (CurArea.current > 1)
1468 {
1469 CurArea.current--;
1470 }
1471 root = CurArea.current;
1472 }
1473
1474 /* right - goes one message to the right */
1475
right(void)1476 static void right(void)
1477 {
1478 direction = RIGHT;
1479 if (CurArea.current < CurArea.messages)
1480 {
1481 CurArea.current++;
1482 }
1483 else if (SW->rightnextunreadarea)
1484 {
1485 next_area();
1486 }
1487 highest();
1488 }
1489
1490 /*
1491 * Gets a number from the user and goes to that message
1492 * number (if valid).
1493 */
1494
gotomsg(unsigned long i)1495 static void gotomsg(unsigned long i)
1496 {
1497 EVT e;
1498 WND *hWnd, *hCurr;
1499 char buf[10];
1500 int done = 0;
1501 int disp = 1;
1502 int ret;
1503 int pos;
1504
1505 TTBeginOutput();
1506
1507 hCurr = WndTop();
1508 hWnd = WndPopUp(30, 6, INSBDR | SHADOW, cm[IP_BTXT], cm[IP_NTXT]);
1509 WndTitle(" Jump to Message ", cm[IP_NTXT]);
1510 WndWriteStr(1, 1, cm[IP_NTXT], "Message #");
1511
1512 TTEndOutput();
1513
1514 if (i != 0)
1515 {
1516 sprintf(buf, "%lu", i);
1517 }
1518 else
1519 {
1520 strcpy(buf, "");
1521 }
1522 pos = strlen(buf);
1523
1524 while (!done)
1525 {
1526 ret = WndGetLine(17, 1, 6, buf, cm[IP_ETXT], &pos, 0, 0, disp, &e);
1527 switch (e.msgtype)
1528 {
1529 case WND_WM_CHAR:
1530 switch (ret)
1531 {
1532 case Key_Ent:
1533 i = atoi(buf);
1534
1535 if (i == 0)
1536 {
1537 done = 1;
1538 i = CurArea.current;
1539 }
1540 else
1541 {
1542 if (i > 0 && i <= CurArea.messages)
1543 {
1544 done = 1;
1545 }
1546 }
1547 break;
1548
1549 case Key_Esc:
1550 done = 1;
1551 i = CurArea.current;
1552 break;
1553
1554 default:
1555 break;
1556 }
1557 break;
1558
1559 default:
1560 break;
1561 }
1562 disp = 0;
1563 }
1564 WndClose(hWnd);
1565 WndCurr(hCurr);
1566 CurArea.current = i;
1567 highest();
1568 }
1569
1570 /* newarea - gets a new area from the user and goes to it */
1571
newarea(void)1572 static int newarea(void)
1573 {
1574 int new;
1575
1576 new = mainArea();
1577
1578 if (new >= 0)
1579 {
1580 if (CurArea.status)
1581 {
1582 highest();
1583 AreaSetLast(&CurArea);
1584 MsgAreaClose();
1585 }
1586 set_area(new);
1587 SetupArea();
1588 }
1589
1590 return new;
1591 }
1592
1593 /* start - begins reading the initial configuration file */
1594
start(char * cfg,char * afn)1595 static int start(char *cfg, char *afn)
1596 {
1597 opening(cfg, afn);
1598 SW->grouparea = -1;
1599
1600 do
1601 {
1602 /* don't allow a separator to be come current area */
1603 SW->area = group_getareano(++(SW->grouparea));
1604 } while (SW->area < 0);
1605
1606 message = NULL;
1607 return 0;
1608 }
1609
1610 /* go_last - goes to the highest-read message in the msgbase */
1611
go_last(void)1612 static void go_last(void)
1613 {
1614 CurArea.current = min(CurArea.lastread, CurArea.messages);
1615 root = CurArea.current;
1616 }
1617
1618 /* slast - goes to the very last msg in the msgbase */
1619
slast(void)1620 static void slast(void)
1621 {
1622 CurArea.current = CurArea.messages;
1623 highest();
1624 }
1625
1626 /* astart - goes to the first read msg in the msgbase (for this session) */
1627
astart(void)1628 static void astart(void)
1629 {
1630 CurArea.current = min(areastart, CurArea.messages);
1631 highest();
1632 }
1633
1634 /* link_from - goes to the message that the current message is a reply to */
1635
link_from(void)1636 static void link_from(void)
1637 {
1638 if (!message || !message->replyto)
1639 {
1640 return;
1641 }
1642
1643 CurArea.current = message->replyto;
1644 }
1645
1646 /* view - toggles the showing of hidden information */
1647
view(void)1648 static void view(void)
1649 {
1650 SW->shownotes = !SW->shownotes;
1651 message = KillMsg(message);
1652 }
1653
1654 /*
1655 * Links up the msgbase, putting up a small menu if there is more
1656 * than one thread to go to. Quite complicated.
1657 */
1658
link_to(void)1659 static void link_to(void)
1660 {
1661 msg *m;
1662 unsigned long cnt, k = 0;
1663 char txtbuf[40];
1664 char *replies[11];
1665
1666 if (!message)
1667 {
1668 return;
1669 }
1670
1671 for (cnt = 0; cnt < 10; cnt++)
1672 {
1673 if (message->replies[(size_t) cnt] != 0)
1674 {
1675 k++;
1676 }
1677 }
1678 if (k < 1)
1679 {
1680 return;
1681 }
1682 else
1683 {
1684 if (k == 1)
1685 {
1686 for (cnt = 0; cnt <= 10; cnt++)
1687 {
1688 if (message->replies[(size_t) cnt] != 0)
1689 {
1690 break;
1691 }
1692 }
1693 CurArea.current = message->replies[(size_t) cnt];
1694 CurArea.lastread = max(CurArea.lastread, CurArea.current);
1695 return;
1696 }
1697 }
1698
1699 k = 0;
1700 for (cnt = 0; cnt < 10; cnt++)
1701 {
1702 if (message->replies[(size_t) cnt] != 0)
1703 {
1704 if ((m = MsgReadHeader(message->replies[(size_t) cnt],
1705 RD_HEADER)) != NULL)
1706 {
1707 sprintf(txtbuf, "%5ld : %.22s", message->replies[(size_t) cnt],
1708 m->isfrom);
1709
1710 replies[(size_t) k++] = xstrdup(txtbuf);
1711
1712 KillMsg(m);
1713 }
1714 }
1715 }
1716
1717 replies[(size_t) k] = NULL;
1718
1719 cnt = DoMenu(maxx - 43, 9, maxx - 6, 9 + (int)k - 1, replies, 0, SELBOX_LINKTO, "");
1720
1721 if (cnt != (unsigned long)-1)
1722 {
1723 CurArea.current = atoi(replies[(size_t) cnt]);
1724 CurArea.lastread = max(CurArea.lastread, CurArea.current);
1725 }
1726
1727 for (k = 0; k < 10; k++)
1728 {
1729 if (replies[(size_t) k] == NULL)
1730 {
1731 break;
1732 }
1733 xfree(replies[(size_t) k]);
1734 }
1735 }
1736
1737 /*
1738 * go_next; Does the same as above but ignores all but the first reply
1739 * chain.
1740 */
1741
go_next(void)1742 static void go_next(void)
1743 {
1744 if (!message || !message->replies[0])
1745 {
1746 return;
1747 }
1748
1749 back = CurArea.current;
1750 CurArea.current = message->replies[0];
1751 CurArea.lastread = max(CurArea.lastread, CurArea.current);
1752 }
1753
1754 /*
1755 * Goes to the first msg in a reply chain (you must have navigated
1756 * through it already).
1757 */
1758
go_root()1759 static void go_root()
1760 {
1761 back = CurArea.current;
1762 CurArea.current = root;
1763 highest();
1764 }
1765
1766 /* go_back - goes back to where you were in the reply chain (untested) */
1767
go_back()1768 static void go_back()
1769 {
1770 CurArea.current = back;
1771 highest();
1772 }
1773
1774 /* rotate - Sets the ROT13 char */
1775
rotate()1776 static void rotate()
1777 {
1778 rot13 = (rot13 + 1) % 3;
1779 message = KillMsg(message);
1780 }
1781
shell_to_dos(void)1782 void shell_to_dos(void)
1783 {
1784 #if defined(MSDOS) && !defined(NODOSSWAP) && !defined(__FLAT__)
1785 int rc;
1786 char swapfn[PATHLEN];
1787 char **envp = environ, **env, *envbuf, *envptr, *ep;
1788 int swapping = USE_ALL | HIDE_FILE | DONT_SWAP_ENV;
1789 int envlen = 0;
1790
1791 if (envp != NULL)
1792 {
1793 for (env = envp; *env != NULL; env++)
1794 {
1795 envlen += strlen(*env) + 1;
1796 }
1797 }
1798
1799 if (envlen)
1800 {
1801 envlen = (envlen + 32) & 0xfff0;
1802 envbuf = xmalloc(envlen);
1803 envptr = envbuf;
1804
1805 if (FP_OFF(envptr) & 0x0f)
1806 {
1807 envptr += 16 - (FP_OFF(envptr) & 0x0f);
1808 }
1809
1810 ep = envptr;
1811
1812 for (env = envp; *env != NULL; env++)
1813 {
1814 strcpy(ep, *env);
1815 ep = ep + strlen(*env) + 1;
1816 }
1817 *ep = 0;
1818 }
1819 if (ST->swap_path)
1820 {
1821 sprintf(swapfn, "%s\\%s", ST->swap_path, SWAP_FILENAME);
1822 }
1823 else
1824 {
1825 strcpy(swapfn, SWAP_FILENAME);
1826 }
1827
1828 rc = prep_swap(swapping, swapfn);
1829
1830 if (rc > -1)
1831 {
1832 rc = do_spawn(swapping, ST->comspec, "", envlen, envptr);
1833 }
1834 else
1835 {
1836 fprintf(stderr, "\nError occured during do_spawn(); rc=%d. Press Enter to return...", rc);
1837 while (GetKey() != 13)
1838 {
1839 }
1840 }
1841 #elif defined(PACIFIC)
1842 spawnl(ST->comspec, NULL);
1843 #elif defined(UNIX)
1844 system(ST->comspec);
1845 #elif defined(__FLAT__) || defined(OS2)
1846 spawnl(0, ST->comspec, ST->comspec, NULL);
1847 #else
1848 system("");
1849 #endif
1850 }
1851
go_dos(void)1852 static void go_dos(void)
1853 {
1854 char tmp[PATHLEN];
1855
1856 mygetcwd(tmp, PATHLEN);
1857 setcwd(ST->home);
1858 WndClose(hMnScr);
1859 KillHotSpots();
1860 TTgotoxy(term.NRow - 1, 0);
1861 TTclose();
1862 cursor(1);
1863 fputs("\nEnter the command \"EXIT\" to return to " PROG ".\n", stderr);
1864 shell_to_dos();
1865 cursor(0);
1866 InitScreen();
1867 BuildHotSpots();
1868 DrawHeader();
1869 ShowNewArea();
1870 message = KillMsg(message);
1871 cursor(0);
1872 setcwd(tmp);
1873 }
1874
rundos(void)1875 static void rundos(void)
1876 {
1877 WND *hCurr, *hWnd;
1878 char curdir[PATHLEN];
1879 char cmd[64], tmp[40];
1880 int ret;
1881
1882 mygetcwd(curdir, PATHLEN);
1883 memset(cmd, 0, sizeof cmd);
1884
1885 #if defined(MSDOS)
1886 if (!GetString(" System Command ", "Enter DOS command to execute:", cmd, 64))
1887 {
1888 return;
1889 }
1890 #elif defined(OS2)
1891 if (!GetString(" System Command ", "Enter OS/2 command to execute:", cmd, 64))
1892 {
1893 return;
1894 }
1895 #else
1896 if (!GetString(" System Command ", "Enter system command to execute:", cmd, 64))
1897 {
1898 return;
1899 }
1900 #endif
1901
1902 if (cmd[0] == '\0')
1903 {
1904 strcpy(cmd, ST->comspec);
1905 }
1906
1907 hCurr = WndTop();
1908 hWnd = WndOpen(0, 0, maxx - 1, maxy - 1, NBDR, 0, cm[CM_NTXT]);
1909
1910 cursor(1);
1911 ret = system(cmd);
1912 cursor(0);
1913
1914 #if defined(MSDOS)
1915 sprintf(tmp, "DOS command returned %d", ret);
1916 #elif defined(OS2)
1917 sprintf(tmp, "OS/2 command returned %d", ret);
1918 #else
1919 sprintf(tmp, "System command returned %d", ret);
1920 #endif
1921 ChoiceBox(" Info ", tmp, " Ok ", NULL, NULL);
1922
1923 WndClose(hWnd);
1924 WndCurr(hCurr);
1925 setcwd(curdir);
1926 message = KillMsg(message);
1927 }
1928
nada(void)1929 static void nada(void)
1930 {
1931 /* do nothing */
1932 }
1933
dolist(void)1934 void dolist(void)
1935 {
1936 if (SW->direct_list)
1937 endMain = 1;
1938 else
1939 {
1940 if (message != NULL)
1941 {
1942 do_list();
1943 ClearScreen();
1944 DrawHeader();
1945 ShowNewArea();
1946 }
1947 }
1948 }
1949
list(void)1950 static void list(void)
1951 {
1952 dolist();
1953 }
1954
CKey(int ch)1955 int CKey(int ch)
1956 {
1957 return ((int)ConvertKey(ch));
1958 }
1959
show_usage(void)1960 void show_usage(void)
1961 {
1962 printf(
1963 "%-30s; %s\n"
1964 "-------------------------------------------------------------------------------\n"
1965 "\n"
1966 "Usage: MSGED [options]\n"
1967 "\n"
1968 "-a<areafile> Use <areafile> instead of SQUISH.CFG.\n"
1969 "-c<configfile> Use <configfile> instead of MSGED.CFG.\n"
1970 "-I Display debug information at startup, then exit.\n"
1971 "-? Display this help.\n"
1972 "-h Display this help.\n"
1973 "-hc <source> <target> Compile help file.\n"
1974 "-hi <source> Decompile compiled help file.\n"
1975 "-k Display keyboard scan codes.\n",
1976 PROG " " VERPROJECT " " VERNUM VERPATCH VERBRANCH "; Mail Reader",
1977 "Compiled on " __DATE__ " at " __TIME__
1978 );
1979 }
1980
1981 int cmd_dbginfo = 0;
1982 int cmd_usage = 0;
1983 int cmd_helpcmp = 0;
1984 int cmd_helpinfo = 0;
1985 int cmd_keycode = 0;
1986 static char cmd_cfgfnm[250];
1987 static char cmd_areafnm[250];
1988
1989 opt_t opttable[] =
1990 {
1991 {"?", OPTBOOL, &cmd_usage},
1992 {"i", OPTBOOL, &cmd_dbginfo},
1993 {"I", OPTBOOL, &cmd_dbginfo},
1994 {"hc", OPTBOOL, &cmd_helpcmp},
1995 {"HC", OPTBOOL, &cmd_helpcmp},
1996 {"hi", OPTBOOL, &cmd_helpinfo},
1997 {"HI", OPTBOOL, &cmd_helpinfo},
1998 {"h", OPTBOOL, &cmd_usage},
1999 {"H", OPTBOOL, &cmd_usage},
2000 {"k", OPTBOOL, &cmd_keycode},
2001 {"K", OPTBOOL, &cmd_keycode},
2002 {"c", OPTSTR, cmd_cfgfnm},
2003 {"C", OPTSTR, cmd_cfgfnm},
2004 {"a", OPTSTR, cmd_areafnm},
2005 {"A", OPTSTR, cmd_areafnm},
2006 {NULL, 0, NULL}
2007 };
2008
message_reading_mode(void)2009 static void message_reading_mode(void)
2010 {
2011 EVT event;
2012 int newmsg;
2013
2014 if (window_resized)
2015 {
2016 window_resized = 0; /* ack! */
2017 WndClose(hMnScr);
2018 KillHotSpots();
2019 TTclose();
2020 InitScreen();
2021 adapt_margins();
2022 BuildHotSpots();
2023 ShowNewArea();
2024 }
2025
2026 DrawHeader();
2027
2028 endMain = 0;
2029 message = KillMsg(message);
2030 message = readmsg(CurArea.current);
2031
2032 if (!CurArea.status || message == NULL || !CurArea.messages)
2033 {
2034 ClearMsgScreen();
2035 ShowMsgHeader(message);
2036 ChoiceBox(" Notice ", "There are no messages stored in this area", " Ok ", NULL, NULL);
2037 }
2038
2039 newmsg = 1;
2040
2041 while (!endMain)
2042 {
2043
2044 if (!CurArea.messages || newmsg || !CurArea.status || message == NULL)
2045 {
2046 TTBeginOutput();
2047
2048 if (!CurArea.status || message == NULL || !CurArea.messages)
2049 {
2050 ClearMsgScreen();
2051 }
2052
2053 ShowMsgHeader(message);
2054
2055 newmsg = 0;
2056
2057 if (message != NULL)
2058 {
2059 RefreshMsg(message->text, 6);
2060 }
2061
2062 TTEndOutput();
2063 }
2064
2065 oldmsg = CurArea.current;
2066 command = MnuGetMsg(&event, hMnScr->wid);
2067 switch (event.msgtype)
2068 {
2069 case WND_WM_RESIZE:
2070 window_resized = 1; /* we'll exit to redraw the
2071 screen */
2072 break;
2073
2074 case WND_WM_COMMAND:
2075 switch (command)
2076 {
2077 case LMOU_CLCK:
2078 switch (event.id)
2079 {
2080 case ID_LNDN:
2081 link_from();
2082 break;
2083
2084 case ID_LNUP:
2085 link_to();
2086 break;
2087
2088 default:
2089 break;
2090 }
2091 break;
2092
2093 case MOU_LBTDN:
2094 case LMOU_RPT:
2095 switch (event.id)
2096 {
2097 case ID_SCRUP:
2098 Go_Up();
2099 break;
2100
2101 case ID_SCRDN:
2102 Go_Dwn();
2103 break;
2104
2105 case ID_MGLFT:
2106 left();
2107 break;
2108
2109 case ID_MGRGT:
2110 right();
2111 break;
2112
2113 default:
2114 break;
2115 }
2116 break;
2117
2118 default:
2119 break;
2120 }
2121 break;
2122
2123 case WND_WM_MOUSE:
2124 switch (command)
2125 {
2126 case MOU_LBTDN:
2127 if (event.x >= (maxx - MNU_LEN - 1) && event.y == 0)
2128 {
2129 command = ProcessMenu(&MouseMnu, &event, 0);
2130 }
2131
2132 if (command == ID_QUIT)
2133 {
2134 quit();
2135 }
2136 break;
2137
2138 default:
2139 break;
2140 }
2141 break;
2142
2143 case WND_WM_CHAR:
2144 switch (command)
2145 {
2146 case Key_PgUp:
2147 Go_PgUp();
2148 break;
2149
2150 case Key_PgDn:
2151 case Key_Spc:
2152 Go_PgDwn();
2153 break;
2154
2155 case Key_Up:
2156 Go_Up();
2157 break;
2158
2159 case Key_Dwn:
2160 Go_Dwn();
2161 break;
2162
2163 default:
2164 if (command & 0xff)
2165 {
2166 if (isdigit(command & 0xff))
2167 {
2168 gotomsg((command & 0xff)- 0x30);
2169 }
2170 else
2171 {
2172 if (mainckeys[command & 0xff])
2173 {
2174 (*mainckeys[command & 0xff]) ();
2175 }
2176 }
2177 }
2178 else
2179 {
2180 if (mainakeys[command >> 8])
2181 {
2182 (*mainakeys[command >> 8]) ();
2183 }
2184 }
2185 break;
2186 }
2187 break;
2188 }
2189
2190 if (window_resized && endMain == 0) endMain = 2;
2191
2192 if (CurArea.messages > 0 &&
2193 (!message || oldmsg != CurArea.current || CurArea.current == 0))
2194 {
2195 message = KillMsg(message);
2196 if (CurArea.current == 0)
2197 {
2198 CurArea.current = 1;
2199 }
2200 if (CurArea.status)
2201 {
2202 message = readmsg(CurArea.current);
2203 newmsg = 1;
2204 }
2205 }
2206 }
2207 }
2208
2209
main(int argc,char * argv[])2210 int main(int argc, char *argv[])
2211 {
2212 int optup;
2213
2214 optup = getopts(argc, argv, opttable);
2215 if (cmd_keycode || cmd_helpcmp || cmd_helpinfo || cmd_usage)
2216 {
2217 if (cmd_usage)
2218 {
2219 show_usage();
2220 }
2221 else if (cmd_keycode)
2222 {
2223 keycode();
2224 }
2225 else if (cmd_helpcmp)
2226 {
2227 helpcmp(argc - optup + 1, &argv[optup - 1]);
2228 }
2229 else if (cmd_helpinfo)
2230 {
2231 helpinfo(argc - optup + 1, &argv[optup - 1]);
2232 }
2233 return (0);
2234 }
2235
2236 #ifdef USE_CRITICAL
2237 /* Removed by cleanup() */
2238 install24h();
2239 #endif
2240
2241 #if !defined(PACIFIC) && !defined(__MINGW32__)
2242 tzset();
2243 #endif
2244
2245 randomize();
2246
2247 #ifdef USE_MSGAPI
2248 MsgApiInit();
2249 #endif
2250
2251 if (*cmd_cfgfnm && *cmd_areafnm)
2252 {
2253 command = start(cmd_cfgfnm, cmd_areafnm);
2254 }
2255 else if (*cmd_cfgfnm)
2256 {
2257 command = start(cmd_cfgfnm, NULL);
2258 }
2259 else if (*cmd_areafnm)
2260 {
2261 command = start(NULL, cmd_areafnm);
2262 }
2263 else
2264 {
2265 command = start(NULL, NULL);
2266 }
2267
2268 if (ST->helpfile)
2269 {
2270 HelpInit(ST->helpfile);
2271 }
2272
2273 BuildHotSpots();
2274 if (scan)
2275 {
2276 arealist_area_scan(1);
2277 }
2278 /* DrawHeader(); */
2279 RegisterKeyProc(CKey); /* to allow for macros in the system */
2280
2281 while (endMain == 2 || newarea() >= 0)
2282 {
2283 if (SW->direct_list)
2284 {
2285 while (do_list())
2286 {
2287 message_reading_mode();
2288 }
2289 }
2290 else
2291 {
2292 message_reading_mode();
2293 }
2294
2295 if (CurArea.status && endMain != 2)
2296 {
2297 highest();
2298 AreaSetLast(&CurArea);
2299 MsgAreaClose();
2300 }
2301 }
2302
2303 cleanup(NULL);
2304 return errorlevel;
2305 }
2306
2307