/*-------------------------------------------------------------------------*/ /* ADTLIB.C a collection of general purpose supplements to */ /* C, the system V libraries, and the IBM PC bindings */ /*-------------------------------------------------------------------------*/ #define LG_YES 1 #define LG_NO 0 #define TRUE LG_YES #define FALSE LG_NO #define N_ERR LG_NO #define R_ERR -1 /*--------- BEGINING OF THE GENERAL PURPOSE FUNCTIONS ---------------------*/ struct { int rows; int cols; } screen_size = {25, 80}; /*----------------------------------------------------------------------*/ /* Additional string handling functions */ /*----------------------------------------------------------------------*/ /*-----------------Chtostr----------------------------------------------*/ char *chtostr( /* converts a character into a string */ char *str, char al ) { str[0]=al; str[1]='\0'; return(str); } /*---------------Strbuild-------------------------------------------------*/ char *strbuild( char *dest, /* destination, is overwritten */ char *src1, ... /* list of strings, terminated by NULL, */ ) /* to concatenate */ { va_list argpointer char *srcn; if(src1 != NULL) { strcpy(dest,src1) va_start(argpointer, src1); srcn=va_arg(argpointer, char *); while(srcn != NULL) { strcat(dest,srcn) srcn=va_arg(argpointer, char *); } va_end(argpointer); } return(dest); } /*---------------------------------------------------------------------*/ /* Additional screen handling */ /*---------------------------------------------------------------------*/ /*-------------------------- Scrnputs ---------------------------------*/ scrnputs(int row, /* the starting position: row */ int icol, /* col */ char *s, /* the source string to put into the slot */ char fill, /* fill character for the rest of the slot */ char attrib, /* attribute of the slot */ int length, /* length of the slot */ int restore /* LG_YES to put the cursor back where it was */ ) { int col, trow, tcol; if(restore == LG_YES) { tcol=curscol(); trow=cursrow(); /* save cursor position */ } poscurs(row,icol); for( col = icol; col < icol+length; col++) { if( s[(col-icol)] != NULL_BYTE ) { poscurs(row, col); writechs(s[(col-icol)],attrib,1); } else break; } if( col < (icol+length)) { poscurs(row, col); writechs(fill, attrib, (icol+length-col)); } if(restore == LG_YES) poscurs(trow,tcol); /* restore cursor position */ } /*-------------------------------------------------------------------------*/ w_roll(int min_row, int max_row, /* maximum and minimum rows */ int min_col, int max_col, /* ditto columns */ int scroll, /* rows downward (upward is -) to scroll */ char attrib) /* to fill with */ { union REGS regs; regs.h.ch=min_row; regs.h.cl=min_col; regs.h.dh=max_row; regs.h.dl=max_col; regs.h.bh=attrib; if(scroll > 0 ) { regs.h.ah=7; regs.h.al=scroll; int86(0x10, ®s, ®s); } if(scroll < 0 ) { regs.h.ah=6; regs.h.al=-scroll; int86(0x10, ®s, ®s); } } /*-------------------------------------------------------------*/ /* Supplemental Comparison Routines */ /*-------------------------------------------------------------*/ int iclamp( int val, /* argument to be clamped within the limits: */ int lval, /* lowest permitted value */ int uval /* highest permitted value */ ) { if (val < lval) return lval; else if (val > uval) return uval; else return val; } /*--------------------*/ int imin( int a, int b ) { if(a < b) return(a); else return(b); } /*-----------------*/ int imax( int a, int b ) { if(a > b) return(a); else return(b); } /*----------------*/ inrange(int val, char mintest, int min, char maxtest, int max ) { if( (val < min) || ( (val == min) && mintest != '=')) return(FALSE); else if( (val > max) || ( (val == max) && maxtest != '=')) return(FALSE); else return(TRUE); } /*-------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ struct key_in { int charin, int have_char_q, int char_is_ext_q, int have_move_q, int down_move, int right_move, int mou_chng_q, int mou_l_bt, int mou_r_bt, int mou_c_bt, } nkey; /* revise so that it accepts the name of a routine to isolate the movement */ /* keys instead of being passed itself */ ---------------- get_mov_ch( struct key_in *nkey, int v_scale, /*number of pixels per arrow key*/ int h_scale, int (*is_move)() ) { int mve_fnd, dn_mve, rt_mve; /* here is where the mouse decoding logic will go */ nkey->charin=getch(); if( nkey->charin == NULL_BYTE ) /* if this is an extended keycode */ { nkey->charin=getch(); /* get the second byte and put it in the same place */ nkey->char_is_ext_q=LG_YES; } else { *is_ext_q=LG_NO; } if((*is_move)(nkey) == LG_YES) { nkey->have_char_q=LG_NO; nkey->have_move_q=LG_YES; } else { nkey->have_char_q=LG_YES; nkey->have_move_q=LG_NO; nkey->down_move= 0; nkey->right_move= 0; } /*it is only in this version that chars and movement are mutually */ /* exclusive */ nkey->mou_chng_q=LG_NO; nkey->mou_l_bt=LG_NO; nkey->mou_r_bt=LG_NO; nkey->mou_c_bt=LG_NO; /*the dummying for an eventual mouse*/ } /* uses getch() to get characters with waiting, provides for extended */ /* chars, will eventually support mouse as well */ /*-----------------------------------------------------------------------*/ /* Drive and directory validation */ /*-----------------------------------------------------------------------*/ is_valid_drive_name( /* confirms that this */ char *drive_name /* character string drivename */ ) /* is in proper form and points to */ { /* an extant drive */ struct dfree disk_map; if(drive_name != NULL) return(LG_NO); else { if(strchr(drive_name, ':') == NULL) { strcat(drive_name, ":"); /*make sure there is a colon */ } getdfree(drv_nam_to_int(drive_name), disk_map); /*use a function intended */ if(disk_map.df_sclus == R_ERR) return(LG_NO); /* another purpose, hoping */ else return(LG_YES); /* to trigger its fault reporting */ } } /*-------------------------------------------------------------------------*/ is_valid_dir(char *drive_name, char *dir_name) { int s_attrib=FA_NORMAL|FA_DIREC; struct ffblk dir_entry; char specpath[65]; strbuild(&specpath, drive_name, dir_name, NULL); specpath[strlen(specpath)-1]='\0'; if(findfirst(specpath,dir_entry,s_attrib) == R_ERR) return(LG_NO); else if((dir_entry.ff_attrib&FA_DIRECT)) return(LG_YES); else return(LG_NO); } /*--------------------------------------------------------------------------*/ path_rectify( char *dest_path, char *src_path ) /* converts the drive-dir portion of a path to fully explicit form */ /* finding a valid drive-dir if necesary */ /* file and extension remain unchanged */ /* returns R_ERR if could not use the drive-dir supplied, */ /* N_ERR otherwise */ { char curr_dir[80]; char n_dir_name[80] char drive_name[3]; char dir_name[80]; char file_name[9]; char extension_name[5]; int r_code=N_ERR; /* unless otherwise specified return N_ERR */ strupr(start_path); /* make it all uppercase */ fnsplit( src_path, &drive_name, &dir_name, &file_name, &extension_name ); if(drive_name == NULL) drv_num_to_str(&drive_name, getdisk()); /*if no drive is specified, use the current drive */ else if(!is_valid_drive_name(&drive_name)) { /* if the drive specifed is invalid, use the current drive */ r_code=R_ERR; drv_num_to_str(&drive_name, getdisk()); } chtostr(&cur_dir, '\\'); getcurdir(drv_nam_to_int(drive_name), &cur_path[1]); if(dir_name[0] != '\\') /* if the dir does not begin from root */ strbuild(&n_dir_name, /* splice in the current dir */ &cur_path, &dir_name, NULL); if(!is_valid_dir(&drive_name, n_dir_name)) { strcpy(&n_dir_name, &cur_dir); r_code=R_ERR; } fnmerge(dest_path, &drive_name,&n_dir_name, &file_name, &extension_name); return(r_code); } /*-------------------------------------------------------------------------*/ char *wildcard(char *dstpath, char *srcpath) { char *i, *last_delim; last_delim=NULL; strcpy(dstpath, srcpath); for(i=dstpath; *i != '\0'; i++) if( (*i == '\\') || (*i == ':') ) last_delim=i; if(last_delim == NULL) strcpy(dstpath, "*.*"); else strcpy(last_delim+1, "*.*"); return(&dstpath) } /*--------------------------------------------------------------------------*/ char *drv_num_to_str(char *str, int drive_n) /* converts the drive number */ { /* returned by MS-DOS into */ str[0]=(char)('A'+drive_n); /* a name string */ str[1]=':'; str[2]='\0'; return(str) } /*-------------------------------------------------------------------------*/ int drv_nam_to_int(char *str) /*converts a name string into a */ { /* drive number acceptable to */ char c; /* MS-DOS */ c=str[0]; c=toupper(c); c=c-'A'+1; return(c); } /*---------------------------------------------------------------------*/ int is_file_n_char(char c) /* is it valid in a MS-DOS filename LG_YES or LG_NO */ { if(isalnum(c)) return(LG_YES); else switch(c) { case :'~' case :'!' case :'@' case :'#' case :'$' case :'%' case :'^' case :'&' case :'(' case :')' case :'-' case :'_' case :'{' case :'}' case :'\'' return(LG_YES); default: return(LG_NO); } /*----------------------------------------------------------------------*/ char *cstrcat(char *s, char c) /* concatenates a char onto a string */ { char *i; for(i=s; (*i != '\0'); i++); /* find the end of the string */ *i=c; i++; *i='\0'; return(s); } /*-----------------------*/ int max_strlen_in_arr_ptrstr(char *array[], int n_elements) { int max_len, i; max_len=0; for(i=0; i < n_elements; i++) max_len=imax( strlen(array[i]), max_len ); return(max_len) } /* returns the length of the longest string */ /*-------------------*/