                             CONSOLE INPUT

                            Matthew Probert
                           Servile  Software



The C programming language provides a number of functions for reading 
data from the console (keyboard). None of them are much good however!

scanf():

scanf() is the function you are likely to be offered by most books on 
C as the function for reading data from the console. It is useless in 
my opinion. If you try to read a string with scanf() such as:

        printf("\nEnter your name: ");
        scanf("%s",name);
        
Only the first word typed in will be stored. scanf() will stop storing 
data after the first whitespace character (and this includes spaces). 
So okay you could change this to read:

        printf("\nEnter your name: ");
        scanf("%s %s",first_name,last_name);
        
But what if the user has three names?

gets():

Next is gets() which it is claimed reads a string from the stream 
stdin. It is better than scanf() in that it continues storing data 
until carriage return is pressed. It doesn't store the carriage 
return. So if we use the earlier example:

        printf("\nEnter your name: ");
        gets(name);

and the user types in "John Rodgers Smith", gets() will store "John 
Rodgers Smith" in the variable name. And if name is an array shorter 
than the length of typed in text, gets() will store the remainder of 
the entered text overwriting whatever happened to occur in memory 
following the allocation for name. This is one of the great strengths 
of C, it allows you to make a complete mess of memory!

fgets():

Almost the same as gets() is fgets(). This reads data from a specified 
stream untill one of three criteria are met:

        1) An EOF character is read
        2) A carriage return is read
        3) The specified number of bytes have been read

There are three important differences between fgets() and gets(). 
Firstly fgets() reads data from any stream, so we must specify stdin 
to read from the console. Secondly, the terminating carriage return 
character is stored. And lastly the programmer can specify the maximum 
number of bytes to read and store, giving the programmer control over 
the memory overflow problem associated with gets().

        printf("\nEnter your name: ");
        fgets(name,30,stdin);
        
Will allow up to thirty characters to be typed in at the console (or 
redirected in from a file using the appropriate DOS filter command) 
and this data will be stored in the variable name. Including any 
terminating carriage return.

The advantage of using fgets() over a custom written input routine is 
one of convenience. Data is entered just as it is at the DOS command 
prompt with all DOS editing keys functioning normally. This is also 
maybe a disadvantage, but it is convenient.

Here though is a simple but more programmer-friendly input routine 
which allows the programmer to specify the maximum number of bytes to 
be read. INPUT() returns the last character typed. The input string 
is stored in the first parameter upto a maximum length of 'length' 
bytes:

------------------------------Cut Here------------------------------


int INPUT(char *text,unsigned length)
{
	/*
		Receive text input from the operator
		Overtype mode only
	*/

	int key_pos;
	int key;
	int start_row;
	int start_col;
	int end;
	char temp[1000];
	char *p;
	int x;
	int y;

	/*
		Locate current text cursor location
	*/
	start_col = wherex();
	start_row = wherey();

	/*
		Initialise varables
	*/
	key_pos = 0;
	end = strlen(text);
	cprintf("%s",text);
	gotoxy(start_col,start_row);

	/*
		Loop
	*/
	for(;;)
	{
		key = getch();
		if (key == 0)
		{
			/* Extended key presses */
			key = getch();

			if (key == 79)
				while(key_pos < end)
					key_pos++;
			else
			if (key == 71)
				key_pos = 0;
			else
			if ((key == 75) && (key_pos > 0))
				key_pos--;
			else
			if ((key == 77) && (key_pos < end))
				key_pos++;
			else
			if (key == 83)
			{
				p = text + key_pos;
				while(*(p+1))
				{
					*p = *(p+1);
					p++;
				}
				*p = 32;
				if (end > 0)
					end--;
				gotoxy(start_col,start_row);
				cprintf("%s ",text);
				if ((key_pos > 0) && (key_pos == end))
					key_pos--;
			}
			gotoxy(start_col+key_pos,start_row);
		}
		else
		if (key == 13 || key == 27)
			break;
		else
		if ((key == 8) && (key_pos > 0))
		{
			end--;
			key_pos--;
			text[key_pos--] = '\0';
			strcpy(temp,text);
			p = text + key_pos + 2;
			strcat(temp,p);
			strcpy(text,temp);
			/*
				Get rid of last character
			*/
			gotoxy(start_col,start_row);
			cprintf("%s ",text);
			x = wherex();
			y = wherey();
			x--;
			if (x < 1)
			{
				y--;
				x = 77;
			}

			key_pos++;
			gotoxy(x,y);
		}
		else
		if ((key > 31) && (key_pos < length))
		{
			text[key_pos++] = (char)key;
			if (key_pos > end)
			{
				end++;
				text[end] = '\0';
			}
			gotoxy(start_col,start_row);
			cprintf("%s",text);
			gotoxy(start_col + key_pos,start_row);
		}
		else
		if((key > 31) && (key_pos == length))
		{
			text[end] = 0;
			return 13;
		}
	}
	text[end] = '\0';
	return key;
}
------------------------------Cut Here------------------------------

