home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / lora299s.zip / READTXT.CPP < prev    next >
C/C++ Source or Header  |  1997-05-23  |  60KB  |  1,987 lines

  1.  
  2. #include "_ldefs.h"
  3. #include "lorawin.h"
  4. #include "msgbase.h"
  5.  
  6. PSZ Months[] = {
  7.    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  8.    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  9. };
  10.  
  11. USHORT TotalLines, DoRescan = TRUE, ShowKludges = FALSE;
  12. USHORT NetMail, EMail, BadMsgs, Dupes;
  13. CHAR   AreaKey[16];
  14. ULONG  Number;
  15. class  TConfig *Cfg;
  16. class  TMsgBase *Msg;
  17. class  TUser *User;
  18. class  TMsgData *Data;
  19. class  TScan *Scan;
  20.  
  21. // ----------------------------------------------------------------------
  22.  
  23. VOID DisplayButton (USHORT y, USHORT x, CHAR *Text, USHORT Shadow)
  24. {
  25.    USHORT ButtonSize = 8;
  26.    CHAR Temp[48];
  27.  
  28.    if (strlen (Text) > ButtonSize)
  29.       ButtonSize = (USHORT)(strlen (Text) + 1);
  30.    Temp[ButtonSize + 1] = '\0';
  31.  
  32.    memset (Temp, ' ', ButtonSize + 1);
  33.    Temp[ButtonSize] = '▄';
  34.    wprints (y, x, Shadow, Temp);
  35.  
  36.    memset (&Temp[1], '▀', ButtonSize);
  37.    wprints ((short)(y + 1), x, Shadow, Temp);
  38.  
  39.    Temp[ButtonSize] = '\0';
  40.    memset (Temp, ' ', ButtonSize);
  41.    memcpy (&Temp[(ButtonSize - strlen (Text)) / 2], Text, strlen (Text));
  42.    wprints (y, x, BLACK|_GREEN, Temp);
  43. }
  44.  
  45. VOID GetTextField (USHORT y, USHORT x, CHAR *Text, USHORT FieldSize, USHORT Size)
  46. {
  47.    CHAR Temp[128], String[128];
  48.  
  49.    if (FieldSize < Size)
  50.       Size = FieldSize;
  51.    memset (Temp, '?', Size);
  52.    Temp[Size] = '\0';
  53.  
  54.    strcpy (String, Text);
  55.    winpbeg (WHITE|_BLUE, WHITE|_BLUE);
  56.    winpdef (y, x, String, Temp, 0, 2, NULL, 0);
  57.    if (winpread () != W_ESCPRESS)
  58.       strcpy (Text, strbtrim (String));
  59.    hidecur ();
  60. }
  61.  
  62. VOID DisplayTextField (USHORT y, USHORT x, CHAR *Text, USHORT FieldSize, USHORT Size)
  63. {
  64.    CHAR Temp[128];
  65.  
  66.    if (FieldSize < Size)
  67.       Size = FieldSize;
  68.  
  69.    memset (Temp, ' ', Size);
  70.    Temp[Size] = '\0';
  71.    wprints (y, x, WHITE|_BLUE, Temp);
  72.    wprints (y, x, WHITE|_BLUE, Text);
  73. }
  74.  
  75. USHORT MessageBox (PSZ Caption, PSZ Text)
  76. {
  77.    int menu_sel = 996;
  78.    USHORT RetVal = FALSE;
  79.  
  80.    wopen (9, 24, 15, 55, 1, WHITE|_RED, WHITE|_RED);
  81.    wshadow (DGREY|_BLACK);
  82.    wtitle (Caption, TCENTER, WHITE|_RED);
  83.  
  84.    DisplayButton (3, 6, "   Ok   ", BLACK|_RED);
  85.    DisplayButton (3, 16, " Cancel ", BLACK|_RED);
  86.  
  87.    wprints (1, 2, WHITE|_RED, Text);
  88.  
  89.    do {
  90.       wmenubegc ();
  91.       wmenuitem (3, 6, "   Ok   ", 'O', 996, 0, NULL, 0, 0);
  92.       wmenuitem (3, 16, " Cancel ", 'C', 997, 0, NULL, 0, 0);
  93.       wmenuend ((short)menu_sel, M_OMNI|M_SAVE, 0, 0, BLACK|_GREEN, YELLOW|_GREEN, DGREY|_GREEN, WHITE|_GREEN);
  94.  
  95.       switch (menu_sel = wmenuget ()) {
  96.          case 996:
  97.             RetVal = TRUE;
  98.             break;
  99.          case 997:
  100.             RetVal = FALSE;
  101.             break;
  102.       }
  103.    } while (menu_sel != -1 && menu_sel != 996 && menu_sel != 997);
  104.  
  105.    wclose ();
  106.  
  107.    return (RetVal);
  108. }
  109.  
  110. // ----------------------------------------------------------------------
  111.  
  112. typedef struct {
  113.    CHAR   Key[16];
  114.    CHAR   Description[64];
  115.    ULONG  Messages;
  116.    ULONG  New;
  117.    CHAR   Tag[64];
  118. } SCANDATA;
  119.  
  120. class TScan
  121. {
  122. public:
  123.    TScan (void);
  124.    ~TScan (void);
  125.  
  126.    CHAR   Key[16];
  127.    CHAR   Description[64];
  128.    ULONG  Messages;
  129.    ULONG  New;
  130.    CHAR   Tag[64];
  131.  
  132.    VOID   Add (VOID);
  133.    VOID   Clear (VOID);
  134.    USHORT First (VOID);
  135.    USHORT Next (VOID);
  136.    USHORT Read (PSZ key);
  137.    VOID   Update (VOID);
  138.  
  139. private:
  140.    class  TCollection Data;
  141. };
  142.  
  143. TScan::TScan (void)
  144. {
  145.    Data.Clear ();
  146. }
  147.  
  148. TScan::~TScan (void)
  149. {
  150.    Data.Clear ();
  151. }
  152.  
  153. VOID TScan::Add (VOID)
  154. {
  155.    SCANDATA sd;
  156.  
  157.    strcpy (sd.Key, Key);
  158.    strcpy (sd.Description, Description);
  159.    sd.Messages = Messages;
  160.    sd.New = New;
  161.    strcpy (sd.Tag, Tag);
  162.  
  163.    Data.Add (&sd, sizeof (SCANDATA));
  164. }
  165.  
  166. VOID TScan::Clear (VOID)
  167. {
  168.    Data.Clear ();
  169. }
  170.  
  171. USHORT TScan::First (VOID)
  172. {
  173.    USHORT RetVal = FALSE;
  174.    SCANDATA *sd;
  175.  
  176.    if ((sd = (SCANDATA *)Data.First ()) != NULL) {
  177.       strcpy (Key, sd->Key);
  178.       strcpy (Description, sd->Description);
  179.       Messages = sd->Messages;
  180.       New = sd->New;
  181.       strcpy (Tag, sd->Tag);
  182.       RetVal = TRUE;
  183.    }
  184.  
  185.    return (RetVal);
  186. }
  187.  
  188. USHORT TScan::Next (VOID)
  189. {
  190.    USHORT RetVal = FALSE;
  191.    SCANDATA *sd;
  192.  
  193.    if ((sd = (SCANDATA *)Data.Next ()) != NULL) {
  194.       strcpy (Key, sd->Key);
  195.       strcpy (Description, sd->Description);
  196.       Messages = sd->Messages;
  197.       New = sd->New;
  198.       strcpy (Tag, sd->Tag);
  199.       RetVal = TRUE;
  200.    }
  201.  
  202.    return (RetVal);
  203. }
  204.  
  205. USHORT TScan::Read (PSZ key)
  206. {
  207.    USHORT RetVal = FALSE;
  208.    SCANDATA *sd;
  209.  
  210.    if ((sd = (SCANDATA *)Data.First ()) != NULL)
  211.       do {
  212.          if (!stricmp (sd->Key, key)) {
  213.             strcpy (Key, sd->Key);
  214.             strcpy (Description, sd->Description);
  215.             Messages = sd->Messages;
  216.             New = sd->New;
  217.             strcpy (Tag, sd->Tag);
  218.             RetVal = TRUE;
  219.             break;
  220.          }
  221.       } while ((sd = (SCANDATA *)Data.Next ()) != NULL);
  222.  
  223.    return (RetVal);
  224. }
  225.  
  226. VOID TScan::Update (VOID)
  227. {
  228.    SCANDATA *sd;
  229.  
  230.    if ((sd = (SCANDATA *)Data.Value ()) != NULL) {
  231.       sd->Messages = Messages;
  232.       sd->New = New;
  233.    }
  234. }
  235.  
  236. // ----------------------------------------------------------------------
  237.  
  238. class TTextEditor
  239. {
  240. public:
  241.    TTextEditor (void);
  242.    ~TTextEditor (void);
  243.  
  244.    USHORT StartCol, StartRow;
  245.    USHORT Width, Height;
  246.    class  TCollection Text;
  247.  
  248.    USHORT Run (VOID);
  249.  
  250. private:
  251.    USHORT cx, cy;
  252.    CHAR   *Buffer, *Cursor;
  253.    ULONG  LineCrc[51];
  254.  
  255.    VOID   Display (USHORT line);
  256.    VOID   DisplayScreen (VOID);
  257.    PSZ    GetFirstChar (USHORT start, USHORT line);
  258.    VOID   GotoXY (USHORT x, USHORT y);
  259.    VOID   MoveCursor (USHORT start);
  260.    VOID   SetCursor (USHORT start);
  261. };
  262.  
  263. TTextEditor::TTextEditor (void)
  264. {
  265.    StartCol = 0;
  266.    StartRow = 7;
  267.    Width = 79;
  268.    Height = 17;
  269. }
  270.  
  271. TTextEditor::~TTextEditor (void)
  272. {
  273. }
  274.  
  275. VOID TTextEditor::GotoXY (USHORT x, USHORT y)
  276. {
  277.    gotoxy_ ((short)(y + StartRow - 1), (short)(x + StartCol - 1));
  278. }
  279.  
  280. VOID TTextEditor::Display (USHORT start)
  281. {
  282.    USHORT y, nCol, curLine;
  283.    CHAR *p = Buffer, Line[128], Temp[128];
  284.    ULONG Crc;
  285.  
  286.    nCol = 0;
  287.    curLine = 1;
  288.  
  289.    for (y = 1; y <= Height + 1; ) {
  290.       if (*p == '\0') {
  291.          Crc = StringCrc32 ("", 0xFFFFFFFFL);
  292.          if (Crc != LineCrc[y] && y <= Height) {
  293.             LineCrc[y] = Crc;
  294.             memset (Temp, ' ', Width);
  295.             Temp[Width] = '\0';
  296.             prints ((short)(y + StartRow - 1), StartCol, LGREY|_BLACK, Temp);
  297.          }
  298.          y++;
  299.       }
  300.       while (*p != '\0') {
  301.          if (Cursor == p) {
  302.             cx = (USHORT)(nCol + 1);
  303.             cy = y;
  304.          }
  305.          if (*p == '\n') {
  306.             p++;
  307.             Line[nCol] = '\0';
  308.             if (curLine >= start) {
  309.                Crc = StringCrc32 (Line, 0xFFFFFFFFL);
  310.                if (Crc != LineCrc[y] && y <= Height) {
  311.                   LineCrc[y] = Crc;
  312.                   memset (Temp, ' ', Width);
  313.                   Temp[Width] = '\0';
  314.                   prints ((short)(y + StartRow - 1), StartCol, LGREY|_BLACK, Temp);
  315.                   if (!strncmp (Line, "---", 3) || !strncmp (Line, " * Origin:", 10))
  316.                      prints ((short)(y + StartRow - 1), StartCol, WHITE|_BLACK, Line);
  317.                   else if (strchr (Line, '>') != NULL)
  318.                      prints ((short)(y + StartRow - 1), StartCol, YELLOW|_BLACK, Line);
  319.                   else if (*p == 0x01 || !strncmp (p, "SEEN-BY:", 8))
  320.                      prints ((short)(y + StartRow - 1), StartCol, CYAN|_BLACK, Line);
  321.                   else
  322.                      prints ((short)(y + StartRow - 1), StartCol, LGREY|_BLACK, Line);
  323.                }
  324.                y++;
  325.             }
  326.             curLine++;
  327.             nCol = 0;
  328.             break;
  329.          }
  330.          else {
  331.             Line[nCol++] = *p++;
  332.             if (nCol >= Width) {
  333.                Line[nCol] = '\0';
  334.                while (nCol > 1 && Line[nCol] != ' ') {
  335.                   nCol--;
  336.                   p--;
  337.                }
  338.                if (nCol > 1) {
  339.                   while (Line[nCol] == ' ') {
  340.                      nCol++;
  341.                      p++;
  342.                   }
  343.                }
  344.                Line[nCol] = '\0';
  345.  
  346.                if (curLine >= start) {
  347.                   Crc = StringCrc32 (Line, 0xFFFFFFFFL);
  348.                   if (Crc != LineCrc[y] && y <= Height) {
  349.                      LineCrc[y] = Crc;
  350.                      memset (Temp, ' ', Width);
  351.                      Temp[Width] = '\0';
  352.                      prints ((short)(y + StartRow - 1), StartCol, LGREY|_BLACK, Temp);
  353.                      if (!strncmp (Line, "---", 3) || !strncmp (Line, " * Origin:", 10))
  354.                         prints ((short)(y + StartRow - 1), StartCol, WHITE|_BLACK, Line);
  355.                      else if (strchr (Line, '>') != NULL)
  356.                         prints ((short)(y + StartRow - 1), StartCol, YELLOW|_BLACK, Line);
  357.                      else if (*p == 0x01 || !strncmp (p, "SEEN-BY:", 8))
  358.                         prints ((short)(y + StartRow - 1), StartCol, CYAN|_BLACK, Line);
  359.                      else
  360.                         prints ((short)(y + StartRow - 1), StartCol, LGREY|_BLACK, Line);
  361.                   }
  362.                   y++;
  363.                }
  364.                curLine++;
  365.  
  366.                nCol = 0;
  367.                break;
  368.             }
  369.          }
  370.       }
  371.    }
  372.  
  373.    if (cy <= Height)
  374.       GotoXY (cx, cy);
  375. }
  376.  
  377. VOID TTextEditor::MoveCursor (USHORT start)
  378. {
  379.    USHORT y, nCol, curLine;
  380.    CHAR *p = Buffer, Line[128];
  381.  
  382.    nCol = 0;
  383.    curLine = 1;
  384.  
  385.    for (y = 1; y <= Height; ) {
  386.       for (;;) {
  387.          if (Cursor == p) {
  388.             cx = (USHORT)(nCol + 1);
  389.             cy = y;
  390.          }
  391.          if (*p == '\n') {
  392.             p++;
  393.             Line[nCol] = '\0';
  394.             if (curLine >= start)
  395.                y++;
  396.             curLine++;
  397.             nCol = 0;
  398.             break;
  399.          }
  400.          else {
  401.             Line[nCol++] = *p++;
  402.             if (nCol >= Width) {
  403.                Line[nCol] = '\0';
  404.                while (nCol > 1 && Line[nCol] != ' ') {
  405.                   nCol--;
  406.                   p--;
  407.                }
  408.                if (nCol > 1) {
  409.                   while (Line[nCol] == ' ') {
  410.                      nCol++;
  411.                      p++;
  412.                   }
  413.                }
  414.                Line[nCol] = '\0';
  415.  
  416.                if (curLine >= start)
  417.                   y++;
  418.                curLine++;
  419.  
  420.                nCol = 0;
  421.                break;
  422.             }
  423.          }
  424.       }
  425.    }
  426.  
  427.    GotoXY (cx, cy);
  428. }
  429.  
  430. VOID TTextEditor::SetCursor (USHORT start)
  431. {
  432.    USHORT y, nCol, curLine;
  433.    CHAR *p = Buffer, Line[128];
  434.  
  435.    nCol = 0;
  436.    curLine = 1;
  437.  
  438.    for (y = 1; y <= Height; ) {
  439.       for (;;) {
  440.          if (cy == y && cx == (nCol + 1))
  441.             Cursor = p;
  442.          if (*p == '\n') {
  443.             p++;
  444.             Line[nCol] = '\0';
  445.             if (cy == y && cx > (nCol + 1)) {
  446.                Cursor = p - 1;
  447.                cx = (USHORT)(nCol + 1);
  448.             }
  449.             if (curLine >= start)
  450.                y++;
  451.             curLine++;
  452.             nCol = 0;
  453.             break;
  454.          }
  455.          else {
  456.             Line[nCol++] = *p++;
  457.             if (nCol >= Width) {
  458.                Line[nCol] = '\0';
  459.                while (nCol > 1 && Line[nCol] != ' ') {
  460.                   nCol--;
  461.                   p--;
  462.                }
  463.                if (nCol > 1) {
  464.                   while (Line[nCol] == ' ') {
  465.                      nCol++;
  466.                      p++;
  467.                   }
  468.                }
  469.                Line[nCol] = '\0';
  470.                if (cy == y && cx > (nCol + 1)) {
  471.                   Cursor = p - 1;
  472.                   cx = (USHORT)(nCol + 1);
  473.                }
  474.                if (curLine >= start)
  475.                   y++;
  476.                curLine++;
  477.                nCol = 0;
  478.                break;
  479.             }
  480.          }
  481.       }
  482.    }
  483.  
  484.    GotoXY (cx, cy);
  485. }
  486.  
  487. PSZ TTextEditor::GetFirstChar (USHORT start, USHORT line)
  488. {
  489.    USHORT y, nCol, curLine;
  490.    CHAR *p = Buffer, Line[128];
  491.    PSZ RetVal = NULL;
  492.  
  493.    nCol = 0;
  494.    curLine = 1;
  495.  
  496.    for (y = 1; y <= Height + 1; ) {
  497.       for (;;) {
  498.          if (line == y && nCol == 0)
  499.             RetVal = p;
  500.          if (*p == '\n') {
  501.             p++;
  502.             Line[nCol] = '\0';
  503.             if (curLine >= start)
  504.                y++;
  505.             curLine++;
  506.             nCol = 0;
  507.             break;
  508.          }
  509.          else {
  510.             Line[nCol++] = *p++;
  511.             if (nCol >= Width) {
  512.                Line[nCol] = '\0';
  513.                while (nCol > 1 && Line[nCol] != ' ') {
  514.                   nCol--;
  515.                   p--;
  516.                }
  517.                if (nCol > 1) {
  518.                   while (Line[nCol] == ' ') {
  519.                      nCol++;
  520.                      p++;
  521.                   }
  522.                }
  523.                Line[nCol] = '\0';
  524.                if (curLine >= start)
  525.                   y++;
  526.                curLine++;
  527.                nCol = 0;
  528.                break;
  529.             }
  530.          }
  531.       }
  532.    }
  533.  
  534.    if (*RetVal == '\0')
  535.       RetVal = NULL;
  536.  
  537.    return (RetVal);
  538. }
  539.  
  540. VOID TTextEditor::DisplayScreen (VOID)
  541. {
  542. }
  543.  
  544. USHORT TTextEditor::Run (VOID)
  545. {
  546.    int i, c;
  547.    unsigned int bytes;
  548.    USHORT RetVal = FALSE, lineStart = 1;
  549.    CHAR *a, *p;
  550.  
  551.    if (Text.First () == NULL)
  552.       Text.Add ("");
  553.  
  554.    showcur ();
  555.    DisplayScreen ();
  556.  
  557.    bytes = 0;
  558.    if ((p = (CHAR *)Text.First ()) != NULL)
  559.       do {
  560.          bytes += strlen (p) + 1;
  561.       } while ((p = (CHAR *)Text.Next ()) != NULL);
  562.  
  563.    if (bytes > 32767)
  564.       bytes += 10240;
  565.    else
  566.       bytes = 32767;
  567.    Buffer = (CHAR *)malloc (bytes);
  568.  
  569.    a = Buffer;
  570.    if ((p = (CHAR *)Text.First ()) != NULL)
  571.       do {
  572.          strcpy (a, p);
  573.          a = strchr (a, '\0');
  574.          strcpy (a, "\n");
  575.          a = strchr (a, '\0');
  576.       } while ((p = (CHAR *)Text.Next ()) != NULL);
  577.  
  578.    for (i = 0; i < 51; i++)
  579.       LineCrc[i] = 0L;
  580.  
  581.    Cursor = Buffer;
  582.    Display (1);
  583.  
  584.    while (RetVal == FALSE) {
  585.       videoupdate ();
  586.       while (!kbmhit ())
  587.          ;
  588.       c = getxch ();
  589.       if (c == 0x1B) {
  590.          hidecur ();
  591.          if (MessageBox (" Abort Message ", "Are you really sure ?") == TRUE)
  592.             break;
  593.          MoveCursor (lineStart);
  594.          showcur ();
  595.       }
  596.       else if ((c >= 32 && c <= 255 && c != 127) || c == 0x0D) {
  597.          if (c == 0x0D)
  598.             c = '\n';
  599.          memmove (Cursor + 1, Cursor, strlen (Cursor) + 1);
  600.          *Cursor++ = (CHAR)c;
  601.          Display (lineStart);
  602.       }
  603.       else if (c == 0x08 || c == 127) {
  604.          if (Cursor > Buffer) {
  605.             Cursor--;
  606.             memmove (Cursor, Cursor + 1, strlen (&Cursor[1]) + 1);
  607.             Display (lineStart);
  608.          }
  609.       }
  610.       else if (c == 0x19) { // CTRL-Y
  611.          if ((p = GetFirstChar (lineStart, cy)) != NULL) {
  612.             if ((a = GetFirstChar (lineStart, (USHORT)(cy + 1))) != NULL)
  613.                memmove (p, a, strlen (a) + 1);
  614.             else
  615.                strcpy (p, "\n");
  616.             SetCursor (lineStart);
  617.             Display (lineStart);
  618.          }
  619.       }
  620.       else {
  621.          switch (c) {
  622.             case 0x4D00:  // Freccia a destra
  623.                Cursor++;
  624.                if (*Cursor != '\0')
  625.                   MoveCursor (lineStart);
  626.                else
  627.                   Cursor--;
  628.                break;
  629.  
  630.             case 0x4B00:  // Freccia a sinistra
  631.                if (Cursor > Buffer) {
  632.                   Cursor--;
  633.                   MoveCursor (lineStart);
  634.                }
  635.                break;
  636.  
  637.             case 0x4800:  // Freccia su'
  638.                if (cy > 1) {
  639.                   cy--;
  640.                   SetCursor (lineStart);
  641.                }
  642.                else if (lineStart > 1) {
  643.                   lineStart--;
  644.                   SetCursor (lineStart);
  645.                   Display (lineStart);
  646.                }
  647.                break;
  648.  
  649.             case 0x5000:  // Freccia giu'
  650.                if (GetFirstChar (lineStart, (USHORT)(cy + 1)) != NULL) {
  651.                   cy++;
  652.                   if (cy > Height) {
  653.                      cy--;
  654.                      lineStart++;
  655.                      SetCursor (lineStart);
  656.                      Display (lineStart);
  657.                   }
  658.                   else
  659.                      SetCursor (lineStart);
  660.                }
  661.                break;
  662.  
  663.             case 0x5300:  // Delete
  664.                memmove (Cursor, Cursor + 1, strlen (&Cursor[1]) + 1);
  665.                Display (lineStart);
  666.                break;
  667.  
  668.             case 0x4700:  // Home
  669.                Cursor = GetFirstChar (lineStart, cy);
  670.                MoveCursor (lineStart);
  671.                break;
  672.  
  673.             case 0x4F00:  // End
  674.                if ((p = GetFirstChar (lineStart, (USHORT)(cy + 1))) == NULL)
  675.                   p = strchr (Cursor, '\0');
  676.                Cursor = p - 1;
  677.                MoveCursor (lineStart);
  678.                break;
  679.  
  680.             case 0x1F00:  // Alt-S = Save
  681.                hidecur ();
  682.                if (MessageBox (" Save Message ", "Are you really sure ?") == TRUE)
  683.                   RetVal = TRUE;
  684.                showcur ();
  685.                break;
  686.          }
  687.       }
  688.       if (cy > 25) {
  689.          lineStart++;
  690.          SetCursor (lineStart);
  691.          Display (lineStart);
  692.       }
  693.       else if (cy < 1 && lineStart > 1) {
  694.          lineStart--;
  695.          cy++;
  696.          Display (lineStart);
  697.       }
  698.    }
  699.  
  700.    hidecur ();
  701.  
  702.    Text.Clear ();
  703.  
  704.    if (RetVal == TRUE && Buffer != NULL) {
  705.       a = Buffer;
  706.       while ((p = strchr (a, '\n')) != NULL) {
  707.          if (p > a) {
  708.             p--;
  709.             if (*p == '\r')
  710.                *p = '\0';
  711.             p++;
  712.          }
  713.          *p = '\0';
  714.          Text.Add (a);
  715.          a = p + 1;
  716.       }
  717.       Text.Add (a);
  718.    }
  719.  
  720.    if (Buffer != NULL)
  721.       free (Buffer);
  722.  
  723.    return (RetVal);
  724. }
  725.  
  726. // ----------------------------------------------------------------------
  727.  
  728. VOID CScanDlg (VOID)
  729. {
  730.    USHORT IsUser = FALSE, EscPressed = FALSE;
  731.    ULONG LastRead;
  732.    class TMsgBase *Msg;
  733.    class TMsgData *Data;
  734.  
  735.    if (Scan != NULL)
  736.       Scan->Clear ();
  737.  
  738.    if ((User = new TUser (Cfg->UserFile)) != NULL) {
  739.      if (User->GetData (Cfg->SysopName) == TRUE)
  740.         IsUser = TRUE;
  741.    }
  742.  
  743.    Msg = NULL;
  744.    switch (Cfg->NetMailStorage) {
  745.       case ST_JAM:
  746.          Msg = new JAM (Cfg->NetMailPath);
  747.          break;
  748.       case ST_SQUISH:
  749.          Msg = new SQUISH (Cfg->NetMailPath);
  750.          break;
  751.       case ST_FIDO:
  752.          Msg = new FIDOSDM (Cfg->NetMailPath);
  753.          break;
  754.       case ST_ADEPT:
  755.          Msg = new ADEPT (Cfg->NetMailPath);
  756.          break;
  757.       case ST_HUDSON:
  758.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->NetMailBoard);
  759.          break;
  760.    }
  761.    if (Msg != NULL) {
  762.       LastRead = 0L;
  763.       if (IsUser == TRUE && User != NULL) {
  764.          if (User->MsgTag->Read ("NetMail") == TRUE)
  765.             LastRead = User->MsgTag->LastRead;
  766.       }
  767.  
  768.       if (Scan != NULL) {
  769.          strcpy (Scan->Key, "NetMail");
  770.          strcpy (Scan->Description, "FidoNet E-Mail");
  771.          Scan->Messages = Msg->Number ();
  772.          Scan->New = Msg->Number () - Msg->UidToMsgn (LastRead);
  773.          Scan->Tag[0] = '\0';
  774.          Scan->Add ();
  775.       }
  776.  
  777.       delete Msg;
  778.    }
  779.  
  780.    Msg = NULL;
  781.    switch (Cfg->MailStorage) {
  782.       case ST_JAM:
  783.          Msg = new JAM (Cfg->MailPath);
  784.          break;
  785.       case ST_SQUISH:
  786.          Msg = new SQUISH (Cfg->MailPath);
  787.          break;
  788.       case ST_FIDO:
  789.          Msg = new FIDOSDM (Cfg->MailPath);
  790.          break;
  791.       case ST_ADEPT:
  792.          Msg = new ADEPT (Cfg->MailPath);
  793.          break;
  794.       case ST_HUDSON:
  795.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->MailBoard);
  796.          break;
  797.    }
  798.    if (Msg != NULL) {
  799.       LastRead = 0L;
  800.       if (IsUser == TRUE && User != NULL) {
  801.          if (User->MsgTag->Read ("EMail") == TRUE)
  802.             LastRead = User->MsgTag->LastRead;
  803.       }
  804.  
  805.       if (Scan != NULL) {
  806.          strcpy (Scan->Key, "EMail");
  807.          strcpy (Scan->Description, "Personal E-Mail");
  808.          Scan->Messages = Msg->Number ();
  809.          Scan->New = Msg->Number () - Msg->UidToMsgn (LastRead);
  810.          Scan->Tag[0] = '\0';
  811.          Scan->Add ();
  812.       }
  813.  
  814.       delete Msg;
  815.    }
  816.  
  817.    Msg = NULL;
  818.    switch (Cfg->BadStorage) {
  819.       case ST_JAM:
  820.          Msg = new JAM (Cfg->BadPath);
  821.          break;
  822.       case ST_SQUISH:
  823.          Msg = new SQUISH (Cfg->BadPath);
  824.          break;
  825.       case ST_FIDO:
  826.          Msg = new FIDOSDM (Cfg->BadPath);
  827.          break;
  828.       case ST_ADEPT:
  829.          Msg = new ADEPT (Cfg->BadPath);
  830.          break;
  831.       case ST_HUDSON:
  832.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->BadBoard);
  833.          break;
  834.    }
  835.    if (Msg != NULL) {
  836.       LastRead = 0L;
  837.       if (IsUser == TRUE && User != NULL) {
  838.          if (User->MsgTag->Read ("BadMsgs") == TRUE)
  839.             LastRead = User->MsgTag->LastRead;
  840.       }
  841.  
  842.       if (Scan != NULL) {
  843.          strcpy (Scan->Key, "BadMsgs");
  844.          strcpy (Scan->Description, "Bad Messages");
  845.          Scan->Messages = Msg->Number ();
  846.          Scan->New = Msg->Number () - Msg->UidToMsgn (LastRead);
  847.          Scan->Tag[0] = '\0';
  848.          Scan->Add ();
  849.       }
  850.  
  851.       delete Msg;
  852.    }
  853.  
  854.    Msg = NULL;
  855.    switch (Cfg->DupeStorage) {
  856.       case ST_JAM:
  857.          Msg = new JAM (Cfg->DupePath);
  858.          break;
  859.       case ST_SQUISH:
  860.          Msg = new SQUISH (Cfg->DupePath);
  861.          break;
  862.       case ST_FIDO:
  863.          Msg = new FIDOSDM (Cfg->DupePath);
  864.          break;
  865.       case ST_ADEPT:
  866.          Msg = new ADEPT (Cfg->DupePath);
  867.          break;
  868.       case ST_HUDSON:
  869.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->DupeBoard);
  870.          break;
  871.    }
  872.    if (Msg != NULL) {
  873.       LastRead = 0L;
  874.       if (IsUser == TRUE && User != NULL) {
  875.          if (User->MsgTag->Read ("Dupes") == TRUE)
  876.             LastRead = User->MsgTag->LastRead;
  877.       }
  878.  
  879.       if (Scan != NULL) {
  880.          strcpy (Scan->Key, "Dupes");
  881.          strcpy (Scan->Description, "Duplicate Messages");
  882.          Scan->Messages = Msg->Number ();
  883.          Scan->New = Msg->Number () - Msg->UidToMsgn (LastRead);
  884.          Scan->Tag[0] = '\0';
  885.          Scan->Add ();
  886.       }
  887.  
  888.       delete Msg;
  889.    }
  890.  
  891.    wopen (11, 19, 13, 61, 0, LRED|_BLACK, YELLOW|_BLACK);
  892.    wshadow (DGREY|_BLACK);
  893.  
  894.    if ((Data = new TMsgData (Cfg->SystemPath)) != NULL) {
  895.       if (Data->First () == TRUE)
  896.          do {
  897.             if (kbmhit ()) {
  898.                if ((getxch () & 0xff) == 0x1b)
  899.                   EscPressed = TRUE;
  900.             }
  901.             if (EscPressed == FALSE) {
  902.                wcclear (YELLOW|_BLACK);
  903.                Data->Display[41] = '\0';
  904.                wprints (0, (short)((41 - strlen (Data->Display)) / 2), YELLOW|_BLACK, Data->Display);
  905.                videoupdate ();
  906.  
  907.                Msg = NULL;
  908.                switch (Data->Storage) {
  909.                  case ST_JAM:
  910.                     Msg = new JAM (Data->Path);
  911.                     break;
  912.                  case ST_SQUISH:
  913.                     Msg = new SQUISH (Data->Path);
  914.                     break;
  915.                  case ST_FIDO:
  916.                     Msg = new FIDOSDM (Data->Path);
  917.                     break;
  918.                  case ST_ADEPT:
  919.                     Msg = new ADEPT (Data->Path);
  920.                     break;
  921.                  case ST_HUDSON:
  922.                     Msg = new HUDSON (Data->Path, (UCHAR)Data->Board);
  923.                     break;
  924.                }
  925.  
  926.                if (Msg != NULL) {
  927.                   LastRead = 0L;
  928.                   if (IsUser == TRUE && User != NULL) {
  929.                      if (User->MsgTag->Read (Data->Key) == TRUE)
  930.                         LastRead = User->MsgTag->LastRead;
  931.                   }
  932.  
  933.                   if (Scan != NULL) {
  934.                      strcpy (Scan->Key, Data->Key);
  935.                      strcpy (Scan->Description, Data->Display);
  936.                      Scan->Messages = Msg->Number ();
  937.                      Scan->New = Msg->Number () - Msg->UidToMsgn (LastRead);
  938.                      strcpy (Scan->Tag, Data->EchoTag);
  939.                      Scan->Add ();
  940.                   }
  941.  
  942.                   delete Msg;
  943.                }
  944.             }
  945.          } while (Data->Next () == TRUE);
  946.    }
  947.  
  948.    wclose ();
  949. }
  950.  
  951. // ----------------------------------------------------------------------
  952.  
  953. VOID DisplayScreen (VOID)
  954. {
  955.    CHAR Temp[128];
  956.  
  957.    videoinit ();
  958.  
  959.    hidecur ();
  960.    if (wopen (0, 0, 24, 79, 5, LGREY|_BLACK, LGREY|_BLACK) != 0) {
  961. //      box_ (1, 0, 24, 79, 0, LGREY|_BLACK);
  962.       box_ (1, 0, 6, 79, 0, LGREY|_BLACK);
  963. //      whline (6, 0, 80, 0, LGREY|_BLACK);
  964.       whline (24, 0, 80, 0, LGREY|_BLACK);
  965.       if (Cfg->MailAddress.First () == TRUE)
  966.          prints (0, 1, LGREEN|_BLACK, Cfg->MailAddress.String);
  967. #if !defined(__POINT__)
  968.       sprintf (Temp, "%s Mail Reader v%s", NAME, VERSION);
  969. #else
  970.       sprintf (Temp, "%s v%s", NAME, VERSION);
  971. #endif
  972.       prints (0, (USHORT)(78 - strlen (Temp)), LGREEN|_BLACK, Temp);
  973.  
  974.       prints (2, 1, YELLOW|_BLACK, "    Msg:");
  975.       prints (3, 1, YELLOW|_BLACK, "   From:");
  976.       prints (4, 1, YELLOW|_BLACK, "     To:");
  977.       prints (5, 1, YELLOW|_BLACK, "Subject:");
  978.    }
  979.  
  980.    videoupdate ();
  981. }
  982.  
  983. VOID ParseAddress (PSZ text, PSZ name, PSZ address)
  984. {
  985.    CHAR Temp[128], *p, *a;
  986.  
  987.    strcpy (Temp, text);
  988.    if (strchr (Temp, '(') != NULL) {
  989.       if ((p = strtok (Temp, " ")) != NULL) {
  990.          if ((p = strtok (NULL, "")) != NULL) {
  991.             while (*p == ' ')
  992.                p++;
  993.             if (*p == '(') {
  994.                strcpy (Temp, ++p);
  995.                p = strchr (Temp, '\0');
  996.                while (--p > Temp) {
  997.                   if (*p == ')') {
  998.                      *p = '\0';
  999.                      break;
  1000.                   }
  1001.                }
  1002.                strcpy (name, Temp);
  1003.                strcpy (Temp, text);
  1004.                if ((p = strtok (Temp, " ")) != NULL)
  1005.                   strcpy (address, p);
  1006.             }
  1007.             else {
  1008.                strcpy (Temp, text);
  1009.                if ((p = strtok (Temp, " ")) != NULL)
  1010.                   strcpy (name, p);
  1011.             }
  1012.          }
  1013.       }
  1014.    }
  1015.    else if ((p = strchr (Temp, '<')) != NULL) {
  1016.       *p++ = '\0';
  1017.       if ((a = strchr (p, '>')) != NULL)
  1018.          *a = '\0';
  1019.       strcpy (address, p);
  1020.       p = Temp;
  1021.       if (*p == '"')
  1022.          strcpy (Temp, ++p);
  1023.       p = strchr (Temp, '\0');
  1024.       while (--p > Temp) {
  1025.          if (*p != ' ' && *p != '"')
  1026.             break;
  1027.          *p = '\0';
  1028.       }
  1029.       strcpy (name, Temp);
  1030.    }
  1031. }
  1032.  
  1033. VOID DisplayText (USHORT start)
  1034. {
  1035.    USHORT y;
  1036.    CHAR *p;
  1037.  
  1038.    if (Msg != NULL) {
  1039.       fill_ (7, 0, 23, 79, ' ', LGREY|_BLACK);
  1040.  
  1041.       y = 7;
  1042.       if ((p = (CHAR *)Msg->Text.First ()) != NULL)
  1043.          do {
  1044.             if ((*p != 0x01 && strncmp (p, "SEEN-BY:", 8)) || ShowKludges == TRUE) {
  1045.                if (start > 0)
  1046.                   start--;
  1047.                if (start == 0) {
  1048.                   if (!strcmp (p, "---") || !strncmp (p, "--- ", 4) || !strncmp (p, " * Origin: ", 11))
  1049.                      prints (y, 0, WHITE|_BLACK, p);
  1050.                   else if (strchr (p, '>') != NULL && (strchr (p, '>') - p) <= 6)
  1051.                      prints (y, 0, YELLOW|_BLACK, p);
  1052.                   else if (*p == 0x01 || !strncmp (p, "SEEN-BY:", 8))
  1053.                      prints (y, 0, CYAN|_BLACK, p);
  1054.                   else
  1055.                      prints (y, 0, LGREY|_BLACK, p);
  1056.                   y++;
  1057.                }
  1058.             }
  1059.          } while ((p = (CHAR *)Msg->Text.Next ()) != NULL && y < 24);
  1060.    }
  1061. }
  1062.  
  1063. VOID DisplayMessage (VOID)
  1064. {
  1065.    CHAR Temp[128], *p;
  1066.    USHORT gotFrom = FALSE, gotTo = FALSE;
  1067.    ULONG Msgn;
  1068.  
  1069.    TotalLines = 0;
  1070.  
  1071.    if (Msg != NULL) {
  1072.       if (Msg->Read (Number, 80) == FALSE) {
  1073.          Msg->New ();
  1074.          Msgn = 0L;
  1075.       }
  1076.       else
  1077.          Msgn = Msg->UidToMsgn (Number);
  1078.  
  1079.       if (Scan != NULL) {
  1080.          Scan->New = Msg->Number () - Msgn;
  1081.          Scan->Update ();
  1082.       }
  1083.  
  1084.       if ((p = (CHAR *)Msg->Text.First ()) != NULL)
  1085.          do {
  1086.             if ((*p != 0x01 && strncmp (p, "SEEN-BY:", 8)) || ShowKludges == TRUE)
  1087.                TotalLines++;
  1088.             if (!strncmp (p, " * Origin: ", 11)) {
  1089.                Msg->ToAddress[0] = '\0';
  1090.  
  1091.                strcpy (Temp, &p[11]);
  1092.                p = strchr (Temp, '\0');
  1093.                while (--p > Temp) {
  1094.                   if (*p != ' ' && *p != ')')
  1095.                      break;
  1096.                   *p = '\0';
  1097.                }
  1098.                if (p > Temp) {
  1099.                   while (--p > Temp) {
  1100.                      if (*p == '(' || *p == ' ')
  1101.                         break;
  1102.                   }
  1103.                }
  1104.                if (*p == '(' || *p == ' ')
  1105.                   p++;
  1106.                strcpy (Msg->FromAddress, p);
  1107.  
  1108.                if (strchr (p, '@') == NULL && strchr (p, ':') == NULL && strchr (p, '/') == NULL) {
  1109.                   if ((p = (CHAR *)Msg->Text.Next ()) != NULL) {
  1110.                      Msg->ToAddress[0] = '\0';
  1111.  
  1112.                      strcpy (Temp, p);
  1113.                      p = strchr (Temp, '\0');
  1114.                      while (--p > Temp) {
  1115.                         if (*p != ' ' && *p != ')')
  1116.                            break;
  1117.                         *p = '\0';
  1118.                      }
  1119.                      if (p > Temp) {
  1120.                         while (--p > Temp) {
  1121.                            if (*p == '(' || *p == ' ')
  1122.                               break;
  1123.                         }
  1124.                      }
  1125.                      if (*p == '(' || *p == ' ')
  1126.                         p++;
  1127.                      strcpy (Msg->FromAddress, p);
  1128.                   }
  1129.                }
  1130.             }
  1131.             else if (!strncmp (p, "\001MSGID: ", 8)) {
  1132.                strcpy (Temp, &p[8]);
  1133.                if ((p = strtok (Temp, " ")) != NULL) {
  1134.                   if (strchr (p, ':') != NULL && strchr (p, '/') != NULL) {
  1135.                      Msg->ToAddress[0] = '\0';
  1136.                      strcpy (Msg->FromAddress, p);
  1137.                   }
  1138.                }
  1139.             }
  1140.             else if (!strncmp (p, "\001From: ", 7)) {
  1141.                Msg->FromAddress[0] = '\0';
  1142.                if (gotTo == FALSE)
  1143.                   Msg->ToAddress[0] = '\0';
  1144.                ParseAddress (&p[7], Msg->From, Msg->FromAddress);
  1145.                gotFrom = TRUE;
  1146.             }
  1147.             else if (!strncmp (p, "\001To: ", 5)) {
  1148.                if (gotFrom == FALSE)
  1149.                   Msg->FromAddress[0] = '\0';
  1150.                Msg->ToAddress[0] = '\0';
  1151.                ParseAddress (&p[5], Msg->To, Msg->ToAddress);
  1152.                gotTo = TRUE;
  1153.             }
  1154.          } while ((p = (CHAR *)Msg->Text.Next ()) != NULL);
  1155.  
  1156.       sprintf (Temp, "%lu of %lu (%lu left)                        ", Msgn, Msg->Number (), Msg->Number () - Msgn);
  1157.       prints (2, 10, LGREY|_BLACK, Temp);
  1158.       sprintf (Temp, "%-30.30s", Msg->From);
  1159.       if (!stricmp (Msg->From, Cfg->SysopName))
  1160.          prints (3, 10, WHITE|_BLACK, Temp);
  1161.       else
  1162.          prints (3, 10, LGREY|_BLACK, Temp);
  1163.       sprintf (Temp, "%-16.16s", Msg->FromAddress);
  1164.       prints (3, 41, LGREY|_BLACK, Temp);
  1165.       if (Msgn != 0L) {
  1166.          sprintf (Temp, "%02d %s %d %2d:%02d:%02d", Msg->Written.Day, Months[Msg->Written.Month - 1], Msg->Written.Year, Msg->Written.Hour, Msg->Written.Minute, Msg->Written.Minute);
  1167.          prints (3, 59, LGREY|_BLACK, Temp);
  1168.       }
  1169.       else
  1170.          prints (3, 59, LGREY|_BLACK, "                    ");
  1171.  
  1172.       sprintf (Temp, "%-30.30s", Msg->To);
  1173.       if (!stricmp (Msg->To, Cfg->SysopName))
  1174.          prints (4, 10, WHITE|_BLACK, Temp);
  1175.       else
  1176.          prints (4, 10, LGREY|_BLACK, Temp);
  1177.       sprintf (Temp, "%-16.16s", Msg->ToAddress);
  1178.       prints (4, 41, LGREY|_BLACK, Temp);
  1179.       if (Msgn != 0L) {
  1180.          sprintf (Temp, "%02d %s %d %2d:%02d:%02d", Msg->Arrived.Day, Months[Msg->Arrived.Month - 1], Msg->Arrived.Year, Msg->Arrived.Hour, Msg->Arrived.Minute, Msg->Arrived.Second);
  1181.          prints (4, 59, LGREY|_BLACK, Temp);
  1182.       }
  1183.       else
  1184.          prints (4, 59, LGREY|_BLACK, "                    ");
  1185.  
  1186.       sprintf (Temp, "%-69.69s", Msg->Subject);
  1187.       prints (5, 10, LGREY|_BLACK, Temp);
  1188.  
  1189.       DisplayText (1);
  1190.    }
  1191. }
  1192.  
  1193. VOID ExportMessage (VOID)
  1194. {
  1195.    FILE *fp;
  1196.    CHAR *p, Temp[128], Key[32];
  1197.    ULONG Msgn;
  1198.  
  1199.    TotalLines = 0;
  1200.  
  1201.    if (Msg != NULL) {
  1202.       Msgn = Msg->UidToMsgn (Number);
  1203.  
  1204.       if ((fp = fopen ("reader.out", "at")) != NULL) {
  1205.          strcpy (Temp, "───────────────────────────────────────────────────────────────────────────────");
  1206.          sprintf (Key, " %s ", AreaKey);
  1207.          memcpy (&Temp[1], Key, strlen (Key));
  1208.          fprintf (fp, "%s\n", Temp);
  1209.          fprintf (fp, "     Msg: %lu of %lu\n", Msgn, Msg->Number ());
  1210.          fprintf (fp, "    From: %-30.30s %-16.16s %02d %s %d %2d:%02d:%02d\n", Msg->From, Msg->FromAddress, Msg->Written.Day, Months[Msg->Written.Month - 1], Msg->Written.Year, Msg->Written.Hour, Msg->Written.Minute, Msg->Written.Minute);
  1211.          fprintf (fp, "      To: %-30.30s %-16.16s %02d %s %d %2d:%02d:%02d\n", Msg->To, Msg->ToAddress, Msg->Arrived.Day, Months[Msg->Arrived.Month - 1], Msg->Arrived.Year, Msg->Arrived.Hour, Msg->Arrived.Minute, Msg->Arrived.Minute);
  1212.          fprintf (fp, " Subject: %.69s\n", Msg->Subject);
  1213.          strcpy (Temp, "───────────────────────────────────────────────────────────────────────────────");
  1214.          fprintf (fp, "%s\n", Temp);
  1215.  
  1216.          if ((p = (CHAR *)Msg->Text.First ()) != NULL)
  1217.             do {
  1218.                if ((*p != 0x01 && strncmp (p, "SEEN-BY:", 8)) || ShowKludges == TRUE) {
  1219.                   if (*p == 0x01)
  1220.                      *p = '@';
  1221.                   fprintf (fp, "%s\n", p);
  1222.                }
  1223.             } while ((p = (CHAR *)Msg->Text.Next ()) != NULL);
  1224.  
  1225.          fprintf (fp, "\n");
  1226.  
  1227.          fclose (fp);
  1228.       }
  1229.    }
  1230. }
  1231.  
  1232. VOID ClearScreen (VOID)
  1233. {
  1234.    wcloseall ();
  1235.    showcur ();
  1236.    videoupdate ();
  1237.    closevideo ();
  1238. }
  1239.  
  1240. USHORT ChangeArea (VOID)
  1241. {
  1242.    int i;
  1243.    USHORT start, RetVal = FALSE;
  1244.    CHAR Temp[128], **Array, *p;
  1245.    struct stat statbuf;
  1246.    class TCollection List;
  1247.  
  1248.    if (wopen (4, 2, 22, 76, 0, LCYAN|_BLACK, BLUE|_BLACK) != 0) {
  1249.       wtitle (" Area List ", TCENTER, LCYAN|_BLACK);
  1250.       wshadow (DGREY|_BLACK);
  1251.       wprints (0, 0, YELLOW|_BLACK, " Key             Msgs.    New  Description                               ");
  1252.  
  1253.       sprintf (Temp, "%sarealist.rsn", Cfg->SystemPath);
  1254.       if (stat (Temp, &statbuf) == 0) {
  1255.          DoRescan = TRUE;
  1256.          unlink (Temp);
  1257.       }
  1258.  
  1259.       if (Scan == NULL)
  1260.          Scan = new TScan;
  1261.       if (Scan != NULL && DoRescan == TRUE) {
  1262.          CScanDlg ();
  1263.          DoRescan = FALSE;
  1264.       }
  1265.  
  1266.       start = 0;
  1267.       i = 0;
  1268.       if (Scan->First () == TRUE)
  1269.          do {
  1270.             sprintf (Temp, " %-15.15s %5lu  %5lu  %-41.41s ", Scan->Key, Scan->Messages, Scan->New, Scan->Description);
  1271.             List.Add (Temp);
  1272.             if (!stricmp (Scan->Key, AreaKey))
  1273.                start = (short)i;
  1274.             i++;
  1275.          } while (Scan->Next () == TRUE);
  1276.  
  1277.       if (List.Elements > 0) {
  1278.          i = 0;
  1279.          Array = (CHAR **)malloc ((List.Elements + 1) * sizeof (CHAR *));
  1280.          if ((p = (CHAR *)List.First ()) != NULL)
  1281.             do {
  1282.                Array[i++] = p;
  1283.             } while ((p = (CHAR *)List.Next ()) != NULL);
  1284.          Array[i] = NULL;
  1285.          if ((i = wpickstr (6, 3, 21, 75, 5, LGREY|_BLACK, LGREY|_BLACK, WHITE|_BLUE, Array, start, NULL)) != -1) {
  1286.             Temp[0] = '\0';
  1287.             if ((p = strtok (Array[i], " ")) != NULL)
  1288.                strcpy (Temp, p);
  1289.             NetMail = BadMsgs = Dupes = EMail = FALSE;
  1290.  
  1291.             if (Scan != NULL)
  1292.                Scan->Read (Temp);
  1293.             if (!stricmp (Temp, "NetMail"))
  1294.                NetMail = TRUE;
  1295.             else if (!stricmp (Temp, "EMail"))
  1296.                EMail = TRUE;
  1297.             else if (!stricmp (Temp, "BadMsgs"))
  1298.                BadMsgs = TRUE;
  1299.             else if (!stricmp (Temp, "Dupes"))
  1300.                Dupes = TRUE;
  1301.             else
  1302.                Data->Read (Temp, FALSE);
  1303.             RetVal = TRUE;
  1304.          }
  1305.          if (Array != NULL)
  1306.             free (Array);
  1307.       }
  1308.       else
  1309.          getxch ();
  1310.  
  1311.       wclose ();
  1312.    }
  1313.  
  1314.    return (RetVal);
  1315. }
  1316.  
  1317. USHORT CMessageListDlg (VOID)
  1318. {
  1319.    int i;
  1320.    USHORT start, RetVal = FALSE;
  1321.    CHAR Temp[128], **Array, *p;
  1322.    ULONG ListNumber;
  1323.    class TCollection List;
  1324.  
  1325.    if (wopen (4, 2, 22, 76, 0, LCYAN|_BLACK, BLUE|_BLACK) != 0) {
  1326.       wtitle (" Message List ", TCENTER, LCYAN|_BLACK);
  1327.       wshadow (DGREY|_BLACK);
  1328.       wprints (0, 0, YELLOW|_BLACK, " Num. From              To                Subject");
  1329.       videoupdate ();
  1330.  
  1331.       start = 0;
  1332.       i = 0;
  1333.       ListNumber = Msg->Lowest ();
  1334.       do {
  1335.          if (Msg->ReadHeader (ListNumber) == TRUE) {
  1336.             sprintf (Temp, " %4lu %-16.16s  %-16.16s  %.30s ", Msg->UidToMsgn (ListNumber), Msg->From, Msg->To, Msg->Subject);
  1337.             List.Add (Temp);
  1338.             if (Number == ListNumber)
  1339.                start = (short)i;
  1340.             i++;
  1341.          }
  1342.       } while (Msg->Next (ListNumber) == TRUE);
  1343.  
  1344.       if (List.Elements > 0) {
  1345.          i = 0;
  1346.          Array = (CHAR **)malloc ((List.Elements + 1) * sizeof (CHAR *));
  1347.          if ((p = (CHAR *)List.First ()) != NULL)
  1348.             do {
  1349.                Array[i++] = p;
  1350.             } while ((p = (CHAR *)List.Next ()) != NULL);
  1351.          Array[i] = NULL;
  1352.          if ((i = wpickstr (6, 3, 21, 75, 5, LGREY|_BLACK, LGREY|_BLACK, WHITE|_BLUE, Array, start, NULL)) != -1) {
  1353.             Temp[0] = '\0';
  1354.             if ((p = strtok (Array[i], " ")) != NULL)
  1355.                strcpy (Temp, p);
  1356.             Number = Msg->MsgnToUid (atol (Temp));
  1357.             RetVal = TRUE;
  1358.          }
  1359.          if (Array != NULL)
  1360.             free (Array);
  1361.       }
  1362.       else
  1363.          getxch ();
  1364.  
  1365.       wclose ();
  1366.    }
  1367.  
  1368.    return (RetVal);
  1369. }
  1370.  
  1371. USHORT CMsgHeaderDlg (VOID)
  1372. {
  1373.    int menu_sel = 996;
  1374.    USHORT RetVal = FALSE;
  1375.  
  1376.    wopen (7, 2, 14, 76, 1, WHITE|_LGREY, WHITE|_LGREY);
  1377.    wshadow (DGREY|_BLACK);
  1378.    wtitle (" New Message ", TCENTER, WHITE|_LGREY);
  1379.  
  1380.    DisplayButton (4, 2, "   Ok   ");
  1381.    DisplayButton (4, 12, " Cancel ");
  1382.  
  1383.    do {
  1384.       wmenubegc ();
  1385.       wmenuitem (0, 1, " From    ", 0, 1, 0, NULL, 0, 0);
  1386.       wmenuitem (0, 42, " From Address ", 0, 2, 0, NULL, 0, 0);
  1387.       wmenuitem (1, 1, " To      ", 0, 3, 0, NULL, 0, 0);
  1388.       wmenuitem (1, 42, " To Address   ", 0, 4, 0, NULL, 0, 0);
  1389.       wmenuitem (2, 1, " Subject ", 0, 5, 0, NULL, 0, 0);
  1390.       wmenuitem (4, 2, "   Ok   ", 'O', 996, 0, NULL, 0, 0);
  1391.       wmenuitem (4, 12, " Cancel ", 'C', 997, 0, NULL, 0, 0);
  1392.       wmenuend ((short)menu_sel, M_OMNI|M_SAVE, 0, 0, BLACK|_GREEN, YELLOW|_GREEN, DGREY|_GREEN, WHITE|_GREEN);
  1393.  
  1394.       DisplayTextField (0, 11, Msg->From, 30, 30);
  1395.       DisplayTextField (0, 57, Msg->FromAddress, 15, 15);
  1396.       DisplayTextField (1, 11, Msg->To, 30, 30);
  1397.       DisplayTextField (1, 57, Msg->ToAddress, 15, 15);
  1398.       DisplayTextField (2, 11, Msg->Subject, 61, 61);
  1399.  
  1400.       switch (menu_sel = wmenuget ()) {
  1401.          case 1:
  1402.             GetTextField (0, 11, Msg->From, 30, 30);
  1403.             break;
  1404.          case 2:
  1405.             GetTextField (0, 57, Msg->FromAddress, 15, 15);
  1406.             break;
  1407.          case 3:
  1408.             GetTextField (1, 11, Msg->To, 30, 30);
  1409.             break;
  1410.          case 4:
  1411.             GetTextField (1, 57, Msg->ToAddress, 15, 15);
  1412.             break;
  1413.          case 5:
  1414.             GetTextField (2, 11, Msg->Subject, 61, 61);
  1415.             break;
  1416.          case 996:
  1417.             RetVal = TRUE;
  1418.             break;
  1419.          case 997:
  1420.             RetVal = FALSE;
  1421.             break;
  1422.       }
  1423.    } while (menu_sel != -1 && menu_sel != 996 && menu_sel != 997);
  1424.  
  1425.    wclose ();
  1426.  
  1427.    return (RetVal);
  1428. }
  1429.  
  1430. VOID EditMessage (USHORT Reply, USHORT DoQuote)
  1431. {
  1432.    int i;
  1433.    CHAR Temp[128], Quote[16], FidoAddress[64], *p;
  1434.    CHAR Header[128], Footer[128];
  1435.    class TTextEditor *Editor;
  1436.    struct dostime_t d_time;
  1437.    struct dosdate_t d_date;
  1438.  
  1439.    if (Reply == TRUE) {
  1440.       if (Msg->Read (Number, 72) == FALSE) {
  1441.          Msg->New ();
  1442.          Reply = FALSE;
  1443.       }
  1444.    }
  1445.  
  1446.    _dos_getdate (&d_date);
  1447.    _dos_gettime (&d_time);
  1448.  
  1449.    if (Msg != NULL) {
  1450.       if (Reply == TRUE) {
  1451.          strcpy (FidoAddress, Msg->FromAddress);
  1452.  
  1453.          if ((p = (CHAR *)Msg->Text.First ()) != NULL)
  1454.             do {
  1455.                if (!strncmp (p, " * Origin: ", 11)) {
  1456.                   Msg->ToAddress[0] = '\0';
  1457.  
  1458.                   strcpy (Temp, &p[11]);
  1459.                   p = strchr (Temp, '\0');
  1460.                   while (--p > Temp) {
  1461.                      if (*p != ' ' && *p != ')')
  1462.                         break;
  1463.                      *p = '\0';
  1464.                   }
  1465.                   if (p > Temp) {
  1466.                      while (--p > Temp) {
  1467.                         if (*p == '(' || *p == ' ')
  1468.                            break;
  1469.                      }
  1470.                   }
  1471.                   if (*p == '(' || *p == ' ')
  1472.                      p++;
  1473.                   strcpy (Msg->FromAddress, p);
  1474.                   strcpy (FidoAddress, p);
  1475.                   break;
  1476.                }
  1477.                else if (!strncmp (p, "\001MSGID: ", 8)) {
  1478.                   strcpy (Temp, &p[8]);
  1479.                   if ((p = strtok (Temp, " ")) != NULL) {
  1480.                      if (strchr (p, ':') != NULL && strchr (p, '/') != NULL) {
  1481.                         Msg->ToAddress[0] = '\0';
  1482.                         strcpy (Msg->FromAddress, p);
  1483.                         strcpy (FidoAddress, p);
  1484.                      }
  1485.                   }
  1486.                   break;
  1487.                }
  1488.                else if (!strncmp (p, "\001From: ", 7)) {
  1489.                   Msg->FromAddress[0] = '\0';
  1490.                   Msg->ToAddress[0] = '\0';
  1491.                   ParseAddress (&p[7], Msg->From, Msg->FromAddress);
  1492.                   break;
  1493.                }
  1494.             } while ((p = (CHAR *)Msg->Text.Next ()) != NULL);
  1495.  
  1496.          if (DoQuote == TRUE) {
  1497.             Quote[0] = ' ';
  1498.             Quote[1] = '\0';
  1499.             i = 1;
  1500.  
  1501.             strcpy (Temp, Msg->From);
  1502.             if ((p = strtok (Temp, " ")) != NULL)
  1503.                do {
  1504.                   Quote[i++] = *p;
  1505.                } while ((p = strtok (NULL, " ")) != NULL);
  1506.  
  1507.             Quote[i++] = '>';
  1508.             Quote[i++] = ' ';
  1509.             Quote[i] = '\0';
  1510.          }
  1511.  
  1512.          Cfg->MailAddress.First ();
  1513.  
  1514.          strcpy (Msg->To, Msg->From);
  1515.          strcpy (Msg->ToAddress, Msg->FromAddress);
  1516.          strcpy (Msg->From, Cfg->SysopName);
  1517.          strcpy (Msg->FromAddress, Cfg->MailAddress.String);
  1518.       }
  1519.       else {
  1520.          Msg->New ();
  1521.          Cfg->MailAddress.First ();
  1522.  
  1523.          strcpy (Msg->To, "All");
  1524.          strcpy (Msg->From, Cfg->SysopName);
  1525.          strcpy (Msg->FromAddress, Cfg->MailAddress.String);
  1526.       }
  1527.  
  1528.       if (CMsgHeaderDlg () == TRUE) {
  1529.          strcpy (Temp, Msg->To);
  1530.          if ((p = strtok (Temp, " ")) != NULL)
  1531.             sprintf (Header, "Hello, %s!\n", p);
  1532.          else
  1533.             sprintf (Header, "Hello!\n");
  1534.  
  1535.          if (Scan != NULL && Scan->Tag[0] != '\0') {
  1536.             Cfg->MailAddress.First ();
  1537.             sprintf (Footer, " \n--- %s v%s\n * Origin: %s (%s)", NAME, VERSION, Cfg->SystemName, Cfg->MailAddress.String);
  1538.          }
  1539.          else
  1540.             sprintf (Footer, " \n--- %s v%s", NAME, VERSION);
  1541.  
  1542.          Msg->Written.Day = Msg->Arrived.Day = d_date.day;
  1543.          Msg->Written.Month = Msg->Arrived.Month = d_date.month;
  1544.          Msg->Written.Year = Msg->Arrived.Year = d_date.year;
  1545.          Msg->Written.Hour = Msg->Arrived.Hour = d_time.hour;
  1546.          Msg->Written.Minute = Msg->Arrived.Minute = d_time.minute;
  1547.          Msg->Written.Second = Msg->Arrived.Second = d_time.second;
  1548.  
  1549.          sprintf (Temp, "%lu of %lu                                   ", Msg->Number () + 1L, Msg->Number () + 1L);
  1550.          prints (2, 10, LGREY|_BLACK, Temp);
  1551.          sprintf (Temp, "%-30.30s", Msg->From);
  1552.          prints (3, 10, LGREY|_BLACK, Temp);
  1553.          sprintf (Temp, "%-16.16s", Msg->FromAddress);
  1554.          prints (3, 41, LGREY|_BLACK, Temp);
  1555.          sprintf (Temp, "%02d %s %d %2d:%02d:%02d", Msg->Written.Day, Months[Msg->Written.Month - 1], Msg->Written.Year, Msg->Written.Hour, Msg->Written.Minute, Msg->Written.Minute);
  1556.          prints (3, 59, LGREY|_BLACK, Temp);
  1557.  
  1558.          sprintf (Temp, "%-30.30s", Msg->To);
  1559.          prints (4, 10, LGREY|_BLACK, Temp);
  1560.          sprintf (Temp, "%-16.16s", Msg->ToAddress);
  1561.          prints (4, 41, LGREY|_BLACK, Temp);
  1562.          sprintf (Temp, "%02d %s %d %2d:%02d:%02d", Msg->Arrived.Day, Months[Msg->Arrived.Month - 1], Msg->Arrived.Year, Msg->Arrived.Hour, Msg->Arrived.Minute, Msg->Arrived.Second);
  1563.          prints (4, 59, LGREY|_BLACK, Temp);
  1564.  
  1565.          sprintf (Temp, "%-68.68s", Msg->Subject);
  1566.          prints (5, 10, LGREY|_BLACK, Temp);
  1567.  
  1568.          if ((Editor = new TTextEditor) != NULL) {
  1569.             Editor->Text.Add (Header);
  1570.             while ((p = (CHAR *)Msg->Text.First ()) != NULL) {
  1571.                if (((*p != 0x01 && strncmp (p, "SEEN-BY:", 8)) || ShowKludges == TRUE) && DoQuote == TRUE) {
  1572.                   sprintf (Temp, "%s%s", Quote, p);
  1573.                   Editor->Text.Add (Temp);
  1574.                }
  1575.                Msg->Text.Remove ();
  1576.             }
  1577.             Editor->Text.Add (Footer);
  1578.  
  1579.             if (Editor->Run () == TRUE)
  1580.                Msg->Add (Editor->Text);
  1581.  
  1582.             delete Editor;
  1583.          }
  1584.       }
  1585.    }
  1586. }
  1587.  
  1588. VOID CHelpDlg (VOID)
  1589. {
  1590.    if (wopen (4, 14, 22, 76, 0, YELLOW|_BLACK, BLUE|_BLACK) != 0) {
  1591.       wtitle (" Help ", TCENTER, YELLOW|_BLACK);
  1592.       wshadow (DGREY|_BLACK);
  1593.       prints (22, 16, YELLOW|_BLACK, " Press any key to close ");
  1594.  
  1595.       wprints (0,  1, LGREY|_BLACK, "A, Alt-A        Change message area");
  1596.       wprints (1,  1, LGREY|_BLACK, "E, Alt-E, Ins   Write new message");
  1597.       wprints (2,  1, LGREY|_BLACK, "L, Alt-L        List messages");
  1598.       wprints (3,  1, LGREY|_BLACK, "R, Alt-R        Reply to current message");
  1599.       wprints (4,  1, LGREY|_BLACK, "Q, Alt-Q        Reply to current message (quoted)");
  1600.       wprints (5,  1, LGREY|_BLACK, "V, Alt-V        Show/hide kludge lines");
  1601.       wprints (6,  1, LGREY|_BLACK, "W, Alt-W        Write current message to disk (READER.OUT)");
  1602.       wprints (7,  1, LGREY|_BLACK, "X, Alt-X        Exit");
  1603.       wprints (8,  1, LGREY|_BLACK, "Right           Next message");
  1604.       wprints (9,  1, LGREY|_BLACK, "Left            Previous message");
  1605.       wprints (10, 1, LGREY|_BLACK, "End             Display last part of current message");
  1606.       wprints (11, 1, LGREY|_BLACK, "Home            Display first part of current message");
  1607.       wprints (12, 1, LGREY|_BLACK, "Down            Scroll message display");
  1608.       wprints (13, 1, LGREY|_BLACK, "Up              Scroll message display");
  1609.       wprints (14, 1, LGREY|_BLACK, "PgDn            Display next page of message");
  1610.       wprints (15, 1, LGREY|_BLACK, "PgUp            Display previous page of message");
  1611.  
  1612.       getxch ();
  1613.       wclose ();
  1614.    }
  1615. }
  1616.  
  1617. void main (int argc, char *argv[])
  1618. {
  1619.    int i;
  1620.    USHORT Line, EndRun;
  1621.    CHAR Temp[128], *Config, *Channel;
  1622.    time_t t, last_time = 0;
  1623.    struct tm *ltm;
  1624.  
  1625.    Config = Channel = NULL;
  1626.  
  1627.    for (i = 1; i < argc; i++) {
  1628.       if (Config == NULL)
  1629.          Config = argv[i];
  1630.       else if (Channel == NULL)
  1631.          Channel = argv[i];
  1632.    }
  1633.  
  1634.    if (Config == NULL)
  1635.       Config = getenv ("LORA_CONFIG");
  1636.    if (Channel == NULL)
  1637.       Channel = getenv ("LORA_CHANNEL");
  1638.  
  1639.    if ((Cfg = new TConfig) != NULL) {
  1640.       Cfg->TaskNumber = 1;
  1641.       if (Cfg->Load (Config, Channel) == FALSE)
  1642.          Cfg->Default ();
  1643.    }
  1644.  
  1645.    Data = new TMsgData (Cfg->SystemPath);
  1646.    Scan = NULL;
  1647.  
  1648.    DisplayScreen ();
  1649.  
  1650.    Msg = NULL;
  1651.    switch (Cfg->NetMailStorage) {
  1652.       case ST_JAM:
  1653.          Msg = new JAM (Cfg->NetMailPath);
  1654.          break;
  1655.       case ST_SQUISH:
  1656.          Msg = new SQUISH (Cfg->NetMailPath);
  1657.          break;
  1658.       case ST_FIDO:
  1659.          Msg = new FIDOSDM (Cfg->NetMailPath);
  1660.          break;
  1661.       case ST_ADEPT:
  1662.          Msg = new ADEPT (Cfg->NetMailPath);
  1663.          break;
  1664.       case ST_HUDSON:
  1665.          Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->NetMailBoard);
  1666.          break;
  1667.    }
  1668.  
  1669.    NetMail = TRUE;
  1670.    strcpy (AreaKey, "NetMail");
  1671.    Number = 0L;
  1672.    if ((User = new TUser (Cfg->UserFile)) != NULL) {
  1673.       if (User->GetData (Cfg->SysopName) == TRUE) {
  1674.          if (User->MsgTag->Read (AreaKey) == TRUE)
  1675.             Number = User->MsgTag->LastRead;
  1676.       }
  1677.       delete User;
  1678.    }
  1679.    if (Msg->ReadHeader (Number) == FALSE) {
  1680.       if (Msg->Next (Number) == FALSE)
  1681.          Msg->Previous (Number);
  1682.    }
  1683.  
  1684.    DisplayMessage ();
  1685.    Line = 1;
  1686.    prints (1, 1, LCYAN|_BLACK, " NetMail ");
  1687.    videoupdate ();
  1688.  
  1689.    kbput (0x1E00);
  1690.  
  1691.    EndRun = FALSE;
  1692.    while (EndRun == FALSE) {
  1693.       if (kbmhit ()) {
  1694.          switch (getxch ()) {
  1695.             case 0x3B00:
  1696.                CHelpDlg ();
  1697.                break;
  1698.             case 0x5000:   // Freccia giu'
  1699.                if ((TotalLines - Line + 1) > 17)
  1700.                   DisplayText (++Line);
  1701.                break;
  1702.             case 0x5100:   // Pagina giu'
  1703.                if ((TotalLines - Line + 1) > 17) {
  1704.                   Line += 17;
  1705.                   DisplayText (Line);
  1706.                }
  1707.                break;
  1708.             case 0x4800:   // Freccia su
  1709.                if (Line > 1)
  1710.                   DisplayText (--Line);
  1711.                break;
  1712.             case 0x4900:   // Pagina su
  1713.                if (Line > 17) {
  1714.                   Line -= 17;
  1715.                   DisplayText (Line);
  1716.                }
  1717.                else if (Line > 1) {
  1718.                   Line = 1;
  1719.                   DisplayText (Line);
  1720.                }
  1721.                break;
  1722.             case 0x4D00:   // Freccia destra
  1723.                if (Msg->Next (Number) == TRUE) {
  1724.                   DisplayMessage ();
  1725.                   Line = 1;
  1726.                }
  1727.                break;
  1728.             case 0x4B00:   // Freccia sinistra
  1729.                if (Msg->Previous (Number) == TRUE) {
  1730.                   DisplayMessage ();
  1731.                   Line = 1;
  1732.                }
  1733.                break;
  1734.             case 0x7500:   // Ctrl-End
  1735.                Number = Msg->Highest ();
  1736.                DisplayMessage ();
  1737.                Line = 1;
  1738.                break;
  1739.             case 0x7700:   // Ctrl-Home
  1740.                Number = Msg->Lowest ();
  1741.                DisplayMessage ();
  1742.                Line = 1;
  1743.                break;
  1744.             case 'A':
  1745.             case 0x1E00:   // Alt-A  - Cambio Area
  1746.                if ((User = new TUser (Cfg->UserFile)) != NULL) {
  1747.                   if (User->GetData (Cfg->SysopName) == TRUE) {
  1748.                      if (User->MsgTag->Read (AreaKey) == TRUE) {
  1749.                         User->MsgTag->LastRead = Number;
  1750.                         User->MsgTag->Update ();
  1751.                      }
  1752.                      else {
  1753.                         User->MsgTag->New ();
  1754.                         strcpy (User->MsgTag->Area, AreaKey);
  1755.                         User->MsgTag->Tagged = FALSE;
  1756.                         User->MsgTag->LastRead = Number;
  1757.                         User->MsgTag->Add ();
  1758.                      }
  1759.                      User->Update ();
  1760.                   }
  1761.                   delete User;
  1762.                }
  1763.  
  1764.                Data = new TMsgData (Cfg->SystemPath);
  1765.  
  1766.                if (ChangeArea () == TRUE) {
  1767.                   if (NetMail == FALSE && Dupes == FALSE && BadMsgs == FALSE && EMail == FALSE) {
  1768.                      strcpy (AreaKey, Data->Key);
  1769.                      whline (1, 1, 77, 0, LGREY|_BLACK);
  1770.                      sprintf (Temp, " %.70s ", Data->Display);
  1771.                      prints (1, 1, LCYAN|_BLACK, Temp);
  1772.                      switch (Data->Storage) {
  1773.                         case ST_JAM:
  1774.                            Msg = new JAM (Data->Path);
  1775.                            break;
  1776.                         case ST_SQUISH:
  1777.                            Msg = new SQUISH (Data->Path);
  1778.                            break;
  1779.                         case ST_FIDO:
  1780.                            Msg = new FIDOSDM (Data->Path);
  1781.                            break;
  1782.                         case ST_ADEPT:
  1783.                            Msg = new ADEPT (Data->Path);
  1784.                            break;
  1785.                         case ST_HUDSON:
  1786.                            Msg = new HUDSON (Data->Path, (UCHAR)Data->Board);
  1787.                            break;
  1788.                         case ST_USENET:
  1789.                            Msg = new USENET (Cfg->NewsServer, Data->NewsGroup);
  1790.                            break;
  1791.                      }
  1792.                   }
  1793.                   else if (NetMail == TRUE) {
  1794.                      strcpy (AreaKey, "NetMail");
  1795.                      whline (1, 1, 77, 0, LGREY|_BLACK);
  1796.                      sprintf (Temp, " %.70s ", AreaKey);
  1797.                      prints (1, 1, LCYAN|_BLACK, Temp);
  1798.                      switch (Cfg->NetMailStorage) {
  1799.                         case ST_JAM:
  1800.                            Msg = new JAM (Cfg->NetMailPath);
  1801.                            break;
  1802.                         case ST_SQUISH:
  1803.                            Msg = new SQUISH (Cfg->NetMailPath);
  1804.                            break;
  1805.                         case ST_FIDO:
  1806.                            Msg = new FIDOSDM (Cfg->NetMailPath);
  1807.                            break;
  1808.                         case ST_ADEPT:
  1809.                            Msg = new ADEPT (Cfg->NetMailPath);
  1810.                            break;
  1811.                         case ST_HUDSON:
  1812.                            Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->NetMailBoard);
  1813.                            break;
  1814.                      }
  1815.                   }
  1816.                   else if (EMail == TRUE) {
  1817.                      strcpy (AreaKey, "EMail");
  1818.                      whline (1, 1, 77, 0, LGREY|_BLACK);
  1819.                      sprintf (Temp, " %.70s ", AreaKey);
  1820.                      prints (1, 1, LCYAN|_BLACK, Temp);
  1821.                      switch (Cfg->MailStorage) {
  1822.                         case ST_JAM:
  1823.                            Msg = new JAM (Cfg->MailPath);
  1824.                            break;
  1825.                         case ST_SQUISH:
  1826.                            Msg = new SQUISH (Cfg->MailPath);
  1827.                            break;
  1828.                         case ST_FIDO:
  1829.                            Msg = new FIDOSDM (Cfg->MailPath);
  1830.                            break;
  1831.                         case ST_ADEPT:
  1832.                            Msg = new ADEPT (Cfg->MailPath);
  1833.                            break;
  1834.                         case ST_HUDSON:
  1835.                            Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->MailBoard);
  1836.                            break;
  1837.                      }
  1838.                   }
  1839.                   else if (Dupes == TRUE) {
  1840.                      strcpy (AreaKey, "Dupes");
  1841.                      whline (1, 1, 77, 0, LGREY|_BLACK);
  1842.                      sprintf (Temp, " %.70s ", AreaKey);
  1843.                      prints (1, 1, LCYAN|_BLACK, Temp);
  1844.                      switch (Cfg->DupeStorage) {
  1845.                         case ST_JAM:
  1846.                            Msg = new JAM (Cfg->DupePath);
  1847.                            break;
  1848.                         case ST_SQUISH:
  1849.                            Msg = new SQUISH (Cfg->DupePath);
  1850.                            break;
  1851.                         case ST_FIDO:
  1852.                            Msg = new FIDOSDM (Cfg->DupePath);
  1853.                            break;
  1854.                         case ST_ADEPT:
  1855.                            Msg = new ADEPT (Cfg->DupePath);
  1856.                            break;
  1857.                         case ST_HUDSON:
  1858.                            Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->DupeBoard);
  1859.                            break;
  1860.                      }
  1861.                   }
  1862.                   else if (BadMsgs == TRUE) {
  1863.                      strcpy (AreaKey, "BadMsgs");
  1864.                      whline (1, 1, 77, 0, LGREY|_BLACK);
  1865.                      sprintf (Temp, " %.70s ", AreaKey);
  1866.                      prints (1, 1, LCYAN|_BLACK, Temp);
  1867.                      switch (Cfg->BadStorage) {
  1868.                         case ST_JAM:
  1869.                            Msg = new JAM (Cfg->BadPath);
  1870.                            break;
  1871.                         case ST_SQUISH:
  1872.                            Msg = new SQUISH (Cfg->BadPath);
  1873.                            break;
  1874.                         case ST_FIDO:
  1875.                            Msg = new FIDOSDM (Cfg->BadPath);
  1876.                            break;
  1877.                         case ST_ADEPT:
  1878.                            Msg = new ADEPT (Cfg->BadPath);
  1879.                            break;
  1880.                         case ST_HUDSON:
  1881.                            Msg = new HUDSON (Cfg->HudsonPath, (UCHAR)Cfg->BadBoard);
  1882.                            break;
  1883.                      }
  1884.                   }
  1885.  
  1886.                   if (Msg != NULL && Scan != NULL) {
  1887.                      Scan->Messages = Msg->Number ();
  1888.                      Scan->Update ();
  1889.                   }
  1890.  
  1891.                   Number = 0L;
  1892.                   if ((User = new TUser (Cfg->UserFile)) != NULL) {
  1893.                      if (User->GetData (Cfg->SysopName) == TRUE) {
  1894.                         if (User->MsgTag->Read (AreaKey) == TRUE)
  1895.                            Number = User->MsgTag->LastRead;
  1896.                      }
  1897.                      delete User;
  1898.                   }
  1899.  
  1900.                   if (Msg != NULL)
  1901.                      Msg->Next (Number);
  1902.                   DisplayMessage ();
  1903.                   Line = 1;
  1904.                }
  1905.                break;
  1906.             case 'E':
  1907.             case 0x1200:   // Alt-E = Edit new message
  1908.             case 0x5200:   // Ins   = Edit new message
  1909.                EditMessage (FALSE, FALSE);
  1910.                if (Number == 0L)
  1911.                   Msg->Next (Number);
  1912.                DisplayMessage ();
  1913.                break;
  1914.             case 'L':
  1915.             case 0x2600:   // Alt-L = List messages
  1916.                if (CMessageListDlg () == TRUE) {
  1917.                   DisplayMessage ();
  1918.                   Line = 1;
  1919.                }
  1920.                break;
  1921.             case 'R':
  1922.             case 0x1300:   // Alt-R = Reply
  1923.                EditMessage (TRUE, FALSE);
  1924.                if (Number == 0L)
  1925.                   Msg->Next (Number);
  1926.                DisplayMessage ();
  1927.                break;
  1928.             case 'Q':
  1929.             case 0x1000:   // Alt-Q = Reply + Quote
  1930.                EditMessage (TRUE, TRUE);
  1931.                if (Number == 0L)
  1932.                   Msg->Next (Number);
  1933.                DisplayMessage ();
  1934.                break;
  1935.             case 'V':
  1936.             case 0x2F00:   // Alt-V  - Show Kludges
  1937.                ShowKludges = (ShowKludges == TRUE) ? FALSE : TRUE;
  1938.                DisplayMessage ();
  1939.                Line = 1;
  1940.                break;
  1941.             case 'W':
  1942.             case 0x1100:   // Alt-W  - Export Message
  1943.                ExportMessage ();
  1944.                break;
  1945.             case 'X':
  1946.             case 0x2D00:   // Alt-X  - Uscita
  1947.                if (MessageBox (" Quit ", "Are you really sure ?") == TRUE)
  1948.                   EndRun = TRUE;
  1949.                break;
  1950.          }
  1951.       }
  1952.       if ((t = time (NULL)) != last_time) {
  1953.          last_time = t;
  1954.          ltm = localtime (&last_time);
  1955.          sprintf (Temp, " %02d:%02d:%02d ", ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
  1956.          prints (24, (short)(79 - strlen (Temp)), LCYAN|_BLACK, Temp);
  1957.          sprintf (Temp, " %02d %s %04d ", ltm->tm_mday, Months[ltm->tm_mon], ltm->tm_year + 1900);
  1958.          prints (24, 1, LCYAN|_BLACK, Temp);
  1959.       }
  1960.    }
  1961.  
  1962.    if ((User = new TUser (Cfg->UserFile)) != NULL) {
  1963.       if (User->GetData (Cfg->SysopName) == TRUE) {
  1964.          if (User->MsgTag->Read (AreaKey) == TRUE) {
  1965.             User->MsgTag->LastRead = Number;
  1966.             User->MsgTag->Update ();
  1967.          }
  1968.          else {
  1969.             User->MsgTag->New ();
  1970.             strcpy (User->MsgTag->Area, AreaKey);
  1971.             User->MsgTag->Tagged = FALSE;
  1972.             User->MsgTag->LastRead = Number;
  1973.             User->MsgTag->Add ();
  1974.          }
  1975.          User->Update ();
  1976.       }
  1977.       delete User;
  1978.    }
  1979.  
  1980.    if (Data != NULL)
  1981.       delete Data;
  1982.    if (Cfg != NULL)
  1983.       delete Cfg;
  1984.  
  1985.    ClearScreen ();
  1986. }
  1987.