rolodex database program -- part 2 of 3
sources-request at panda.UUCP
sources-request at panda.UUCP
Fri Mar 14 09:42:23 AEST 1986
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 <stdio.h>
#ifdef TERMINFO
#include <term.h>
#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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <ctype.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <stdio.h>
#include <ctype.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <stdio.h>
#include <ctype.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <name>: <data> (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 <sys/file.h>
#include <stdio.h>
#include <ctype.h>
#include <sgtty.h>
#include <sys/time.h>
#include <signal.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <sys/file.h>
#include <stdio.h>
#include <ctype.h>
#include <sgtty.h>
#include <signal.h>
#include <curses.h>
#include <pwd.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <name1> <name2> ... */
/* 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 <stdio.h>
#include <ctype.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 <stdio.h>
#include <ctype.h>
#include "sys5.h"
#ifdef TMC
#include <ctools.h>
#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 (<name>: <value>): ");
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
More information about the Mod.sources
mailing list