Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: rolodex database program -- part 2 of 3 Message-ID: <1515@panda.UUCP> Date: 13 Mar 86 23:42:23 GMT Sender: jpn@panda.UUCP Lines: 2563 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 28 Submitted by: ihnp4!think!massar (JP Massar) #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # choices.h # clear.c # datadef.h # io.c # menuaux.c # operations.c # options.c # rlist.c # rolo.c # rolodefs.h # rolofiles.h # search.c # update.c # This archive created: Thu Mar 13 18:29:52 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'choices.h'" '(685 characters)' if test -f 'choices.h' then echo shar: will not over-write existing file "'choices.h'" else cat << \SHAR_EOF > 'choices.h' typedef enum { P_CONTINUE, P_NEXT_PERSON, P_ABORT, P_HELP } P_Choices; typedef enum { M_SEARCH_BY_OTHER, M_SEARCH_BY_NAME, M_PRINT_TO_LASER_PRINTER, M_HELP, M_EXIT, M_PERUSE, M_SAVE, M_ADD } Main_Choices; typedef enum { A_ABORT_ADD, A_BACKUP, A_FILL_IN_REST, A_ABORT_ROLO, A_HELP, A_NO_DATA } Add_Choices; typedef enum { E_ABORT, E_UPDATE, E_DELETE, E_CONTINUE, E_PREV, E_HELP, E_SCAN } E_Choices; typedef enum { U_ABORT, U_HELP, U_END_UPDATE } U_Choices; typedef enum { S_ABORT, S_HELP, S_SCAN_ONE_BY_ONE } S_Choices; typedef enum { O_ABORT, O_HELP, O_BACKUP, O_DONE_OTHERS } O_Choices; SHAR_EOF if test 685 -ne "`wc -c < 'choices.h'`" then echo shar: error transmitting "'choices.h'" '(should have been 685 characters)' fi fi echo shar: extracting "'clear.c'" '(930 characters)' if test -f 'clear.c' then echo shar: will not over-write existing file "'clear.c'" else cat << \SHAR_EOF > 'clear.c' #include #ifdef TERMINFO #include #endif #undef putchar int putchar(); static int ok_to_clear; #ifdef TERMCAP static char clear_screen[128] = 0; static int lines; #endif clearinit () { #ifdef TERMINFO int i; setupterm(getenv("TERM"),1,&i); ok_to_clear = (i == 1) ? 1 : 0; if (i != 1) { fprintf(stderr,"Warning: Terminal type unknown\n"); } return (i == 1) ? 0 : -1; #endif #ifdef TERMCAP char tc[1024]; char *ptr = clear_screen; if (tgetent(tc, getenv("TERM")) < 1) { ok_to_clear = 0; return; } tgetstr("cl", &ptr); lines = tgetnum("li"); ok_to_clear = (clear_screen[0] != 0 && lines > 0); #endif } clear_the_screen () { #ifdef TERMINFO if (!ok_to_clear) return; tputs(clear_screen,lines,putchar); fflush(stdout); #endif #ifdef TERMCAP if (!ok_to_clear) return; tputs(clear_screen,lines,putchar); fflush(stdout); #endif } SHAR_EOF if test 930 -ne "`wc -c < 'clear.c'`" then echo shar: error transmitting "'clear.c'" '(should have been 930 characters)' fi fi echo shar: extracting "'datadef.h'" '(1911 characters)' if test -f 'datadef.h' then echo shar: will not over-write existing file "'datadef.h'" else cat << \SHAR_EOF > 'datadef.h' #define ABORTSTRING "\\" #define ABORTCHAR '\\' #define MAXMATCHES 17 #define N_BASIC_FIELDS 8 #define OTHER -1 typedef enum Basic_Field { R_NAME = 0, R_WORK_PHONE, R_HOME_PHONE, R_COMPANY, R_WORK_ADDRESS, R_HOME_ADDRESS, R_REMARKS, R_UPDATED }; extern char *Field_Names[]; /* A Rolodex entry */ typedef struct { char *basicfields[N_BASIC_FIELDS]; int n_others; char **other_fields; } Rolo_Entry, *Ptr_Rolo_Entry; #define get_basic_rolo_field(n,x) (((x) -> basicfields)[(n)]) #define get_n_others(x) ((x) -> n_others) #define get_other_field(n,x) (((x) -> other_fields)[n]) #define set_basic_rolo_field(n,x,s) (((x) -> basicfields[(n)]) = (s)) #define set_n_others(x,n) (((x) -> n_others) = (n)) #define incr_n_others(x) (((x) -> n_others)++) #define set_other_field(n,x,s) ((((x) -> other_fields)[n]) = (s)) typedef struct link { Ptr_Rolo_Entry entry; int matched; struct link *prev; struct link *next; } Rolo_List, *Ptr_Rolo_List; #define get_next_link(x) ((x) -> next) #define get_prev_link(x) ((x) -> prev) #define get_entry(x) ((x) -> entry) #define get_matched(x) ((x) -> matched) #define set_next_link(x,y) (((x) -> next) = (y)) #define set_prev_link(x,y) (((x) -> prev) = (y)) #define set_entry(x,y) (((x) -> entry) = (y)) #define set_matched(x) (((x) -> matched) = 1) #define unset_matched(x) (((x) -> matched) = 0); extern Ptr_Rolo_List Begin_Rlist; extern Ptr_Rolo_List End_Rlist; #define MAXLINELEN 80 #define DIRPATHLEN 100 extern int changed; extern int reorder_file; extern int rololocked; extern char *rolo_emalloc(); extern char *malloc(); extern Ptr_Rolo_List new_link_with_entry(); extern char *copystr(); extern int compare_links(); extern char *timestring(); extern char *homedir(), *libdir(); extern char *getenv(); extern char *ctime(); extern char *select_search_string(); extern int in_search_mode; SHAR_EOF if test 1911 -ne "`wc -c < 'datadef.h'`" then echo shar: error transmitting "'datadef.h'" '(should have been 1911 characters)' fi fi echo shar: extracting "'io.c'" '(8455 characters)' if test -f 'io.c' then echo shar: will not over-write existing file "'io.c'" else cat << \SHAR_EOF > 'io.c' #include #include #include #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "datadef.h" #include "rolofiles.h" char *Field_Names[N_BASIC_FIELDS] = { "Name: ", "Work Phone: ", "Home Phone: ", "Company: ", "Work Address: ", "Home Address: ", "Remarks: ", "Date Updated: " }; Ptr_Rolo_List Begin_Rlist = 0; Ptr_Rolo_List End_Rlist = 0; Ptr_Rolo_List Current_Entry = 0; static char *rolofiledata; read_rolodex (fd) int fd; { struct stat statdata; int filesize,i,j,k,start_of_others,warning_given; Ptr_Rolo_Entry newentry,oldentry,currententry; Ptr_Rolo_List newlink,rptr; char *next_field,*next_other,*oldname,*currentname; char **other_pointers; int n_entries = 0; /* find out how many bytes are in the file */ fstat(fd,&statdata); if ((filesize = statdata.st_size) == 0) { return(0); } /* create an array of characters that big */ rolofiledata = rolo_emalloc(filesize); /* read them all in at once for efficiency */ if (filesize != read(fd,rolofiledata,filesize)) { fprintf(stderr,"rolodex read failed\n"); exit(-1); } j = 0; /* for each entry in the rolodex file */ while (j < filesize) { n_entries++; /* create the link and space for the data entry */ newlink = new_link_with_entry(); newentry = get_entry(newlink); if (j == 0) { Begin_Rlist = newlink; set_prev_link(newlink,0); set_next_link(newlink,0); } else { set_next_link(End_Rlist,newlink); set_prev_link(newlink,End_Rlist); set_next_link(newlink,0); } End_Rlist = newlink; /* locate each required field in the character array and change */ /* the ending line feed to a null. Insert a pointer to the */ /* beginning of the field into the data entry */ for (i = 0; i < N_BASIC_FIELDS; i++) { next_field = rolofiledata + j; while (rolofiledata[j] != '\n') { j++; } rolofiledata[j] = '\0'; j++; set_basic_rolo_field(i,newentry,next_field); } /* the end of an entry is indicated by two adjacent newlines */ if (rolofiledata[j] == '\n') { j++; newentry -> other_fields = 0; continue; } /* there must be additional, user-inserted fields. Find out how many. */ start_of_others = j; while (1) { while (rolofiledata[j] != '\n') { j++; } incr_n_others(newentry); j++; if (rolofiledata[j] == '\n') { j++; break; } } /* allocate an array of character pointers to hold these fields */ other_pointers = (char **)rolo_emalloc(get_n_others(newentry)*sizeof(char *)); /* separate each field and insert a pointer to it in the char array */ k = start_of_others; for (i = 0; i < get_n_others(newentry); i++) { next_other = rolofiledata + k; while (rolofiledata[k] != '\n') { k++; } rolofiledata[k] = '\0'; other_pointers[i] = next_other; k++; } /* insert the pointer to this character array into the data entry */ newentry -> other_fields = other_pointers; } /* check that all the entries are in alphabetical order by name */ warning_given = 0; rptr = get_next_link(Begin_Rlist); while (rptr != 0) { if (1 == compare_links(get_prev_link(rptr),rptr)) { if (!warning_given) fprintf(stderr,"Warning, rolodex out of order\n"); warning_given = 1; reorder_file = 1; } rptr = get_next_link(rptr); } return(n_entries); } write_rolo_list (fp) FILE *fp; /* write the entire in-core rolodex to a file */ { Ptr_Rolo_List rptr; Ptr_Rolo_Entry entry; int j; rptr = Begin_Rlist; while (rptr != 0) { entry = get_entry(rptr); for (j = 0; j < N_BASIC_FIELDS; j++) { fprintf(fp,"%s\n",get_basic_rolo_field(j,entry)); } for (j = 0; j < get_n_others(entry); j++) { fprintf(fp,"%s\n",get_other_field(j,entry)); } fprintf(fp,"\n"); rptr = get_next_link(rptr); } } write_rolo (fp1,fp2) FILE *fp1; FILE *fp2; { write_rolo_list(fp1); write_rolo_list(fp2); } display_basic_field (name,value,show,up) char *name; char *value; int show,up; { int semi = 0; int i; if (all_whitespace(value) && !show) return; printf("%-25s",name); while (*value != '\0') { if (*value == ';') { while (*++value == ' '); putchar('\n'); for (i = 0; i < (up ? 28 : 25); i++) putchar(' '); semi = 1; } else { semi = 0; putchar(*value++); } } putchar('\n'); } display_other_field (fieldstring) char *fieldstring; { int already_put_sep = 0; int count = 0; int i; while (*fieldstring != '\0') { if (*fieldstring == ';' && already_put_sep) { while (*++fieldstring == ' '); putchar('\n'); for (i = 0; i < 25; i++) putchar(' '); continue; } putchar(*fieldstring); count++; if (*fieldstring == ':' && !already_put_sep) { for (i = count; i < 24; i++) putchar(' '); already_put_sep = 1; } fieldstring++; } putchar('\n'); } summarize_entry_list (rlist,ss) Ptr_Rolo_List rlist; char *ss; /* print out the Name field for each entry that is tagged as matched */ /* and number each entry. */ { int count = 1; clear_the_screen(); printf("Entries that match '%s' :\n\n",ss); while (rlist != 0) { if (get_matched(rlist)) { printf ( "%d. \t%s\n", count++, get_basic_rolo_field((int) R_NAME,get_entry(rlist)) ); } rlist = get_next_link(rlist); } putchar('\n'); } display_field_names () /* display and number each standard field name. */ { int j; char *name; clear_the_screen(); for (j = 0; j < N_BASIC_FIELDS - 1; j++) { name = Field_Names[j]; printf("%d. ",j+1); while (*name != ':') putchar(*name++); putchar('\n'); } printf("%d. ",N_BASIC_FIELDS); printf("A user created item name\n\n"); } display_entry (entry) Ptr_Rolo_Entry entry; { int j,n_others; char *string; clear_the_screen(); /* display the standard fields other than Date Updated */ for (j = 0; j < N_BASIC_FIELDS - 1; j++) { string = get_basic_rolo_field(j,entry); display_basic_field(Field_Names[j],string,0,0); } /* display any additional fields the user has defined for this entry */ n_others = get_n_others(entry); for (j = 0; j < n_others; j++) { string = get_other_field(j,entry); display_other_field(string); } /* display the Date Updated field */ j = N_BASIC_FIELDS - 1; display_basic_field(Field_Names[j],get_basic_rolo_field(j,entry),0,0); fprintf(stdout,"\n"); } display_entry_for_update (entry) Ptr_Rolo_Entry entry; /* same as display_entry, except each item is numbered and the Date Updated */ /* item is not displayed */ { int j,n_others; char *string; int count = 1; clear_the_screen(); for (j = 0; j < N_BASIC_FIELDS - 1; j++) { string = get_basic_rolo_field(j,entry); printf("%d. ",count++); display_basic_field(Field_Names[j],string,1,1); } n_others = get_n_others(entry); for (j = 0; j < n_others; j++) { string = get_other_field(j,entry); printf("%d. ",count++); display_other_field(string); } printf("%d. Add a new user defined field\n",count); fprintf(stdout,"\n"); } int cathelpfile (filepath,helptopic,clear) char *filepath, *helptopic; int clear; { FILE *fp; char buffer[MAXLINELEN]; if (clear) clear_the_screen(); if (NULL == (fp = fopen(filepath,"r"))) { if (helptopic) { printf("No help available on %s, sorry.\n\n",helptopic); } else { fprintf(stderr,"Fatal error, can't open %s\n",filepath); exit(-1); } return; } while (NULL != fgets(buffer,MAXLINELEN,fp)) printf("%s",buffer); printf("\n"); fclose(fp); return; } any_char_to_continue () { char buffer[80]; printf("RETURN to continue: "); fgets(buffer,80,stdin); return; } SHAR_EOF if test 8455 -ne "`wc -c < 'io.c'`" then echo shar: error transmitting "'io.c'" '(should have been 8455 characters)' fi fi echo shar: extracting "'menuaux.c'" '(1433 characters)' if test -f 'menuaux.c' then echo shar: will not over-write existing file "'menuaux.c'" else cat << \SHAR_EOF > 'menuaux.c' #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" rolo_menu_yes_no (prompt,rtn_default,help_allowed,helpfile,subject) char *prompt; int rtn_default; int help_allowed; char *helpfile, *subject; { int rval; reask : rval = menu_yes_no_abort_or_help ( prompt,ABORTSTRING,help_allowed,rtn_default ); switch (rval) { case MENU_EOF : user_eof(); break; case MENU_HELP : cathelpfile(libdir(helpfile),subject,1); goto reask; break; default : return(rval); break; } } rolo_menu_data_help_or_abort (prompt,helpfile,subject,ptr_response) char *prompt, *helpfile, *subject; char **ptr_response; { int rval; reask : rval = menu_data_help_or_abort(prompt,ABORTSTRING,ptr_response); if (rval == MENU_EOF) user_eof(); if (rval == MENU_HELP) { cathelpfile(libdir(helpfile),subject,1); goto reask; } return(rval); } rolo_menu_number_help_or_abort (prompt,low,high,ptr_ival) char *prompt; int low,high,*ptr_ival; { int rval; if (MENU_EOF == (rval = menu_number_help_or_abort ( prompt,ABORTSTRING,low,high,ptr_ival ))) user_eof(); return(rval); } SHAR_EOF if test 1433 -ne "`wc -c < 'menuaux.c'`" then echo shar: error transmitting "'menuaux.c'" '(should have been 1433 characters)' fi fi echo shar: extracting "'operations.c'" '(8950 characters)' if test -f 'operations.c' then echo shar: will not over-write existing file "'operations.c'" else cat << \SHAR_EOF > 'operations.c' #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "mem.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" #include "choices.h" extern char *ctime(); Ptr_Rolo_List create_entry (basicdata,otherdata) char **basicdata, **otherdata; { Ptr_Rolo_List newlink; Ptr_Rolo_Entry newentry; int i,j; newlink = new_link_with_entry(); newentry = get_entry(newlink); for (j = 0; j < N_BASIC_FIELDS; j++) { set_basic_rolo_field(j,newentry,basicdata[j]); } j = 0; while (otherdata[j] != 0) j++; set_n_others(newentry,j); if (j > 0) { newentry -> other_fields = (char **) rolo_emalloc(j*sizeof(char *)); for (i = 0; i < j; i++) { set_other_field(i,newentry,otherdata[i]); } } else newentry -> other_fields = 0; return(newlink); } other_fields () { int rval; rval = rolo_menu_yes_no ( "Additional fields? ",DEFAULT_NO,1, "morefieldshelp","additional fields" ); return(rval == MENU_YES); } add_the_entry () { return(MENU_YES == rolo_menu_yes_no ( "Add new entry to rolodex? ",DEFAULT_YES,1, "newaddhelp","adding newly entered entry" )); } rolo_add () { int i,j,k,rval,menuval; long timeval; char *response; char *basicdata[N_BASIC_FIELDS], *otherdata[100], *datum; Ptr_Rolo_List rlink; for (j = 0; j < 100; j++) otherdata[j] = 0; for (j = 0; j < N_BASIC_FIELDS; j++) basicdata[j] = 0; cathelpfile(libdir("addinfo"),0,1); /* 'k' and 'kludge' are are kludge to allow us to back up from entering */ /* user defined fields to go an correct wrong basic field information. */ k = 0; kludge : for (j = k; j < N_BASIC_FIELDS - 1; j++) { redo : rval = menu_match ( &menuval,&response, Field_Names[j], 0,0,0,1,5, "\\",A_ABORT_ADD, "^",A_BACKUP, "!",A_FILL_IN_REST, "?",A_HELP, "",A_NO_DATA ); switch (rval) { case MENU_NO_MATCH : basicdata[j] = copystr(response); if (j == 0 && strlen(basicdata[j]) == 0) { printf("Each entry must have a name!\n"); goto redo; } break; case MENU_MATCH : switch (menuval) { case A_BACKUP : if (j == 0) return; j--; goto redo; break; case A_ABORT_ADD : return; break; case A_FILL_IN_REST : if (j == 0) { fprintf(stderr,"You must enter at least a name...\n"); goto redo; } goto add_entry; break; case A_HELP : cathelpfile(libdir("addhelp"),"adding entries",1); any_char_to_continue(); clear_the_screen(); cathelpfile(libdir("addinfo"),0,0); for (i = 0; i < j; i++) { printf("%s%s\n",Field_Names[i],basicdata[i]); } goto redo; break; case A_NO_DATA : if (basicdata[j] != 0) basicdata[j][0] = '\0'; break; default : fprintf(stderr,"Impossible rval from rolo_add menu_match\n"); save_and_exit(-1); break; } break; case MENU_EOF : user_eof(); break; case MENU_ERROR : case MENU_AMBIGUOUS : default : fprintf(stderr,"Impossible return from rolo_add menu_match\n"); save_and_exit(-1); break; } } if (other_fields()) { for (j = 0; j < 100; j++) { redo_other : rval = menu_match ( &menuval,&response, "Enter : (type RETURN to quit) : ", 0,0,0,0,5, "\\",O_ABORT, "?",O_HELP, "Help",O_HELP, "^",O_BACKUP, "",O_DONE_OTHERS ); switch (rval) { case MENU_MATCH : switch (menuval) { case O_DONE_OTHERS : goto add_entry; break; case O_BACKUP : if (j == 0) { k = N_BASIC_FIELDS - 2; goto kludge; } else { j--; printf("Deleting %s\n",otherdata[j]); goto redo_other; } break; case O_ABORT : return; break; case O_HELP : cathelpfile(libdir("otherformathelp"),"user-item format",1); any_char_to_continue(); goto redo_other; } break; case MENU_NO_MATCH : if (0 == index(response,':')) { printf("No field name provided -- separate with a ':'.\n"); goto redo_other; } otherdata[j] = copystr(response); break; case MENU_EOF : user_eof(); break; case MENU_AMBIGUOUS : case MENU_ERROR : default : fprintf(stderr,"Impossible rval from add_other menu_match\n"); save_and_exit(-1); } } } add_entry : basicdata[N_BASIC_FIELDS - 1] = timestring(); rlink = create_entry(basicdata,otherdata); clear_the_screen(); display_entry(get_entry(rlink)); if (add_the_entry()) { printf ( "Adding entry for %s to rolodex\n", get_basic_rolo_field((int) R_NAME,get_entry(rlink)) ); rolo_insert(rlink,compare_links); changed = 1; sleep(2); } else { return; } } entry_action (rlink) Ptr_Rolo_List rlink; { static entry_menu_displayed = 0; int rval,menuval; char *response; if (!entry_menu_displayed) cathelpfile(libdir("entrymenu"),0,0); entry_menu_displayed = 1; redo : rval = menu_match ( &menuval, &response, "Action (? for help) : ", 0,1,1,1,7, "\\",E_ABORT, "?",E_HELP, "",E_CONTINUE, "-",E_DELETE, "+",E_UPDATE, "<",E_PREV, "%",E_SCAN ); if (rval != MENU_MATCH) { if (rval == MENU_EOF) user_eof(); fprintf(stderr,"Impossible return from entry_action menu_match\n"); save_and_exit(-1); } switch (menuval) { case E_ABORT : case E_CONTINUE : case E_PREV : break; case E_SCAN : rolo_peruse_mode(get_next_link(rlink)); break; case E_UPDATE : rolo_update_mode(rlink); break; case E_DELETE : rolo_delete(rlink); printf("Entry deleted\n"); sleep(1); changed = 1; break; case E_HELP : cathelpfile ( libdir(in_search_mode ? "esearchhelp" : "escanhelp"), "entry actions", 1 ); any_char_to_continue(); clear_the_screen(); display_entry(get_entry(rlink)); goto redo; break; default : fprintf(stderr,"Impossible menuval in entry_action\n"); save_and_exit(-1); } return(menuval); } display_list_of_entries (rlist) Ptr_Rolo_List rlist; { Ptr_Rolo_List old; while (rlist != 0) { if (!get_matched(rlist)) goto next; loop : display_entry(get_entry(rlist)); switch (entry_action(rlist)) { case E_CONTINUE : break; case E_ABORT : return; break; case E_PREV : old = rlist; find_prev_match : if (get_prev_link(rlist) == 0) { rlist = old; printf("No previous entry in scan list\n"); sleep(2); } else { rlist = get_prev_link(rlist); if (!get_matched(rlist)) goto find_prev_match; } goto loop; break; default : printf("Displaying next entry in scan list...\n"); sleep(1); break; } next : rlist = get_next_link(rlist); } printf("No further entries to scan...\n"); sleep(2); } rolo_peruse_mode (first_rlink) Ptr_Rolo_List first_rlink; { int rval; Ptr_Rolo_List rlist = first_rlink; if (0 == Begin_Rlist) { fprintf(stderr,"No further entries in rolodex...\n"); sleep(2); return; } while (rlist != 0) { set_matched(rlist); rlist = get_next_link(rlist); } display_list_of_entries(first_rlink); rlist = first_rlink; while (rlist != 0) { unset_matched(rlist); rlist = get_next_link(rlist); } } SHAR_EOF if test 8950 -ne "`wc -c < 'operations.c'`" then echo shar: error transmitting "'operations.c'" '(should have been 8950 characters)' fi fi echo shar: extracting "'options.c'" '(6785 characters)' if test -f 'options.c' then echo shar: will not over-write existing file "'options.c'" else cat << \SHAR_EOF > 'options.c' #include #include #include #include #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "mem.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" #include "choices.h" print_short () /* print the names and phone numbers of everyone in the rolodex. */ { Ptr_Rolo_List rptr; Ptr_Rolo_Entry entry; rptr = Begin_Rlist; if (rptr == 0) { fprintf(stderr,"No entries to print out...\n"); return; } fprintf ( stdout, "\nNAME WORK PHONE HOME PHONE" ); fprintf ( stdout, "\n---- ---------- ----------\n\n\n" ); while (rptr != 0) { entry = get_entry(rptr); fprintf ( stdout, "%-25s %-25s %-25s\n", get_basic_rolo_field((int) R_NAME,entry), get_basic_rolo_field((int) R_WORK_PHONE,entry), get_basic_rolo_field((int) R_HOME_PHONE,entry) ); rptr = get_next_link(rptr); } } person_match (person,entry) char *person; Ptr_Rolo_Entry entry; /* Match against a rolodex entry's Name and Company fields. */ /* Thus if I say 'rolo CCA' I will find people who work at CCA. */ /* This is good because sometimes you will forget a name but remember */ /* the company the person works for. */ { char *name, *company; int len; len = strlen(person); name = get_basic_rolo_field((int) R_NAME,entry); company = get_basic_rolo_field((int) R_COMPANY,entry); if (strncsearch(name,strlen(name),person,len)) return(1); if (strncsearch(company,strlen(company),person,len)) return(1); return(0); } int find_all_person_matches (person) char *person; { Ptr_Rolo_List rptr = Begin_Rlist; int count = 0; while (rptr != 0) { unset_matched(rptr); if (person_match(person,get_entry(rptr))) { set_matched(rptr); count++; } rptr = get_next_link(rptr); } return(count); } look_for_person (person) char *person; /* search against Name and Company over the rolodex. If a match is found */ /* display the entry and give the user a choice of what to do next. */ { Ptr_Rolo_List rptr; int found = 0,result,nmatches; static displayed_menu = 0; char *response; rptr = Begin_Rlist; while (rptr != 0) { if (person_match(person,get_entry(rptr))) { clear_the_screen(); display_entry(get_entry(rptr)); if (!found) { nmatches = find_all_person_matches(person); if (nmatches > 1) { printf ( "There are %d other entries which match '%s'\n\n", nmatches - 1, person ); } } found = 1; try_again : if (!displayed_menu) cathelpfile(libdir("poptionmenu"),0,0); displayed_menu = 1; menu_match ( &result, &response, "Select option (? for help): ", 0,1,1,1,6, "Continue",P_CONTINUE, "",P_CONTINUE, "Next",P_NEXT_PERSON, "\\",P_ABORT, "Help",P_HELP, "?",P_HELP ); switch (result) { case P_CONTINUE : break; case P_NEXT_PERSON : return; break; case P_ABORT : roloexit(0); break; case P_HELP : cathelpfile(libdir("poptionshelp"),"person search options",1); goto try_again; default : fprintf(stderr,"Impossible return from menu_match\n"); exit(-1); } } rptr = get_next_link(rptr); } if (!found) { fprintf(stderr,"\nNo entry found for '%s'\n\n",person); sleep(2); } else { printf("No further matches for '%s'\n",person); sleep(2); } } print_people () { int index; char *person; index = 1; while (T) { if (0 == (person = non_option_arg(index++))) break; look_for_person(person); } } interactive_rolo () /* Top level of the iteractive rolodex. This code is just a big switch */ /* which passes responsibility off to various routines in 'operations.c' */ /* and 'update.c' */ { int result,rval,field_index; char *response,*field_name,*search_string; fprintf(stdout,"\n\nTMC ROLODEX, Version %s\n\n\n",VERSION); while (1) { cathelpfile(libdir("mainmenu"),0,0); rval = menu_match ( &result, &response, "Select option (? for help): ", 0,1,0,1,7, "+",M_ADD, "%",M_PERUSE, "\\",M_EXIT, "?",M_HELP, "*",M_SAVE, "$",M_SEARCH_BY_OTHER, "!",M_PRINT_TO_LASER_PRINTER ); switch (rval) { case MENU_AMBIGUOUS : case MENU_ERROR : fprintf(stderr,"Impossible return 1 from main menu_match\n"); exit(-1); break; case MENU_NO_MATCH : response = copystr(response); rolo_search_mode((int) R_NAME,Field_Names[(int) R_NAME],response); break; case MENU_MATCH : switch (result) { case M_ADD : rolo_add(); break; case M_SEARCH_BY_OTHER : if ((-1 == select_field_to_search_by(&field_index,&field_name)) || (0 == (search_string = select_search_string()))) { break; } rolo_search_mode(field_index,field_name,search_string); break; case M_PRINT_TO_LASER_PRINTER : fprintf(stderr,"Not implemented\n"); sleep(1); break; case M_PERUSE : rolo_peruse_mode(Begin_Rlist); break; case M_EXIT : save_and_exit(0); break; case M_SAVE : if (changed) { save_to_disk(); sleep(1); } else { printf("No changes to be saved...\n"); sleep(2); } break; case M_HELP : cathelpfile(libdir("moptionhelp"),"top level menu",1); any_char_to_continue(); break; default : fprintf(stderr,"Impossible result from menu_match...\n"); save_and_exit(-1); } break; case MENU_EOF : user_eof(); break; default : fprintf(stderr,"Impossible return 2 from menu_match\n"); save_and_exit(-1); } clear_the_screen(); } } SHAR_EOF if test 6785 -ne "`wc -c < 'options.c'`" then echo shar: error transmitting "'options.c'" '(should have been 6785 characters)' fi fi echo shar: extracting "'rlist.c'" '(2445 characters)' if test -f 'rlist.c' then echo shar: will not over-write existing file "'rlist.c'" else cat << \SHAR_EOF > 'rlist.c' #include "datadef.h" int rlength (rlist) Ptr_Rolo_List rlist; { return((rlist == 0) ? 0 : 1 + rlength(get_next_link(rlist))); } Ptr_Rolo_List new_link_with_entry () { Ptr_Rolo_List newlink; Ptr_Rolo_Entry newentry; newlink = (Ptr_Rolo_List) rolo_emalloc(sizeof(Rolo_List)); unset_matched(newlink); newentry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry)); set_n_others(newentry,0); newentry -> other_fields = 0; set_entry(newlink,newentry); return(newlink); } rolo_insert (link,compare) Ptr_Rolo_List link; int (*compare)(); { Ptr_Rolo_List rptr; if (Begin_Rlist == 0) { Begin_Rlist = link; End_Rlist = link; set_prev_link(link,0); set_next_link(link,0); return; } /* find the element it goes before, alphabetically, and insert it */ rptr = Begin_Rlist; while (rptr != 0) { if (1 == (*compare)(rptr,link)) { set_prev_link(link,get_prev_link(rptr)); set_next_link(link,rptr); if (get_prev_link(rptr) != 0) set_next_link(get_prev_link(rptr),link); else Begin_Rlist = link; set_prev_link(rptr,link); return; } rptr = get_next_link(rptr); } /* it goes at the end */ set_next_link(End_Rlist,link); set_prev_link(link,End_Rlist); set_next_link(link,0); End_Rlist = link; return; } rolo_delete (link) Ptr_Rolo_List link; { if (get_next_link(link) == 0 && get_prev_link(link) == 0) { Begin_Rlist = 0; End_Rlist = 0; return; } if (get_prev_link(link) == 0) { Begin_Rlist = get_next_link(link); set_prev_link(Begin_Rlist,0); return; } if (get_next_link(link) == 0) { End_Rlist = get_prev_link(link); set_next_link(End_Rlist,0); return; } set_next_link(get_prev_link(link),get_next_link(link)); set_prev_link(get_next_link(link),get_prev_link(link)); return; } compare_links (l1,l2) Ptr_Rolo_List l1,l2; { Ptr_Rolo_Entry e1,e2; char *n1,*n2; e1 = get_entry(l1); e2 = get_entry(l2); n1 = get_basic_rolo_field((int) R_NAME,e1); n2 = get_basic_rolo_field((int) R_NAME,e2); return(nocase_compare(n1,strlen(n1),n2,strlen(n2))); } rolo_reorder () { Ptr_Rolo_List rptr,oldlink; rptr = Begin_Rlist; Begin_Rlist = 0; while (rptr != 0) { oldlink = get_next_link(rptr); rolo_insert(rptr,compare_links); rptr = oldlink; } } SHAR_EOF if test 2445 -ne "`wc -c < 'rlist.c'`" then echo shar: error transmitting "'rlist.c'" '(should have been 2445 characters)' fi fi echo shar: extracting "'rolo.c'" '(8738 characters)' if test -f 'rolo.c' then echo shar: will not over-write existing file "'rolo.c'" else cat << \SHAR_EOF > 'rolo.c' #include #include #include #include #include #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "mem.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" static char rolodir[DIRPATHLEN]; /* directory where rolo data is */ static char filebuf[DIRPATHLEN]; /* stores result of homedir() */ int changed = 0; int reorder_file = 0; int rololocked = 0; int in_search_mode = 0; char *rolo_emalloc (size) int size; /* error handling memory allocator */ { char *rval; if (0 == (rval = malloc(size))) { fprintf(stderr,"Fatal error: out of memory\n"); save_and_exit(-1); } return(rval); } char *copystr (s) char *s; /* memory allocating string copy routine */ { char *copy; if (s == 0) return(0); copy = rolo_emalloc(strlen(s) + 1); strcpy(copy,s); return(copy); } char *timestring () /* returns a string timestamp */ { char *s; long timeval; time(&timeval); s = ctime(&timeval); s[strlen(s) - 1] = '\0'; return(copystr(s)); } user_interrupt () /* if the user hits C-C (we assume he does it deliberately) */ { unlink(homedir(ROLOLOCK)); fprintf(stderr,"\nAborting rolodex, no changes since last save recorded\n"); exit(-1); } user_eof () /* if the user hits C-D */ { unlink(homedir(ROLOLOCK)); fprintf(stderr,"\nUnexpected EOF on terminal. Saving rolodex and exiting\n"); save_and_exit(-1); } roloexit (rval) int rval; { if (rololocked) unlink(homedir(ROLOLOCK)); exit(rval); } save_to_disk () /* move the old rolodex to a backup, and write out the new rolodex and */ /* a copy of the new rolodex (just for safety) */ { FILE *tempfp,*copyfp; char d1[DIRPATHLEN], d2[DIRPATHLEN]; int r; tempfp = fopen(homedir(ROLOTEMP),"w"); copyfp = fopen(homedir(ROLOCOPY),"w"); if (tempfp == NULL || copyfp == NULL) { fprintf(stderr,"Unable to write rolodex...\n"); fprintf(stderr,"Any changes made have not been recorded\n"); roloexit(-1); } write_rolo(tempfp,copyfp); fclose(tempfp); fclose(copyfp); if (rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) || rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) { fprintf(stderr,"Rename failed. Revised rolodex is in %s\n",ROLOCOPY); roloexit(-1); } printf("Rolodex saved\n"); sleep(1); changed = 0; } save_and_exit (rval) int rval; { if (changed) save_to_disk(); roloexit(rval); } extern struct passwd *getpwnam(); char *home_directory (name) char *name; { struct passwd *pwentry; if (0 == (pwentry = getpwnam(name))) return(""); return(pwentry -> pw_dir); } char *homedir (filename) char *filename; /* e.g., given "rolodex.dat", create "/u/massar/rolodex.dat" */ /* rolodir generally the user's home directory but could be someone else's */ /* home directory if the -u option is used. */ { nbuffconcat(filebuf,3,rolodir,"/",filename); return(filebuf); } char *libdir (filename) char *filename; /* return a full pathname into the rolodex library directory */ /* the string must be copied if it is to be saved! */ { nbuffconcat(filebuf,3,ROLOLIB,"/",filename); return(filebuf); } rolo_only_to_read () { return(option_present(SUMMARYFLAG) || n_non_option_args() > 0); } locked_action () { if (option_present(OTHERUSERFLAG)) { fprintf(stderr,"Someone else is modifying that rolodex, sorry\n"); exit(-1); } else { cathelpfile(libdir("lockinfo"),"locked rolodex",0); exit(-1); } } main (argc,argv) int argc; char *argv[]; { int fd,in_use,read_only,rolofd; Bool not_own_rolodex; char *user; FILE *tempfp; clearinit(); clear_the_screen(); /* parse the options and arguments, if any */ switch (get_args(argc,argv,T,T)) { case ARG_ERROR : roloexit(-1); case NO_ARGS : break; case ARGS_PRESENT : if (ALL_LEGAL != legal_options(LEGAL_OPTIONS)) { fprintf(stderr,"illegal option\nusage: %s\n",USAGE); roloexit(-1); } } /* find the directory in which the rolodex file we want to use is */ not_own_rolodex = option_present(OTHERUSERFLAG); if (not_own_rolodex) { if (NIL == (user = option_arg(OTHERUSERFLAG,1)) || n_option_args(OTHERUSERFLAG) != 1) { fprintf(stderr,"Illegal syntax using -u option\nusage: %s\n",USAGE); roloexit(-1); } } else { if (0 == (user = getenv("HOME"))) { fprintf(stderr,"Cant find your home directory, no HOME\n"); roloexit(-1); } } if (not_own_rolodex) { strcpy(rolodir,home_directory(user)); if (*rolodir == '\0') { fprintf(stderr,"No user %s is known to the system\n",user); roloexit(-1); } } else strcpy(rolodir,user); /* is the rolodex readable? */ if (0 != access(homedir(ROLODATA),R_OK)) { /* No. if it exists and we cant read it, that's an error */ if (0 == access(homedir(ROLODATA),F_OK)) { fprintf(stderr,"Cant access rolodex data file to read\n"); roloexit(-1); } /* if it doesn't exist, should we create one? */ if (option_present(OTHERUSERFLAG)) { fprintf(stderr,"No rolodex file belonging to %s found\n",user); roloexit(-1); } /* try to create it */ if (-1 == (fd = creat(homedir(ROLODATA),0644))) { fprintf(stderr,"couldnt create rolodex in your home directory\n"); roloexit(-1); } else { close(fd); fprintf(stderr,"Creating empty rolodex...\n"); } } /* see if someone else is using it */ in_use = (0 == access(homedir(ROLOLOCK),F_OK)); /* are we going to access the rolodex only for reading? */ if (!(read_only = rolo_only_to_read())) { /* No. Make sure no one else has it locked. */ if (in_use) { locked_action(); } /* create a lock file. Catch interrupts so that we can remove */ /* the lock file if the user decides to abort */ if (!option_present(NOLOCKFLAG)) { if ((fd = open(homedir(ROLOLOCK),O_EXCL|O_CREAT,00200|00400)) < 0) { fprintf(stderr,"unable to create lock file...\n"); exit(1); } rololocked = 1; close(fd); signal(SIGINT,user_interrupt); } /* open a temporary file for writing changes to make sure we can */ /* write into the directory */ /* when the rolodex is saved, the old rolodex is moved to */ /* a '~' file, the temporary is made to be the new rolodex, */ /* and a copy of the new rolodex is made */ if (NULL == (tempfp = fopen(homedir(ROLOTEMP),"w"))) { fprintf(stderr,"Can't open temporary file to write to\n"); roloexit(-1); } fclose(tempfp); } allocate_memory_chunk(CHUNKSIZE); if (NULL == (rolofd = open(homedir(ROLODATA),O_RDONLY))) { fprintf(stderr,"Can't open rolodex data file to read\n"); roloexit(-1); } /* read in the rolodex from disk */ /* It should never be out of order since it is written to disk ordered */ /* but just in case... */ if (!read_only) printf("Reading in rolodex from %s\n",homedir(ROLODATA)); read_rolodex(rolofd); close(rolofd); if (!read_only) printf("%d entries listed\n",rlength(Begin_Rlist)); if (reorder_file && !read_only) { fprintf(stderr,"Reordering rolodex...\n"); rolo_reorder(); fprintf(stderr,"Saving reordered rolodex to disk...\n"); save_to_disk(); } /* the following routines live in 'options.c' */ /* -s option. Prints a short listing of people and phone numbers to */ /* standard output */ if (option_present(SUMMARYFLAG)) { print_short(); exit(0); } /* rolo ... */ /* print out info about people whose names contain any of the arguments */ if (n_non_option_args() > 0) { print_people(); exit(0); } /* regular rolodex program */ interactive_rolo(); exit(0); } SHAR_EOF if test 8738 -ne "`wc -c < 'rolo.c'`" then echo shar: error transmitting "'rolo.c'" '(should have been 8738 characters)' fi fi echo shar: extracting "'rolodefs.h'" '(262 characters)' if test -f 'rolodefs.h' then echo shar: will not over-write existing file "'rolodefs.h'" else cat << \SHAR_EOF > 'rolodefs.h' #define VERSION "2.0" #define CHUNKSIZE 100000 /* storage size for holding data file */ #define NOLOCKFLAG 'l' #define SUMMARYFLAG 's' #define OTHERUSERFLAG 'u' #define LEGAL_OPTIONS "lsu" #define USAGE "rolo [ person1 person2 ...] [ -l -s -u user ] " SHAR_EOF if test 262 -ne "`wc -c < 'rolodefs.h'`" then echo shar: error transmitting "'rolodefs.h'" '(should have been 262 characters)' fi fi echo shar: extracting "'rolofiles.h'" '(280 characters)' if test -f 'rolofiles.h' then echo shar: will not over-write existing file "'rolofiles.h'" else cat << \SHAR_EOF > 'rolofiles.h' #define ROLOBAK ".rolodex~" #define ROLODATA ".rolodex.dat" #define ROLOPRINT "roloprint.text" #define ROLOLOCK ".rolodexdata.lock" #define ROLOTEMP ".rolotemp" #define ROLOCOPY ".rolocopy" /* This is now defined in the Makefile */ /* #define ROLOLIB "/usr/local/lib/rolo" */ SHAR_EOF if test 280 -ne "`wc -c < 'rolofiles.h'`" then echo shar: error transmitting "'rolofiles.h'" '(should have been 280 characters)' fi fi echo shar: extracting "'search.c'" '(9108 characters)' if test -f 'search.c' then echo shar: will not over-write existing file "'search.c'" else cat << \SHAR_EOF > 'search.c' #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "mem.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" #include "choices.h" char *select_search_string () /* returns 0 if user wants to quit, otherwise returns a user-provided string */ { int rval; char *response; rval = rolo_menu_data_help_or_abort ( "Enter string to search for: ", "searchstringhelp", "string to search for", &response ); switch (rval) { case MENU_ABORT : return(0); break; case MENU_DATA : return(copystr(response)); break; } } select_field_to_search_by (ptr_index,ptr_name) int *ptr_index; char **ptr_name; /* returns -1 if the user wishes to abort, otherwise returns 0. */ /* if the user wishes to search by a user-defined field, *ptr_index is OTHER */ /* and *ptr_name is the user-provided name of the field. */ { char *response; int nchoices = N_BASIC_FIELDS; int field_index,rval; redo : /* list out each basic field that the user can search by. The user is */ /* also given an option to search by a user-provided field. At the */ /* moment you cannot search by 'Date Updated' */ display_field_names(); reask : rval = rolo_menu_number_help_or_abort ( "Number of item to search by? ", 1,nchoices,&field_index ); switch (rval) { case MENU_ABORT : return(-1); break; case MENU_HELP : cathelpfile(libdir("fieldsearchhelp"),"entering search field",1); any_char_to_continue(); goto redo; break; case MENU_DATA : if (field_index != nchoices) { *ptr_index = field_index - 1; *ptr_name = copystr(Field_Names[*ptr_index]); return(0); } /* the user wants to search by a user-specified field */ else { reask2 : rval = rolo_menu_data_help_or_abort ( "Name of user-defined field? ", "userfieldhelp", "name of user field to search by", &response ); switch (rval) { case MENU_ABORT : return(-1); break; case MENU_DATA : *ptr_index = OTHER; *ptr_name = copystr(response); return(0); break; } } break; } } match_by_name_or_company (search_string,sslen) char *search_string; int sslen; { char *name,*company; Ptr_Rolo_Entry entry; Ptr_Rolo_List rlist; int count = 0; rlist = Begin_Rlist; while (rlist != 0) { entry = get_entry(rlist); name = get_basic_rolo_field((int) R_NAME,entry); company = get_basic_rolo_field((int) R_COMPANY,entry); if (strncsearch(name,strlen(name),search_string,sslen) || strncsearch(company,strlen(company),search_string,sslen)) { set_matched(rlist); count++; } } return(count); } match_link (rlink,field_index,field_name,fnlen,search_string,sslen) /* if a match is present, sets the 'matched' field in the link, and */ /* returns 1, otherwise returns 0. */ Ptr_Rolo_List rlink; int field_index; char *field_name; int fnlen; char *search_string; int sslen; { Ptr_Rolo_Entry entry; char *field; char name[100]; int j; entry = get_entry(rlink); if (field_index == OTHER) { for (j = 0; j < get_n_others(entry); j++) { field = get_other_field(j,entry); while (*field != ':') *field++; *field = '\0'; remove_excess_blanks(name,get_other_field(j,entry)); *field++ = ':'; if (0 != nocase_compare(name,strlen(name),field_name,fnlen)) { continue; } if (strncsearch(field,strlen(field),search_string,sslen)) { set_matched(rlink); return(1); } } return(0); } else { field = get_basic_rolo_field(field_index,entry); if (strncsearch(field,strlen(field),search_string,sslen)) { set_matched(rlink); return(1); } return(0); } } find_all_matches (field_index,field_name,search_string,ptr_first_match) /* mark every entry in the rolodex which matches against the search_string */ /* If the search_string is a substring of the data in the given field then */ /* that is a match. Return the number of matches. If there are any */ /* matches *ptr_first_match will contain the first matching link. */ int field_index; char *field_name, *search_string; Ptr_Rolo_List *ptr_first_match; { char buffer[100]; int fnlen,sslen; int count = 0; Ptr_Rolo_List rlist = Begin_Rlist; remove_excess_blanks(buffer,field_name); fnlen = strlen(buffer); sslen = strlen(search_string); while (rlist != 0) { unset_matched(rlist); if (match_link(rlist,field_index,buffer,fnlen,search_string,sslen)) { if (count++ == 0) *ptr_first_match = rlist; } rlist = get_next_link(rlist); } return(count); } rolo_search_mode (field_index,field_name,search_string) int field_index; char *field_name; char *search_string; { int rval,n,j,menuval,ival; char *response; Ptr_Rolo_List first_match,rmatch,rlist; /* mark every entry in the rolodex that satisfies the search criteria */ /* and return the number of items so marked. */ in_search_mode = 1; n = find_all_matches(field_index,field_name,search_string,&first_match); if (n == 0) { printf ( "No match found for search string '%s' for field '%s'\n", search_string, field_name ); sleep(2); goto rtn; } /* if the match is unique, just display the entry. */ else if (n == 1) { display_entry(get_entry(first_match)); switch (entry_action(first_match)) { case E_CONTINUE : printf("No further matches...\n"); sleep(2); break; default : break; } goto rtn; } /* if there are too many matches to itemize them on a single small */ /* screen, tell the user that there are lots of matches and suggest */ /* he specify a better search string, but give him the option of */ /* iterating through every match. */ else if (n > MAXMATCHES) { clear_the_screen(); printf("There are %d entries that match '%s' !\n",n,search_string); printf("Type 'v' to view them one by one,\n"); printf("or '\\' to abort and enter a more specific search string: "); rval = rolo_menu_data_help_or_abort ( "","manymatchhelp","many matching entries",&response ); if (rval == MENU_ABORT) goto rtn; display_list_of_entries(Begin_Rlist); goto rtn; } /* there are a small number of matching entries. List the name of each */ /* matching entry and let the user select which one he wants to view, */ /* or whether he wants to iterate through each matching entry. */ else { relist : summarize_entry_list(Begin_Rlist,search_string); cathelpfile(libdir("pickentrymenu"),0,0); rval = menu_match ( &menuval,&response, ": ", 0,1,0,1,4, "\\",S_ABORT, "?",S_HELP, "Help",S_HELP, "",S_SCAN_ONE_BY_ONE ); switch (rval) { case MENU_MATCH : switch (menuval) { case S_HELP : cathelpfile(libdir("pickentryhelp"),"selecting entry to view",1); any_char_to_continue(); goto relist; break; case S_ABORT : goto rtn; break; case S_SCAN_ONE_BY_ONE : display_list_of_entries(Begin_Rlist); goto rtn; break; } break; /* make sure the user entered a valid integer, ival */ /* if so, find the ivalth entry marked as matched in the rolodex */ /* and display it. */ case MENU_NO_MATCH : ival = str_to_pos_int(response,1,n); if (ival < 0) { printf("Not a valid number... Please try again\n"); sleep(2); goto relist; } rlist = Begin_Rlist; for (j = 0; j < ival; j++) { while (rlist != 0) { if (get_matched(rmatch = rlist)) break; rlist = get_next_link(rlist); } if (rlist != 0) rlist = get_next_link(rlist); } display_entry(get_entry(rmatch)); switch (entry_action(rmatch)) { case E_CONTINUE : case E_PREV : goto relist; break; default : goto rtn; break; } break; } } rtn : in_search_mode = 0; } SHAR_EOF if test 9108 -ne "`wc -c < 'search.c'`" then echo shar: error transmitting "'search.c'" '(should have been 9108 characters)' fi fi echo shar: extracting "'update.c'" '(6022 characters)' if test -f 'update.c' then echo shar: will not over-write existing file "'update.c'" else cat << \SHAR_EOF > 'update.c' #include #include #include "sys5.h" #ifdef TMC #include #else #include "ctools.h" #endif #include "args.h" #include "menu.h" #include "mem.h" #include "rolofiles.h" #include "rolodefs.h" #include "datadef.h" #include "choices.h" char *get_new_value () { char buffer[200]; int rval; switch (rval = getline(stdin,buffer,199)) { case AT_EOF : user_eof(); break; case TOO_MANY_CHARS : fprintf(stderr,"Line too long, truncated...\n"); sleep(1); break; default : if ('\\' == *buffer && rval == 1) return(0); break; } return(copystr(buffer)); } Ptr_Rolo_Entry copy_entry (entry) Ptr_Rolo_Entry entry; { Ptr_Rolo_Entry new_entry; int j,n; char **otherfields; new_entry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry)); /* copy the basic fields, but get a new timestamp */ for (j = 0; j < N_BASIC_FIELDS - 1; j++) { set_basic_rolo_field(j,new_entry,copystr(get_basic_rolo_field(j,entry))); } set_basic_rolo_field(N_BASIC_FIELDS - 1,new_entry,timestring()); /* copy the user-defined fields, if necessary */ set_n_others(new_entry,n = get_n_others(entry)); if (n > 0) { otherfields = (char **) rolo_emalloc(n * sizeof(char *)); new_entry -> other_fields = otherfields; for (j = 0; j < n; j++) { set_other_field(j,new_entry,copystr(get_other_field(j,entry))); } } else new_entry -> other_fields = 0; return(new_entry); } rolo_update_mode (rlink) Ptr_Rolo_List rlink; /* Update the fields of an entry. The user is not allowed to modify the */ /* timestamp field. */ { int rval,menuval,findex,updated,newlen,n,nfields,j,name_changed; char *response,*s,*newfield,*newval,*other, **others; Ptr_Rolo_Entry entry,old_entry; cancel_update : entry = copy_entry(old_entry = get_entry(rlink)); updated = 0; name_changed = 0; redisplay : display_entry_for_update(updated ? entry : old_entry); nfields = (N_BASIC_FIELDS - 1) + get_n_others(entry); reask : cathelpfile(libdir("updatemenu"),0,0); rval = menu_match ( &menuval,&response, ": ", 0,1,0,1,4, "\\",U_ABORT, "?",U_HELP, "Help",U_HELP, "",U_END_UPDATE ); switch (rval) { case MENU_MATCH : switch (menuval) { case U_HELP : cathelpfile(libdir("updatehelp"),"updating",1); any_char_to_continue(); clear_the_screen(); goto redisplay; case U_ABORT : if (updated) { printf("Previous updates to fields in this entry ignored\n"); } return; break; case U_END_UPDATE : if (!updated) goto reask; display_entry(entry); if (MENU_YES == rolo_menu_yes_no ( "Confirm Update? ",DEFAULT_YES,1, "confirmhelp","confirming update" )) { printf("Update confirmed\n"); sleep(1); set_entry(rlink,entry); if (name_changed) { rolo_delete(rlink); rolo_insert(rlink,compare_links); } changed = 1; return; } else { printf("Updates ignored...\n"); sleep(1); updated = 0; goto cancel_update; } break; } break; case MENU_NO_MATCH : /* check that the response is an integer within range */ findex = str_to_pos_int(response,1,nfields+1); if (findex < 0) { printf("Not a valid number...Please try again\n"); goto reask; } findex--; /* we can either be updating a standard field or a user-defined field */ /* or adding a new field */ if (findex < N_BASIC_FIELDS - 1) { name_changed = (findex == 0); printf("Updating '%s'\n",Field_Names[findex]); printf("Old value: %s\n",get_basic_rolo_field(findex,entry)); printf("New value: "); if (0 == (newval = copystr(get_new_value()))) break; set_basic_rolo_field(findex,entry,newval); updated = 1; } else if (findex != nfields) { findex -= N_BASIC_FIELDS - 1; printf("Updating \'"); s = other = get_other_field(findex,entry); while (*s != ':') putc(*s++,stdout); printf("\' field\n"); printf("Old value: %s\n",++s); printf("New value: "); if (0 == (newval = copystr(get_new_value()))) break; if (strlen(newval) == 0) { for (j = findex; j < get_n_others(entry); j++) { set_other_field(j,entry,get_other_field(j+1,entry)); } set_n_others(entry,get_n_others(entry) - 1); } else { *s = '\0'; newlen = strlen(other) + strlen(newval) + 2; newfield = rolo_emalloc(newlen); nbuffconcat(newfield,3,other," ",newval); set_other_field(findex,entry,newfield); } updated = 1; } else { loop: printf("New field (: ): "); if (0 == (newfield = copystr(get_new_value()))) break; if (0 == index(newfield,':')) { fprintf(stderr,"No field name. Use a ':'...\n"); goto loop; } n = get_n_others(entry); set_n_others(entry,n + 1); others = (char **) rolo_emalloc((n + 1) * sizeof(char *)); for (j = 0; j < n; j++) others[j] = get_other_field(j,entry); others[n] = newfield; entry -> other_fields = others; updated = 1; } break; case MENU_EOF : user_eof(); break; default : fprintf(stderr,"Impossible return from update menu_match\n"); save_and_exit(-1); break; } goto redisplay; } SHAR_EOF if test 6022 -ne "`wc -c < 'update.c'`" then echo shar: error transmitting "'update.c'" '(should have been 6022 characters)' fi fi exit 0 # End of shell archive