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