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

Vc.C - The Visual Calculator

This program finally ties nearly everything together because it uses nearly every concept covered in the entire tutorial. It is so big that I will not even try to cover the finer points of its operation. Only a few of the more important points will be discussed. The first thing you should do is go through the tutorial for VC included in the file VC.DOC. There are several dozen steps for you to execute, with each step illustrating some aspect of the Visual Calculator. You will get a good feel for what it is capable of doing and make your study of the source code very profitable. In addition, you will probably find many ways to use the Visual Calculator to solve problems involving calculations where the simplicity of the problem at hand does not warrant writing a program.

Notice that the structure definitions, used in all of the separate parts of the program, are defined in the fileSTRUCT.DEF(renamed STRUCT.Hin the Applix 1616 version). You should include STRUCT.H with the other Applix 1616 header files. During program development, when it became necessary to change one of the structures slightly, it was not necessary to change it in all of the files, only one file required modification which was then "included" in the source files. Notice that the transcript data is stored in a doubly linked list with the data itself being stored in a separate dynamically allocated char string. This line is pointed to by the pointer "lineloc". For ease of development, the similar functions were grouped together and compiled separately. Thus, all of the functions involving the monitor were included in the file named video.c, and all of the functions involving the data storage were grouped into the file.c collection.

Dividing your program in a way similar to this should simplify debugging and future modifications. Of special interest is the "monitor()" function. In the Applix 1616 version, this function is deleted, as the 1616 supports both colour and monochrome monitors without change. In the MS-DOS world, this function examines the video mode through use of a DOS command and if it is a 7, it assumes it is a monochrome monitor, otherwise it assumes a color monitor. The colors of the various fields are established at this time and used throughout the program. Most of the data is written directly to the video memory, but some is written through the standard
MS-DOS BIOS routines.

The file definc.c is simply a catalogue of the functions to aid in finding the functions. This file was generated as one of the first files and was maintained and updated for use during the entire design and coding lifetime.Feel free, after understanding this code, to modify it in any way you desire for your own use. To compile and link this, copy all five of the VC files (data.c, file.c, vc.c, video.c, struct.h) into a directory and include that directory in your xpath. Type: relcc -v -W1 -lf vc.c data.c video.c file.c (Note that the -lf option must be included so that the compiler uses the float library, while the others are optional.) Or use the makefile included on the distribution disk, if you have the make utility.


#include "/sys/ctype.h"
#include "/sys/stdio.h"
#include "/f0/struct.h"
#include "/sys/syscalls.h"
struct vars allvars[12]; /* this is the main variable storage */
int varinuse = 0; /* which variable is being used now */
char inline[60]; /* input line area */
int col; /* used for searching across the input */
int errcode; /* error code number */
int colerr; /* column where error occured */
int printit = 1; /* 1 = print a transcript */
int ignore; /* 1 = ignore calculations for line */
extern char strngout[]; /* output message area */
struct lines *top, *bot, *q, *p, *arrow, *trnsend
;
/* ************************************************************* main */
/* The main control loop for the program. Initializes everything */
/* and reads statements until no errors. Continues reading until */
/* F10 occurs in subordinate function where control is returned to */
/* 1616OS. */


main()
{
top = bot = q = p = arrow = trnsend = NULL;
initfk(); /* sets up function keys */
initdata(&allvars[0]); /* initializes all data */
bkgndvid(); /* display video background - double lines */
valusvid(); /* display starting values of all variables */
strtrans("Welcome to the Visual Calculator - Applix 1616 - Version
1.00",0);transout();
do {
poscurs(22,7);
printf(" input >
");
printf(" ");
do { /* repeat untill no errors */
readline(); /* get an input line */
errdis(" "); /* clear error msg */
parse(); /* parse the line */
if (errcode)
errout(); /* output error message */
} while (errcode);
if (ignore == 1)
strtrans(inline,0); /* store comment in transcript */
else
strtrans(inline,1); /* store "inline" in transcript */
transout();
} while (1); /* continuous loop */
}

/* ********************************************************** readline */
/* This function reads a line by inputting one character at a time and */
/* deciding what to do with it if a special character, or adding it to */
/* the input line if not a special character. The routine takes care of*/
/* such things as backspace, cursor movement and delete keys. The final*/

/* result is a line of text stored in the buffer "inline" and the line */
/* displayed on the monitor. */
readline()
{
int index;
int c,temp;
int row = 22,col = 17;
if (errcode) { /* error recovery allow reenter */
index = colerr;
errcode = 0;
}
else { /* normal input routine */
index = 0;
for (temp = 0;temp < 60;temp++)
inline[temp] = 0; /* clear input buffer */
}
poscurs(row,col+index); /* starting location of cursor */
do { /* repeat this do loop until a return is hit */
while ((c = getch()) == EOF); /* get a keystroke */
if ((c == 2) || (c == 3) || (c == 4) || (c == 5) || (c == 12) ||
(c == 24) || (c == 18) || (c == 19) || (c == 127)) {
switch (c) {
case 19 : if (index) { /* left arrow */
index = index -1; /* back up cursor */
}
break;
case 4 : if (index < 61) { /* right arrow */
if (inline[index] == 0); /* zero found */
inline[index] = ’ ’; /* blank over 0 */
index = index + 1; /* cursor forward */
}
break;
case 5 : movarrow(-1); /* up arrow */
break;
case 24 : movarrow(1); /* down arrow */
break;
case 18 : movarrow(-8); /* page up */
break;
case 3 : movarrow(8); /* page down */
break;
case 12 : movarrow(-1000); /* home */
break;
case 2 : movarrow(1000); /* end */
break;
case 127 : temp = index; /* delete key */
/* move all characters left one space */
while (inline[temp]) {
inline[temp] = inline[temp+1];
putchar(inline[temp++]);
}
putchar(’ ’); /* blank in last place */
break;
default : poscurs(15,5);
printf(" S%3d",c);
}
poscurs(row,col+index); /* actually put cursor in position*/
}

if (c == 0) { /* a zero here says a special key was hit */
/* get the key and act on it as needed */
int spec;
spec = getch(); /* this is the special code found */
switch (spec) {
case 59 : helpm(); /* F1 - Help math */
transout();
break;
case 60 : helps(); /* F2 - Help system */
transout();
break;
case 61 :
break; /* F3 - Spare */
case 62 : /* F4 - Mark transcript */
arrow->marked = (arrow->marked?0:1);
transout();
break;
case 63 : fileout(); /* F5 - Store transcript */
break;
case 64 : filein(); /* F6 - retrieve trans */
errcode = 0;
break;
case 65 :
break; /* F7 - Spare */
case 66 :
break; /* F8 - Spare */
case 67 : /* F9 - Edit a line */
strcpy(inline,arrow->lineloc);
poscurs(22,17);
printf("%s",inline);
break;
case 68 : poscurs(22,17); /* F10 - Quit to 1616OS */
printf("Quit? (Y/N) ");
c = getch();
if ((c == ’Y’) || (c == ’y’)) {
clrscrn();
exit(0);
}
else {
poscurs(22,17);
printf(" ");
break;
}
default : poscurs(15,5);
printf(" S%3d",spec);
}
poscurs(row,col+index); /* actually put cursor in position */
}
else { /* normal letter or char hit */
int curr, next;
if (islower(c)) c = toupper(c); /* convert to upper case */
if ((c >= ’\40’) && (c <= ’\176’)) { /* printable char */
poscurs(row,col+index);
putchar(c);
next = inline[index];
inline[index++] = c;
curr = index;
while((next != 0) && (curr <=60)) { /* move remainder */
temp = next; /* line right */
next = inline[curr];
inline[curr++] = temp;
putchar(temp);
}
}
else {
if ((c == 8) && index){ /* backspace */

index--;
poscurs(row,col+index); /* back up cursor */
temp = index;
while (inline[temp]) {
inline[temp] = inline[temp+1];
putchar(inline[temp++]);
}
putchar(’ ’);
}
}
poscurs(row,col+index);
}
} while (c != 13); /* newline found, line input is complete
*/
}

/* ************************************************************ parse */
/* This function does checking of the input line for logical errors in */
/* construction, then turns control over to the function "calcdata" for*/
/* the actual calculations. */
parse()
{
int index,parcol;
double newval;
char name[8];
varinuse = -1;
errcode = 0;
col = 0;
ignore = 1; /* ignore this line */
if (inline[0] == ’#’) { /* get list of variable names */
getnames();
return;
}
while (inline[col] == ’ ’) col++; /* ignore leading blanks */
if (inline[col] == ’$’) return; /* ignore a comment line */
if (inline[col] == 0) return; /* ignore a blank line */
ignore = 0; /* don’t ignore this line */
name[0] = inline[col++]; /* find variable name */
index = 1;
while ((((inline[col] >= ’A’ ) && (inline[col] <= ’Z’ )) ||
((inline[col] >= ’0’ ) && (inline[col] <= ’9’ ))) &&
(index <= 5 )) { /* continue var or function name */
name[index++] = inline[col++];
}
name[index] = 0;
for (index = 0;index < 12;index++) {
if ((strcmp(name,allvars[index].varname)) == 0)
varinuse = index; /* variable name found */
}
if (varinuse < 0)
errchk(3); /* unknown variable name */
while (inline[col] == ’ ’) col++; /* ignore leading blanks */
if (inline[col] == ’=’) col++;
else errchk(8); /* missing equal sign */
parcol = 0; /* now check for correct parenthesis matchup */
index = col;
do {
if (inline[col] == ’(’) parcol++;
if (inline[col++] == ’)’) parcol--;
if (parcol < 0) errchk(1); /* paren count went negative */
}
while (inline[col]);
if (parcol)
errchk(2); /* left over parenthesis */
col = index;
Example Programs C Tutorial 14-13
calcdata(&newval); /* now go evaluate the full expression */
if (errcode == 0) { /* don’t update value if error found */
allvars[varinuse].value = newval;
disnew(varinuse); /* display the changed value */
}
}

/* *************************************************************** errout
*/
/* This is the function that displays the blinking error messages on the
*/
/* monitor. Note the extra errors for expansion of the table.
*/
errout()
{
switch (errcode) {
case 1 : errdis("extra right parenthesis ");
break;
case 2 : errdis("missing right parenthesis");
break;
case 3 : errdis("unknown variable name ");
break;
case 4 : errdis("invalid math operator");
break;
case 5 : errdis("negative value for SQRT");
break;
case 6 : errdis("Function not found");
break;
case 7 : errdis("negative value for LOG");
break;
case 8 : errdis("equal sign missing");
break;
case 9 : errdis("invalid data field");
break;
case 10 : errdis("division by zero");
break;
case 11 : errdis("File doesn’t exist");
break;
case 12 : break;
case 13 : errdis("Out of memory");
break;
case 14 : errdis("Dash expected");
break;
case 15 : errdis("Invalid format code");
break;
case 16 : errdis("Neg value for FACTORIAL");
break;
case 17 : errdis("Err 17");
break;
default : errdis("unknown error");
poscurs(21,70);
printf("%d",errcode);
}
poscurs(22,12+colerr);
}

/* ************************************************************* initfk()
*/
/* This function is used by APPLIX 1616 to initialise the function keys
*/
/* for the Visual Calculator
*/
char fkey1[] = { 128, 59, 0 };
char fkey2[] = { 128, 60, 0 };
char fkey3[] = { 128, 61, 0 };
char fkey4[] = { 128, 62, 0 };
char fkey5[] = { 128, 63, 0 };
char fkey6[] = { 128, 64, 0 };

char fkey7[] = { 128, 65, 0 };
char fkey8[] = { 128, 66, 0 };
char fkey9[] = { 128, 67, 0 };
char fkey10[] = { 128, 68, 0 };
initfk()
{
DEF_FK( 0, fkey1);
DEF_FK( 1, fkey2);
DEF_FK( 2, fkey3);
DEF_FK( 3, fkey4);
DEF_FK( 4, fkey5);
DEF_FK( 5, fkey6);
DEF_FK( 6, fkey7);
DEF_FK( 7, fkey8);
DEF_FK( 8, fkey9);
DEF_FK( 9, fkey10);
}

/* ****************************************************************/