#include "define.h" #include #include #include "rpcfg.h" /* GLOBAL variables, naughty but nice */ extern struct COMMAND print_codes[11]; /* Array to hold printer commands */ extern char print_name[80]; /* Printers name */ extern int coloura,quality; /* Have we got colour, nlq? 0=No */ extern int driver_loaded; #ifdef NO_ISXDIGIT int isxdigit(c) /************************************************************************** Emulates ANSII standard function isxdigit, returns 0 if character is not a valid hexidecimal digit, non-zero if it is valid. **************************************************************************/ char c; { if ( (isdigit(c)==0) && ((tolower(c)<'a')||(tolower(c)>'f')) ) return 0; return 1; } #endif void display_error(err,line) /**************************************************************************** SUBROUTINE : display_error VERSION : 1.0 AUTHOR : ROBERT ALLEY DATE : 5/7/90 DESCRIPTION : Display an error message LOGIC USED : STEP 1. Based on the error code, build an error string, display it and return. RETURNS : none. PARAMETERS : err I Error number (As defined in RPCFG.H) line I Line error occured on (Start at 0) VARIABLES : mess[80] Char String to hold error message CONSTANTS : None. REQD. FILES : None. REQD. SUBPG.: None. NOTES : None. USAGE : display_error(err_num,line_num); ****************************************************************************/ int err,line; { char mess[80]; switch (err) { case TOOLONG: sprintf(mess,"[3][Error :Line too long|in line %d][OK]",line); break; case RANOFFE: sprintf(mess,"[3][Error :Ran off the end|of file at line %d][OK]",line); break; case TOOBIGN: sprintf(mess,"[3][Error :To many characters|in # at line %d][OK]",line); break; case NOMEMOR: sprintf(mess,"[3][Error :Ran out of memory][OK]"); break; case SYNTAXE: sprintf(mess,"[3][Error :Syntax error|at line %d][OK]",line); break; default : sprintf(mess,"[3][Error in line %d][OK]",line); break; } form_alert(1,mess); } int convert(line,commands) /**************************************************************************** SUBROUTINE : convert VERSION : 1.0 AUTHOR : ROBERT ALLEY DATE : 5/7/90 DESCRIPTION : Convert a string of commands into a list of numbers and place them in a command structure. LOGIC USED : STEP 1. Get the next character in the string. if its a $, go into hex mode, ignore if a space. STEP 2. If its a comma, put a 0 teminator on the end of the temporary string. Convert the string to a number (either hex or decimal coversion). if conversion didnt work or we have got too many commands, return an error. Zero hex flag and temporary counter. STEP 3. All other characters, if not in hex mode, check the character is a digit, if not return an error. If in hex mode check its a valid hex digit, if not return an error. Stick character in temporary string, if string is too long, return an error. STEP 4. Repeat 1-3 until the end of the line is reached. Allocate enough space for the command list. If space cant be allocated, return an error. Copy the commands to the allocated space, fill in the length and return. RETURNS : Integer error status (Error codes defined in RPCFG.H) 0=OK. PARAMETERS : line Char * Line to parse commands COMMAND * Structure to hold commands read VARIABLES : character Int Current character being processed count Int Current character number hex Int Flag for hex mode, 1=Hex # num Int Number of values converted values[5] Int array of command numbers tcount I Number of characters in temp string temp[80] Char Temporary string error I Error status returned by sscanf. CONSTANTS : None. REQD. FILES : None. REQD. SUBPG.: None. NOTES : None. USAGE : error_status=convert(line_to_convert,commands_found); ****************************************************************************/ char *line; struct COMMAND *commands; { int character; /* char being processed */ int count=0; /* current char number */ int hex=0; /* flag for hexi number */ int num=0; /* number of values stroed */ int values[MAXLEN]; /* holds converted numbers */ int tcount=0; /* number of chars in temp */ char temp[MAXCHA]; /* temp holder for numbers (as text) */ int error; /* error status returned by sscanf */ /* STEP 1. */ do { character=line[count++]; switch (character) { case '$' : hex=1; break; case ' ' : break; case 0 : /* STEP 2. */ case ',' : temp[tcount]=0; /* Put terminator on end */ if (hex==1) { error=sscanf(temp,"%x",&values[num++]); } else { error=sscanf(temp,"%d",&values[num++]); } if (error!=1) return(SYNTAXE); if (num >= MAXLEN) return(TOOLONG); hex=tcount=0; break; /* STEP 3. */ default : if (hex==0) if ( (isdigit(character))==0) return(SYNTAXE); if (hex==1) if ( (isxdigit(character))==0) return(SYNTAXE); temp[tcount++]=character; if (tcount >= MAXCHA) return(TOOBIGN); break; } /* STEP 4. */ } while (character != 0); if ( (commands->list=(int *)malloc(num*sizeof(int)))==NULL) return(NOMEMOR); else memcpy(commands->list,values,num*sizeof(int)); commands->length=num; return(0); } read_line(infile,line,linen) /**************************************************************************** SUBROUTINE : read_line VERSION : 1.0 AUTHOR : ROBERT ALLEY DATE : DESCRIPTION : Read a line from a printer config file. Ignores characters after a semi-colon (;) (Comments). Ignores blank lines. Leading spaces not placed in string. LOGIC USED : STEP 1. While the finished flag hasnt been set. Get a character from the file stream. STEP 2. If its a ';', read in the rest of the line, increment line counter. If its a space, ignore it. If its a new line, increment line number. if its the EOF, return error status. STEP 3. Put the character in the string. While the characters not EOL, ';' or newline: put it in the string, read in a new character. If last character was ';', read in the rest of the line. Increment line counter, set finished flag. STEP 4. Put 0 at end of string, return 0. RETURNS : Integer error string, 0 for no error. PARAMETERS : infile FILE * File to read from (assumed open) line char * Pointer to string to fill linen I * Line number VARIABLES : character I Current character being processed finished I Flag for finished reading 1=YES count I Number of characters put in string. CONSTANTS : None. REQD. FILES : Whatever infile refers to. REQD. SUBPG.: None. NOTES : None. USAGE : error=readline(FILE *infile,char *line,int *linen); ****************************************************************************/ FILE *infile; char *line; int *linen; { int character; /* current character */ int finished=0; /* finished yet ??? */ int count=0; /* STEP 1. */ while (finished==0) { character=getc(infile); switch (character) { /* STEP 2. */ case ';': while (character != '\n') character=getc(infile); (*linen)++; break; case ' ': /* Basically ignore it ! */ break; case '\n': (*linen)++; break; case EOF : return(RANOFFE); break; /* STEP 3. */ default : while ((character !=';') && (character !='\n') && (character != EOF)) { line[count++]=character; if (count >= MAXLEN) return (TOOLONG); character=getc(infile); } if (character==';') while(character != '\n') character=getc(infile); (*linen)++; finished=1; break; } } /* STEP 4. */ line[count]=0; return(0); } int rpd(name,colour,nlq,driver) /**************************************************************************** SUBROUTINE : rpd VERSION : 1.0 AUTHOR : ROBERT ALLEY DATE : 5/7/90 DESCRIPTION : Read printer details LOGIC USED : STEP 1. Open file, if we cant return an error. STEP 2. Get a line, return if an error occurs, check for valid version number, return error if not. STEP 3. Get the printer name, return if an error occurs. STEP 4. Read a line, returning on error, if its a one weve got a colour printer so read and convert the three colour commands. STEP 5. Read and convert line 3-4. STEP 6. read a line, if its a one weve got a NLQ printer so read the nlq on/off commands. STEP 7. Read an convert line 7-10. RETURNS : Integer error number, 0=No error. PARAMETERS : name Char * String to hold printer name colour Int * Is printer colour? 0=No 1=Yes nlq int * Is printer NLq 0=No, 1=Yes VARIABLES : driver FILE * File to read from line[80] Char Current line read error Int Error code, 0=OK linen Int Current line number comnum Int Command number CONSTANTS : None. REQD. FILES : None. REQD. SUBPG.: read_line convert display_error NOTES : Line numbers start at 0. USAGE : error_status=rpd(printer_name,is_colour,is_nlq); ****************************************************************************/ int *colour,*nlq; char *name; FILE *driver; { char line[80]; /* line read */ int error,linen=0; /* error code, linenumber */ int comnum; /* command number being processed */ /* STEP 2. */ error=read_line(driver,line,&linen); /* get first line **/ if (error != 0) { /* if error, display and abort */ display_error(error,linen); return(1); } if (strcmp(line,"CLED1.2") != 0) { /* is it a valid version ? */ form_alert(1,"[3][Unrecognised version| of driver][OK]"); return(1); } /* STEP 3. */ error=read_line(driver,name,&linen); /* get name of printer */ if (error != 0) { /* if error, display and abort */ display_error(error,linen); return(1); } /* STEP 4. */ error=read_line(driver,line,&linen); /* get 1st command, colour mode */ if (error != 0) { /* if error, display and abort */ display_error(error,linen); return(1); } if (tolower(line[0])=='y') { /* if printer is colour */ *colour=1; /* set colour flag */ for (comnum=0;comnum<=2;comnum++) { /* get next 3 commands */ error=read_line(driver,line,&linen); if (error != 0) { display_error(error,linen); return(1); } if ( (error=convert(line,&print_codes[comnum])) != 0) { display_error(error,linen); return(1); } } } else *colour=0; /* STEP 5. */ for (comnum=3;comnum<=4;comnum++) { /* get commands 3 and 4 */ error=read_line(driver,line,&linen); if (error != 0) { display_error(error,linen); return(1); } if ( (error=convert(line,&print_codes[comnum])) != 0) { display_error(error,linen); return(1); } } /* STEP 6. */ error=read_line(driver,line,&linen); /* get nlq mode */ if (error != 0) { display_error(error,linen); return(1); } if (tolower(line[0])=='y') { /* if it does nlq */ *nlq=1; /* set the flag */ for (comnum=5;comnum<=6;comnum++) { /* read nlq on/off cammands */ error=read_line(driver,line,&linen); if (error != 0) { display_error(error,linen); return(1); } if ( (error=convert(line,&print_codes[comnum])) != 0) { display_error(error,linen); return(1); } } } else *nlq=0; /* STEP 7. */ for (comnum=7;comnum<=10;comnum++) { /* get commands 7-10 */ error=read_line(driver,line,&linen); if (error != 0) { display_error(error,linen); return(1); } if ( (error=convert(line,&print_codes[comnum])) != 0) { display_error(error,linen); return(1); } } } load_prn_drv() { FILE *p_driver; if ( (p_driver=fopen("print.drv","r"))==NULL) { form_alert(1,"[3][ ERROR|Unable to load driver|Cant print][OK]"); driver_loaded=0; } else { if ( (driver_loaded=rpd(print_name,&coloura,&quality,p_driver))!=0) { form_alert(1,"[3][ ERROR|Unable to load driver|Cant print][OK]"); driver_loaded=0; } else driver_loaded=1; fclose(p_driver); } } load_driver(directory) char *directory; { FILE *read; int abort,ok; static char file[128]=""; abort=0; while (abort==0) { abort = select(file,directory); if (abort ==0) { if ( (read=fopen(file,"r"))==(FILE *)NULL) { abort=form_alert(1,"[3][Error opening file][Abort|Continue]"); if (abort==2) abort=0; } else abort=2; } } if (abort != 1) { if ( (ok=rpd(print_name,&coloura,&quality,read))!=0) { if (driver_loaded==0) form_alert(1,"[3][ ERROR|Unable to load driver| Cant print][OK]"); else form_alert(1,"[3][ ERROR|Unable to load driver| old driver used][OK]"); } else driver_loaded=1; fclose(read); } }