twitter
    Find out what I'm doing, Follow Me :)

Why This Chapter?

Although every program in this tutorial has been a complete program, each one has also been a very small program intended to teach you some principle of programming in C. It would do you a disservice to leave you at that point without introducing you to a few larger programs to illustrate how to put together the constructs you have learned to create a major program. This chapter contains four programs of increasing complexity, each designed to take you into a higher plateau of programming, and each designed to be useful to you in some way.

DOSEX was intended to illustrate how to make MS-DOS system calls and will teach you, through self-study, how the system responds to the keyboard. DOSEX has been modified by Tim Ward to use Applix 1616 system calls instead of MS-DOS calls. WHATNEXT reads commands input on the command line and will aid you in setting up a variable batch file, one that requests an operator input and responds to the input by branching to a different part of the batch file.

LIST is the source code for the program you used to print out the C source files when you began studying C with the aid of this tutorial. Finally we come to VC, the Visual Calculator, which you should find to be a useful program even if you don’t study its source code. VC uses most of the programming techniques we have studied in this course and a few that we never even mentioned such as separately compiled subroutines.
We will take a look at the example programs one at a time but without a complete explanation of any of them because you have been studying C for some time now and should be able to read and understand most of these programs on your own. One other thing must be mentioned, these programs use lots of nonstandard constructs and you will probably need to modify some of them to get them to compile with your particular compiler.
That will be left as an exercise for you. dosexibm.c - The MS-DOS Example Program The copy of MS-DOS that you received with your IBM-PC or compatible has many internal MS-DOS calls that you can use as a programmer to control your peripheral devices and read information or status from them. Some of the earlier IBM DOS manuals, MS-DOS 2.0 and earlier, have these calls listed in the back of the manual along with how to use them. Most of the manuals supplied with compatible computers make no mention of these calls even though they are extremely useful. These calls can be accessed from nearly any programming language but they do require some initial study to learn how to use them. This program is intended to aid
you in this study.
Display the program on your monitor or print it out for reference. It is merely a loop watching for a keyboard input or a change in the time. If either happens, it reacts accordingly. In line 23, the function "kbhit()" returns a value of 1 if a key has been hit but not yet read from the input buffer by the program. This is a nonstandard function and may require a name change for your particular compiler. There will probably be several similar calls that will need changed for your compiler in order to compile and run the programs in chapter 14.

Look at the function named "get_time" for an example of a MS-DOS call. An interrupt 21(hex) is called after setting the AH register to 2C(hex) = 44(decimal). The time is returned in the CH, CL, and DH registers. Refer to the MS-DOS call definitions in your copy of MS-DOS (if available). If the definitions are not included there, Peter Norton’s book, "Programmers Guide to the IBM PC" is recommended as a good reference manual for these calls and many other programming techniques. You will notice it is somewhat more complex than the Applix 1616 equivalent.

Another useful function is the "pos_cursor()" function that positions the cursor anywhere on the monitor that you desire by using a MS-DOS interrupt. This call has been modified in the Applix 1616 version, to use an equivalent system call. In the MS-DOS case, the interrupt used is 10(hex) which is the general monitor interrupt. This particular service is number 2 of about 10 different monitor services available. This particular function may not be needed by your compiler because some compilers have a cursor positioning function predefined for your use. This function is included here as another example to you.

The next function, service number 6 of interrupt 10(hex) is the window scroll service. It should be self explanatory. The window scroll service has been deleted from the Applix version. Full details of Conal Walsh’s window support are provided in the tutorials commencing in mPeripheral issue 10.

In this program, the cursor is positioned and some data is output to the monitor, then the cursor is "hidden" by moving it to line 26 which is not displayed. After you compile and run the program, you will notice that the cursor is not visible on the monitor. This is possible in any program, but be sure to put the cursor in view before returning to DOS because DOS does not like to have a "hidden" cursor and may do some strange things.

Some time spent studying this program will be valuable to you as it will reveal how the keyboard data is input to the computer. Especially of importance is how the special keys such as function keys, arrows, etc. are handled.

dosex_1616.c - is the Applix 1616 program equivalent to the above.
/* **********************************************************************/
/* This is an example program to illustrate how to ; */
/* 1. Get the time and date from APPLIX 1616/OS using a system call */
/* 2. Set the cursor to any position on the screen using a 1616/OS video*/
/* driver escape code */
/* 3. Read characters from the keyboard and display their codes */
/* 4. How to scroll a window up on the monitor */
/* 5. Format a program for ease of reading and understanding */

/* **********************************************************************/
#include "/sys/stdio.h"
#include "/sys/syscalls.h"
#include "/sys/ctype.h"
main( )
{
int character, x;
x = 2;
draw_box(); /* draw the boxes around the fields */
pos_cursor(33,19);
printf("Type Q to quit");
do {
if (kbhit()) { /* has a key been hit */
if (x <= 16) { /* scroll output in window down a */
pos_cursor(9,x+1); /* line. */
++x;
}
else if
(x <= 31){
pos_cursor(50,x-14); /* return to top of window on right */
++x; /* hand side. */
}
else {
x = 2; /* return to top of window on left */
pos_cursor(9,x+1); /* hand side. */
}
character = getch(); /* read it in */
14-2 C Tutorial Example Programs
disp_char(character); /* display it */
}
get_time(); /* get the time of day and display it. */
} while (character != ’Q’); /* Quit when a Q is found */
pos_cursor(0,0); /* put cursor at top of screen */
}
/* *********************************************************** drawbox */
/* This routine draws a box on the screen. The keys hit, the time and */
/* date are displayed in these boxes. Nothing special about these */
/* boxes, they are simple output using the printf function. */
/* ******************************************************************* */
draw_box()
{
int index;
char line[81];
for (index = 0;index < 80;index++) /* three blank rows */
line[index] = ’ ’;
line[80] = NULL; /* end of string */
for (index = 0;index < 3;index++)
printf("%s",line);
line[8] = 201; /* draw top line of box */
for (index = 9;index < 70;index++)
line[index] = 205;
line[70] = 187;
printf("%s",line);
line[8] = 186; /* draw sides of large box */
for (index = 9;index < 70;index++)
line[index] = ’ ’;
line[70] = 186;
for (index = 0;index <15;index++)
printf("%s",line);
line[8] = 204; /* draw line between boxes */
for (index = 9;index < 70;index++)
line[index] = 205;
line[70] = 185;
printf("%s",line);
line[8] = 186; /* sides of time/date box */
for (index = 9;index < 70;index++)
line[index] = ’ ’;
line[70] = 186;
printf("%s",line);
line[8] = 200; /* bottom line of the box */
for (index = 9;index < 70;index++)
line[index] = 205;
line[70] = 188;
printf("%s",line);
for (index = 0;index < 80;index++) /* three blank rows */
line[index] = ’ ’;
for (index = 0;index < 3;index++)
printf("%s",line);
}

/* ********************************************************* disp_char */
/* This routine displays characters hit on the monitor. If the first */
/* character is a zero, it is a special character hit, and the zero is */
/* displayed. Next character is read, and is displayed on the monitor. */

/* ******************************************************************* */
disp_char(inchar)
int inchar;
{
int c;
c = inchar;
Example Programs C Tutorial 14-3
if (c == 13) {
return;
}
if ( isupper(c) ) {
printf("%4d (%c) Uppercase ",c,c);
}
if ( islower(c) ) {
printf("%4d (%c) Lowercase ",c,c);
}
if ( isspace(c) ) {
printf("%4d (%c) White Space",c,c);
}
if ( ispunct(c) ) {
printf("%4d (%c) Punctuation",c,c);
}
if ( isdigit(c) ) {
printf("%4d (%c) Digit ",c,c);
}
pos_cursor(25,1); /* hide the cursor on the 26th line */
}
/* ******************************************************* pos_cursor */
/* Function is used to position the cursor on the screen using the */
/* 1616OS video escape call */
/* ****************************************************************** */
pos_cursor(xpos,ypos)
int xpos, ypos;
{
printf("\033=%c%c", ypos + 32, xpos + 32);
}
/* ********************************************************get_time */
/* Routine calls the 1616OS function call for time of day. Returns */
/* the time of day to calling program in a do while loop so it */
/* is conviently updated */
/* **************************************************************** */
get_time()
{
char *time, BUF[22];
time = GETTDSTR(BUF); /* 1616 syscall for timedate string */
pos_cursor(10,19); /* cursor positioning function */
printf("%s",time);
pos_cursor(50,19);
printf("%s",time);
}