home *** CD-ROM | disk | FTP | other *** search
/ The Arcade BBS / arcadebbs.zip / arcadebbs / bbstools / MODS / ACHAT40.ZIP / ACHAT.C next >
Encoding:
C/C++ Source or Header  |  1995-07-08  |  46.0 KB  |  1,369 lines

  1. /* achat 4.0  June 4, 1995 */
  2.  
  3. #include "vars.h"   /* this into source, then comment out this line    */
  4.                     /* if you have errors and you choose to block read */
  5. #pragma hdrstop
  6.  
  7. #include <conio.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <dos.h>
  13. #include <dir.h>
  14.  
  15.  
  16.  
  17.  
  18.  
  19. /* if NO_RANDOM_AT_START is defined, then the sysop will be prompted for */
  20. /* a chat screen upon entering the Asylum Chat                           */
  21. /* Leave it commented out to let the BBS randomly pick one for you       */
  22. // #define NO_RANDOM_AT_START
  23.  
  24.  
  25. /* amount of lines it pulls up from the bottom when scrolling back to top */
  26. #define AMOUNT_TO_WRAP_UP (3)
  27.  
  28.  
  29.  
  30. typedef struct
  31. {
  32.   unsigned char xpos, ypos, length;
  33. } lines_record;
  34.  
  35.  
  36.  
  37. typedef struct
  38. {
  39.   int amount_colors;
  40.  
  41.   unsigned char colors[16];  /* up to 16 colors */
  42. } color_record;
  43.  
  44.  
  45. #define ACHAT_MAX_WIDTH 100
  46.  
  47.  
  48.  
  49. #define AMOUNT_COLOR_SETS (5)
  50. const color_record colors[AMOUNT_COLOR_SETS] = {
  51.  /* blue set */ { 4, 1, 9,  3, 11, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0 },
  52.  /* red  set */ { 4, 4, 5, 12, 13, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0 },
  53.  /* gray set */ { 4, 0, 7,  8, 15, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0 },
  54.  /* brwn set */ { 4, 3, 6, 10, 14, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0 },
  55.  /* all clrs */ { 0, 1, 2,  3,  4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }};
  56.  
  57.  
  58. static int sys_rand_color_set, user_rand_color_set;
  59.  
  60. static lines_record *sys_lines, *user_lines;
  61. static char far *sys_text, *user_text, achat_dir[128]="";
  62.  
  63. static int amount_sys_lines, amount_user_lines;
  64. static int sys_upper_color, sys_lower_color, sys_numeric_color;
  65. static int user_upper_color, user_lower_color, user_numeric_color;
  66.  
  67. static int sys_bk_color, sys_rand_freq, sys_cur_color;
  68. static int user_bk_color, user_rand_freq, user_cur_color;
  69.  
  70. static int sys_line, sys_pos, user_line, user_pos, alt_achat_clear;
  71. static int flip_sides, no_user_side, chat_done, pick_file;
  72.  
  73. static int tl_x, tl_y, to_x, to_y, time_on_color=7, time_left_color=7;
  74. static int us_x, us_y, us_c=7, sy_x, sy_y, sy_c=7;
  75.  
  76. static FILE *achat_desc;
  77.  
  78. static char *welcome_text;
  79.  
  80. void achat(char *sysop_name)
  81. {
  82.   char fname[25], temp[50];
  83.   int save_topdata = topdata;
  84.   char WelcomeText[81];
  85.  
  86.  
  87.   welcome_text = WelcomeText;     /* save a few bytes of static storage */
  88.   topdata=0;
  89.   topscreen();
  90.   CLS();
  91.  
  92.   flip_sides = 0;
  93.   chat_done = 0;
  94.  
  95. #ifndef NO_RANDOM_AT_START
  96.   pick_file = 0;                    /* get a random ansi screen            */
  97. #else
  98.   pick_file = 1;                    /* prompt sysop for ansi screen name   */
  99. #endif
  100.  
  101.  
  102.   sprintf(achat_dir, "%sACHAT\\", syscfg.gfilesdir);
  103.  
  104.  
  105. #ifndef NO_RANDOM_AT_START
  106.   if(modem_speed < 9600)            /* if modem_speed is 0-9599, then show */
  107.   {                                 /* the low modem speed chat screen     */
  108.     char temp[201];                 /* called '2400.ANS', if it doens't    */
  109.                                     /* exist, then go get one like normal  */
  110.     sprintf(temp, "%s2400.ANS", achat_dir);
  111.     if(exist(temp))
  112.       pick_file = -1;               /* set low modem speed flag            */
  113.   }
  114. #endif
  115.  
  116.  
  117.   /* This while loop is present so that we can set chat_done = true, but   */
  118.   /* not turn off chatting, this will free up current memory and reload    */
  119.   /* a new chat menu                                                       */
  120.   while(chatting && !hangup)
  121.   {
  122.  
  123.     chat_done = 0;                      /* in case it gets turned off,     */
  124.                                         /* like what happens when you want */
  125.                                         /* a new chat menu set loaded      */
  126.     if(pick_file < 0)
  127.     {
  128.       strcpy(fname, "2400.ANS");
  129.       pick_file = 0;
  130.     }
  131.     else if(pick_file > 0)
  132.     {
  133.       pick_file = 0;
  134.       if(!select_achat_filename(fname))
  135.         return;
  136.     }
  137.     else if(!get_achat_filename(fname)) /* Pick a random screen to chat in */
  138.       return;
  139.  
  140.     if(!achat_read_config(fname))
  141.       return;                           /* Read the INI file to define it  */
  142.  
  143.     display_achat_screen(fname, sysop_name); /* print the screen           */
  144.  
  145.     if(us_x > 0 && us_y > 0)
  146.     {
  147.       GOTO_XY(us_x, us_y);
  148.       setc(us_c);
  149.       strcpy(temp,thisuser.name);      /* move this out of the #ifdef in*/
  150.       properize(temp);                 /* newuser.c if you have probs   */
  151.       outstr(temp);                    /* sysop name                    */
  152.     }
  153.     if(sy_x > 0 && sy_y > 0)
  154.     {
  155.       GOTO_XY(sy_x, sy_y);
  156.       setc(sy_c);
  157.       strcpy(temp,sysop_name);         /* move from #ifdef in           */
  158.       properize(temp);                 /* newuser.c if you have probs   */
  159.       outstr(temp);                    /* the users name                */
  160.     }
  161.  
  162.  
  163.     sys_line = sys_pos   = 0;           /* Set up a few global variables   */
  164.     user_line = user_pos = 0;
  165.  
  166.     go_do_achat();                      /* And run the chat program        */
  167.  
  168.     if(sys_lines)  free(sys_lines);     /* free memory if it was allocated */
  169.     if(user_lines) free(user_lines);
  170.     if(sys_text)   free(sys_text);
  171.     if(user_text)  free(user_text);
  172.   }
  173.  
  174.   topdata=save_topdata;
  175.   topscreen();
  176. }
  177.  
  178.  
  179. void go_do_achat(void)
  180. {
  181.   int key;
  182.   unsigned long counter = 0;
  183.  
  184.   chatting = 3;
  185.  
  186.   GOTO_XY(sys_lines[0].xpos + sys_pos, sys_lines[0].ypos); /* set cursor up      */
  187.  
  188.   if(welcome_text[0])                    /* display welcome message      */
  189.   {
  190.     display_achat_string(welcome_text, 1);
  191.     display_achat_string("\n\n", 1);
  192.   }
  193.  
  194.   while(!chat_done && chatting && !hangup)
  195.   {
  196.     if(counter % 10 == 0)                /* every 10 key strokes, update */
  197.     {                                    /* then time on and time left   */
  198.       if(to_x > 0 && to_y > 0)
  199.       {
  200.         SaveCursor();                    /* Save the cursor position     */
  201.         GOTO_XY(to_x, to_y);             /* reposition it for writting   */
  202.         setc(time_on_color);             /* the amount of time on        */
  203.         outstr(ctim(timer() - timeon));  /* How long user has been on    */
  204.         RecallCursor();                  /* and restore the cursor pos   */
  205.       }
  206.       if(tl_x > 0 && tl_y > 0)
  207.       {
  208.         SaveCursor();                    /* Save our cursor position,    */
  209.         GOTO_XY(tl_x, tl_y);             /* set it for writting the time */
  210.         setc(time_left_color);           /* left for this logon          */
  211.         outstr(ctim(nsl()));             /* How much time the user has   */
  212.         RecallCursor();                  /* Put cursor back where it was */
  213.       }
  214.     }
  215.     ++counter;                           /* amount of keys processed     */
  216.  
  217.  
  218.     key = getkey();                      /* Add the key to our screen.   */
  219.     add_achat_key(key, flip_sides ? !lastcon : lastcon);
  220.                                          /* lastcon is a variable which  */
  221.   }                                      /* is set to 1 if the last key  */
  222.   outchr(12);                            /* was made by the local user   */
  223. }                                        /* and 0 for remote user        */
  224.  
  225.  
  226.  
  227. char *achat_fix_fname(char *fname)
  228. {
  229.   char *tmp;
  230.  
  231.   if(fname)                              /* Just a saftey check          */
  232.   {
  233.     tmp = strchr(fname, '.');            /* see if a dot exists          */
  234.     if(!tmp)                             /* if not                       */
  235.       strcat(fname, ".INI");             /* append a .INI                */
  236.     else                                 /* otherwise starting at        */
  237.       strcpy(tmp, ".INI");               /* the '.', copy .INI to it     */
  238.   }
  239.   return(fname);
  240. }
  241.  
  242. int achat_read_config(char *fname)
  243. {
  244.   char ini_pn[201];
  245.   ini_record *ini_info;
  246.   char temp[201], tmp_line[50];
  247.   int x, temp_number[10];
  248.  
  249.  
  250.   tl_x = tl_y = to_x = to_y = -1;   /* default to no time on and t.left */
  251.   us_x = us_y = sy_x = sy_y = -1;   /* default to no sysop or user name */
  252.   time_on_color = time_left_color = 7;
  253.   us_c = sy_c = 7;
  254.   sys_bk_color = user_bk_color = -1; /* default to random color is off  */
  255.   sys_rand_freq=user_rand_freq = -1; /* default to random color is off  */
  256.   sys_rand_color_set = 0;            /* blue color set                  */
  257.   user_rand_color_set = 0;           /* blue color set                  */
  258.  
  259.   strcpy(temp, fname);                   /* don't change our orig fname */
  260.   achat_fix_fname(temp);                 /* make sure extension is .INI */
  261.  
  262.  
  263.   /* all Asylum Chat stuff is located in a directory called ACHAT off of */
  264.   /* your gfiles directory                                               */
  265.   sprintf(ini_pn, "%s%s", achat_dir, temp);
  266.  
  267.   if((ini_info = open_ini(ini_pn, IF_OREAD)) == NULL)  /* try to open INI file         */
  268.   {
  269.     pl("Can't open INI file for ACHAT"); /* Printed out for sysop to see */
  270.     pausescr();
  271.     return 0;
  272.   }
  273.  
  274.   /*-----------------------------------------------------------------*/
  275.   /* Welcome text is text that is first displayed on entry of the    */
  276.   /* chat screen                                                     */
  277.  
  278.   ini_read_string(ini_info, "Sysop", "Welcome", welcome_text);
  279.  
  280.  
  281.   /*-----------------------------------------------------------------*/
  282.   /* Time on - shows the amount of time the user has left on the bbs */
  283.   /* this time is updated every 10 key strokes, and only shown if    */
  284.   /* the to_x has a value greater than -1                            */
  285.  
  286.   if(ini_read_string(ini_info, "Macros", "Time On", temp))
  287.     achat_get_3_fields(temp, &to_x, &to_y, &time_on_color);
  288.  
  289.  
  290.   /*-----------------------------------------------------------------*/
  291.   /* Time left - Alot like time on, but shows how much time is left  */
  292.   /* on the board... it is only shown if coordinates greater than -1 */
  293.   /* are given                                                       */
  294.  
  295.   if(ini_read_string(ini_info, "Macros", "Time Left", temp))
  296.     achat_get_3_fields(temp, &tl_x, &tl_y, &time_left_color);
  297.  
  298.  
  299.   /*-----------------------------------------------------------------*/
  300.   /* An alternate the the $> and $<, you can specify the User and    */
  301.   /* sysop name positions and color in the .INI file                 */
  302.   if(ini_read_string(ini_info, "Macros", "User Name", temp))
  303.     achat_get_3_fields(temp, &us_x, &us_y, &us_c);
  304.  
  305.   if(ini_read_string(ini_info, "Macros", "Sysop Name", temp))
  306.     achat_get_3_fields(temp, &sy_x, &sy_y, &sy_c);
  307.  
  308.  
  309.  
  310.   /* Find out how many lines are setup for this screen on the sysop side */
  311.   amount_sys_lines = ini_read_number(ini_info, "SYSOP", "Amount of Lines");
  312.  
  313.   if(!amount_sys_lines)
  314.     { sysoplog("Err-NSL"); close_ini(ini_info); return 0; }
  315.  
  316.  
  317.   /* find out if there is a user side or not... if not, it will be like  */
  318.   /* chatting in the stock non-two way chat, but you still have an ansi  */
  319.   no_user_side = ini_read_boolean(ini_info, "SYSOP", "No user side");
  320.  
  321.  
  322.   /* Find out how many lines are setup for this screen on the user side */
  323.   amount_user_lines = ini_read_number(ini_info, "USER", "Amount of Lines");
  324.  
  325.   if(!amount_user_lines && no_user_side==0)
  326.     { sysoplog("Err-NUL"); close_ini(ini_info); return 0; }
  327.  
  328.  
  329.   sys_lines  = (lines_record *)malloc(amount_sys_lines * sizeof(lines_record));
  330.   user_lines = (lines_record *)malloc(amount_user_lines * sizeof(lines_record));
  331.  
  332.   sys_text  = (char *)malloc(amount_sys_lines * ACHAT_MAX_WIDTH);
  333.   user_text = (char *)malloc(amount_user_lines * ACHAT_MAX_WIDTH);
  334.  
  335.   memset(sys_text, 0, amount_sys_lines * ACHAT_MAX_WIDTH);
  336.   memset(user_text, 0, amount_user_lines * ACHAT_MAX_WIDTH);
  337.  
  338.  
  339.   /* Check to see if any thing was unable to get memory */
  340.   if(!sys_lines || !sys_text)
  341.   {
  342.     sysoplog("Err-NM");    /* The memory is free'd at the end of */
  343.                            /* function 'achat'                   */
  344.  
  345.     close_ini(ini_info);
  346.     return 0;
  347.   }
  348.  
  349.  
  350.  
  351.  /*---------------------------------------------------------------------*/
  352.  /* Check to see if any thing was unable to get memory                  */
  353.  /* the absense of user_text or user_lines is only fatal if there is    */
  354.  /* in fact a user side.  We obviously don't need memory allocated      */
  355.  /* or lines specified for a user side if there isn't one present       */
  356.  
  357.   if(no_user_side == 0)                /* see if there is a user side   */
  358.   {
  359.     if(!user_lines || !user_text)      /* if so, there better be both   */
  360.     {                                  /* lines and memory, else fail   */
  361.       sysoplog("Err-NM");              /* The memory is free'd at the   */
  362.                                        /* end of function 'achat'       */
  363.  
  364.       close_ini(ini_info);        /* release ini info stuff        */
  365.       return 0;                        /* and return with failure       */
  366.     }
  367.   }
  368.  
  369.  
  370.  
  371.  
  372.  /*---------------------------------------------------------------------*/
  373.  /* loop through all the line and read in the line information          */
  374.  /* for the sysop side of the screen                                    */
  375.  
  376.  
  377.   for(x = 1; x <= amount_sys_lines; ++x)
  378.   {
  379.     sprintf(tmp_line, "Line %d", x);
  380.     sprintf(temp, "1, %d, 80", x);
  381.     ini_read_string(ini_info, "SYSOP", tmp_line, temp);
  382.  
  383.     if(!parse_achat_line_info(temp, &sys_lines[x-1]))
  384.     {
  385.       sprintf(temp, "Check '%s' in %s in the [SYSOP] section", tmp_line, fname);
  386.       sysoplog(temp);
  387.       outstr(temp);
  388.       pausescr();
  389.     }
  390.   }
  391.  
  392.  
  393.  
  394.  
  395.  /*---------------------------------------------------------------------*/
  396.  /* Parse through all the lines and read in the line information        */
  397.  /* For the users side of the screen                                    */
  398.  
  399.   for(x = 1; x <= amount_user_lines; ++x)
  400.   {
  401.     sprintf(tmp_line, "Line %d", x);
  402.     sprintf(temp, "1, %d, 80", x);
  403.     ini_read_string(ini_info, "USER", tmp_line, temp);
  404.  
  405.     if(!parse_achat_line_info(temp, &user_lines[x-1]))
  406.     {
  407.       sprintf(temp, "Check '%s' in %s in the [USER] section", tmp_line, fname);
  408.       sysoplog(temp);
  409.       outstr(temp);
  410.       pausescr();
  411.     }
  412.   }
  413.  
  414.  
  415.  
  416.  /* -------------------------------------------------------------------- */
  417.  /* Read sysop color options ...                                         */
  418.  /*                                                                      */
  419.  /* You can have 2 different (almost 3) types of colors:                 */
  420.  /*   Defined colors for upper/lower/digits                              */
  421.  /*   Rotating colors                                                    */
  422.  /*   You can have a modified rotating colors which rotates every word   */
  423.  /*   change                                                             */
  424.  /*   Rotating colors can be 1 or 5 types, rotates through blue, red,    */
  425.  /*   gray, brown or all colors                                          */
  426.  
  427.   if(ini_read_boolean(ini_info, "SYSOP", "Random Colors"))
  428.   {
  429.  
  430.     strcpy(temp, "0,3");       /* Bg color is 0 and rotate every 3 chars */
  431.  
  432.     ini_read_string(ini_info, "SYSOP", "Random Options", temp);
  433.     achat_get_fields(temp, temp_number, 2);
  434.     sys_bk_color = temp_number[0];
  435.     sys_rand_freq = temp_number[1];
  436.  
  437.     if(sys_bk_color > 15)             /* make bk color a 0-7 color       */
  438.       sys_bk_color = sys_bk_color >> 4;
  439.  
  440.  
  441.     sys_bk_color &= 7;                /* mask out blink or anything else */
  442.  
  443.  
  444.     strcpy(temp, "BLUE");
  445.     ini_read_string(ini_info, "SYSOP", "Random Color Set", temp);
  446.     if(strcmpi(temp, "BLUE")==0)
  447.       sys_rand_color_set = 0;
  448.     else if(strcmpi(temp, "RED")==0)
  449.       sys_rand_color_set = 1;
  450.     else if(strcmpi(temp, "GRAY")==0)
  451.       sys_rand_color_set = 2;
  452.     else if(strcmpi(temp, "BROWN")==0)
  453.       sys_rand_color_set = 3;
  454.     else if(strcmpi(temp, "ALL")==0)
  455.       sys_rand_color_set = 4;
  456.  
  457.     sys_cur_color = colors[sys_rand_color_set].colors[0];
  458.   }     /* allow sys_other_colors to still read, just in case error here */
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  /*----------------------------------------------------------------------*/
  465.  /* These are the colors that will be used for the sysops side           */
  466.  /* looking at the names, uppercase, lowercase and anything left         */
  467.  /* over can have there own uniq colors                                  */
  468.  
  469.   sys_upper_color   = ini_read_number(ini_info,"SYSOP","Uppercase Color");
  470.   sys_lower_color   = ini_read_number(ini_info,"SYSOP","Lowercase Color");
  471.   sys_numeric_color = ini_read_number(ini_info,"SYSOP","Numeric Color");
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  /* -------------------------------------------------------------------- */
  478.  /* Read user color options ...                                          */
  479.  /*                                                                      */
  480.  /* You can have 2 different (almost 3) types of colors:                 */
  481.  /*   Defined colors for upper/lower/digits                              */
  482.  /*   Rotating colors                                                    */
  483.  /*   You can have a modified rotating colors which rotates every word   */
  484.  /*   change                                                             */
  485.  
  486.  
  487.   if(ini_read_boolean(ini_info, "USER", "Random Colors"))
  488.   {
  489.     strcpy(temp, "0,3");    /* Back color is 0 and rotate every 3 chars */
  490.     ini_read_string(ini_info, "USER", "Random Options", temp);
  491.     achat_get_fields(temp, temp_number, 2);
  492.     user_bk_color = temp_number[0];
  493.     user_rand_freq = temp_number[1];
  494.  
  495.     if(user_bk_color > 15)      /* make bk color a 0-7 color       */
  496.       user_bk_color = user_bk_color >> 4;
  497.  
  498.     user_bk_color &= 7;         /* mask out blink or anything else */
  499.  
  500.     strcpy(temp, "BLUE");
  501.     ini_read_string(ini_info, "USER", "Random Color Set", temp);
  502.     if(strcmpi(temp, "BLUE")==0)
  503.       user_rand_color_set = 0;
  504.     else if(strcmpi(temp, "RED")==0)
  505.       user_rand_color_set = 1;
  506.     else if(strcmpi(temp, "GRAY")==0)
  507.       user_rand_color_set = 2;
  508.     else if(strcmpi(temp, "BROWN")==0)
  509.       user_rand_color_set = 3;
  510.     else if(strcmpi(temp, "ALL")==0)
  511.       user_rand_color_set = 4;
  512.  
  513.     user_cur_color = colors[user_rand_color_set].colors[0];
  514.   }     /* allow user_other_colors to still read, just in case error here */
  515.  
  516.  
  517.   /* these are the colors that will be used for the user side */
  518.   user_upper_color =   ini_read_number(ini_info, "USER", "Uppercase Color");
  519.   user_lower_color =   ini_read_number(ini_info, "USER", "Lowercase Color");
  520.   user_numeric_color = ini_read_number(ini_info, "USER", "Numeric Color");
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  /*------------------------------------------------------------------------*/
  527.  /* Alt Clear Screen - If true, will use the WWIV style wrapping, where it */
  528.  /* pulls the bottom 3 lines up to the top.                                */
  529.  /* You must be careful that your screen can properly support this though  */
  530.  /* If turned off, it will do a Wildcat style, where it clears 2 lines     */
  531.  /* below the line you are on at a time, leaving the rest of the screen    */
  532.  /* untouched.                                                             */
  533.  
  534.   alt_achat_clear = ini_read_boolean(ini_info, "SYSOP", "Alt Clear Screen");
  535.  
  536.   close_ini(ini_info);
  537.  
  538.  
  539.   return 1;
  540. }
  541.  
  542. int achat_get_3_fields(char *line, int *one, int *two, int *three)
  543. {
  544.   int fields[3];
  545.  
  546.   if(achat_get_fields(line, fields, 3) != 3)
  547.     return 0;
  548.  
  549.   *one=fields[0];
  550.   *two=fields[1];
  551.   *three=fields[2];
  552.  
  553.   return 1;
  554. }
  555.  
  556.  
  557. int achat_get_fields(char *line , int *fields, int max)
  558. {
  559.   char *p;
  560.   int amount = 0;
  561.  
  562.   p=strtok(line, ",");
  563.   while(p && amount < max)
  564.   {
  565.     fields[amount++]=atoi(p);
  566.     p=strtok(NULL, ",");
  567.   }
  568.   return(amount);                  /* return the amount of fields done    */
  569. }
  570.  
  571.  
  572. int parse_achat_line_info(char *line, void *destin)
  573. {
  574.   char *tmp, *tmp1;
  575.   lines_record *dest;
  576.   int fields[3];
  577.  
  578.   dest = (lines_record *) destin;  /* so that I don't have to put struct  */
  579.                                    /* lines_record in vardec.h            */
  580.  
  581.   if(achat_get_fields(line, fields, 3) != 3)
  582.     return 0;                      /* we need 3 numbers, if we don't get  */
  583.                                    /* them, return with failure           */
  584.  
  585.   dest->xpos  = fields[0];
  586.   dest->ypos  = fields[1];
  587.   dest->length= fields[2];
  588.  
  589.   return 1;                        /* success */
  590. }
  591.  
  592.  
  593.  
  594. /* This function will pull up a random chat file, it will search through  */
  595. /* a directory called 'ACHAT' off of your gfiles directory.  It will find */
  596. /* out how many files are there, then pick one randomly                   */
  597. char *get_achat_filename(char *fname)
  598. {
  599.   struct ffblk ff;
  600.   char file[201];
  601.   int amount = 0, cur;
  602.   int done = 0;
  603.  
  604.   sprintf(file, "%s*.ANS", achat_dir);         /* Wildcard search */
  605.  
  606.   done = findfirst(file, &ff, 0);              /* Find first match         */
  607.  
  608.   if(done != 0)                                /* if one was found...      */
  609.     ++amount;                                  /* increment amount found   */
  610.  
  611.   while(!done)                                 /* loop through, finding    */
  612.   {                                            /* all matches              */
  613.     done = findnext(&ff);
  614.     ++amount;                                  /* keep track of amount found */
  615.   }
  616.  
  617.   if(!amount)                                  /* if none were found..     */
  618.     { sysoplog("Err-NoANS"); return NULL; }    /* tell and return          */
  619.  
  620.   amount = rand() % amount;                    /* pick one radomly         */
  621.  
  622.   cur = 0;
  623.   done = findfirst(file, &ff, 0);              /* Then do a findfirst/     */
  624.   while(!done && cur != amount)                /* findnext that many times */
  625.   {                                            /* and that will be our     */
  626.     done = findnext(&ff);                      /* random file              */
  627.     ++cur;
  628.   }
  629.  
  630.   strcpy(fname, ff.ff_name);                   /* copy the found filename  */
  631.   return(fname);                               /* and return it            */
  632. }
  633.  
  634.  
  635.  
  636. /* This file will print out our ansi menu without being able to be aborted */
  637. /* It will also intercept two macros, one '$<' for sysop's name, and the   */
  638. /* other $> for the user name.                                             */
  639. int printfile_na(char *fn, char *sysop_name)
  640. {
  641.  
  642.   char *ss, s2[201], prop_name[101];
  643.   long pos, len;
  644.   int i, ch;
  645.  
  646.   pos=0;
  647.  
  648.   if(exist(fn))          /* First see if the full pathname is specified */
  649.     strcpy(s2, fn);      /* if so, just copy it to s2                   */
  650.   else
  651.   {
  652.     sprintf(s2,"%s%s", languagedir,fn);  /* no? try the language dir */
  653.     if(!exist(fn))
  654.       sprintf(s2,"%s%s",syscfg.gfilesdir,fn);  /* still no, try gfiles dir */
  655.   }
  656.  
  657.   CLS();
  658.   ss=get_file(s2,&len);                /* Read the file into memory     */
  659.   if (ss!=NULL)                        /* if it was read....            */
  660.   {
  661.     pos = 0;                           /* starting from the begining    */
  662.     while(pos < len && !hangup)        /* read through all bytes of the */
  663.     {                                  /* file, displaying them one at  */
  664.       lines_listed = 0;                /* keep pause away               */
  665.  
  666.       if(ss[pos] == '$')               /* possible macro                */
  667.       {
  668.         if(ss[pos+1] == '<')           /* less than sign means show the */
  669.         {
  670.           SaveCursor();                /* Save our current position     */
  671.           strcpy(prop_name,sysop_name);/* move this out of the #ifdef in*/
  672.           properize(prop_name);        /* newuser.c if you have probs   */
  673.           outstr(prop_name);           /* sysop name                    */
  674.           RecallCursor();              /* go back to original position  */
  675.           CURSORRIGHT(2);              /* and fool the ansi to think    */
  676.                                        /* only 2 chars were printed     */
  677.           pos+=2;                      /* inc pos by two                */
  678.           continue;                    /* and jump back to 'while'      */
  679.         }
  680.         if(ss[pos+1] == '>')           /* greater than sign mean show   */
  681.         {
  682.           SaveCursor();
  683.           strcpy(prop_name,thisuser.name); /* move from #ifdef in       */
  684.           properize(prop_name);        /* newuser.c if you have probs   */
  685.           outstr(prop_name);           /* the users name                */
  686.           RecallCursor();              /* go back to original position  */
  687.           CURSORRIGHT(2);              /* and fool the ansi to think    */
  688.                                        /* only 2 chars were printed     */
  689.           pos+=2;                      /* increment the pos by 2 and    */
  690.           continue;                    /* jump up to the while loop     */
  691.         }
  692.         if(ss[pos+1] == ',')           /* less than sign means show the */
  693.         {
  694.           tl_x = WhereX()+1;           /* where to position the time    */
  695.           tl_y = WhereY()+1;           /* left when doing updates       */
  696.           SaveCursor();                /* Save our current position     */
  697.           outstr(ctim(nsl()));         /* Time left                     */
  698.           RecallCursor();              /* go back to original position  */
  699.           CURSORRIGHT(2);              /* and fool the ansi to think    */
  700.                                        /* only 2 chars were printed     */
  701.           pos+=2;                      /* inc pos by two                */
  702.           continue;                    /* and jump back to 'while'      */
  703.         }
  704.         if(ss[pos+1] == '.')           /* greater than sign mean show   */
  705.         {
  706.           to_x = WhereX()+1;           /* where to position the time    */
  707.           to_y = WhereY()+1;           /* left when doing updates       */
  708.  
  709.           SaveCursor();
  710.           outstr(ctim(timer()-timeon));/* Time on                       */
  711.           RecallCursor();              /* go back to original position  */
  712.           CURSORRIGHT(2);              /* and fool the ansi to think    */
  713.                                        /* only 2 chars were printed     */
  714.           pos+=2;                      /* increment the pos by 2 and    */
  715.           continue;                    /* jump up to the while loop     */
  716.         }
  717.       }                                /* End of if possible macro      */
  718.  
  719.       outchr(ss[pos++]);               /* display non macro character   */
  720.  
  721.       if(!empty() && lastcon)          /* allow SYSOP (only) to abort   */
  722.       {                                /* the display                   */
  723.         ch=inkey();                    /* get key, if one is waiting    */
  724.         if(ch==' ')                    /* if it is a space, then break  */
  725.                     break;                       /* out of our while loop         */
  726.             }
  727.     }
  728.  
  729.     free(ss);                          /* free up our memory that was   */
  730.     return(1);                         /* allocated by get_file         */
  731.   }
  732.   else
  733.     return(0);                         /* file was not printed          */
  734. }
  735.  
  736.  
  737.  
  738. void SaveCursor(void)
  739. {                                      /* ansi sequence to save the     */
  740.   outstr("\033[s");                    /* cursor position, so that it   */
  741. }                                      /* may be moved and restored     */
  742.  
  743. void RecallCursor(void)
  744. {                                      /* ansi sequence to recall the   */
  745.   outstr("\033[u");                    /* cursor position from a        */
  746. }                                      /* previous SaveCursor           */
  747.  
  748.  
  749. void display_achat_screen(char *fname, char *sysop_name)
  750. {
  751.   char fn[201];
  752.  
  753.   CLS();                               /* clear the screen                */
  754.   sprintf(fn, "%s%s", achat_dir, fname); /* point to ansi */
  755.   printfile_na(fn, sysop_name);        /* and print it out                */
  756. }
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763. void display_achat_char(int c, int sysop)
  764. {
  765.   static int sys_counter=0, user_counter=0;
  766.   int color;
  767.  
  768.   if(sysop && sys_rand_freq > 0)
  769.   {
  770.     ++sys_counter;
  771.  
  772.     if((sys_rand_freq != 32 && sys_counter % sys_rand_freq == 0) ||
  773.        (sys_rand_freq == 32 && c == 32))
  774.     {
  775.       ++sys_cur_color;
  776.  
  777.       if(sys_cur_color > colors[sys_rand_color_set].amount_colors)
  778.         sys_cur_color = 0;
  779.  
  780.     }
  781.     color = colors[sys_rand_color_set].colors[sys_cur_color];
  782.     if(color == sys_bk_color)
  783.       ++color;
  784.     setc(color + (sys_bk_color <<4));
  785.   }
  786.   else if(!sysop && user_rand_freq > 0)
  787.   {
  788.     ++user_counter;
  789.  
  790.     if((user_rand_freq != 32 && user_counter % user_rand_freq == 0) ||
  791.        (user_rand_freq == 32 && c == 32))
  792.     {
  793.       ++user_cur_color;
  794.       if(user_cur_color > colors[user_rand_color_set].amount_colors)
  795.         user_cur_color = 0;
  796.     }
  797.     color = colors[user_rand_color_set].colors[user_cur_color];
  798.     if(color == user_bk_color)
  799.       ++color;
  800.     setc(color + (user_bk_color << 4));
  801.   }
  802.   else
  803.   {
  804.     if(islower(c))               /* use lower color for lower case keys */
  805.       setc(sysop > 0 ? sys_lower_color : user_lower_color);
  806.     else if(isupper(c))          /* use upper color for upper case keys */
  807.       setc(sysop > 0? sys_upper_color : user_upper_color);
  808.     else                         /* use numeric color for all other keys */
  809.       setc(sysop > 0 ? sys_numeric_color : user_numeric_color);
  810.   }
  811.   outchr(c);
  812. }
  813.  
  814.  
  815. /* This function displays a null terminated string.  It is called by  */
  816. /* function 'add_achat_key', but if you notice, to print each key, it */
  817. /* turns around and calls 'add_achat_key', this is so it properly     */
  818. /* handles any wrapping that my need to be done, as well as any other */
  819. /* special keys that are handled in that function, as opposed to      */
  820. /* directly printing them out to the screen.                          */
  821. void display_achat_string(char *s, int sysop)
  822. {
  823.   while(*s)
  824.     add_achat_key(*s++, sysop);
  825. }
  826.  
  827.  
  828.  
  829. /* This function clears the entire typeable area for either the sysop or */
  830. /* user, depending on what is specified                                  */
  831. void clear_achat_type_area(int sysop)
  832. {
  833.   int x = 0, xpos, ypos, length;
  834.   int amount = sysop ? amount_sys_lines : amount_user_lines;
  835.  
  836.   while(x < amount)                  /* loop through all the lines */
  837.   {
  838.     if(sysop)                        /* get the x, y and length    */
  839.     {                                /* depending on if it is the  */
  840.       xpos = sys_lines[x].xpos;      /* sysop or user side we are  */
  841.       ypos = sys_lines[x].ypos;      /* erasing                    */
  842.       length = sys_lines[x].length;
  843.     }
  844.     else
  845.     {
  846.       xpos = user_lines[x].xpos;
  847.       ypos = user_lines[x].ypos;
  848.       length = user_lines[x].length;
  849.     }
  850.                              /* use the lower color as the erase color */
  851.     setc(sysop ? sys_lower_color : user_lower_color);
  852.     GOTO_XY(xpos, ypos);     /* set to first postion                   */
  853.  
  854.     repeat_char(' ', length-1); /* and display 'length-1' spaces       */
  855.     ++x;
  856.  
  857.   }
  858. }
  859.  
  860.  
  861. void wwiv_style_wrap_up(int sysop)
  862. {
  863.   int amount = sysop ? amount_sys_lines : amount_user_lines, x;
  864.   char *this_text = sysop ? sys_text : user_text, *t;
  865.  
  866.  
  867.   /* clear out all typeable area for sysop or user */
  868.   clear_achat_type_area(sysop);
  869.  
  870.   /* if we are trying to wrap more than the amount of lines we */
  871.   /* have to use + 2, then don't wrap anything up at all       */
  872.   if(amount + 2 < AMOUNT_TO_WRAP_UP)
  873.     return;
  874.  
  875.   if(sysop)
  876.     { sys_pos = 0; sys_line = 0; }
  877.   else
  878.     { user_pos = 0; user_line = 0; }
  879.      
  880.   for(x=0; x < AMOUNT_TO_WRAP_UP; x++)
  881.   {
  882.     t = this_text+((amount-AMOUNT_TO_WRAP_UP+x)*ACHAT_MAX_WIDTH);
  883.     if(t[0] != 13)              /* don't display empty line */
  884.       display_achat_string(t, sysop);
  885.   }
  886. }
  887.  
  888.  
  889. /* This function is like the above, but instead of clearing the whole   */
  890. /* screen, it will only clear the next two lines on either the sysop or */
  891. /* user side                                                            */
  892. void clear_achat_next_two_lines(int sysop)
  893. {
  894.   int x, y, xpos, ypos, length;
  895.   int amount = sysop ? amount_sys_lines : amount_user_lines;
  896.  
  897.   if(alt_achat_clear)    /* if you have the alternate clear option */
  898.     return;
  899.  
  900.   for(x = 1; x <= 2; x++)         /* loop twice */
  901.   {
  902.  
  903.     y = sysop ? sys_line + x : user_line + x;  /* figure out what the next line is */
  904.     if(y >= amount)                /* see if we wrapped back up to the */
  905.       y -= amount;                 /* top of the screen                */
  906.  
  907.     if(sysop)
  908.     {
  909.       xpos = sys_lines[y].xpos;
  910.       ypos = sys_lines[y].ypos;
  911.       length = sys_lines[y].length;
  912.       sys_pos = 0;
  913.     }
  914.     else
  915.     {
  916.       xpos = user_lines[y].xpos;
  917.       ypos = user_lines[y].ypos;
  918.       length = user_lines[y].length;
  919.       user_pos = 0;
  920.     }
  921.     setc(sysop ? sys_lower_color : user_lower_color);
  922.     GOTO_XY(xpos, ypos);
  923.  
  924.     repeat_char(' ', length-1);   /* display 'lenght-1' spaces to clear line */
  925.   }
  926. }
  927.  
  928.  
  929.  
  930.  
  931.  
  932. void add_achat_key(int key, int sysop)
  933. {
  934.   lines_record *this_lines;
  935.   int this_pos, this_line, this_amount;
  936.   char temp[50];
  937.   char *this_text;
  938.  
  939.  
  940.   if(no_user_side)    /* if we don't have a user side, then get the specs  */
  941.     if(!sysop)        /* from the sysop definition, but set it so we know  */
  942.       sysop = -1;      /* it is the user so we can use the user color still */
  943.  
  944.  
  945.   this_lines  = sysop ? &sys_lines[sys_line] : &user_lines[user_line];
  946.   this_line   = sysop ? sys_line : user_line;
  947.   this_pos    = sysop ? sys_pos  : user_pos;
  948.   this_amount = sysop ? amount_sys_lines : amount_user_lines;
  949.   this_text   = sysop ? sys_text  + (this_line * ACHAT_MAX_WIDTH) :
  950.                         user_text + (this_line * ACHAT_MAX_WIDTH);
  951.  
  952.   switch(key)
  953.   {
  954.     case 18:                         /* ^R to load a new menu set         */
  955.       if(lastcon)                    /* only the sysop can reload the     */
  956.       {
  957.         chat_done = 1;               /* menus                             */
  958.         return;
  959.       }
  960.       break;
  961.  
  962.     case 26:                         /* ^Z to flip sides                  */
  963.       if(lastcon)
  964.       {
  965.         flip_sides = !flip_sides;
  966.         return;
  967.       }
  968.       break;
  969.  
  970.     case 14:                         /* ^N load a chat screen by name     */
  971.       if(lastcon)
  972.       {
  973.         chat_done = 1;
  974.         pick_file = 1;
  975.         return;
  976.       }
  977.  
  978.  
  979.     case 3:                          /* color codes                       */
  980.       return;                        /* don't want any                    */
  981.  
  982.     case 8:                          /* backspace                         */
  983.       if(this_pos)                   /* if we aren't up against left wall */
  984.       {
  985.         GOTO_XY(this_lines[0].xpos+(sysop ? sys_pos : user_pos), this_lines[0].ypos);
  986.         setc(sysop ? sys_lower_color : user_lower_color);
  987.  
  988.         if(sysop)                    /* decrement position                */
  989.           --sys_pos;
  990.         else
  991.           --user_pos;
  992.  
  993.         backspace();                 /* and erase previous character      */
  994.       }
  995.       return;
  996.  
  997.     case 13:                              /* carriage return */
  998.     case 10:                              /* line feed       */
  999.       this_text[this_pos++] = key;        /* put key in our buffer          */
  1000.       this_text[this_pos] = 0;            /* keep buffer null terminated    */
  1001.  
  1002.       if(!alt_achat_clear)                /* if you have the alt clear opt */
  1003.         clear_achat_next_two_lines(sysop);/* then clear next two lines     */
  1004.       else if(this_line >= this_amount-1)
  1005.       {
  1006.         wwiv_style_wrap_up(sysop);     /* else if we need to go to the top,*/
  1007.         return;                        /* then clear the whole thing       */
  1008.       }
  1009.       if(this_line < this_amount-1)    /* if we don't need to wrap back up */
  1010.       {                                /* to the top...                    */
  1011.         if(sysop)
  1012.           { ++sys_line; sys_pos = 0; } /* increment line and set pos to 0 */
  1013.         else
  1014.           { ++user_line; user_pos = 0; }
  1015.  
  1016.         GOTO_XY(this_lines[1].xpos, this_lines[1].ypos);
  1017.         return;
  1018.       }
  1019.  
  1020.       if(sysop)            /* if we do need to jump back up to the top... */
  1021.         { sys_line = 0; GOTO_XY(sys_lines[0].xpos, sys_lines[0].ypos); }
  1022.       else
  1023.         { user_line = 0; GOTO_XY(user_lines[0].xpos, user_lines[0].ypos); }
  1024.  
  1025.       return;
  1026.  
  1027.     case 7:   /* Bell ^G */
  1028.         outcomch(7);
  1029.         return;
  1030.  
  1031.     case 23:                    /* ^W delete word */
  1032.       if(this_pos)
  1033.       {
  1034.         GOTO_XY(this_lines[0].xpos+(sysop ? sys_pos : user_pos), this_lines[0].ypos);
  1035.         setc(sysop ? sys_lower_color : user_lower_color);
  1036.  
  1037.         --this_pos;
  1038.         while(isspace(this_text[this_pos]) && this_pos > -1)
  1039.           { --this_pos; backspace(); }
  1040.  
  1041.         if(this_pos < 0)
  1042.           this_pos = 0;
  1043.  
  1044.         while(!(isspace(this_text[this_pos])) && this_pos > -1)
  1045.           { --this_pos; backspace(); }
  1046.  
  1047.         if(this_pos < 0)
  1048.           this_pos = 0;
  1049.  
  1050.         if(sysop)
  1051.           sys_pos = this_pos;
  1052.         else
  1053.           user_pos = this_pos;
  1054.  
  1055.         this_text[this_pos] = 0;
  1056.       }
  1057.       return;
  1058.  
  1059.  
  1060.     case 24:                    /* ^X erase line */
  1061.       if(this_pos)
  1062.       {
  1063.         GOTO_XY(this_lines[0].xpos+(sysop ? sys_pos : user_pos), this_lines[0].ypos);
  1064.         setc(sysop ? sys_lower_color : user_lower_color);
  1065.  
  1066.         if(sysop)                    /* set position back to 0 */
  1067.           sys_pos=0;
  1068.         else
  1069.           user_pos=0;
  1070.  
  1071.         while(this_pos)
  1072.           { backspace(); --this_pos; }
  1073.  
  1074.         this_text[0] = 0;
  1075.  
  1076.       }
  1077.       return;
  1078.  
  1079.     case 9:         /* tab, just display 4 spaces */
  1080.       display_achat_string("    ", sysop);
  1081.       return;
  1082.  
  1083.  
  1084.     default:
  1085.       if(key < 32)  /* kill non printable characters */
  1086.         return;
  1087.       break;
  1088.   }
  1089.  
  1090.  
  1091.  
  1092.   if(this_pos >= this_lines->length-1)  /* if we need word wrap to the next */
  1093.   {                                     /* line on the screen               */
  1094.     int wrap, x = 0, y, marker;
  1095.     int save_wrap_pos;
  1096.  
  1097.  
  1098.     if(!alt_achat_clear)               /* if you have the alt clear         */
  1099.       clear_achat_next_two_lines(sysop);/* option, then clear next two lines */
  1100.     else if(this_line >= this_amount-1)
  1101.       wwiv_style_wrap_up(sysop);      /* else if we need to go to the top,  */
  1102.                                       /* then clear the whole thing         */
  1103.  
  1104.  
  1105.     /* Re-read these values since they may change with the wwiv style */
  1106.     /* wrapping the text up and all...                                */
  1107.     this_lines  = sysop ? &sys_lines[sys_line] : &user_lines[user_line];
  1108.     this_line   = sysop ? sys_line : user_line;
  1109.     this_pos    = sysop ? sys_pos  : user_pos;
  1110.     this_amount = sysop ? amount_sys_lines : amount_user_lines;
  1111.     this_text   = sysop ? sys_text  + (this_line * ACHAT_MAX_WIDTH) :
  1112.                           user_text + (this_line * ACHAT_MAX_WIDTH);
  1113.  
  1114.  
  1115.  
  1116.     /* determin the amount of characters we are going to wrap.  I have it  */
  1117.     /* setup to wrap a 25% of the size of the current line                 */
  1118.     wrap = this_lines->length / 4;
  1119.  
  1120.  
  1121.  
  1122.     /* put cursor right past last character, so that we can, one by one,    */
  1123.     /* delete them as we count backwards                                    */
  1124.     GOTO_XY(this_lines->xpos + this_pos, this_lines->ypos);
  1125.     y=this_pos;   /* set a marker, so that we know what or original pos is  */
  1126.     --this_pos;   /* decrement one to get off of the null which I keep here */
  1127.     while(!isspace(this_text[this_pos]) && x < wrap)
  1128.     {                      /* loop back until we find a space (or x >= wrap */
  1129.       ++x;
  1130.       --this_pos;
  1131.       backspace();         /* erase those characters */
  1132.     }
  1133.  
  1134.  
  1135.  
  1136.     /* save our point of wrap, so that once we get done putting the text */
  1137.     /* to be wrapped in a string to be displayed on the next line, we    */
  1138.     /* will put a space at this position and terminate our chat line     */
  1139.     save_wrap_pos = this_pos;
  1140.  
  1141.     /* Now, we know how many characters we removed from the screen, put    */
  1142.     /* those in our temp string so that we can later display them on our   */
  1143.     /* next line                                                           */
  1144.     ++this_pos;  /* get off of the white space we just found */
  1145.     x = 0;
  1146.     while(this_pos < y)
  1147.     {
  1148.       temp[x] = this_text[this_pos];
  1149.       ++this_pos;
  1150.       ++x;
  1151.     }
  1152.     temp[x++] = key;        /* add the key we just entered      */
  1153.     temp[x] = 0;            /* you know it has to be terminated */
  1154.  
  1155.  
  1156.     /* set a SPACE/NULL      at this point of wrapping... this will kill   */
  1157.     /* a character if we wrapped in the middle of a word, but I am going   */
  1158.     /* to chat this as not an often happening, and when it does, it wont   */
  1159.     /* be noticed... but who knows what will have to be done later....     */
  1160.     this_text[save_wrap_pos] = ' ';
  1161.     this_text[save_wrap_pos+1] = 0;
  1162.  
  1163.  
  1164.  
  1165.     if(this_line >= this_amount-1)               /* if we need to wrap back  */
  1166.     {                                            /* up to the top, copy the  */
  1167.       strcpy(sysop ? sys_text : user_text, temp);/* text to the front of the */
  1168.       if(sysop)                                  /* text screen              */
  1169.         sys_line = 0;                            /* set line # to 0          */
  1170.       else
  1171.         user_line = 0;
  1172.     }
  1173.     else                                         /* if we are just going to  */
  1174.     {                                            /* the next line            */
  1175.       strcpy(this_text+(ACHAT_MAX_WIDTH), temp); /* copy text into the corct */
  1176.       if(sysop)                                  /* spot and then            */
  1177.         ++sys_line;                              /* increment line # by 1    */
  1178.       else
  1179.         ++user_line;
  1180.     }
  1181.  
  1182.     if(sysop)                                    /* anyway, since we wrapped */
  1183.       sys_pos = 0;                               /* to the next line, our    */
  1184.     else                                         /* 'x' position is now 0    */
  1185.       user_pos = 0;
  1186.  
  1187.  
  1188.     display_achat_string(temp, sysop);           /* display our temp string  */
  1189.     return;                                      /* on the next line         */
  1190.  
  1191.   }
  1192.  
  1193.   /* if we get here, we are not wrapping, just displaying the key */
  1194.  
  1195.                                          /* set cursor to correct position */
  1196.   GOTO_XY(this_lines->xpos + this_pos, this_lines->ypos);
  1197.   display_achat_char(key, sysop);        /* and display char with correct color */
  1198.  
  1199.   this_text[this_pos++] = key;           /* put key in our buffer          */
  1200.   this_text[this_pos] = 0;               /* keep buffer null terminated    */
  1201.  
  1202.   if(sysop)                              /* increment position by one */
  1203.     ++sys_pos;
  1204.   else
  1205.     ++user_pos;
  1206.  
  1207.   return;
  1208. }
  1209.  
  1210.  
  1211. /* Mostly written by Swordfish, thanks everyone for all the help you give me */
  1212. char *select_achat_filename(char *fname)
  1213. {
  1214.   struct ffblk ff;
  1215.   char file[101];
  1216.   int amount = 0, cur;
  1217.   int done = 0;
  1218.   int fli,x,ru;
  1219.   char s[80];
  1220.  
  1221.  
  1222.  
  1223.   sprintf(file, "%s*.ANS", achat_dir);         /* Wildcard search */
  1224.   done = findfirst(file, &ff, 0);              /* Find first match         */
  1225.  
  1226.   if(!done)                                    /* if one was found...      */
  1227.     ++amount;                                  /* increment amount found   */
  1228.  
  1229.   while(done != 0)                             /* loop through, finding    */
  1230.   {                                            /* all matches              */
  1231.     done = findnext(&ff);
  1232.     ++amount;                                  /* keep track of amount found */
  1233.   }
  1234.  
  1235.   if(!amount)                                  /* if none were found..     */
  1236.     { sysoplog("Err-NoANS"); return NULL; }    /* tell and return          */
  1237.  
  1238.   curatr=WHITE;
  1239.   pr_Wait(1);
  1240.   movecsr(31, 1);
  1241.   show_achat_screens();
  1242.  
  1243. welldone:
  1244.   savescreen(&screensave);
  1245.   strcpy(s,"1");
  1246.   curatr=YELLOW+(BLUE<<4);
  1247.   makewindow(20,0,43,3);
  1248.   movecsr(22,1);
  1249.   outs("Choose:");
  1250.   movecsr(31,1);
  1251.   outs(charstr(30,32));
  1252.   movecsr(31,1);
  1253.   editline(s,30,ALL,&ru,s);
  1254.  
  1255.  
  1256.   if (s[0]=='?') {
  1257.     show_achat_screens();
  1258.     goto welldone;
  1259.   }
  1260.  
  1261.   curatr=YELLOW;
  1262.   fli=atoi(s)-1;
  1263.   cur = 0;
  1264.   done = findfirst(file, &ff, 0);
  1265.   while(!done && cur != fli)
  1266.   {
  1267.     done = findnext(&ff);
  1268.     ++cur;
  1269.   }
  1270.   strcpy(fname, ff.ff_name);
  1271.   return(fname);
  1272. }
  1273.  
  1274. void show_achat_screens(void)
  1275. {
  1276.   struct ffblk ff;
  1277.   char finfo[101], file[101], desc[101];
  1278.   int done, amount = 1;
  1279.  
  1280.   curatr=WHITE;
  1281.   sprintf(file, "%s*.ANS", achat_dir);         /* Wildcard search          */
  1282.   done = findfirst(file, &ff, 0);              /* Find first match         */
  1283.  
  1284.   outs("\r\n\r\n\r\n");
  1285.   open_achat_descriptions();
  1286.   while(!done)                                 /* loop through, finding    */
  1287.   {                                            /* all matches              */
  1288.     get_achat_description(ff.ff_name, desc);
  1289.     sprintf(finfo, "%2d) %-12.12s %2ldk %s\r\n", amount++, ff.ff_name, ff.ff_fsize > 1023 ? ff.ff_fsize / 1024L : 1L, desc);
  1290.     outs(finfo);
  1291.     done = findnext(&ff);
  1292.   }
  1293.   close_achat_descriptions();
  1294.   outs("\r\n");
  1295. }
  1296.  
  1297.  
  1298. void open_achat_descriptions(void)
  1299. {
  1300.   char fname[151];
  1301.   sprintf(fname, "%sDESCRIPT.ION", achat_dir);
  1302.   achat_desc=fopen(fname, "r");
  1303.  
  1304.   if(!achat_desc)
  1305.   {
  1306.     sprintf(fname, "%sFILES.BBS", achat_dir);
  1307.     achat_desc=fopen(fname, "r");
  1308.   }
  1309. }
  1310.  
  1311. void close_achat_descriptions(void)
  1312. {
  1313.   if(achat_desc)
  1314.     fclose(achat_desc);
  1315. }
  1316.  
  1317.  
  1318. char *get_achat_description(char *name, char *desc)
  1319. {
  1320.   char temp[201], *tmp;
  1321.   int x;
  1322.  
  1323.  
  1324.   if(!achat_desc)
  1325.     { *desc=0; return NULL; }
  1326.  
  1327.  
  1328.   fseek(achat_desc, 0, SEEK_SET);
  1329.  
  1330.  
  1331.   while(1)
  1332.   {
  1333.     if(!fgets(temp, 200, achat_desc))
  1334.       { *desc=0; return NULL; }
  1335.  
  1336.     tmp = strchr(temp, ' ');
  1337.     if(!tmp)
  1338.       continue;
  1339.  
  1340.     tmp[0] = 0;
  1341.     ++tmp;
  1342.  
  1343.     if(strcmpi(name, temp) == 0)
  1344.     {
  1345.  
  1346.       strcpy(desc, tmp);
  1347.       x = strlen(desc);
  1348.       --x;
  1349.  
  1350.       if(x > 55)
  1351.         { x = 54; desc[x+1] = 0; }
  1352.  
  1353.  
  1354.       if(x >= 0 && isspace(desc[x]))
  1355.       {
  1356.         while(x > 0 && isspace(desc[x]))
  1357.           --x;
  1358.         if(!isspace(desc[x]))
  1359.           ++x;
  1360.         desc[x] = 0;
  1361.       }
  1362.       return(desc);
  1363.     }
  1364.   }
  1365. }
  1366.  
  1367.  
  1368.  
  1369.