home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / BBS / NETMAIL / MSGD2SRC.ZIP / MSGED.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-09  |  19.1 KB  |  1,045 lines

  1. /*
  2.  
  3. Title:    MsgEd
  4.  
  5. File:    Msged.c
  6.  
  7. Author: Jim Nutt
  8.  
  9. Copr:    released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
  10.  
  11. Description:
  12.  
  13.     Small, fast fido message editor.
  14.  
  15. Support Files:
  16.  
  17.     msged.h
  18.  
  19. */
  20.  
  21. #define MAIN
  22.  
  23. #include "msged.h"
  24. #include "maincmds.h"
  25. #include "bmg.h"
  26.  
  27. #include <process.h>
  28.  
  29. #if defined(__TURBOC__)
  30. #include <dir.h>
  31. #else
  32. #include <direct.h>
  33. #endif
  34.  
  35. #ifdef __ZTC__
  36. #include <dos.h>
  37. static int brk;
  38. #endif
  39.  
  40. unsigned int _vcm_maxres = 0;
  41.  
  42. void    _pascal r_assignkey(unsigned int key, char *label);
  43. char *    _pascal r_getbind(unsigned int key);
  44. char *    _pascal r_getlabels(int i);
  45.  
  46. int     _pascal setcwd(char *path);
  47. static    void _near _pascal set_area(int area);
  48. static    void _near _pascal empty(void);
  49. static    void _near _pascal highest(void);
  50. static    int _near _pascal start(char *, char *);
  51.  
  52. int     direction = RIGHT;
  53.  
  54. static    int     lastfound = 0;
  55. static    int     command;
  56. static    int     root = 0;        /* root message of a thread */
  57. static    int     back = 0;
  58.  
  59. char * _pascal show_address(ADDRESS a)
  60.  
  61. {
  62.     static char s[80];
  63.     char field[20];
  64.  
  65.     memset(s,0,sizeof s);
  66.     memset(field,0,sizeof field);
  67.  
  68.     if (a.notfound) {
  69.         strcpy(s,"unknown address");
  70.         return(s);
  71.     }
  72.  
  73.     if (a.fidonet) {
  74.         if (a.zone) {
  75.             strcat(s,itoa(a.zone,field,10));
  76.             strcat(s,":");
  77.         }
  78.         strcat(s,itoa(a.net,field,10));
  79.         strcat(s,"/");
  80.         strcat(s,itoa(a.node,field,10));
  81.         if (a.point) {
  82.             strcat(s,".");
  83.             strcat(s,itoa(a.point,field,10));
  84.         }
  85.  
  86.         if (a.domain != NULL) {
  87.             strcat(s,"@");
  88.             strcat(s,strlwr(a.domain));
  89.         }
  90.     }
  91.  
  92.     if (a.internet) {
  93.         strncpy(s,a.domain,60);
  94.     }
  95.  
  96.     if (a.bangpath) {
  97.         char *t,*t1;
  98.  
  99.         t1 = strrchr(a.domain,'!');
  100.         if (t1 == NULL)
  101.             strcpy(s,a.domain);
  102.         else {
  103.             *t1 = '\0';
  104.             t = strrchr(a.domain,'!');
  105.             if (!t)
  106.                 t = a.domain;
  107.             *t1 = '!';
  108.             strcat(strcpy(s,"..."),t);
  109.         }
  110.  
  111.     }
  112.  
  113.     return(s);
  114. }
  115.  
  116. static void _near _pascal delete()
  117.  
  118. {
  119.     deletemsg();
  120. }
  121.  
  122. static void _near _pascal doreply()
  123.  
  124. {
  125.     reply();
  126. }
  127.  
  128. static void _near _pascal doquote()
  129.  
  130. {
  131.     quote();
  132. }
  133.  
  134. static void _near _pascal move()
  135.  
  136. {
  137.     movemsg();
  138. }
  139.  
  140. static void _near _pascal outtxt()
  141.  
  142. {
  143.     writetxt();
  144. }
  145.  
  146. static void _near _pascal set()
  147.  
  148. {
  149.     settings();
  150. }
  151.  
  152. static void _near _pascal new()
  153.  
  154. {
  155.     newmsg();
  156. }
  157.  
  158. static void _near _pascal dochange()
  159.  
  160. {
  161.     change();
  162. }
  163.  
  164. char *    _pascal r_getbind(unsigned int key)
  165.  
  166. {
  167.     unsigned int i = 0;
  168.     void (_near _pascal *action)();
  169.  
  170.     if (key & 0xff)
  171.         action = mainckeys[key & 0xff];
  172.     else
  173.         action = mainakeys[(key >> 8) & 0xff];
  174.  
  175.     while ((maincmds[i].label != NULL) &&
  176.            (action != maincmds[i].action))
  177.         i++;
  178.  
  179.     return(maincmds[i].label);
  180.  
  181. }
  182.  
  183. char *    _pascal r_getlabels(int i)
  184.  
  185. {
  186.     return(maincmds[i].label);
  187. }
  188.  
  189. void    _pascal r_assignkey(unsigned int key, char *label)
  190.  
  191. {
  192.     unsigned int i = 0;
  193.  
  194.     while ((maincmds[i].label != NULL) &&
  195.            (strncmp(maincmds[i].label,label,strlen(maincmds[i].label)) != 0))
  196.         i++;
  197.  
  198.     if (maincmds[i].label != NULL)
  199.         if (key & 0xff)
  200.             mainckeys[key & 0xff] = maincmds[i].action;
  201.         else
  202.             mainakeys[(key >> 8) & 0xff] = maincmds[i].action;
  203. }
  204.  
  205. ADDRESS _pascal parsenode(char *t)
  206.  
  207. {
  208.     ADDRESS tmp;
  209.     char *t1 = t;
  210.     int  n = 0;
  211.     int point = 0;
  212.  
  213.     tmp = thisnode; /* msc doesn't allow auto struct initializers */
  214.     tmp.point = tmp.notfound = 0;
  215.     tmp.fidonet = 1;
  216.     tmp.internet = 0;
  217.     tmp.bangpath = 0;
  218.     if (thisnode.domain != NULL)
  219.         tmp.domain = strdup(thisnode.domain);
  220.  
  221.     if (t == NULL) {
  222.         tmp.notfound = 1;
  223.         return(tmp);
  224.     }
  225.  
  226.     while (isspace(*t)) t++;
  227.     if (!isdigit(*t)) {
  228.         tmp.notfound = 1;
  229.         tmp.fidonet = 0;
  230.         tmp.internet = 0;
  231.         tmp.bangpath = 0;
  232.         return(tmp);
  233.     }
  234.  
  235.     while (t1) {
  236.         n = (int) strtol(t1,&t1,10);
  237.         if (t1 == NULL) {
  238.             if (point) tmp.point = n;
  239.             else tmp.node = n;
  240.             if (tmp.zone == 0) tmp.zone = thisnode.zone;
  241.             return(tmp);
  242.         }
  243.         switch (*t1) {
  244.  
  245.             case ')' :
  246.             case ' ' :
  247.             case '\0':
  248.                 if (point) tmp.point = n;
  249.                 else tmp.node = n;
  250.                 if (tmp.zone == 0) tmp.zone = thisnode.zone;
  251.                 return(tmp);
  252.  
  253.             case ':' :
  254.                 tmp.zone = n;
  255.                 break;
  256.  
  257.             case '/' :
  258.                 tmp.net = n;
  259.                 break;
  260.  
  261.             case '.' :
  262.                 tmp.node = n;
  263.                 point = 1;
  264.                 break;
  265.  
  266.             case '@' :
  267.                 if (point) tmp.point = n;
  268.                 else tmp.node = n;
  269.                 if (tmp.domain != NULL) free(tmp.domain);
  270.                 tmp.domain = strdup(t1+1);
  271.                 if (strchr(tmp.domain,' ')) *strchr(tmp.domain,' ') = '\0';
  272.                 if (tmp.zone == 0) tmp.zone = thisnode.zone;
  273.                 return(tmp);
  274.         }
  275.         t1++;
  276.     }
  277.  
  278.     if (tmp.zone == 0) tmp.zone = thisnode.zone;
  279.     return(tmp);
  280. }
  281.  
  282. void _pascal dispose(MSG *message)
  283.  
  284. {
  285.     if (message == NULL)
  286.         return;
  287.  
  288.     if (message->text != NULL)
  289.         message->text = clearbuffer(message->text);
  290.     release(message->isto);
  291.     release(message->isfrom);
  292.     release(message->reply);
  293.     release(message->subj);
  294.     release(message->to.domain);
  295.     release(message->from.domain);
  296.     release(message);
  297. }
  298.  
  299. static void _near _pascal quit()
  300.  
  301. {
  302.     cleanup();
  303. }
  304.  
  305. void _pascal cleanup()
  306. {
  307. #ifdef _OS2_
  308.     int errorlevel = 0;
  309. #else
  310.     unsigned char errorlevel = 0;
  311. #endif
  312.     FILE   *fp;
  313.     AREA *a;
  314.  
  315.     highest();
  316.     msg_last(arealist[area]);
  317.  
  318.     setcwd(home);
  319. #ifdef __ZTC__
  320.     dos_set_ctrl_break(brk);
  321. #endif
  322.  
  323.     cls();
  324.  
  325.     video_end();
  326.  
  327.     if (*confmail == '+')
  328.         fp = fopen(confmail+1,"at");
  329.     else
  330.         fp = fopen(confmail, "wt");
  331.  
  332.     for (a = &(arealist[area = 0]); area < areas; a = &(arealist[++area])) {
  333.         errorlevel |= (a->netmail && a->new)? 0x01:0;
  334.         errorlevel |= (a->echomail && a->new)?0x02:0;
  335.         errorlevel |= (a->uucp && a->new)?      0x04:0;
  336.         errorlevel |= (a->news && a->new)?      0x08:0;
  337.         errorlevel |= (a->local && a->new)?   0x10:0;
  338.  
  339.         if (a->echomail && a->new)
  340.             fprintf(fp, "%s\n", a->tag);
  341.     }
  342.  
  343.     printf("\nexiting with errorlevel %d\n",errorlevel);
  344.  
  345.     if (messages)
  346.         free(messages);
  347.  
  348.     if (arealist)
  349.         handle_free(arealist);
  350.  
  351. #ifdef _OS2_
  352.     fclose(fp);
  353. #else
  354.     fcloseall();
  355. #endif
  356.  
  357.     exit(errorlevel);
  358. }
  359.  
  360. void _pascal outamemory()
  361. {
  362.     fprintf(stderr, "\ni've run out of memory!  aborting....\n");
  363.     cleanup();
  364. }
  365.  
  366. static void _near _pascal empty()
  367.  
  368. {
  369.     arealist[area].last = arealist[area].current = arealist[area].first = 0;
  370.     cls();
  371.     gotoxy(3, maxy / 2);
  372.     set_color(co_hilite);
  373.     bprintf("%s is empty!",arealist[area].description);
  374.     set_color(co_normal);
  375. }
  376.  
  377. static void _near _pascal search()
  378.  
  379. {
  380.     char   *t = NULL;
  381.     int     tmp = 0;
  382.     MSG    *m;
  383.  
  384.     static    bmgARG pattern;
  385.     static    char prompt[bmgMAXPAT];
  386.     static    char patstr[bmgMAXPAT];
  387.  
  388.     gotoxy(9, 1);
  389.     clreol();
  390.     set_color(co_info);
  391.     bputs("Find: ");
  392.     set_color(co_normal);
  393.     bgets(prompt,sizeof(prompt)-1,sizeof(prompt)-1);
  394.  
  395.     if (strlen(prompt) == 0)
  396.         return;
  397.  
  398.     if (strcmpl(prompt,patstr) == 0)
  399.         tmp = lastfound + 1;
  400.     else {
  401.         tmp = arealist[area].current;
  402.         lastfound = 0;
  403.         memset(patstr,0,sizeof(patstr));
  404.         memset(&pattern,0,sizeof(bmgARG));
  405.         strncpy(patstr,prompt,sizeof(prompt));
  406.         bmgCompile(patstr,&pattern,TRUE);
  407.     }
  408.  
  409.     gotoxy(9,1);
  410.     clreol();
  411.     set_color(co_info);
  412.     for (;tmp < arealist[area].messages; tmp++) {
  413.         if (keyhit() && (getkey() == ABORT)) {
  414.             msg_readtext(-1);
  415.             return;
  416.         }
  417.  
  418.         if ((m = msg_readheader(msgnum(tmp))) != NULL) {
  419.             gotoxy(9,1);
  420.             bprintf("Looking at #%d for \"%s\"",msgnum(tmp),prompt);
  421.             if (bmgSearch(m->isto,strlen(m->isto),&pattern) != NULL) {
  422.                 lastfound = tmp;
  423.                 set_color(co_normal);
  424.                 arealist[area].current = tmp;
  425.                 msg_readtext(-1);
  426.                 return;
  427.             }
  428.  
  429.             if (bmgSearch(m->isfrom,strlen(m->isfrom),&pattern) != NULL) {
  430.                 lastfound = tmp;
  431.                 set_color(co_normal);
  432.                 arealist[area].current = tmp;
  433.                 msg_readtext(-1);
  434.                 return;
  435.             }
  436.  
  437.             if (bmgSearch(m->subj,strlen(m->subj),&pattern) != NULL) {
  438.                 lastfound = tmp;
  439.                 set_color(co_normal);
  440.                 arealist[area].current = tmp;
  441.                 msg_readtext(-1);
  442.                 return;
  443.             }
  444.  
  445.             while ((t = msg_readtext(msgnum(tmp))) != NULL) {
  446.                 if (bmgSearch(t,strlen(t),&pattern) != NULL) {
  447.                     lastfound = tmp;
  448.                     set_color(co_normal);
  449.                     if (t) free(t);
  450.                     arealist[area].current = tmp;
  451.                     msg_readtext(-1);
  452.                     return;
  453.                 }
  454.                 if (t) free(t);
  455.                 t = NULL;
  456.             }
  457.         }
  458.     }
  459.     msg_readtext(-1);
  460.     set_color(co_normal);
  461. }
  462.  
  463. int _pascal confirm()
  464.  
  465. {
  466.     int ch;
  467.  
  468.     if (!(confirmations))                                   /*WRA*/
  469.         return(TRUE);
  470.  
  471.     gotoxy(9,1);
  472.     clreol();
  473.     set_color(co_warn);
  474.     bputs("*warning* ");
  475.     bputs("do you really want to do this? (y/n) ");
  476.     video_update();
  477.  
  478.     do {
  479.         ch = getkey() & 0x7f;
  480.         ch = tolower(ch);
  481.  
  482.     } while ((ch != 'y') && (ch != 'n'));
  483.  
  484.     bputc((char) ch);
  485.     set_color(co_normal);
  486.     return(ch == 'y');
  487. }
  488.  
  489. static void _near _pascal rundos()
  490.  
  491. {
  492.     char tmp[PATHLEN];
  493.     char cmd[64];
  494.  
  495.     getcwd(tmp,PATHLEN);
  496.     memset(cmd,0,sizeof cmd);
  497.     gotoxy(9,1);
  498.     clreol();
  499.     set_color(co_info);
  500.     bputs("DOS command: ");
  501.     bgets(cmd,63,63);
  502.     cls();
  503.     system(cmd);
  504.     maxx = maxy = 0;
  505.     video_init();
  506.     rm = maxx - 1;
  507.     puts("\nPress any key to return to msged.");
  508.     getkey();
  509.     setcwd(tmp);
  510. }
  511.  
  512. static    void _near _pascal set_area(int area)
  513.  
  514. {
  515.     lastfound = 1;
  516.     arealist[area].messages = msg_scan((&(arealist[area])));
  517.     direction = RIGHT;
  518.     back = root = 0;
  519.     back = root = arealist[area].current;
  520.     dispose(message);
  521.     message = NULL;
  522. }
  523.  
  524. void _pascal areascan()
  525.  
  526. {
  527.     scan_areas();
  528. }
  529.  
  530. static void _near _pascal scan_areas()
  531.  
  532. {
  533.     int a = 0;
  534.  
  535.     highest();
  536.     msg_last(arealist[area]);
  537.     set_color(co_warn);
  538.     for (;a < areas; a++) {
  539.         gotoxy(9,1);
  540.         clreol();
  541.         video_update();
  542.         bprintf("scanning %s for new mail (<esc> to interrupt)",arealist[a].description);
  543.         if (keyhit() && (getkey() == ABORT))
  544.             break;
  545.         else
  546.             arealist[a].messages = msg_scan((&arealist[a]));
  547.     }
  548.  
  549.     set_color(co_normal);
  550.     scanned = 1;
  551.     arealist[area].messages = msg_scan((&arealist[area]));
  552. }
  553.  
  554. static void _near _pascal next_area()
  555.  
  556. {
  557.     int oarea = area;
  558.  
  559.     override = FALSE;
  560.     if (areas < 2)
  561.         return;
  562.     highest();
  563.     msg_last(arealist[area]);
  564.     if (scanned) {
  565.         area = (area + 1) % areas;
  566.         while ((arealist[area].messages - arealist[area].lastread - 1) <= 0) {
  567.             area = (area + 1) % areas;
  568.             if (area == oarea) {
  569.                 area = (area + 1) % areas;
  570.                 break;
  571.             }
  572.         }
  573.     }
  574.     else
  575.         area = (area + 1) % areas;
  576.     set_area(area);
  577. }
  578.  
  579. static void _near _pascal prev_area()
  580.  
  581. {
  582.     int oarea = area;
  583.  
  584.     override = FALSE;
  585.     if (areas < 2)
  586.         return;
  587.     highest();
  588.     msg_last(arealist[area]);
  589.     if (scanned) {
  590.         area--;
  591.         area = (area < 0)?areas-1:area;
  592.         while ((arealist[area].messages - arealist[area].lastread - 1) <= 0) {
  593.             area--;
  594.             area = (area < 0)?areas-1:area;
  595.             if (area == oarea) {
  596.                 area--;
  597.                 area = (area < 0)?areas-1:area;
  598.                 break;
  599.             }
  600.         }
  601.     }
  602.     else {
  603.         area--;
  604.         area = (area < 0)?areas-1:area;
  605.     }
  606.     set_area(area);
  607. }
  608.  
  609. static void _near _pascal highest()
  610.  
  611. {
  612.     arealist[area].lastread = min(max(arealist[area].lastread,arealist[area].current),arealist[area].messages-1);
  613.     root = arealist[area].current;
  614. }
  615.  
  616.  
  617. static void _near _pascal left()
  618.  
  619. {
  620.     back = arealist[area].current;
  621.     direction = LEFT;
  622.  
  623.     if (arealist[area].current > 0)
  624.         arealist[area].current--;
  625.  
  626.     root = arealist[area].current;
  627. }
  628.  
  629. static void _near _pascal right()
  630.  
  631. {
  632.     back = arealist[area].current;
  633.     direction = RIGHT;
  634.  
  635.     if (arealist[area].current < (arealist[area].messages-1))
  636.         arealist[area].current++;
  637.  
  638.     highest();
  639. }
  640.  
  641. static void _near _pascal gotomsg(int i)
  642.  
  643. {
  644.     gotoxy(9, 1);
  645.     clreol();
  646.     set_color(co_info);
  647.     bputs("Goto Message #? ");
  648.     set_color(co_normal);
  649.     back = arealist[area].current;
  650.     i = getnum(0, arealist[area].messages, i);
  651.     if (i == 0)
  652.         return;
  653.     arealist[area].current = i-1;
  654.     highest();
  655. }
  656.  
  657.  
  658. static void _near _pascal newarea()
  659.  
  660. {
  661.     override = FALSE;
  662.     if (areas < 2)
  663.         return;
  664.     highest();
  665.     msg_last(arealist[area]);
  666.     area = selectarea();
  667.     set_area(area);
  668. }
  669.  
  670. static int _near _pascal start(char *cfg, char *afn)
  671.  
  672. {
  673.     opening(cfg,afn);
  674.  
  675.     area = 0;
  676.  
  677.     arealist[area].messages = msg_scan(&(arealist[area]));
  678.  
  679.     gotoxy(6, maxy);
  680.     bputs("Press any key to continue....");
  681.     getkey();
  682.  
  683.     if (arealist[area].messages > 0) {
  684.         if ((message = readmsg(msgnum(arealist[area].current))) != NULL)
  685.             return showmsg(message);
  686.     }
  687.     else
  688.         return 0x1e00;
  689.  
  690.     return 0x1e00;
  691. }
  692.  
  693. static void _near _pascal go_last()
  694.  
  695. {
  696.     arealist[area].current = min(arealist[area].lastread, arealist[area].messages-1);
  697.     root = arealist[area].current;
  698. }
  699.  
  700. static void _near _pascal link_from()
  701.  
  702. {
  703.     int t;
  704.     if (!message->replyto)
  705.         return;
  706.  
  707.     back = arealist[area].current;
  708.     for (t = arealist[area].current; (t > -1) && ((unsigned) msgnum(t) != message->replyto); t--)
  709.         /* null statement */ ;
  710.     if (t > -1)
  711.         arealist[area].current = t;
  712. }
  713.  
  714. static void _near _pascal view()
  715.  
  716. {
  717.     shownotes = !shownotes;
  718.     seenbys = shownotes;
  719. }
  720.  
  721. static void _near _pascal link_to()
  722.  
  723. {
  724.     int t;
  725.     if (!message->replyfrom)
  726.         return;
  727.     back = arealist[area].current;
  728.     for (t = arealist[area].messages - 1; (t > arealist[area].current) && ((unsigned) msgnum(t) != message->replyfrom); t--)
  729.         /* null statement */;
  730.     if (t > arealist[area].current)
  731.         arealist[area].current = t;
  732.  
  733.     arealist[area].lastread = max(arealist[area].lastread,arealist[area].current);
  734. }
  735.  
  736. static void _near _pascal go_root()
  737.  
  738. {
  739.     back = arealist[area].current;
  740.     arealist[area].current = root;
  741.     highest();
  742. }
  743.  
  744. static void _near _pascal rotate()
  745.  
  746. {
  747.     rot13 = (rot13 + 1) % 3;
  748. }
  749.  
  750. static void _near _pascal go_dos()
  751.  
  752. {
  753.     char tmp[PATHLEN];
  754.  
  755.     getcwd(tmp,PATHLEN);
  756.     setcwd(home);
  757.     cls();
  758.     fputs("\nType EXIT to return to msged.\n",stderr);
  759.     spawnl(0,comspec,comspec,NULL);
  760.     maxx = maxy = 0;
  761.     video_init();
  762.     rm = maxx;
  763.     setcwd(tmp);
  764. }
  765.  
  766. static void _near _pascal nada()
  767.  
  768. {
  769. }
  770.  
  771. typedef struct _mlhead {
  772.     int n;
  773.     char to_name[37];
  774.     int  to_net;
  775.     int  to_node;
  776.     char fr_name[37];
  777.     int  fr_net;
  778.     int  fr_node;
  779.     char subj[73];
  780. } MLHEAD;
  781.  
  782. static void _near _pascal update(MLHEAD *headers, int n,int y);
  783. static void _near _pascal showit(MLHEAD *h);
  784. static void _near _pascal getheader(int n, MLHEAD *h);
  785.  
  786. static    char    tmp[16];
  787. static    int     f = 1;
  788.  
  789. void _near _pascal list()
  790.  
  791. {
  792.     MLHEAD *headers = NULL;
  793.     int i = 0, y = 0, ch = 0, a = 0;
  794.     char   *s = NULL;
  795.  
  796.         cls();
  797.         sprintf(tmp,"%%-%d.%ds",maxx,maxx);
  798.         i = a = arealist[area].current;
  799.         highest();
  800.     headers = (MLHEAD *) calloc((maxy+1),sizeof(MLHEAD));
  801.     if (headers == NULL) outamemory();
  802.  
  803.         y = 1;
  804.  
  805.         update(headers,i,y);
  806.  
  807.         ch = 0;
  808.         y = 1;
  809.  
  810.     while ((ch != ENTER) && (ch != ABORT) && arealist[area].messages) {
  811.         gotoxy(1, y);
  812.         clreol();
  813.         set_color(co_hilite);
  814.         showit(&headers[y-1]);
  815.         set_color(co_normal);
  816.  
  817.                 switch (ch = getkey()) {
  818.  
  819.         case 0x1e00 :
  820.                         f = !f;
  821.                         y = 1;
  822.                         update(headers,a,y);
  823.                         break;
  824.  
  825.                 case PGDN:
  826.             i = maxy;
  827.             while ((i > 1) && (a < (arealist[area].messages-1))) {
  828.                                 i--;
  829.                                 a++;
  830.                         }
  831.                         y = 1;
  832.                         update(headers,a,y);
  833.                         break;
  834.  
  835.                 case PGUP:
  836.                         i = maxy;
  837.                         while ((i > 1) && (a > 0)) {
  838.                                 i--;
  839.                                 a--;
  840.                         }
  841.                         y = 1;
  842.                         update(headers,a,y);
  843.                         break;
  844.  
  845.         case UP:
  846.                         if (a > 0) {
  847.                                 gotoxy(1, y);
  848.                 clreol();
  849.                 if (strcmpl(headers[y-1].to_name,username) == 0)
  850.                     set_color(co_info);
  851.                 else
  852.                     set_color(co_normal);
  853.  
  854.                 showit(&headers[y-1]);
  855.                 a--;
  856.                                 y--;
  857.  
  858.                                 if (y < 1) {
  859.                                         y = 1;
  860.                     scrolldown(1, 1, maxx, maxy, 1);
  861.                     memmove((headers + 1),headers,(sizeof(MLHEAD) * maxy));
  862.                     getheader(msgnum(a), &headers[0]);
  863.                     s = strchr(headers[0].fr_name,'\n');
  864.                     if (s != NULL)
  865.                         *s = '\0';
  866.                     s = strchr(headers[0].to_name,'\n');
  867.                     if (s != NULL)
  868.                         *s = '\0';
  869.                 }
  870.                         }
  871.             break;
  872.  
  873.                 case DOWN:
  874.                         if (a < (arealist[area].messages-1)) {
  875.                 gotoxy(1, y);
  876.                 clreol();
  877.                 if (strcmpl(headers[y-1].to_name,username) == 0)
  878.                     set_color(co_info);
  879.                 else
  880.                     set_color(co_normal);
  881.  
  882.                 showit(&headers[y-1]);
  883.                                 a++;
  884.                                 y++;
  885.  
  886.                 if (y > maxy) {
  887.                     y = maxy;
  888.                     scrollup(1, 1, maxx, maxy, 1);
  889.                     memmove(headers,(headers + 1),sizeof(MLHEAD) * (maxy+1));
  890.                     getheader(msgnum(a), &headers[maxy-1]);
  891.                     s = strchr(headers[maxy - 1].fr_name,'\n');
  892.                     if (s != NULL)
  893.                         *s = '\0';
  894.                     s = strchr(headers[maxy - 1].to_name,'\n');
  895.                     if (s != NULL)
  896.                         *s = '\0';
  897.                 }
  898.             }
  899.                         break;
  900.  
  901.                 case ENTER:
  902.             arealist[area].current = a;
  903.             dispose(message);
  904.             message = readmsg(messages[a]);
  905.                         free(headers);
  906.                         return;
  907.  
  908.                 case ABORT:
  909.                         free(headers);
  910.                         return;
  911.  
  912.         default:
  913.             arealist[area].current = a;
  914.                     if (ch & 0xff) {
  915.                 if (isdigit(ch))
  916.                     gotomsg(ch - 0x30);
  917.                 else if (mainckeys[ch])
  918.                     mainckeys[ch & 0xff]();
  919.             }
  920.             else if (mainakeys[ch >> 8])
  921.                 mainakeys[ch >> 8]();
  922.  
  923.             i = a = arealist[area].current;
  924.             update(headers,i,y=1);
  925.         }
  926.         }
  927. }
  928.  
  929. static void _near _pascal update(MLHEAD *headers, int i,int y)
  930.  
  931. {
  932.     char *s = NULL;
  933.  
  934.         clrwnd(1,y,maxx,maxy);
  935.         while ((i <= (arealist[area].messages-1)) && (y <= maxy)) {
  936.                 gotoxy(1,y);
  937.         getheader(msgnum(i), &headers[y-1]);
  938.         s = strchr(headers[y - 1].fr_name,'\n');
  939.         if (s != NULL)
  940.             *s = '\0';
  941.         s = strchr(headers[y - 1].to_name,'\n');
  942.         if (s != NULL)
  943.             *s = '\0';
  944.  
  945.         if (strcmpl(headers[y-1].to_name,username) == 0)
  946.             set_color(co_info);
  947.         else
  948.             set_color(co_normal);
  949.  
  950.         showit(&headers[y-1]);
  951.                 i++;
  952.                 y++;
  953.     }
  954.  
  955. }
  956.  
  957. static void _near _pascal showit(MLHEAD *h)
  958.  
  959. {
  960.     char    line[256];
  961.  
  962.     if (f && arealist[area].netmail)
  963.         sprintf(line,"%4d: %-15.15s@%5d/%-5d to %-15.15s@%5d/%-5d RE: %-70s",
  964.             h->n, h->fr_name,h->fr_net,h->fr_node,
  965.             h->to_name,h->to_net,h->to_node, h->subj);
  966.     else
  967.         sprintf(line,"%4d: %-15.15s to %-15.15s RE: %-70s",
  968.             h->n,h->fr_name,h->to_name,h->subj);
  969.     bprintf(tmp,line);
  970. }
  971.  
  972. static void _near _pascal getheader(int n, MLHEAD *h)
  973.  
  974. {
  975.     MSG *i = NULL;
  976.  
  977.     i = msg_readheader(n);
  978.     memset(h,0,sizeof(MLHEAD));
  979.     if (i == NULL) return;
  980.  
  981.     h->n = i->msgnum;
  982.     h->to_net = i->to.net;
  983.     h->to_node = i->to.node;
  984.     h->fr_net = i->from.net;
  985.     h->fr_node = i->from.node;
  986.     strncpy(h->subj,i->subj,72);
  987.     strncpy(h->to_name,i->isto,36);
  988.     strncpy(h->fr_name,i->isfrom,36);
  989.     dispose(i);
  990. }
  991.  
  992.  
  993. void _cdecl main(int argc, char *argv[])
  994.  
  995. {
  996.     messages = NULL;
  997.     arealist = NULL;
  998.  
  999. #ifdef __ZTC__
  1000.     brk = dos_get_ctrl_break();
  1001.     dos_set_ctrl_break(0);
  1002. #endif
  1003.  
  1004.     if ((argc > 1) && (argc < 3))
  1005.         command = start(argv[1],NULL);
  1006.     else if (argc > 1)
  1007.         command = start(argv[1],argv[2]);
  1008.     else
  1009.         command = start(NULL,NULL);
  1010.  
  1011.     for (;;) {            /* endless loop... exit is through cleanup */
  1012.  
  1013.         if (command & 0xff) {
  1014.             if (isdigit(command))
  1015.                 gotomsg(command - 0x30);
  1016.             else if (mainckeys[command])
  1017.                 mainckeys[command & 0xff]();
  1018.         }
  1019.         else if (mainakeys[command >> 8])
  1020.             mainakeys[command >> 8]();
  1021.  
  1022.         if (arealist[area].messages < 1) {
  1023.             empty();
  1024.             command = getkey();
  1025.         }
  1026.         else {
  1027.             dispose(message);
  1028.             message = NULL;
  1029.  
  1030.             while ((message = readmsg(msgnum(arealist[area].current))) == NULL)
  1031.                 if ((direction == RIGHT) && (arealist[area].current > 0))
  1032.                     arealist[area].current--;
  1033.                 else if (arealist[area].current < arealist[area].last)
  1034.                     arealist[area].current++;
  1035.                 else {
  1036.                     empty();
  1037.                     command = getkey();
  1038.                     continue;
  1039.                 }
  1040.  
  1041.             command = showmsg(message);
  1042.         }
  1043.     }
  1044. }
  1045.