Metropoli BBS
VIEWER: cmdinput.c MODE: TEXT (ASCII)
/* 
 *  CMDINPUT.C - handles command input (tab completion, history, etc.)
 *
 *
 *
 *  Comments:
 *
 *  01/14/95 (Tim Norman) -------------------------------------------------
 *    started.
 *  
 *  08/08/95 (Matt Rains) -------------------------------------------------
 *    i have cleaned up the source code. changes now bring this source into
 *    guidelines for recommended programming practice.
 *
 *    i have added some constants to help making changes easier.
 *
 *  12/12/95 (Tim Norman) -------------------------------------------------
 *    added findxy() function to get max x/y coordinates to display
 *    correctly on larger screens
 *
 *  12/14/95 (Tim Norman) -------------------------------------------------
 *    fixed the Tab completion code that Matt Rains broke by moving local
 *    variables to a more global scope and forgetting to initialize them
 *    when needed
 *
 */

#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <dir.h>

#define D_BS      8
#define D_DELETE  256+83
#define D_TAB     9
#define D_HOME    256+71
#define D_END     256+79
#define D_UP      256+72
#define D_DOWN    256+80
#define D_LEFT    256+75
#define D_RIGHT   256+77
#define D_ENTER   13
#define D_ESC     27
#define D_BEEP    printf("\a")

void history(int, char *); /* prototype for the command-line history */

/* this is inefficient to call each time something is changed */
/* make it better */
void reprint(char *str, int x, int *y, int place, int maxx, int maxy)
{
   int gox;
   int goy;

   str[127] = 0; /* truncate in case it's too long */

   gotoxy(x, *y);

   /* figure out if it's going to scroll... */
   gox = x + strlen(str);
   goy = *y;

   while(gox > maxx)
   {
      gox -= maxx;
      goy++;
   }

   while(goy > maxy)
   {
      goy--;
      (*y)--;
   }

   printf(str);
   clreol();

   gox = x + place;
   goy = *y;

   while(gox > maxx)
   {
      gox -= maxx;
      goy++;
   }

   gotoxy (gox, goy);
   return;
}

/* reposition the cursor */
void reposition(int curx, int cury, int place, int maxx)
{
   int gox;
   int goy;

   gox = curx + place;
   goy = cury;

   while(gox > maxx)
   {
      gox -= maxx;
      goy++;
   }

   gotoxy(gox, goy);
   return;
}

/* get the size of the screen */
void findxy (int *maxx, int *maxy)
{
   struct text_info t;

   gettextinfo (&t);

   *maxx = t.screenwidth;
   *maxy = t.screenheight;
}

/* read in a command line */
void readcommand(char *str, int maxlen)
{
   struct ffblk file;
   int place = 0; 
   int len = 0; 
   int ch;
   int curx; 
   int cury; 
   int count;
   int y;
   int maxx, maxy;

   /* varibles found within code */
   int found_dot = 0; 
   int curplace = 0; 
   int start; 
   int perfectmatch = 1;
   char path[128]; 
   char fname[14]; 
   char maxmatch[13] = "";
   char directory[128];

   /* find the bounds of the current screen */
   findxy (&maxx, &maxy);

   curx = wherex();
   cury = wherey();
   str[0] = 0;

   do
   {
      ch = getch();

      if(ch == 0) /* special key */
      {
         ch = 256 + getch();
      }

      switch(ch)
      {
         case D_BS :
         {
            /* delete character to left of cursor */
            if(place != 0)
            {
               place--;

               for(count = place; count < len; count++)
               {
                  str[count] = str[count + 1];
               }

               len--;

               if(wherex() != 1)
               {
                  printf ("\b \b");
               }
               else
               {
                  y = wherey();
		  gotoxy(maxx, y - 1);
		  printf(" ");
		  gotoxy(maxx, y - 1);
               }

	       reprint(str, curx, &cury, place, maxx, maxy);
            }
            break;
         }
         case D_DELETE :
         {
            /* delete character under cursor */
            if (place != len)
            {
               for(count = place; count < len; count++)
               {
                  str[count] = str[count + 1];
               }

               len--;

               if(place != 0)
               {
                  if(wherex() != 1)
                  {
                     printf("\b \b");
                  }
                  else
                  {
                     y = wherey();
		     gotoxy(maxx, y - 1);
		     printf(" ");
		     gotoxy(maxx, y - 1);
                  }
               }

	       reprint (str, curx, &cury, place, maxx, maxy);
            }
            break;
         }
         case D_HOME :
         {
            /* goto beginning of string */
            gotoxy(curx, cury);
            place = 0;

            break;
         }
         case D_END :
         {
            /* goto end of string */
            place = len;
	    reposition(curx, cury, place, maxx);
             
            break;
         }
         case D_TAB :
         {
	    maxmatch[0] = 0;
	    found_dot = 0;
	    curplace = 0;
	    perfectmatch = 1;

            /* expand current file name */
            if(place == len)  /* only works at end of line */
            {
	       count = len - 1;

	       while(count > 0 && str[count] != ' ') /* find front of word */
	       {
		  count--;
	       }

	       if(str[count] == ' ')  /* if not at beginning, go forward 1 */
               {
                  count++;
               }

               start = count;

               /* extract directory from word */
               strcpy (directory, &str[start]);
               curplace = strlen (directory) - 1;
               while (curplace >= 0 && directory[curplace] != '\\' &&
                  directory[curplace] != ':')
               {
                  directory[curplace] = 0;
                  curplace--;
               }

               strcpy(path, &str[start]);

	       /* look for a . in the filename */
	       for(count = strlen (directory); path[count] != 0; count++)
               {
                  if(path[count] == '.')
                  {
                     found_dot = 1;
                     break;
                  }
               }

               if(found_dot)
               {
                  strcat(path, "*");
               }
               else
               {
                  strcat(path, "*.*");
               }

               curplace = 0; /* current fname */

               if(findfirst(path, &file, 0x3F) == 0) /* find anything */
               {
                  do
                  {
                     if(file.ff_name[0] == '.') /* ignore . and .. */
                     {
                        continue;
                     }

                     strcpy(fname, file.ff_name);

                     if(file.ff_attrib == FA_DIREC)
                     {
                        strcat(fname, "\\");
                     }
                     else
                     {
                        strcat(fname, " ");
                     }

                     if(!maxmatch[0] && perfectmatch)
                     {
                        strcpy(maxmatch, fname);
                     }
                     else
                     {
                        for (count = 0; maxmatch[count] && fname[count];count++)
                        {
                           if (maxmatch[count] != fname[count])
                           {
                              perfectmatch = 0;
                              maxmatch[count] = 0;
                              break;
                           }
                        }
                     }
                  }
                  while(findnext(&file) == 0);

                  strcpy(&str[start], directory);
                  strcat(&str[start], maxmatch);
                  len = strlen(str);
                  place = len;
		  reprint(str, curx, &cury, place, maxx, maxy);

                  if(!perfectmatch)
                  {
                     D_BEEP;
                  }
               }
               else
               {
                  D_BEEP;
               }
            }
            else
            {
               D_BEEP;
            }
         break;
         }
         case D_ENTER :
         {
            /* end input, return to main */
            if(str[0])
            {
               history(0, str); /* add to the history */
            }

            place = len;
	    reprint(str, curx, &cury, place, maxx, maxy);
            printf("\n\n");
            break;
         }
         case D_ESC :
         {
            /* clear str */
            gotoxy(curx, cury);

            for(count = 0; count < strlen(str); count++)
            {
               printf (" ");
            }

            place = len = str[0] = 0;
            gotoxy(curx, cury);
            break;
         }
         case D_UP :
         {
            /* get previous command from buffer */
            gotoxy(curx, cury);

	    for(count = 0; str[count]; count++)
            {
               printf(" ");
            }

            history(-1, str);
            len = strlen(str);
            place = len;
	    reprint(str, curx, &cury, place, maxx, maxy);
            break;
         }
         case D_DOWN :
         {
            /* get next command from buffer */
            gotoxy(curx, cury);

            for(count = 0; count < strlen(str); count++)
            {
               printf(" ");
            }

            history(1, str);
            len = strlen(str);
            place = len;
	    reprint(str, curx, &cury, place, maxx, maxy);
            break;
         }
         case D_LEFT :
         {
            /* move cursor left */
            if(place != 0)
            {
               place--;
            }
            else
            {
               D_BEEP;
            }
	    reposition(curx, cury, place, maxx);
            break;
         }
         case D_RIGHT :
         {
            /* move cursor right */
            if(place != len)
            {
               place++;
            }

	    reposition(curx, cury, place, maxx);
            break;
         }
         default:
         {
            if(ch >= 32 && ch <= 255 && len != maxlen - 2)
            {
               /* insert character into string... */
               for(count = len + 1; count > place; count--)
               {
                  str[count] = str[count - 1];
               }

               str[place] = ch;
               place++;
               len++;
	       reprint(str, curx, &cury, place, maxx, maxy);
            }
            else
            {
               D_BEEP;
            }
            break;
         }
      }
   }
   while(ch != D_ENTER);

   return;
}
[ RETURN TO DIRECTORY ]