home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / GNU_ATP_1_40.lzh / SRC / read.c < prev    next >
C/C++ Source or Header  |  1993-09-11  |  50KB  |  2,301 lines

  1. /*
  2.  
  3.      ATP QWK MAIL READER FOR READING AND REPLYING TO QWK MAIL PACKETS.
  4.      Copyright (C) 1992  Thomas McWilliams
  5.      Copyright (C) 1990  Rene Cougnenc
  6.  
  7.      This program is free software; you can redistribute it and/or modify
  8.      it under the terms of the GNU General Public License as published by
  9.      the Free Software Foundation; either version 1, or ( at your option )
  10.      any later version.
  11.  
  12.      This program is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.      GNU General Public License for more details.
  16.  
  17.      You should have received a copy of the GNU General Public License
  18.      along with this program; if not, write to the Free Software
  19.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. */
  22.  
  23.  
  24. /*
  25.  * Change Log: $Log: read.c,v $
  26.  * Revision 1.400  1992/11/28  09:54:05  root
  27.  * second release
  28.  *
  29.  * Revision 1.310  1992/07/08  23:15:14  root
  30.  * first release -- minor bug fix in read.c
  31.  *
  32.  * Revision 1.30  1992/07/05  15:36:19  root
  33.  * first release of ATP
  34.  *
  35.  * Revision 1.2  1992/04/19  12:50:02  root 1st semifunctional UNIX version.
  36.  *
  37.  */
  38.  
  39. /* define prompts */
  40.  
  41. #define PRMT1 "%s [ %s ] > "
  42.  
  43. #define PRMT2 "%s [ %s ] > "
  44.  
  45. #define PRMTFR "      From: "
  46.  
  47. #define PRMTTO "        To: "
  48.  
  49. #define PRMTSB "   Subject: "
  50.  
  51. #define PRMTSC "  Security: "
  52.  
  53. #include <stdio.h>
  54. #include <strings.h>
  55. #include <time.h>
  56. #include <types.h>
  57. #include <modes.h>
  58. #include "system.h"
  59. #include "ansi.h"
  60. #include "makemail.h"
  61. #include "qlib.h"
  62. #include "reader.h"
  63. #include "readlib.h"
  64.  
  65. /* external function declarations */
  66.  
  67. char *getenv();            /* standard library */
  68. void *malloc();            /* standard library */
  69. void restore_term();    /* file: system.c */
  70. void setup_term();        /* file: system.c */
  71. char *tempnam();        /* file: system.c */
  72.  
  73. /* global function declarations */
  74.  
  75. int main();
  76.  
  77. /* static function declarations */
  78.  
  79. static void Purge();
  80. static void scruter();
  81. static int  findtxt();
  82. static char *findstr();
  83. static int  FindActive();
  84. static void showterms();
  85. static void ReadShell();
  86. static void togltag();
  87. static void Load();
  88. static void Read();
  89. static void chconf();
  90. static void AutoJoin();
  91. static void SaveMsg();
  92. static void Help();
  93. static void Tag();
  94. static int  ReadNext();
  95. static void PutHeader();
  96. static void PrintHeader();
  97. static void Reply();
  98. static int  AddReply();
  99. static void ListConf();
  100. static void GoToNum();
  101. static int  SeekNum();
  102. static void Display();
  103. static void Welcome();
  104. static void GetBbs();
  105.  
  106. /*  end of static function declarations */
  107.  
  108. /* constant declarations */
  109.  
  110. #ifndef TRUE
  111. #define TRUE 1
  112. #endif
  113. #ifndef FALSE
  114. #define FALSE 0
  115. #endif
  116. #define NEXT 0
  117. #define AGAIN 1
  118. #define PREVIOUS 2
  119. #define SCAN 3
  120. #define FIND 4
  121. #define KILL 5
  122. #define NUKE 9
  123. #define PRIVATE 13
  124. #define RPT_MASK 0x03 /* lower 2 bits used for display mode repeat constant */
  125.  
  126. #ifndef SEP
  127. #define SEP '/'
  128. #endif
  129.  
  130. #ifndef SHELL
  131. #define SHELL "SHELL"
  132. #endif
  133.  
  134. /* global variables */
  135.  
  136. char *TagLine = NTAG;    /* PCBoard style tagline */
  137. char *FidoTag = FTAG;    /* Fidonet style tagline */
  138.  
  139. char        CurTag[256];    /* Tag line chosen... */
  140. char        UserTag[256];    /* Save run time defined tag-lines */
  141. char        OrigTag[256];    /* default tag from atprc config file */
  142. static int    dflag = TRUE;    /* toggle for default and user defined tagline */
  143.  
  144. char    HomePath[MAXPATHS];        /* Home directory root of msg dirs */
  145. char    MailPath[MAXPATHS];        /* Where to look for new mail */
  146. char    ReplyPath[MAXPATHS];    /* Where to put replies */
  147. char    WorkPath[MAXPATHS];        /* Where to archive/unarchive mail . */
  148. char    CurBoard[50];            /* Name of the current board... */
  149.  
  150. /* variables used by line editor */
  151. char    *luxptr;    /* passed text to line editor for editing*/
  152.  
  153. /* variables set in configuration file */
  154.  
  155. int        SCREENLINES = 25;    /* default 25, changeable in config file */
  156. int        SaveConf = -1;        /* save current conference */
  157. long    RbufSize = MYBUF;
  158. char    Editor[50];            /* Name of the standard text editor */
  159. char    Archiver[50];
  160. char    UnArchiver[50];
  161. char    qwklist[100];        /* command line for listing QWK packets */
  162. char    speller[100];        /* command line for invoking speller */
  163. int        autotag = TRUE;        /* flag for random taglines */
  164. int        graphics = FALSE;    /* flag for vt100 graphics mode */
  165. int        charset = CHR7BIT;    /* which char set? 4 is dummy = undefnd.*/
  166. int        fido = FALSE;        /* Flag for tagline style */
  167. int        ansi = TRUE;        /* Flag true if ansi output is on */
  168.  
  169. /* variables used for reading, checking, writing, closing files */
  170.  
  171. struct MyIndex    Index;
  172. FILE            *fidx = NULL, *fmsg = NULL;    /* Index File and msg file, globals */
  173. int                FilesOpen = FALSE;    /* Flag if these files are open */
  174. int                FirstDone = FALSE;    /* Set if 1st message in conf is read */
  175. static int        newmail = TRUE;    /* used by AutoJoin() */
  176. int                ActvCnt = 0;    /* tracks number of active conferences */
  177. int                CurConf;        /* Number of current Conference... */
  178. long int        TotMsg;            /* Number of messages in conf */
  179. byte            *rbuf;            /* Pointer to work buffer for messages */
  180. int                pmail = FALSE;    /* Flag indicates if personal mail waiting */
  181. int                ReplyExist = 0;    /* Flag 1 if there are replies to pack */
  182. static int        IsEmpty = TRUE;    /* Flag false if a BBS is loaded */
  183. int                HeadLetter = 1;    /* Flag 1 if automatic header is active */
  184. static int        caps = FALSE;    /* Flag for reply ENTER mode */
  185.  
  186. /*--------------------------------------------------------------------------*/
  187. /* for OS-9 */
  188. #define MAXCMDS 7
  189. static char *cmds[MAXCMDS] =
  190.         { "del", "dir", "makdir", "deldir", "chd", "copy", "list" };
  191. /*--------------------------------------------------------------------------*/
  192.  
  193. int main( argc, argv )
  194. int argc;
  195. char *argv[];
  196. {
  197.     if( strlen( getenv( "PATH" ) ) > ( size_t ) MAXPATHS )
  198.     {
  199.         printf( "PATH environment too long: %d\n", (size_t) MAXPATHS );
  200.         exit( -1 );
  201.     };
  202.     setup_term();
  203.     MakeHomePath();
  204.     if( ReadConfig() )
  205.         return( -1 );
  206.     if( ( ConfName = malloc( sizeof(string16)*2 ) ) == NULL )
  207.         return( -1 );
  208.     Clean();
  209.     clear();
  210.     bblack();
  211.     Title();
  212.     cyan();
  213.  
  214.     strcpy( CurBoard, txt[10] );    /* First default prompt.... */
  215.     strcpy( ConfName[0], txt[9] );    /* "empty" */
  216.     if( fido )
  217.         strcpy( CurTag, FidoTag );    /* setup the default TagLines */
  218.     else
  219.         strcpy( CurTag, TagLine );
  220.     strcat( CurTag, OrigTag );
  221.     if( ( rbuf = (byte *) malloc( MYBUF ) ) == NULL )
  222.     {
  223.         printf( "%s\n", txt[1] );    /* Not enough memory */
  224.         printf( "%lu bytes\n", MYBUF );
  225.         return( 0xFF );
  226.     }
  227.     if( argc == 2 )
  228.         GetBbs( argv[1] );
  229.     if( autotag )
  230.         ChooseTag();
  231.     printf( "%s\n", CurTag );
  232.         ReadShell();
  233.     free( rbuf );
  234.     if( FilesOpen )
  235.     {
  236.         fclose( fidx );
  237.         fclose( fmsg );
  238.     }
  239.     free( ConfName );
  240.     free( ConfNumbers );
  241.     free( ConfActive );
  242.     Clean();
  243.     restore_term();
  244.     return( 0 );
  245. }
  246.  
  247. /*
  248.  * Main Shell
  249.  */
  250.  
  251. static void ReadShell()
  252. {
  253.     char    prompt[80];
  254.     char    *tmp = NULL;
  255.     char    *ptr;
  256.     int        i;
  257.  
  258.     while( 1 )
  259.     {
  260. topcat:
  261.         luxptr = NULL;
  262.         if( pmail && ( CurConf == findCindex( PERS_CONF ) ) )
  263.             sprintf( prompt, PRMT2, CurBoard, ConfName[CurConf] );
  264.         else
  265.             sprintf( prompt, PRMT1, CurBoard, ConfName[CurConf] );
  266.         tmp = readline( prompt );
  267.         printf( "\r %-75s \r", " " );
  268.         clear();
  269.         fflush( stdout );
  270.         StripDel( tmp );
  271.         StripSpaceL( tmp );
  272.  
  273.         /* Internal shell commands */
  274.         for( i = 0; i < MAXCMDS; i++ )
  275.         {
  276.             if( !strnicmp( tmp, cmds[i], strlen( cmds[i] ) ) )
  277.             {
  278.                 system( &tmp[0] );
  279.                 goto topcat;  /* break from loop and take it from the top! */
  280.             }
  281.         }
  282.  
  283.         if( Numeric( tmp ) )
  284.             GoToNum( tmp );
  285.  
  286.         else if( !strnicmp( tmp, "show ", 5 ) )
  287.             showterms();
  288.  
  289.         else if( !strnicmp( tmp, "aide", 4 ) )
  290.             Help();
  291.  
  292.         else if( !strnicmp( tmp, "cls", 3 ) )
  293.             cls();
  294.  
  295.         else if( !strnicmp( tmp, "clean", 5 ) )
  296.             Purge();
  297.  
  298.         else if( !strnicmp( tmp, "conf", 4 ) )
  299.             ListConf();
  300.  
  301.         else if( !strnicmp( tmp, "date", 4 ) )
  302.             Date();
  303.  
  304.         else if( !strnicmp( tmp, "fido", 4 ) )
  305.             togltag();
  306.  
  307.         else if( !strnicmp( tmp, "find ", 5 ) )
  308.             ( void ) findtxt( tmp, FIND );
  309.  
  310.         else if( !strnicmp( tmp, "help", 4 ) )
  311.             Help();
  312.  
  313.         else if( !stricmp( tmp, "last" ) )
  314.         {
  315.             sprintf( prompt, "%ld", TotMsg );
  316.             GoToNum( prompt );
  317.         }
  318.  
  319.         else if( !stricmp( tmp, "next" ) )
  320.             ( void ) findtxt( tmp, NEXT );
  321.  
  322.         else if( !strnicmp( tmp, "scan", 4 ) )
  323.             scruter();
  324.  
  325.         else if( !strnicmp( tmp, "ql", 2 ) )
  326.             Qlist( qwklist );
  327.  
  328.         else if( !strnicmp( ( char * ) tmp, "graph", 4 ) )
  329.         {
  330.             if( graphics )
  331.             {
  332.                 graphics = FALSE;
  333.                 printf(    "\n\t\t +------------------------------+\n" );
  334.                 printf(      "\t\t |                              |\n" );
  335.                 printf(      "\t\t |  vt100 graphics are now OFF  |\n" );
  336.                 printf(      "\t\t |                              |\n" );
  337.                 printf(      "\t\t +------------------------------+\n\n" );
  338.             }
  339.             else
  340.             {
  341.                 graphics = TRUE;
  342.                 printf( "\n\016\t\t lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk\n" );
  343.                 printf(      "\t\t xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax\n" );
  344.                 printf(      "\t\t xaa\017 vt100 graphics are now ON\016 ax\n" );
  345.                 printf(      "\t\t xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax\n" );
  346.                 printf(      "\t\t mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj\n\n\017" );
  347.             }
  348.         }
  349.         else if( !strnicmp( tmp, "head", 4 ) )
  350.         {
  351.             blue();
  352.             high();
  353.             HeadLetter = HeadLetter ? 0 : 1;
  354.             printf( "%s ", txt[101] );    /* "Automatic H." */
  355.             printf( "%s\n", HeadLetter ? txt[85] : txt[86] );    /* "on" / "off" */
  356.         }
  357.         else if( !strnicmp( tmp, "news", 4 ) )
  358.         {
  359.             if( ansi )
  360.             {
  361.                 sprintf( tmp, "%s%s%c%s", HomePath, CurBoard, SEP, NEWSG );
  362.                 if( !access( tmp, S_IREAD ) )
  363.                 {
  364.                     sprintf( tmp, "%s%s", HomePath, CurBoard );
  365.                     view( tmp, NEWSG );
  366.                     continue;
  367.                 }
  368.             }
  369.             sprintf( tmp, "%s%s", HomePath, CurBoard );
  370.             view( tmp, NEWS );
  371.         }
  372.         else if( !strnicmp( tmp, "time", 4 ) )
  373.             Date();
  374.  
  375.         else if( !strnicmp( tmp, "welcome", 4 ) )
  376.             Welcome();
  377.  
  378.         else if( !strnicmp( tmp, "file", 4 ) )
  379.         {
  380.             if( IsEmpty )
  381.             {
  382.                 EmptyMsg();
  383.                 continue;
  384.             }
  385.             sprintf( tmp, "%s%s", HomePath, CurBoard );
  386.             view( tmp, NEWFILES );
  387.         }
  388.         else if( !strnicmp( tmp, "load", 4 ) )
  389.         {
  390.             if( ( !IsEmpty ) && ConfActive[CurConf] )
  391.                 UpdateConf( UPDATE );
  392.             Load( tmp );    /* Load new mail */
  393.         } 
  394.         else if( !strnicmp( tmp, "merde", 5 ) )
  395.             merde();/* Load new mail */
  396.  
  397.         else if( !strnicmp( tmp, "rev", 3 ) )
  398.         {
  399.             if( ( !IsEmpty ) && ConfActive[CurConf] )
  400.                 UpdateConf( UPDATE );    /* Save current conf pointer */
  401.             Read( tmp );    /* read existing mail */
  402.         }
  403.         else if( !strnicmp( tmp, "tag", 3 ) )
  404.             Tag( tmp );    /* change tagline */
  405.  
  406.         else if( !stricmp( tmp, "reset" ) )
  407.         {
  408.             UpdateConf( RESET );
  409.         }
  410.         else if(  tmp[0] == '\0' || tmp[1] == '\0' || tmp[1] == '\040' )
  411.         {
  412.  
  413.             switch ( tmp[0] )
  414.             {
  415.  
  416.             case '!':
  417.                 if( tmp[1] )
  418.                 {
  419.                     system( ( char * ) &tmp[1] );
  420.                 }
  421.                 else
  422.                 {
  423.                     ptr = getenv( SHELL );
  424.                     if( ptr )
  425.                         system( ptr );
  426.                 }
  427.                 break;
  428.  
  429.             case 'c':
  430.             case 'C':
  431.                 if( CurConf == RCONF_IDX && FirstDone )
  432.                         Reply( EDIT, tmp );
  433.                 break;
  434.  
  435.             case 'e':
  436.             case 'E':
  437.                 if( CurConf == RCONF_IDX && tmp[1] == '\0' )
  438.                 {
  439.                     if( FirstDone )
  440.                         Reply( EDIT, tmp );
  441.                 }
  442.                 else
  443.                 {
  444.                     Reply( ENTER, tmp );
  445.                 }
  446.                 break;
  447.  
  448.             case 'j':
  449.             case 'J':
  450.                   chconf( tmp );
  451.                 break;
  452.  
  453.             case 's':
  454.             case 'S':
  455.                 SaveMsg( tmp );
  456.                 break;
  457.  
  458.             default:
  459.             break;
  460.             }
  461.         if( !tmp[1] || !tmp[0] )
  462.         switch( ( int ) tmp[0] )
  463.         {
  464.             case '?':
  465.                 Help();
  466.                 break;
  467.  
  468.             case 'a':
  469.             case 'A':
  470.                 if( FirstDone )
  471.                     Display( 0 );
  472.                 else
  473.                     ReadNext( NEXT );
  474.                 break;
  475.  
  476.             case 'k':
  477.             case 'K':
  478.                 if( CurConf == RCONF_IDX )
  479.                     ReadNext( KILL );
  480.                 break;
  481.  
  482.             case 'm':     /* toggle ANSI mode on/off */
  483.             case 'M':
  484.                 ansi = ansi ? FALSE : TRUE;
  485.                 yellow();
  486.                 high();
  487.                 printf( "%s %s .\n", txt[84], ansi ? txt[85] : txt[86] );
  488.                 break;
  489.  
  490.             case 'p':
  491.             case 'P':
  492.                 if( CurConf == RCONF_IDX )
  493.                     ReadNext( PRIVATE );
  494.                 break;
  495.  
  496.             case 'q':
  497.             case 'Q':
  498.             case 'g':
  499.             case 'G':
  500.                 if( !IsEmpty )
  501.                     UpdateConf( UPDATE );    /* Save current conf pointer */
  502.                 if( FilesOpen )
  503.                 {
  504.                     fclose( fidx );
  505.                     fclose( fmsg );
  506.                     FilesOpen = FALSE;
  507.                 }
  508.                 if( ReplyExist )
  509.                 {
  510.                     red();
  511.                     high();
  512.                     /* Warning, you have */
  513.                     printf( "%s\n%s %s.\n", txt[2], txt[3], CurBoard );
  514.                     /* Replies,pack them ? */
  515.                     sprintf( prompt,"%s", txt[4] );
  516.                     if( YesNo( YES,prompt ) )
  517.                         PackReply();
  518.                 }
  519.                 clear();
  520.                 return;
  521.  
  522.            case 'n':
  523.            case 'N':
  524.                 AutoJoin();
  525.                 break;
  526.  
  527.               case 'r':
  528.             case 'R':
  529.                     if( FirstDone && CurConf != RCONF_IDX )
  530.                        Reply( REPLY, tmp );
  531.                    break;
  532.  
  533.             case '+':
  534.             case 0:
  535.                   ReadNext( NEXT );
  536.                 break;
  537.  
  538.             case '-':
  539.                 ReadNext( PREVIOUS );
  540.                 break;
  541.          }
  542.       }
  543.    }
  544. }
  545.  
  546. static void
  547. togltag( /* void */ )
  548. {                /* switch tagline styles */
  549.     fido = ( fido ? FALSE : TRUE );
  550.     Tag( "tag \177" );
  551. }
  552.  
  553.  
  554. static void
  555. Load( name )
  556. char *name;
  557. {
  558.     char    BbsName[50];
  559.     char    tmp3[MAXPATHS];
  560.     char    tmp2[MAXPATHS];
  561.     char    tmp[MAXPATHS];
  562.     char    OldDat[MAXPATHS];
  563.     char    NewDat[MAXPATHS];
  564.     char    prmbuf[80]; /* buffer for prompt passed to YesNo */
  565.     char    *tptr;
  566.     int        oldage;
  567.     int        newage;
  568.     int     i;
  569.  
  570.     pmail = FALSE;    /* reset global flag to indicate no personal mail yet */
  571.     if( ReplyExist )
  572.     {
  573.         red();
  574.         high();
  575.         /* Warning, you have Replies,pack them ? */
  576.         printf( "%s\n%s %s.\n", txt[2], txt[3], CurBoard );    
  577.         sprintf( prmbuf,"%s", txt[4] );    
  578.         if( YesNo( YES,prmbuf ) )
  579.             PackReply();
  580.         ReplyExist = FALSE;
  581.     }
  582.     BbsName[0] = '\0';
  583.     sscanf( name, "%s %s", tmp, BbsName );
  584.     if( !BbsName[0] )
  585.     {
  586.         red();
  587.         printf( "%s  %s\n", txt[87], txt[88] );    /* "usage" " load.." */
  588.         return;
  589.     }
  590.     printf( "%s %s\n", txt[5], BbsName );
  591.  
  592.     if( strstr( BbsName, ".qw" ) == NULL )
  593.         strcat( BbsName, ".qwk" );
  594.  
  595.     sprintf( tmp, "%s%s", MailPath, BbsName );
  596.  
  597. /*
  598.  *    Now that we've used BbsName to id the packet file strip any
  599.  *    trailing digits so the board's subdir doesn't vary w/ packet #.
  600.  */
  601.  
  602.     tptr = BbsName;
  603.     i = -1;
  604.     while ( BbsName[++i] );
  605.     while ( BbsName[--i] != '.' );
  606.     BbsName[i] = '\0';
  607.     if( !Numeric( tptr ) )
  608.         while ( isdigit( BbsName[--i] ) )
  609.             BbsName[i] = '\0';
  610.  
  611.     if( access( tmp, S_IREAD ) )
  612.     {
  613.         red();
  614.         printf( "%s : %s\n", txt[6], tmp );    /* No mail found */
  615.         printf( "%s\n", txt[7] );    /* Try the read command */
  616.         return;
  617.     }
  618.     Clean();        /* Don't forget to clean work directory ! */
  619.     yellow();
  620.     high();
  621.     printf( "%s\n", txt[8] );    /* " Extracting Messages..." */
  622.     green();
  623.     fflush( stdout );
  624.     getcwd( tmp3, sizeof( tmp3 ) );    /* save current directory */
  625.     chdir( WorkPath ); /* change to work directory */
  626.     sprintf( tmp2, "%s %s", UnArchiver, tmp ); /* build unzip command line */
  627.     system( tmp2 ); /* execute unzip in work dir */
  628.     chdir( tmp3 );  /* restore current directory */
  629.     yellow();
  630.     sprintf( tmp3, "%s%c%s", WorkPath, SEP, CNTRL_FILE );
  631.     if( access( tmp3, S_IREAD | S_IWRITE ) )
  632.     {
  633.         printf( "Error: can't find control file: %s\n", tmp3 );
  634.         return;
  635.     }
  636.     sprintf( tmp2, "%s%s", HomePath, BbsName );    /* Access to a board subdir */
  637.     if( access( tmp2, S_IREAD ) )
  638.         makdir( tmp2, S_IFDIR, S_IREAD | S_IWRITE );
  639.  
  640.     sprintf( OldDat, "%s%s%c%s", HomePath, BbsName, SEP, CNTRL_FILE );
  641.     sprintf( NewDat, "%s%c%s", WorkPath, SEP, CNTRL_FILE );
  642.  
  643.     if( ( oldage = fileage( OldDat ) ) != 0 )
  644.     {
  645.         if( fileage( NewDat ) <= oldage )
  646.         {
  647.             red();
  648.             high();
  649.             /* "New packet older..." */
  650.             printf( "%s\n%s.\n", txt[2], txt[11] );
  651.             /* " Do you want to ... " */
  652.             sprintf( prmbuf , "%s...", txt[12] );
  653.             if( !YesNo( NO,prmbuf ) )
  654.                 return;
  655.         }
  656.     }
  657.     strcpy( CurBoard, BbsName );
  658.     /* Create Index Files */
  659.     MkIndex( WorkPath, tmp2 );
  660.     Chk4Rep();
  661.     Chk4Cnf( tmp2 );
  662.     if( FilesOpen )
  663.     {
  664.         fclose( fidx );
  665.         fclose( fmsg );
  666.         FilesOpen = FALSE;
  667.     }
  668.     IsEmpty = FALSE;
  669.     newmail = TRUE;
  670.     caps = !fido;
  671.     if( pmail )
  672.         CurConf = findCindex( PERS_CONF );
  673.     else
  674.         CurConf = FindActive( LastConf );
  675.     if( CurConf < 0 )
  676.         CurConf = 0;
  677.     GetConf( CurConf );
  678. }
  679.  
  680.  
  681. /*
  682.  * Join a BBS without extracting new mail.
  683.  */
  684.  
  685. static void
  686. Read( name )
  687. char *name;
  688. {
  689.     char            BbsName[50];
  690.     char            tmp[MAXPATHS];
  691.     if( ReplyExist )
  692.     {
  693.         red();
  694.         printf( "%s\n%s %s.\n", txt[2], txt[3], CurBoard );    /* Warning, you have */
  695.         sprintf( tmp,"%s", txt[4] );    /* Replies, pack them? */
  696.         if( YesNo( YES,tmp ) )
  697.             PackReply();
  698.         ReplyExist = FALSE;
  699.         tmp[0] = '\0';
  700.     }
  701.     BbsName[0] = 0;
  702.     sscanf( name, "%s %s", tmp, BbsName );
  703.     if( !BbsName[0] )
  704.     {
  705.         red();
  706.         printf( "%s %s\n", txt[87], txt[89] );    /* "usage " "read..." */
  707.         return;
  708.     }
  709.     printf( "%s %s\n", txt[5], BbsName );    /* "Loading" */
  710.     sprintf( tmp, "%s%s%c%s", HomePath, BbsName, SEP, CNTRL_FILE );
  711.     if( access( tmp, S_IREAD | S_IWRITE ) )
  712.     {
  713.         printf( "%s : %s\n", txt[13], tmp );    /* "No bbs found " */
  714.         return;
  715.     }
  716.     sprintf( tmp, "%s%s", HomePath, BbsName );
  717.     if( ReadControl( tmp ) )
  718.     {
  719.         printf( "%s\n", txt[14] );    /* "Error in CONTROL.DAT." */
  720.         return;
  721.     }
  722.     strcpy( CurBoard, BbsName );
  723.     Chk4Rep();
  724.     Chk4Cnf( tmp );
  725.     if( FilesOpen )
  726.     {
  727.         fclose( fidx );
  728.         fclose( fmsg );
  729.         FilesOpen = FALSE;
  730.     }
  731.     ActvConf();        /* update boolean array of active/inactive flags */
  732.     IsEmpty = FALSE;
  733.     newmail = FALSE;
  734.     caps = !fido;
  735.     CurConf = FindActive( LastConf );
  736.     if( CurConf < 0 )
  737.         CurConf = 0;
  738.     GetConf( CurConf );
  739. }
  740.  
  741.  
  742. /*
  743.  * CHCONF : Change active conference.
  744.  */
  745. static void chconf( buf )
  746. char *buf;
  747. {
  748.     char            Name[50];
  749.     char            tmp[MAXPATHS];
  750.     int             i;
  751.     unsigned int    m;
  752.  
  753.     if( IsEmpty )
  754.     {
  755.         EmptyMsg();
  756.         return;
  757.     }
  758.     Name[0] = 0;
  759.     sscanf( buf, "%s %s", tmp, Name );
  760.     if( !Name[0] )
  761.     {
  762.         red();
  763.         printf( "%s\n", txt[87] );    /* "Usage" */
  764.         printf( "\tj %s\n\t\t%s\n", txt[90], txt[91] );    /* "Conf #" "or" */
  765.         printf( "\tj %s\n", txt[92] );    /* "conf name" */
  766.         printf( "%s\n", txt[93] );    /* "type conf to list..." */
  767.         return;
  768.     }
  769.     if( Numeric( Name ) )
  770.     {    /* a number is given */
  771.         i = atoi( Name );
  772.         if( ( i = findCindex( i ) ) > -1 )
  773.             strcpy( Name, ConfName[i] );
  774.     } 
  775.     else
  776.     {        /* a name is given */
  777.  
  778.         m = strlen( Name );
  779.         for( i = 0; i <= LastConf; i++ )
  780.         {
  781.             if( !stricmp( Name, ConfName[i] ) )
  782.                 break;
  783.         }
  784.         if( i > LastConf )
  785.         {
  786.             for( i = 0; i <= LastConf; i++ )
  787.             {
  788.                 if( !strnicmp( Name, ConfName[i], m ) )
  789.                     break;
  790.             }
  791.         }
  792.     }
  793.  
  794.     if( !stricmp( Name, "MAIN" ) )
  795.         i = 0;        /* Special case for "main board" */
  796.  
  797.     if( i > LastConf || i < 0 )
  798.     {
  799.         printf( "\n%s\n", txt[28] );    /* "Unknown conference" */
  800.         return;
  801.     }
  802.     sprintf( tmp, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i] );
  803.     if( access( tmp, S_IREAD | S_IWRITE ) )
  804.     {
  805.         red();
  806.         printf( "%s : %s  %s\n", txt[6], tmp, ConfName[i] );    /* "No mail found" */
  807.         return;
  808.     }
  809.     UpdateConf( UPDATE );        /* Save current conf pointer */
  810.     if( GetConf( i ) == ERROR )
  811.         return;
  812.     blue();
  813.     high();
  814.     printf( "\n *  %s %s %s. *\n\n", txt[29], ConfName[CurConf], txt[30] );
  815.     /* "Conference " "joined" */
  816. }
  817.  
  818.  
  819. /*
  820.  * Loads next valid conferences.
  821.  */
  822. #define ILR Index.LastRead
  823.  
  824. static void AutoJoin()
  825. {
  826.     char            tmp[MAXPATHS];
  827.     int             i, j;
  828.  
  829.     if( IsEmpty )
  830.     {
  831.         EmptyMsg();
  832.         return;
  833.     }
  834.     if( !ActvCnt )
  835.     {
  836.         chconf( "j MAIN\n" );
  837.         return;
  838.     }
  839.     i = CurConf;
  840.     j = ActvCnt;
  841.     while ( j-- )
  842.     {
  843.         i = FindActive( i );
  844.         sprintf( tmp, "j %d\n", ConfNumbers[i] );
  845.         chconf( tmp );
  846.         if(  ILR < 1 || ILR != ( TotMsg - 1 ) || !newmail )
  847.         {
  848.             return;
  849.         }
  850.         else
  851.             printf( "\t%s.\n", txt[31] );    /* "No new mail" */
  852.     }
  853.     newmail = FALSE;
  854.     printf( "\n" );
  855. }
  856.  
  857. #undef ILR
  858.  
  859. /*
  860.  * Save current message in text file ( append mode ).
  861.  */
  862.  
  863. static void SaveMsg( str )
  864. char *str;
  865. {
  866.     char            dummy[MAXPATHS];
  867.     char            fname[MAXPATHS];
  868.     byte           *ptr;
  869.     FILE           *fp;
  870.     unsigned long   i;
  871.     int             apflag;
  872.  
  873.     if( IsEmpty )
  874.     {
  875.         EmptyMsg();
  876.         return;
  877.     }
  878.     fname[0] = 0;
  879.     sscanf( str, "%s %s", dummy, fname );
  880.     if( !fname[0] )
  881.     {
  882.         high();
  883.         yellow();
  884.         ptr = (byte *) readline( txt[39] );
  885.         clear(); 
  886.         fflush( stdout );
  887.         fname[0] = '\0';
  888.         if( ptr != NULL )
  889.             strcpy( fname, (char *) ptr );
  890.         if( !fname[0] )
  891.         {
  892.             printf( "%s.\n", txt[40] );    /* "Aborted" */
  893.             return;
  894.         }
  895.     }
  896.     apflag = access( fname, S_IWRITE ) ? 1 : 0;
  897.  
  898.     if( ( fp = fopen( fname, "a" ) ) == NULL )
  899.     {
  900.         red();
  901.         high();
  902.         printf( "%s %s\n", txt[51], fname );    /* "unable to open file" */
  903.         return;
  904.     }
  905.     PrintHeader( fp );
  906.     ptr = ( byte * ) ( rbuf + sizeof( struct MsgHeaderType ) );
  907.     i = 0;
  908.     while ( i < Index.Size )
  909.     {
  910.         if( *ptr != 0 )
  911.         {
  912.             if( charset == ISOLAT1 )
  913.                  putc( codelu[  ( unsigned ) ( *ptr ) ] , fp );
  914.             else if( charset == CHR7BIT )
  915.                 putc( code7bit[( unsigned ) ( *ptr ) ] , fp );
  916.             else
  917.                 putc( *ptr, fp );
  918.         }
  919.         i++;
  920.         ptr++;
  921.     }
  922.  
  923.     fprintf( fp, "\n" );
  924.  
  925.     blue();
  926.     high();
  927.     /* printf( "Message %s",apflag ? "Saved in" : "Appended to" ); */
  928.     printf( "%s %s", txt[41], apflag ? txt[42] : txt[43] );
  929.     clear();
  930.     cyan();
  931.     printf( " %s\n", fname );
  932.     fclose( fp );
  933. }
  934.  
  935.  
  936. /*
  937.  * Help message.
  938.  */
  939.  
  940. static void Help()
  941. {
  942.     unsigned      i;
  943.  
  944.     white();
  945.     high();
  946.     printf( "\n%s", hlp[1] );
  947.     clear();
  948.     printf( "\n" );
  949.     for( i = 0; i < strlen( hlp[1] ); i++ )
  950.         putchar( '-' );
  951.     printf( "\n" );
  952.     high();
  953.     printf( "\r\t q,g\t%s\n", hlp[2] );
  954.     printf( "\t k\t%s\n", hlp[3] );
  955.     printf( "\t !\t%s\n", hlp[4] );
  956.     printf( "\t +\t%s\n", hlp[5] );
  957.     printf( "\t -\t%s\n", hlp[6] );
  958.     printf( "\t a\t%s\n", hlp[7] );
  959.     printf( "\t e\t%s\n", hlp[8] );
  960.     printf( "\t j\t%s\n", hlp[9] );
  961.     printf( "\t m\t%s\n", hlp[10] );
  962.     printf( "\t n\t%s\n", hlp[11] );
  963.     printf( "\t r\t%s\n", hlp[12] );
  964.     printf( "\t s\t%s\n", hlp[13] );
  965.     printf( "\t conf\t%s\n", hlp[14] );
  966.     printf( "\t clean\t%s\n", hlp[15] );
  967.     printf( "\t load\t%s\n", hlp[16] );
  968. #ifdef ENGLISH
  969.     printf( "\t review\t%s\n", hlp[17] );
  970. #else
  971.     printf( "\t revois\t%s\n", hlp[17] );
  972. #endif
  973.     printf( "\t files\t%s\n", hlp[18] );
  974.     printf( "\t tag help\t%s\n", hlp[19] );
  975.     printf( "\t head\t%s\n", hlp[22] );
  976.     printf( "\t scan\t%s\n", hlp[24] );
  977.     printf( "\t qlist\t%s\n", hlp[23] );
  978.     printf( "\n" );
  979. }
  980.  
  981.  
  982.  
  983. /*
  984.  * Change Reader Signature :-)
  985.  */
  986. static void Tag( line )
  987. char *line;
  988. {
  989.     char            dummy[50];
  990.     char            tmp[256];
  991.     char            tmp2[256];
  992.     int             i,j;
  993.     tmp2[0] = tmp[0] = 0;
  994.  
  995.     sscanf( line, "%s %s %s", dummy, tmp, tmp2 );
  996.  
  997.     if( tmp2[0] == 0 && ( strnicmp( ( char * ) tmp, "list", 4 ) == 0 ) )
  998.     {    /* list taglines */
  999.         sprintf( tmp2, "%s%s", HomePath, TAGFILE );
  1000.         printf( "%s\n", tmp2 );
  1001.         if( !access( tmp2, S_IREAD ) )
  1002.         {
  1003.             tmp[0] = 0;
  1004.             sprintf( tmp, "%s", HomePath );
  1005.             tagview( tmp, TAGFILE );
  1006.         }
  1007.         printf( "\nDefault Tag : %s", OrigTag );
  1008.         printf( "User defined: %s", UserTag );
  1009.         printf( "\n" );
  1010.         return;
  1011.     }
  1012.     if( tmp2[0] == 0 && Numeric( ( char * ) tmp ) )
  1013.     {    /* try to get a tagline from the list */
  1014.         i = atoi( ( char * ) tmp );
  1015.         i = i < 0 ? -i : i;
  1016.         TagSeek( i );
  1017.         printf( "Current Tag now set to:" );
  1018.         printf( "%s\n", CurTag );
  1019.         return;
  1020.     }
  1021.     if( tmp2[0] == 0 && tmp[0] == '?' )
  1022.     {    /* Print current tag */
  1023.         printf( "Current TagLine is:" );
  1024.         printf( "%s\n", CurTag );
  1025.         return;
  1026.     }
  1027.     if( tmp2[0] == 0 && ( strnicmp( ( char * ) tmp, "rand", 4 ) == 0 ) )
  1028.     {    /* select tag at random */
  1029.         ChooseTag();
  1030.         printf( "Current Tag now set to:" );
  1031.         printf( "%s\n", CurTag );
  1032.         return;
  1033.     }
  1034.     if( ( tmp2[0] == 0 && ( strnicmp( ( char * ) tmp, "help", 4 ) == 0 ) ) || line[3] == '\0' )
  1035.     {    /* select tag help menu */
  1036.         white();
  1037.         high();
  1038.         printf( "\n%s", taghlp[1] );
  1039.         clear();
  1040.         printf( "\n" );
  1041.         for( j = 0; j < ( int ) strlen( taghlp[1] ); j++ )
  1042.             putchar( '-' );
  1043.         printf( "\n" );
  1044.         high();
  1045.         printf( "\t tag list\t%s\n", taghlp[2] );
  1046.         printf( "\t tag ?   \t%s\n", taghlp[3] );
  1047.         printf( "\t tag `n' \t%s\n", taghlp[4] );
  1048.         printf( "\t tag random\t%s\n", taghlp[5] );
  1049.         printf( "\t tag swap\t%s\n", taghlp[6] );
  1050.         printf( "\t tag auto\t%s\n", taghlp[7] );
  1051.         printf( "\t tag     \t%s\n", taghlp[8] );
  1052.         printf( "\t tag help\t%s\n", taghlp[9] );
  1053.         printf( "\t fido    \t%s\n", taghlp[10] );
  1054.         printf( "\n" );
  1055.         printf( "Current TagLine is:" );
  1056.         printf( "%s\n", CurTag );
  1057.         return;
  1058. }
  1059.     if( tmp2[0] == 0 && ( strnicmp( ( char * ) tmp, "auto", 4 ) == 0 ) )
  1060.     {    /* toggle autotag line selection */
  1061.         if( autotag )
  1062.         {
  1063.             autotag = FALSE;
  1064.             printf( "\nautotag is OFF\n\n" );
  1065.         }
  1066.         else
  1067.         {
  1068.             autotag = TRUE;
  1069.             printf( "\nautotag is ON\n" );
  1070.             ChooseTag();
  1071.             printf( "Current Tag now set to:" );
  1072.             printf( "%s\n", CurTag );
  1073.         }
  1074.         return;
  1075.     }
  1076.     if( ( tmp2[0] == 0 ) && ( strnicmp( ( char * ) tmp, "swap", 4 ) == 0 ) )
  1077.     {    /* restore standard tag */
  1078.         dflag = dflag ? FALSE : TRUE;
  1079.         if( fido )
  1080.             strcpy( CurTag, FidoTag );
  1081.         else
  1082.             strcpy( CurTag, TagLine );
  1083.         if( dflag )
  1084.             strcat( CurTag, OrigTag );
  1085.         else
  1086.             strcat( CurTag, UserTag );
  1087.         printf( "Current Tag now set to:" );
  1088.         printf( "%s\n", CurTag );
  1089.         return;
  1090.     }
  1091.     if( !stricmp( ( char * ) tmp, "fido" ) )
  1092.     {
  1093.         fido = ( fido ? FALSE : TRUE );
  1094.         tmp[0] = '\177';
  1095.     }
  1096.     if( tmp[0] == '\177' )
  1097.     {    /* toggle fido tag */
  1098.         strcpy( ( char * ) tmp, ( char * ) CurTag );
  1099.         if( fido )
  1100.         {
  1101.             line = ( char * ) tmp + strlen( TagLine );    /* point to start of tag message */
  1102.             strcpy( CurTag, FidoTag );
  1103.         } 
  1104.         else
  1105.         {
  1106.             line = ( char * ) tmp + strlen( FidoTag );
  1107.             strcpy( CurTag, TagLine );
  1108.         }
  1109.         strcat( CurTag, line );
  1110.         printf( "Current Tag now set to:" );
  1111.         printf( "%s\n", CurTag );
  1112.         return;
  1113.     }
  1114.     if( line[3] == '\040' )
  1115.     {
  1116.         line += 4;    /* Change current tag to User defined Tag */
  1117.         strcpy( UserTag, line );
  1118.         strcat( UserTag, "\n" );
  1119.         if( fido )
  1120.             strcpy( CurTag, FidoTag );
  1121.         else
  1122.             strcpy( CurTag, TagLine );
  1123.         strcat( CurTag, UserTag );
  1124.         dflag = FALSE;
  1125.         printf( "Tag is now set to :" );
  1126.         printf( "%s\n", CurTag );
  1127.     }
  1128.  
  1129. }
  1130.  
  1131.  
  1132. /*
  1133.  * Print Next,previous or current message.
  1134.  */
  1135.  
  1136. static int
  1137. ReadNext( /* const int */ mode )
  1138. int mode;
  1139. {
  1140.     byte            tchar;
  1141.     long            here;
  1142.     size_t          nrecs;
  1143.  
  1144.     if( mode < 0 || mode > 13 )
  1145.         return( 0 );
  1146.  
  1147.     if( IsEmpty )
  1148.     {
  1149.         EmptyMsg();
  1150.         return( 0 );
  1151.     }
  1152.     if( !FilesOpen )
  1153.     {
  1154.         printf( "%s \n", txt[44] );    /* no mail in conf */
  1155.         if( mode == SCAN )
  1156.             return( 0 );
  1157.         else
  1158.             AutoJoin();
  1159.         return( 0 );
  1160.     }
  1161.     /* if needed, seek to new record in conference index file */
  1162.     if(  mode == KILL || mode == NUKE || mode == PREVIOUS || mode == PRIVATE )
  1163.     {
  1164.         here = ftell( fidx ) - ( long ) ( ( mode & RPT_MASK ) * sizeof( struct MyIndex ) );
  1165.         if( here < 0L )
  1166.         {
  1167.             printf( "%s\n", txt[15] );    /* "First message !" */
  1168.             return( 0 );
  1169.         }
  1170.         if( fseek( fidx, here, SEEK_SET ) )
  1171.         {
  1172.             printf( "%s.\n", txt[16] );    /* "Seek error" */
  1173.             return( 0 );
  1174.         }
  1175.     }
  1176.     /* get new index information and check for end of conference */
  1177.     if( fread( &( Index.LastRead ), 1, sizeof( struct MyIndex ), fidx )
  1178.         != sizeof( struct MyIndex ) )
  1179.         {
  1180.         printf( "%s\n", txt[17] );    /* "End of messages." */
  1181.         if( mode == SCAN || mode == FIND )
  1182.             return( 0 );
  1183.         else
  1184.             AutoJoin();
  1185.         return( 0 );
  1186.     }
  1187.     /* use new index information to seek to new message in msg file */
  1188.     if( fseek( fmsg, Index.Offset, SEEK_SET ) )
  1189.     {
  1190.         printf( "%s!\n", txt[16] );    /* "Seek Error" */
  1191.         return( 0 );
  1192.     }
  1193.     fread( &tchar, 1, 1, fmsg );    /* read status into variable */
  1194.     fseek( fmsg, Index.Offset, SEEK_SET );   /* re-seek */
  1195.  
  1196.     if( mode == KILL || mode == NUKE )
  1197.     {
  1198.         tchar = tchar ^ 0x80;        /* XOR status with 0x80 */
  1199.         if( mode == NUKE ) tchar = tchar | 0x80;
  1200.         fwrite( &tchar,1, 1,fmsg );    /* write back new status */
  1201.         fflush( fmsg );
  1202.         fseek( fmsg,Index.Offset, SEEK_SET ); /* re-seek */
  1203.     }
  1204.     if( mode == PRIVATE )
  1205.     {
  1206.         tchar = ( tchar == 0x2A ) ? 0x20 : 0x2A;    /* XOR status with 0x80 */
  1207.         fwrite( &tchar,1, 1,fmsg );    /* write back new status */
  1208.         fflush( fmsg );
  1209.         fseek( fmsg,Index.Offset, SEEK_SET ); /* re-seek */
  1210.     }
  1211.     nrecs = ( ( Index.Size / 128 ) + 1 ) /* Msg + Head */;
  1212.     if( mode == SCAN )
  1213.     {
  1214.         fread( rbuf, 128, 1, fmsg );
  1215.         PutHeader();
  1216.         }
  1217.     else
  1218.     {
  1219.            if(  nrecs > ( RbufSize / 128 ) )
  1220.                if(  !reup( ( unsigned long ) ( nrecs+1 )*128L ) )
  1221.                 return( 0 );
  1222.            if( fread( ( char * ) rbuf, 128, nrecs, fmsg ) != nrecs )
  1223.            {
  1224.                printf( "%s? \n", txt[18] );  /* Read Error */
  1225.             return( 0 );
  1226.     }
  1227.     Display( mode );
  1228.     }
  1229.     return( 1 );
  1230. }
  1231.  
  1232.  
  1233. /*
  1234.  * Prints the Qmail message header pointed by buf .
  1235.  */
  1236.  
  1237. static void
  1238. PutHeader( /* void */ )
  1239. {
  1240.     struct MsgHeaderType Header;
  1241.     /* const */ char */* const */ Space = "\t\t";
  1242.     byte  statu;
  1243.     int i;
  1244.     byte *pntr;
  1245.  
  1246.     memcpy ( &Header.Status, rbuf, sizeof( struct MsgHeaderType ) );
  1247.     pntr =  ( byte * ) Header.MsgDate;
  1248.  
  1249.     if(  charset == ISOLAT1 )
  1250.     {
  1251.        for( i=0; i<88; i++ , pntr++ ) /* translate header info */
  1252.            *pntr = codelu[ ( unsigned ) *pntr  ];
  1253.     }
  1254.     else if(  charset == CHR7BIT )
  1255.     {
  1256.        for( i=0; i<88; i++ , pntr++ ) /* translate header info */
  1257.            *pntr = code7bit[ ( unsigned ) *pntr  ];
  1258.     }
  1259.  
  1260.     /* check for lowercase letters in to/from fields */
  1261.     caps = TRUE;
  1262.     pntr =  ( byte * ) ( Header.ForWhom );
  1263.     for( i=0; i<50; i++ )
  1264.         if( pntr[i] >= 'a' && pntr[i] <= 'z' )
  1265.             caps = FALSE;
  1266.  
  1267.     /* First line */
  1268.     high();
  1269.     green();
  1270.     printf( "\n%s", txt[19] );/* " From :" */
  1271.     yellow();
  1272.     nprint( Header.Author, 25 );
  1273.     printf( Space );
  1274.     green();
  1275.     printf( "%s", txt[23] );    /* "Number" */
  1276.     yellow();
  1277.     nprint( Header.NumMsg, 7 );
  1278.  
  1279.     /* Second line */
  1280.     green();
  1281.     printf( "\n%s", txt[20] );/* "To:" */
  1282.     red();
  1283.     if( !strnicmp( UserName1, ( char * ) ( Header.ForWhom ), strlen( UserName1 ) )||
  1284.        ( !strnicmp( UserName2, ( char * ) ( Header.ForWhom ), strlen( UserName2 ) ) ) )
  1285.         blink();
  1286.     nprint( Header.ForWhom, 25 );
  1287.     printf( Space );
  1288.  
  1289.     clear();
  1290.     green();
  1291.     high();
  1292.     printf( "%s", txt[24] );    /* " Ref # " */
  1293.     red();
  1294.     nprint( Header.RefMsg, 7 );
  1295.  
  1296.     green();
  1297.     printf( "\n%s", txt[21] );/* "Subject" */
  1298.     cyan();
  1299.     nprint( Header.Subject, 25 );
  1300.     printf( Space );
  1301.     green();
  1302.     printf( "%s", txt[25] );    /* "Conf : " */
  1303.     magenta();
  1304.     printf( "%s", ConfName[findCindex( readCnum( ( byte * ) &( Header.BinConfN[0] ) ) )] );
  1305.     green();
  1306.     printf( "\n%s", txt[22] );/* "date:" */
  1307.     red();
  1308.     nprint( Header.MsgDate, 8 );
  1309.     green();
  1310.     printf( "%s", txt[26] );    /* "time:" */
  1311.     red();
  1312.     nprint( Header.MsgTime, 5 );
  1313.     clear();
  1314.     blue();
  1315.     printf( "\t[%ld/%ld]", Index.MsgNum + 1, TotMsg );    /* 0 based, print 1 based. */
  1316.     statu = Header.Status;
  1317.     if( statu == '+' || statu == '*' || statu >= 0x80 )
  1318.     {
  1319.         printf( "\t\t" );
  1320.         red();
  1321.         high();
  1322.         blink();
  1323.         if( statu >= 0x80 )
  1324.             printf( " %s%c", txt[105], BELL );    /* "KILLED MESSAGE" */
  1325.         else
  1326.             printf( " %s%c", txt[27], BELL );    /* "PRIVATE MESSAGE" */
  1327.     }
  1328.     printf( "\n\n" );
  1329.     clear();
  1330.     cyan();
  1331. }
  1332.  
  1333.  
  1334. /*
  1335.  * Prints the Qmail message header in file fp.
  1336.  */
  1337.  
  1338. static void
  1339. PrintHeader( /* FILE * */ fp )
  1340. FILE *fp;
  1341. {
  1342.     struct MsgHeaderType Header;
  1343.     /* const */ char */* const */ Space = "\t\t";
  1344.     int i;
  1345.     byte *pntr;
  1346.  
  1347.     memcpy ( &Header.Status, rbuf, sizeof( struct MsgHeaderType ) );
  1348.     pntr =  ( byte * ) Header.MsgDate;
  1349.  
  1350.     if(  charset == ISOLAT1 )
  1351.     {
  1352.        for( i=0; i<88; i++ , pntr++ ) /* translate header info */
  1353.            *pntr = codelu[ ( unsigned ) *pntr  ];
  1354.     }
  1355.     else if(  charset == CHR7BIT )
  1356.     {
  1357.        for( i=0; i<88; i++ , pntr++ ) /* translate header info */
  1358.            *pntr = code7bit[ ( unsigned ) *pntr  ];
  1359.     }
  1360.  
  1361.  
  1362.    /* First line */
  1363.     fprintf( fp, "\n%s", txt[19] );    /* "from:" */
  1364.     nfprint( fp, Header.Author, 25 );
  1365.     fprintf( fp, Space );
  1366.     fprintf( fp, "%s", txt[23] );    /* "number:" */
  1367.     nfprint( fp, Header.NumMsg, 7 );
  1368.  
  1369.     /* Second line */
  1370.     fprintf( fp, "\n%s", txt[20] );    /* "to :" */
  1371.     nfprint( fp, Header.ForWhom, 25 );
  1372.     fprintf( fp, Space );
  1373.     fprintf( fp, "%s", txt[24] );    /* "ref#" */
  1374.     nfprint( fp, Header.RefMsg, 7 );
  1375.  
  1376.     fprintf( fp, "\n%s", txt[21] );    /* "subj." */
  1377.     nfprint( fp, Header.Subject, 25 );
  1378.     fprintf( fp, Space );
  1379.     fprintf( fp, "%s", txt[25] );    /* "Conf : " */
  1380.     fprintf( fp, "%s", ( char * ) ( ConfName[findCindex( readCnum( ( byte * ) &( Header.BinConfN[0] ) ) )] ) );
  1381.     fprintf( fp, "\n%s", txt[22] );    /* "date :" */
  1382.     nfprint( fp, Header.MsgDate, 8 );
  1383.     fprintf( fp, "%s", txt[26] );    /* "time:" */
  1384.     nfprint( fp, Header.MsgTime, 5 );
  1385.     fprintf( fp, "\t[%ld/%ld]", Index.MsgNum + 1, TotMsg );    /* 0 based, print 1 based. */
  1386.     if( Header.Status == '+' || Header.Status == '*' )
  1387.     {
  1388.         fprintf( fp, "\t\t" );
  1389.         fprintf( fp, "  %s\n", txt[27] );    /* "PRIVATE MESSAGE" */
  1390.     }
  1391.     fprintf( fp, "\n\n" );
  1392. }
  1393.  
  1394. /*
  1395.  * Reply to current message or enter a message
  1396.  * -------------------------------------------
  1397.  */
  1398.  
  1399. #define NulConf -1
  1400. #define unsave( x,y,z ) ( x = y , y = z )
  1401.  
  1402. static void
  1403. Reply( /* const int */ mode, /* const char * */ line )
  1404. int mode;
  1405. char *line;
  1406. {
  1407.     int             i , lowcase;
  1408.     unsigned int    j;
  1409.     char           *intmp;
  1410.     char            fname[MAXPATHS];
  1411.     char            tmp[MAXPATHS];
  1412.     char            dummy[MAXPATHS];
  1413.     int             reedit = FALSE;
  1414.     struct MsgHeaderType *Header;
  1415.     struct QmailRepType Qmail;
  1416. /* #ifdef USESYSTEM */
  1417.     char            cmd[MAXPATHS]; /* non-unix needs this */
  1418. /* #endif */
  1419.     if( IsEmpty )
  1420.     {
  1421.         EmptyMsg();
  1422.         return;
  1423.     }
  1424.  
  1425.     SaveConf = CurConf;
  1426.  
  1427.     if( mode == ENTER )
  1428.     {
  1429.         if( ( sscanf( line, "%s %s", dummy, tmp ) ) == 2 )
  1430.         {
  1431.             if( Numeric( tmp ) )
  1432.             {   /* find proper index for conference */
  1433.                 i = atoi( tmp );
  1434.                 i = findCindex( i );
  1435.             } 
  1436.             else
  1437.             {/* not numeric */
  1438.                 if( !strnicmp( tmp, "MAIN", 4 ) )
  1439.                     i = 0;
  1440.                 else
  1441.                 {   /* search for match in conf list */
  1442.                     j = strlen( tmp );
  1443.                     for( i = 0; i <= LastConf; i++ )
  1444.                         if( !strnicmp( tmp, ConfName[i], j ) )
  1445.                             break;
  1446.                 }
  1447.             }
  1448.             if( i < 0 || i > LastConf )
  1449.             {/* index not found in previous step */
  1450.                 printf( "\n%s\n", txt[28] );    /* Unknown Conference */
  1451.                 unsave( CurConf, SaveConf, NulConf );
  1452.                 return;
  1453.             }
  1454.             CurConf = i;   /* update Current conf. for our purposes */
  1455.         }
  1456.         if( CurConf == PCONF_IDX || CurConf == RCONF_IDX )
  1457.         {
  1458.             unsave( CurConf, SaveConf, NulConf );
  1459.             return;
  1460.         }
  1461.         if( CurConf != SaveConf )
  1462.             printf( "\n%s %d  %s %s\n", txt[29], ConfNumbers[CurConf],
  1463.                ConfName[CurConf], txt[30] );
  1464.     }
  1465.     Header = ( struct MsgHeaderType * ) rbuf;
  1466.     if(  ( SaveConf >= ( RCONF_IDX ) ) && mode != ENTER ) /* get actual conf. from header */
  1467.         CurConf = findCindex( readCnum( ( byte * ) & ( Header->BinConfN[0] ) ) );
  1468.  
  1469.     if(  ( intmp = tempnam( WorkPath, "re" ) )!= NULL ) /* Temporary file */
  1470.         strcpy ( fname, intmp );
  1471.     else
  1472.         sprintf( fname, "%s%c%s", WorkPath, SEP, "reply.tmp" );
  1473.  
  1474. l_edit:            /* this is where we go if we need to re-edit msg. */
  1475.     ResetHeader( &Qmail );
  1476.     printf( "\n" );
  1477.  
  1478. /* get who the message is from */
  1479. morefr:
  1480.      green();
  1481.     strcpy ( dummy , UserName );
  1482.     luxptr = dummy;
  1483.     if( mode == EDIT )
  1484.     {
  1485.         scpy( dummy, ( char * ) ( Header->Author ), 25 );
  1486.     }
  1487. /*    if( strcmp( luxptr, UserName1 ) )    */
  1488. /*        add_history( UserName1 );    */
  1489.     lowcase = fido;     /* True or False boolean valued */
  1490.     if( mode == REPLY )
  1491.     {
  1492.         lowcase = FALSE;
  1493.         intmp = ( char * ) Header->ForWhom;
  1494.         for(  i=0; i < 25; i++ )
  1495.             if(  intmp[i] >= 'a' && intmp[i] <= 'z' )
  1496.                 lowcase = TRUE;
  1497.     }
  1498.     if(  mode == ENTER )
  1499.         lowcase = !caps;
  1500.     if( !lowcase ) /* PCBoard likes uppercase to/from field */
  1501.         strupr( luxptr );
  1502.     intmp = readline( PRMTFR );
  1503.     strcpy( tmp, intmp );
  1504.     luxptr = NULL;
  1505.     StripDel( tmp );
  1506.     if( strlen( tmp ) > ( unsigned ) 25 )
  1507.     {
  1508.             red();
  1509.             printf( "%s\n", txt[34] );    /* "Entry too long ! 25 chars max */
  1510.             goto morefr;
  1511.     }
  1512.     if( tmp[0] )
  1513.         str2mem( ( char * ) Qmail.Author, tmp ); /* Right name in the from field */
  1514.      else
  1515.      {
  1516.         blue();
  1517.         printf( "%s.\n", txt[33] );    /* "message aborted" */
  1518.         unsave( CurConf, SaveConf, NulConf );
  1519.         return;
  1520.     }
  1521.  
  1522. /* get who the message is being sent to */
  1523. moreto:
  1524.     green();
  1525.      luxptr = dummy;
  1526.     if( mode == EDIT )
  1527.         scpy( dummy, ( char * ) ( Header->ForWhom ), 25 );
  1528.     else if(  mode != ENTER )
  1529.         scpy( dummy, ( char * ) ( Header->Author ), 25 );
  1530.     else
  1531.         strcpy( dummy, "All" );
  1532.     /* PCBoard likes uppercase to/from field */
  1533.     if(  !fido || ( caps && ( mode == ENTER ) ) ) 
  1534.         strupr( luxptr );
  1535.     intmp = readline( PRMTTO );
  1536.     /* PCBoard likes uppercase to/from field */
  1537.     if(  !fido || ( caps && ( mode == ENTER ) ) ) 
  1538.         strupr( intmp );
  1539.     strcpy( tmp, intmp );
  1540.     luxptr = NULL;
  1541.     StripDel( tmp );
  1542.     if( strlen( tmp ) > ( unsigned ) 25 )
  1543.     {
  1544.             red();
  1545.             printf( "%s\n", txt[34] );    /* "Entry too long ! 25 chars max */
  1546.             goto moreto;
  1547.     }
  1548.     if( !stricmp( tmp, "N" ) || !tmp[0] )
  1549.     {
  1550.             blue();
  1551.             printf( "%s.\n", txt[33] );    /* "message aborted" */
  1552.             unsave( CurConf, SaveConf, NulConf );
  1553.             return;
  1554.     }
  1555.     str2mem( ( char * ) ( Qmail.ForWhom ), ( char * ) tmp );
  1556.  
  1557. /* get subject of message */
  1558. moresub:
  1559.  
  1560.     green();
  1561.     if( mode != ENTER )
  1562.     {
  1563.             scpy( dummy, ( char * ) ( Header->Subject ), 25 );
  1564.             luxptr =  dummy;
  1565.     }
  1566.     intmp = readline( PRMTSB );
  1567.     strcpy( tmp, intmp );
  1568.     luxptr = NULL;
  1569.     StripDel( tmp );
  1570.     if( strlen( tmp ) > ( unsigned ) 25 )
  1571.     {
  1572.         red();
  1573.         printf( "%s\n", txt[34] );    /* "Entry too long ! 25 chars max */
  1574.         goto moresub;
  1575.     }
  1576.      if( !stricmp( tmp, "N" ) || !tmp[0] )
  1577.      {
  1578.         blue();
  1579.         printf( "%s.\n", txt[33] );    /* "message aborted" */
  1580.         unsave( CurConf, SaveConf, NulConf );
  1581.         return;
  1582.     }
  1583.     str2mem( ( char * ) Qmail.Subject, ( char * ) tmp );
  1584.  
  1585. /* get security of message */
  1586. moresec:
  1587.     green();
  1588.     if( ( mode != ENTER ) &&
  1589.         ( Header->Status == '+' || Header->Status == '*' ) )
  1590.         luxptr =  "Receiver Only ( private )";
  1591.     else
  1592.         luxptr = "None ( public )";
  1593.     intmp = readline( PRMTSC );
  1594.     strcpy( tmp, intmp );
  1595.     luxptr = NULL;
  1596.     StripDel( tmp );
  1597.     StripSpaceL( tmp );
  1598.     if( tmp[0] )
  1599.     {
  1600.         strupr( tmp );
  1601.         if( strlen( tmp ) > ( unsigned ) 25 )
  1602.         {
  1603.             red();
  1604.             printf( "%s\n", txt[35] );    /* "Too long! R=...etc..." */
  1605.             goto moresec;
  1606.         }
  1607.         if( tmp[0] == 'R'/* || !strnicmp( tmp,"priv", 4 ) */ )
  1608.             Qmail.Status = ( char ) 0x2A;
  1609.         else
  1610.             Qmail.Status = ( char ) 0x20;
  1611.      }
  1612.      else
  1613.      {
  1614.         blue();
  1615.         printf( "%s.\n", txt[33] );    /* "message aborted" */
  1616.         unsave( CurConf, SaveConf, NulConf );
  1617.         return;
  1618.     }
  1619.  
  1620.     sprintf( dummy, "%-7d", ConfNumbers[CurConf] );
  1621.     str2mem( ( char * ) Qmail.ConfNum, dummy );    /* Msg goes to the current conference */
  1622.  
  1623.     if( mode == EDIT && SaveConf == RCONF_IDX )
  1624.         scpy( dummy, ( char * ) ( Header->RefMsg ), 7 );
  1625.     else if(  mode  != ENTER )
  1626.         scpy( dummy, ( char * ) ( Header->NumMsg ), 7 );
  1627.  
  1628.     str2mem( ( char * ) Qmail.RefMsg, ( mode == ENTER ) ? "" : dummy );
  1629.  
  1630.     if( mode == REPLY && reedit == FALSE )
  1631.         QuoteMsg( fname );/* Quote original message... */
  1632.     else if( mode == EDIT && reedit == FALSE )
  1633.         StripTag( fname );
  1634.  
  1635.     white();
  1636.     /* "calling editor" */
  1637.     printf( "\n%s\n", txt[38] );
  1638.     sprintf( cmd,"%s %s", Editor, fname );
  1639.     system ( cmd );
  1640.  
  1641.      /* Here is where we ask if spelling needs checking */
  1642.     if( speller[0] )
  1643.     {
  1644.           intmp = readline( "Check spelling [Y/n] ?" );
  1645.         StripDel( intmp );
  1646.         intmp[0] = tolower( intmp[0] );
  1647.         if( intmp[0] != 'n' )
  1648.         {
  1649.             sprintf( cmd, "%s %s", speller, fname );
  1650.             system( cmd );
  1651.         }
  1652.     } /* end of spelling code */
  1653.  
  1654.     /* Here is where we ask if we want to save message */
  1655.     Tag( "tag ?" );
  1656.     printf( "Fido style tagline is %s.\n\n", fido ? "ON" : "OFF" );
  1657.     printf( "select:\n\t`Save' to save reply.\n" );
  1658.     printf( "\t`Edit' to re-edit reply.\n" );
  1659.     printf( "\t`Fido' to toggle tagline style and save reply.\n" );
  1660.     printf( "\t`Abort' to cancel reply.\n\n" );
  1661.     intmp = readline( "Choose: Save, Edit, Fido, Abort  [Save] ?" );
  1662.     strcpy ( tmp, intmp );
  1663.     StripDel( tmp );
  1664.     tmp[0] = tolower( tmp[0] );
  1665.  
  1666.     if( tmp[0] == 'e' )
  1667.     {
  1668.         reedit = TRUE;
  1669.         goto l_edit; /* re-edit message */
  1670.     }
  1671.     
  1672.     if( tmp[0] != 's' && tmp[0] != '\0' && tmp[0] != 'f' )
  1673.     {    /* abort reply */
  1674.         printf( "\n\n%s\n", txt[33] );
  1675.         unlink( fname );
  1676.         unsave( CurConf, SaveConf, NulConf );
  1677.         return;
  1678.     }
  1679.  
  1680.     if( tmp[0] == 'f' )
  1681.     {
  1682.         togltag();
  1683.     }
  1684.     if( !fido )        /* adjust header for fido or not */
  1685.         for( i = 0; i < 50; i++ )
  1686.             Qmail.ForWhom[i] = toupper( Qmail.ForWhom[i] );
  1687.  
  1688.     if( AddReply( fname, (struct QmailRepType *) &(Qmail.Status) ) )
  1689.     {
  1690.         if( autotag )
  1691.             ChooseTag();
  1692.         if( SaveConf == RCONF_IDX )
  1693.         {
  1694.             CurConf = RCONF_IDX;
  1695.             if( mode == EDIT )
  1696.                 ReadNext( NUKE );
  1697.             TotMsg++;
  1698.             sprintf( dummy,"%ld",TotMsg );
  1699.             GoToNum ( dummy );
  1700.         }
  1701.     }
  1702.     unsave( CurConf, SaveConf, NulConf );
  1703.     return;
  1704. }
  1705.  
  1706. /*
  1707.  * Add the reply to a Qmail reply.msg file.
  1708.  */
  1709. static int AddReply( fname, Qmail )
  1710. char *fname;
  1711. struct QmailRepType *Qmail;
  1712. {
  1713.     if( !OpenRepFile( ADDREP ) )
  1714.         return( FALSE );
  1715.     if( KodeMessage( fname, Qmail ) )
  1716.         return( FALSE );
  1717.     ReplyExist = TRUE;
  1718.     return( TRUE );
  1719. }
  1720.  
  1721. /*
  1722.  * LIST CONF : Prints conferences numbers, names and status.
  1723.  */
  1724.  
  1725. static void ListConf()
  1726. {
  1727.  
  1728. #define pers -2
  1729. #define reps -1
  1730.  
  1731.     unsigned        line;
  1732.     int             i=0;
  1733.     char            tmp[MAXPATHS];
  1734.  
  1735.     if( IsEmpty )
  1736.     {
  1737.         EmptyMsg();
  1738.         return;
  1739.     }
  1740.     cls();
  1741.     magenta();
  1742.     high();
  1743.     printf( "\r%s %s\n", txt[78], BoardName );    /* "Liste des conf. sur" */
  1744.     clear();
  1745.     red();
  1746.     printf( "\r" );
  1747.     for( i = 0; i < ( int ) ( strlen( txt[78] ) + strlen( BoardName ) + 1 ); i++ )
  1748.         putchar( '-' );
  1749.     putchar( '\n' );
  1750.  
  1751.     for( i = pers, line = 0; i < RCONF_IDX; i++ )
  1752.     {
  1753.         line++;
  1754.         if( line > SCREENLINES - 5 )
  1755.         {
  1756.             line = 0;
  1757.             printf( "\n" );
  1758.             if( !more( YES ) )
  1759.                 break;
  1760.             cyan();
  1761.         }
  1762.         if( i ==  pers )
  1763.         {    /* List personal conference first */
  1764.             if( pmail )
  1765.                 blink();
  1766.             i = PCONF_IDX;
  1767.         }
  1768.         if( i == reps )     /* List reply conference next */
  1769.             i = RCONF_IDX;
  1770.  
  1771.         sprintf( tmp, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i] );
  1772.         red();
  1773.         high();
  1774.         printf( "\n\t\t%4d ", ConfNumbers[i] );
  1775.         clear();
  1776.         blue();
  1777.         printf( "......... " );
  1778.         magenta();
  1779.         if( ( i == PCONF_IDX )  && pmail )
  1780.             blink();
  1781.         high();
  1782.         printf( "%-15s ", ConfName[i] );
  1783.         clear();
  1784.         blue();
  1785.         printf( "......... " );
  1786.         if( ( i == PCONF_IDX )  && pmail )
  1787.             blink();
  1788.         high();
  1789.         if( access( tmp, S_IREAD | S_IWRITE ) )
  1790.         {
  1791.             printf( "%s", txt[79] );    /* "Inactive" */
  1792.         }
  1793.         else
  1794.         {
  1795.             magenta();
  1796.             printf( "%s", txt[80] );    /* "active" */
  1797.         }
  1798.         if( i == PCONF_IDX )
  1799.         {
  1800.             clear();
  1801.             i = pers;
  1802.         }
  1803.         else if( i == RCONF_IDX )
  1804.             i = reps;
  1805.     }
  1806.     clear();
  1807.     printf( "\n\n" );
  1808. #undef reps
  1809. #undef pers
  1810. }
  1811.  
  1812.  
  1813. /*
  1814.  * Goes to the msg number represented by the string. and print it.
  1815.  * ( Internal count, not BBS numbers ! )
  1816.  */
  1817.  
  1818. static void GoToNum( /* const char * */ str )
  1819. char *str;
  1820. {
  1821.     if( SeekNum( str ) )
  1822.         Display( 0 );
  1823. }
  1824.  
  1825. /*
  1826.  * Seek to specific message number
  1827.  *
  1828.  */
  1829.  
  1830. static int
  1831. SeekNum( str )
  1832. char *str;
  1833. {
  1834.     long int    nb;
  1835.     size_t        nrecs; /* number of records to read */
  1836.  
  1837.     if( IsEmpty )
  1838.     {
  1839.         EmptyMsg();
  1840.         return( 0 );
  1841.     }
  1842.     nb = atol( str );
  1843.     nb = nb - 1;
  1844.     if( nb < 0 || nb >= TotMsg )
  1845.     {
  1846.         red();
  1847.         high();
  1848.         printf( "%s\n", txt[81] );    /* "Number out of range ! " */
  1849.         printf( "%s ", txt[82] );    /* "Valid msgs are" */
  1850.         magenta();
  1851.         printf( "1 " );
  1852.         red();
  1853.         printf( "%s ", txt[83] );    /* "to" */
  1854.         magenta();
  1855.         printf( "%ld\n", TotMsg );
  1856.         return( 0 );
  1857.     }
  1858.     if( fseek( fidx, ( nb * ( long ) sizeof( struct MyIndex ) ), SEEK_SET ) )
  1859.     {
  1860.         printf( "%s !\n", txt[16] );    /* "seek error" */
  1861.         return( 0 );
  1862.     }
  1863.     if( fread( &Index.LastRead, 1, sizeof( struct MyIndex ), fidx )
  1864.         != sizeof( struct MyIndex ) )
  1865.         {
  1866.         printf( "%s\n", txt[17] );    /* "End of messages " */
  1867.         return( 0 );
  1868.     }
  1869.     rewind( fmsg );
  1870.     if( fseek( fmsg, Index.Offset, SEEK_SET ) )
  1871.     {
  1872.         printf( "%s !\n", txt[16] );
  1873.         return( 0 );
  1874.     }
  1875.     nrecs = ( ( Index.Size / 128 ) + 1 ); /* same as ( Index.Size+128 )/128 ) */
  1876.     if( ( fread( ( char * ) rbuf, 128, nrecs , fmsg ) ) != nrecs )
  1877.     {
  1878.          printf( "%s ? \n", txt[18] );    /* "read error" */
  1879.         return( 0 );
  1880.     }
  1881.     rbuf[ ( Index.Size )+128 ] = '\0'; /* terminate buffer like a string */
  1882.     return( 1 ); /* good seek */
  1883.  
  1884. }
  1885.  
  1886.  
  1887. /*
  1888.  * DISPLAY : Prints the current message,stored in memory.
  1889.  */
  1890.  
  1891. static void
  1892. Display( mode )
  1893. int mode;
  1894. {
  1895.  
  1896.     unsigned long   i = 0;
  1897.     int                 QuotedColor, line = 0, count = 0;
  1898.     byte            *ptr, *pt;
  1899.        byte            *linbuf;
  1900.  
  1901.     if( IsEmpty )
  1902.     {
  1903.         EmptyMsg();
  1904.         return;
  1905.     }
  1906.     cls();
  1907.     PutHeader();
  1908.     if( ( linbuf = ( byte * ) malloc( 400 ) ) == NULL )
  1909.     { /* local line buffer */
  1910.         printf( "malloc() failed in read.c module Display()\n\n" );
  1911.         return;
  1912.     }
  1913.     cyan();
  1914.  
  1915.        ptr =  rbuf + Index.Size + 127;  /* strip off trailing junk */
  1916.     while( *ptr == '\0' || *ptr == '\040' || *ptr == '\n' )
  1917.     {
  1918.         *ptr = '\0';
  1919.          ptr--;
  1920.     }
  1921.     *( ++ptr ) = '\n';
  1922.  
  1923.     ptr =  ( rbuf + sizeof( struct MsgHeaderType ) );
  1924.     i = 0;
  1925.     line = QuotedColor = 0;
  1926.     pt = linbuf;
  1927.     *pt = 0;
  1928.  
  1929.     while ( i < Index.Size )
  1930.     {
  1931.         /* Security for long lines */
  1932.         if( count > ( int ) 79 )
  1933.             *ptr = '\n';
  1934.  
  1935.         /* Display a total line */
  1936.         if( *ptr == '\n' )
  1937.         {
  1938.             count = 0;
  1939.             *pt = 0;
  1940.             line++;
  1941.             pt = linbuf;
  1942.  
  1943.             /* Process colors on quoted line */
  1944.             if( IsQuoted( '>', pt ) )
  1945.             {
  1946.                 while ( *pt != '>' )
  1947.                     putchar( *pt++ );
  1948.                 QuotedColor = 1;
  1949.                 red();    /* Quote char in red... */
  1950.                 putchar( *pt++ );
  1951.                 green();    /* Quoted line in green.. */
  1952.                 puts( ( char * ) pt );
  1953.                 cyan();
  1954.                 pt = linbuf;
  1955.             }
  1956.             else
  1957.             {
  1958.                 if( QuotedColor )
  1959.                 {
  1960.                     cyan();
  1961.                     QuotedColor = 0;
  1962.                 }
  1963.                 puts( (char *) linbuf );
  1964.             }
  1965.         }
  1966.         else if( *ptr )
  1967.         {    /* Non 0 chars */
  1968.             if( charset != CHRDOS )
  1969.             {
  1970.                 if(  vtspecial( *ptr ) && graphics )
  1971.                 { /* use vt100 graphics codes */
  1972.                       *pt++ =  '\016';
  1973.                   *pt++ =  codevt[ ( unsigned ) ( *ptr ) ];
  1974.                       *pt   =  '\017';
  1975.                 }
  1976.                 else if( charset == ISOLAT1 )
  1977.                     *pt = codelu[   ( unsigned ) ( *ptr ) ]; /* use iso lookup table */
  1978.                else
  1979.                     *pt = code7bit[ ( unsigned ) ( *ptr ) ];
  1980.             }
  1981.             else
  1982.                 *pt = *ptr;
  1983.             pt++;
  1984.             count++;    /* Security for line length ... */
  1985.         }
  1986.  
  1987.         i++;
  1988.         ptr++;
  1989.  
  1990.         if( line > SCREENLINES - 8 )
  1991.         {
  1992.             line = 0;
  1993.             if( mode == KILL || mode == NUKE || mode == PRIVATE )
  1994.                 break;
  1995.             if( !more( YES ) )
  1996.                 break;
  1997.             cyan();
  1998.         }
  1999.     }
  2000.     free( linbuf );
  2001.     FirstDone = TRUE;
  2002.     printf( "\n" );
  2003. }
  2004.  
  2005.  
  2006.  
  2007. /*
  2008.  * Welcome : Displays the welcome file.
  2009.  */
  2010.  
  2011. static void Welcome()
  2012. {
  2013.     char tmp[MAXPATHS];
  2014.  
  2015.     sprintf( tmp, "%s%s%c%s", HomePath, CurBoard, SEP, WELCOME );
  2016.     if( !access( tmp, S_IREAD ) )
  2017.     {
  2018.         sprintf( tmp, "%s%s", HomePath, CurBoard );
  2019.         view( tmp, WELCOME );
  2020.     }
  2021.     else
  2022.     {
  2023.         sprintf( tmp, "%s%s%c%s", HomePath, CurBoard, SEP, WELCOMEG ); /* ansi welcome */
  2024.         if( !access( tmp, S_IREAD ) )
  2025.         {
  2026.             sprintf( tmp, "%s%s", HomePath, CurBoard );
  2027.             view( tmp, WELCOMEG );
  2028.         }
  2029.     }
  2030. }
  2031.  
  2032. /*
  2033.  * GETBBS : Called by main() with argv[1]. Looks for a new QWK packet, if
  2034.  * older than message base, just  loads the base.
  2035.  */
  2036.  
  2037. static void GetBbs( name )
  2038. char *name;
  2039. {
  2040.     char tmp[MAXPATHS];
  2041.     char packet[MAXPATHS];
  2042.     char base[MAXPATHS];
  2043.  
  2044.     strcpy( tmp, name );
  2045.     if( strstr( name, ".qw" ) == NULL )
  2046.         strcat( tmp, ".qwk" );
  2047.  
  2048.     sprintf( packet, "%s%s", MailPath, tmp );
  2049.  
  2050.     if( access( packet, S_IREAD ) )
  2051.     {/* No new mail found */
  2052.         printf( "%s\n", txt[31] );    /* "no new mail" */
  2053.         Read( name );
  2054.         return;
  2055.     }
  2056.     sprintf( base, "%s%s%c%s", HomePath, name, SEP, CNTRL_FILE );
  2057.     if( access( base, S_IREAD ) )
  2058.     {
  2059.         printf( "%s. ", txt[45] );    /* New BBS in this base. */
  2060.         sprintf( tmp, "load %s", name );
  2061.         Load( tmp );
  2062.         return;
  2063.     }
  2064.     if( fileage( packet ) <= fileage( base ) )
  2065.     {
  2066.         blue();
  2067.         high();
  2068.         printf( "%s. %s.\n", txt[46], txt[47] );
  2069.         sprintf( tmp, "Read %s", name );
  2070.         Read( tmp );
  2071.         return;
  2072.     }
  2073.     sprintf( tmp, "Load %s", name );
  2074.     Load( tmp );
  2075. }
  2076.  
  2077.  
  2078. static void Purge()
  2079. {
  2080.     int        i;
  2081.     char    tmp[80];
  2082.     char    cnf[MAXPATHS];
  2083.     char    idx[MAXPATHS];
  2084.     int        size;
  2085.  
  2086.     if( IsEmpty )
  2087.     {
  2088.         EmptyMsg();
  2089.         return;
  2090.     }
  2091.     magenta();
  2092.     high();            /* Selective erasing of conferences. */
  2093.     printf( "\n%s\n", txt[102] );    /* Effacement sΘlectif des confΘrences */
  2094.     clear();
  2095.     red();
  2096.     printf( "----------------------------------------\n\n" );
  2097.  
  2098.     for( i = 0; i <= LastConf; i++ )
  2099.     {
  2100.         sprintf( cnf, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i] );
  2101.         sprintf( idx, "%s%s%c%d.idx", HomePath, CurBoard, SEP, ConfNumbers[i] );
  2102.  
  2103.         if( ( size = filesize( cnf ) ) == -1 )
  2104.             continue;    /* No such file */
  2105.  
  2106. onemore:
  2107.  
  2108.         green();
  2109.         high();
  2110.         printf( "Conf. %d [ ", ConfNumbers[i] );
  2111.         yellow();
  2112.         printf( "%s", ConfName[i] );
  2113.         green();
  2114.         printf( " ] takes " );
  2115.         yellow();
  2116.         printf( "%ld", size );
  2117.         green();
  2118.         printf( " bytes. Delete ( Y )es ( N )o ( S )top : " );
  2119.  
  2120.         fget( tmp, 5, stdin );
  2121.         strupr( tmp );
  2122.  
  2123.         switch ( ( int ) tmp[0] )
  2124.         {
  2125.         case 'N':
  2126.             break;
  2127.  
  2128.         case 'S':
  2129.             return;
  2130.  
  2131.         case 'Y':
  2132.         case 'O':
  2133.         case 'J':
  2134.             if( unlink( cnf ) == -1 )
  2135.                 printf( "Unable to remove file %s\n", cnf );
  2136.             if( unlink( idx ) == -1 )
  2137.                 printf( "Unable to remove file %s\n", idx );
  2138.             blue();
  2139.             if( i == CurConf )
  2140.             {
  2141.                 Index.LastRead = 0;
  2142.                 Index.MsgNum = 0;
  2143.                 TotMsg = 0;
  2144.                 if( FilesOpen )
  2145.                 {
  2146.                     fclose( fidx );
  2147.                     fclose( fmsg );
  2148.                     FilesOpen = FALSE;
  2149.                     FirstDone = FALSE;
  2150.                 }
  2151.             }
  2152.             ConfActive[i] = FALSE;
  2153.             if( i == findCindex( PERS_CONF ) )
  2154.                 pmail = FALSE;
  2155.             printf( "Conference %d is now empty.\n\n", ConfNumbers[i] );
  2156.             ActvCnt--;    /* one less active conference */
  2157.  
  2158.             break;
  2159.  
  2160.         default:
  2161.             goto onemore;
  2162.         }
  2163.     }
  2164.     if( !ConfActive[CurConf] )
  2165.         AutoJoin();
  2166. }
  2167.  
  2168. /*
  2169.  * scan through the message headers
  2170.  */
  2171.  
  2172. static void scruter()
  2173. {
  2174.     int i, m;
  2175.  
  2176.     m = SCREENLINES / 6;
  2177.     do
  2178.     {
  2179.         cls();
  2180.         for( i = 0; i < m; i++ )
  2181.             if( !ReadNext( SCAN ) )
  2182.                 return;
  2183.     }
  2184.     while( more( YES ) );
  2185.     return;
  2186. }
  2187.  
  2188. /*
  2189.  * search conference for text string
  2190.  *
  2191.  */
  2192.  
  2193. static int findtxt( fndargs, mode )
  2194. char *fndargs;
  2195. int mode;
  2196. { /* valid modes are FIND & NEXT */
  2197.     static char findbuf[256];
  2198.     static long nm;
  2199.     char *fndpt;  /* not used but needed for future use */
  2200.     char nmbuf[30];
  2201.     if( mode == FIND )
  2202.     {
  2203.         strcpy( findbuf, fndargs );
  2204.         nm = 1;
  2205.     }
  2206.     if( findbuf[5] == ( char ) 0 || nm > TotMsg || nm < 1 )
  2207.         return( 0 ); /* nothing to do */
  2208.     while( nm <= TotMsg )
  2209.     {
  2210.         sprintf( nmbuf,"%ld",nm );
  2211.         nm++;
  2212.         if( !SeekNum( nmbuf ) )   /* seek to next message in conference */
  2213.             return( 0 );
  2214.         rbuf[96] = '\0';    /* mark end of header search */
  2215.         if(  ( fndpt = findstr( ( byte * ) &rbuf[128], ( byte * ) &findbuf[5] ) ) != NULL ||
  2216.              ( fndpt = findstr( ( byte * ) &rbuf[21],  ( byte * ) &findbuf[5] ) ) != NULL )
  2217.              {
  2218.             Display( 0 );
  2219.             break;
  2220.         }
  2221.     }
  2222.     return( 1 );
  2223. }
  2224.  
  2225. /* function to look for search string s2 in text string s1 */
  2226. static char *findstr( s1, s2 )
  2227. unsigned char *s1;
  2228. unsigned char *s2;
  2229. {
  2230.     byte *p1, *p2;
  2231.  
  2232.     p1 = s1;
  2233.     p2 = s2;
  2234.  
  2235.     /* while the end of string s1 has not been reached, */
  2236.     while( *s1 )
  2237.     {
  2238.         /* while s2 matches within s1, */
  2239.         /* look for search string s2 */
  2240.         /* strip off lowercase if needed */
  2241.         while ( ( isalpha( *p1 ) ? toupper( *p1 ) : *p1 ) ==
  2242.               ( isalpha( *p2 ) ? toupper( *p2 ) : *p2 ) )
  2243.         {
  2244.             /* advance string compare pointers */
  2245.             p1++;
  2246.             p2++;
  2247.  
  2248.             /* if end of search string s2 is reached, */
  2249.             /* return ptr to position in string s1 where s2 found */
  2250.             if( !*p2 )
  2251.                 return( (char *) s1 );
  2252.  
  2253.             /* if end of string s1 reached prematurely, */
  2254.             /* return NULL indicating incomplete match */
  2255.             if( !*p1 )
  2256.                 return( NULL );
  2257.         }
  2258.         /* if mismatch occurs, advance s1 string pointer */
  2259.         /* and reset search string pointer s2 */
  2260.         p1 = ++s1;
  2261.         p2 = s2;
  2262.     }
  2263.     /* if end of string s1 reached, */
  2264.     /* return NULL indicating string s2 not in s1 */
  2265.     return( NULL );
  2266. }
  2267.  
  2268.  
  2269. /*
  2270.  * Search array for next active conference, wrapping around
  2271.  * to start if need be.
  2272.  */
  2273.  
  2274. static int FindActive( curcon )
  2275. int curcon;
  2276. {
  2277.     int i;
  2278.     for( i = curcon + 1; i <= LastConf; i++ )
  2279.     {
  2280.         if( ConfActive[i] )
  2281.             return( i );
  2282.     }
  2283.     for( i = 0; i <= curcon; i++ )
  2284.     {
  2285.         if( ConfActive[i] )
  2286.             return( i );
  2287.     }
  2288.     return( -1 );
  2289. }
  2290.  
  2291. static void showterms()
  2292. {
  2293.     int i = 0;
  2294.     while( terms[i] != NULL && i < 50 )
  2295.     {
  2296.         printf( "%s\n",terms[i] );
  2297.         i++;
  2298.     }
  2299.  
  2300. }
  2301.