/************************************************************************/ /* Copyright 1992 by the trustees of Dartmouth College */ /* All rights reserved. */ /* */ /* Permission to use, copy, modify and distribute these programs and */ /* their documentation for any purpose and without fee is hereby */ /* granted, provided that this copyright notice and permission ap- */ /* pear on all copies and supporting documentation. The name of the */ /* Trustees of Dartmouth College may not be used in advertising or */ /* publicity relating to distribution of these programs without */ /* specific prior permission. Neither the Trustees of Dartmouth */ /* College nor the author make representations about the suitability */ /* of this software for any purpose. It is provided "as is" without */ /* expressed or implied warranty. */ /************************************************************************/ #ifndef LIST_NAME #define LIST_NAME "/usr/local/doc/list-of-lists" /* Lists file */ #endif #ifndef SQUARE #define SQUARE '_'+128 /* Border (used with box() ) */ #endif #ifndef BATCH_SUB /* * BZS - add another field for sender's mail address */ #define BATCH_SUB "sllsub %s %s %s %s" #define BATCH_USUB "sllusub %s %s %s" #endif /* Check for MS-DOS compiler */ #ifdef __TURBOC__ #define MSDOS #endif #ifdef __MSDOS__ #define MSDOS #endif #ifdef MSDOS #undef LIST_NAME #undef SQUARE #undef BATCH #define LIST_NAME "sll.dat" #define SQUARE 219 #define BATCH #endif /************************************************************************/ /* sll.c */ /* Search the List of lists. */ /* Version 1.1 */ /* Written by Preston Crow */ /* Dartmouth College */ /* */ /* Send maintenence suggestions to: Lists@Dartmouth.Edu */ /* */ /* Note: You will want to change the LIST_NAME constant to the */ /* absolute pathname of the file containing the lists data. This file */ /* must be globally readable. Also, SQUARE may need to be changed for */ /* some implementations of the curses package. The +128 is assumed to */ /* trigger the inverse-video attribute, but this doesn't always seem to */ /* hold true. That is why the default is an underline, not a space */ /* followed by the +128. */ /* */ /* Every effort has been made to make the code as portable as possible */ /* to any Unix system with a curses package, and to allow the code to */ /* compile with a minimum of warnings. Do to errors in some C */ /* packages, sprintf()'s return value is not used. */ /* If you have improvements that will enhance portability, please */ /* E-mail your suggestions to the maintenence address listed above. */ /* */ /* Compile with the command line: */ /* cc sll.c -lcurses -ltermcap */ /* You may use gcc instead of cc or add options for optimization, */ /* warnings, and output name (a.out is the defualt). */ /* */ /* You will see a lot of references to MS-DOS. This is because the */ /* program has been ported to that platform using PCCurses. The */ /* PC version is distributed separately in executable form, but it is */ /* simpler to only have to maintain one set of source files. */ /************************************************************************/ /************************************************************************/ /* Compiler-dependencies. */ /* ANSI should be defined if ANSI-style function headers and prototypes */ /* are allowed. */ /************************************************************************/ #ifdef __STDC__ #define ANSI #endif #ifdef _ANSI_ #define ANSI #endif #ifdef __ANSI__ #define ANSI #endif #ifdef MSDOS #define ANSI #endif /************************************************************************/ /* Include Files */ /************************************************************************/ #include #include #include /* some systems use this as well as */ #include #include #include /* should include this but doesn't always */ #ifndef MSDOS #include #include /* some systems prefer this to */ #endif #ifdef __TURBOC__ #include /* mktemp() function */ #endif #ifndef MSDOS /* * BZS - to get correct host name when running an operating system */ #include #include #include #endif /************************************************************************/ /* Macros used to distinguish between the Unix and MS-DOS versions. */ /************************************************************************/ #ifdef SWEARS #define MAXX maxx /* Swears implements the structure wrong */ #define MAXY maxy #define CURX curx #define CURY cury #else #define MAXX _maxx #define MAXY _maxy #define CURX _curx #define CURY _cury #endif #ifdef MSDOS /* This may be needed for some Unix systems, as well */ #define index(a,b) strchr(a,b) #define rindex(a,b) strrchr(a,b) #endif /************************************************************************/ /* Function prototypes missing in header files on some systems. */ /* Leave them commented out unless you receive implicit declaration */ /* warnings. (I like to be able to compile with no warnings.) */ /************************************************************************/ /******* #ifdef ANSI char *index(char *s,char c); char *rindex(char *s,char c); char *sprintf(char *s,char *format,...); int printf(char *format,...); int fprintf(FILE *stream,char *format,...); int fputs(char *s,FILE *stream); int toupper(int c); char *mktemp(char *template); int unlink(char *path); int fseek(FILE *stream,long offset,int from); int fclose(FILE *stream); int stty(int fd,struct sgttyb *buf); #else extern char *index(),*rindex(),*sprintf(),*mktemp(); extern int printf(),fprintf(),fputs(),toupper(),unlink(),fseek(),fclose(),stty(); #endif char *getlogin(); int mvcur(); int endwin(); int wclear(); int wstandout(); int box(); int wstandend(); int wmove(); int waddstr(); int wrefresh(); int wgetch(); int touchwin(); int delwin(); int werase(); int waddch(); *********/ /************************************************************************/ /* Constants/Macros */ /************************************************************************/ #define MAX_SIZE 2000 /* Maximum record size in list file (exaggerated) */ #ifdef MSDOS #define TMP_FILE ".\\~sllXXXXXX" #else #define TMP_FILE "/tmp/pfcXXXXXX" /* Search results temp. file */ #endif #define MAX_SUB 20 /* Maximum number of lists you can subscribe to at once */ /************************************************************************/ /* Function Prototypes */ /* ANSI versions are first, followed my old style prototypes. */ /************************************************************************/ #ifdef ANSI /* Primary functions */ void intro_test(char *fname); void intro(void); void begin(char *lists,char *tmpfile); int selection(void); int search(char *inname,char *outname); int browse(char *inname,int maxn); void display(char *fields[],int n,int maxn,char mark); void fdisplay(FILE *file,char *fields[]); /* Auxiliary functions */ char *strupr(char *str); void center(WINDOW *win,int y,char *str); void wwaddstr(WINDOW *win,char *str); int wgetstrn(WINDOW *win,char *str,int n); char *catstring(char c); void die(void); void errwin(char *line1,char *line2); int imax(int x,int y); #else void intro_test(); void intro(); void begin(); int selection(); int search(); int browse(); void display(); void fdisplay(); char *strupr(); void center(); void wwaddstr(); int wgetsrtn(); char *catstring(); void die(); void errwin(); int imax(); #endif /************************************************************************/ /* Global variables */ /************************************************************************/ char c='.'; /* category selected */ char t[255]; /* key words in title */ char d[255]; /* key words in description */ /************************************************************************/ /* main() */ /************************************************************************/ #ifdef ANSI int main(int argc,char *argv[]) #else int main(argc,argv) int argc; char *argv[]; #endif { char tmpfile[30]; /* results of the search */ char lists[80]; /* lists file name */ strcpy(lists,LIST_NAME); if (argc>2) { printf("Too many arguments\n"); exit(1); } if (argc==2) strcpy(lists,argv[1]); intro_test(lists); /* Reality checks */ signal(SIGINT,(void(*)())die); /* Typecast avoids warnings */ initscr(); crmode(); /* cbreak() in newer versions */ intro(); begin(lists,tmpfile); mvcur(0,COLS-1,LINES-1,0); endwin(); #ifdef MSDOS system("cls"); /* Restore screen since the curses messes things up */ #endif return(0); /* Indicate normal exit */ } /************************************************************************/ /* intro_test() */ /* Function to make sure things are reasonable before starting curses. */ /* Specifically: */ /* The data file must exist. */ /* The first line must contain at least 7 fields. */ /* The first line must be less than 2000 characters. */ /************************************************************************/ #ifdef ANSI void intro_test(char *fname) #else void intro_test(fname) char *fname; #endif { FILE *in; char line[2000]; int i; char *place; in=fopen(fname,"r"); if (in==NULL) { /* File existence */ fprintf(stderr,"Unable to open the lists data file: %s\n",fname); fprintf(stderr,"Perhaps you should specify a different file on the command line.\n"); exit(1); } fgets(line,sizeof(line),in); if (strlen(line)==sizeof(line)-1) { /* Record size */ fprintf(stderr,"The data file specified (%s) is of the wrong format.\n",fname); fprintf(stderr,"Perhaps you should specify a different file on the command line.\n"); exit(1); } if (line[0] != '\t' || line[2] != '\t') { /* Field structure */ fprintf(stderr,"The data file specified (%s) is of the wrong format.\n",fname); fprintf(stderr,"Perhaps you should specify a different file on the command line.\n"); exit(1); } place=line+3; /* skip over first 2 tabs that we already checked */ for(i=0;i<5;++i) { /* Verify 5+2 fields */ place=index(place,'\t'); if (place==NULL) { fprintf(stderr,"The data file specified (%s) is of the wrong format.\n",fname); fprintf(stderr,"Perhaps you should specify a different file on the command line.\n"); exit(1); } ++place; } fclose(in); } /************************************************************************/ /* intro() */ /* Display introductory information. */ /************************************************************************/ void intro() { clear(); /* Start with blank screen */ standout(); box(stdscr,SQUARE,SQUARE); standend(); move( 2, 2); addstr("SLL: Search the List of Lists"); move( 3, 2); addstr("Version 1.1 Release 1 October 92"); move( 4, 2); addstr("Written by Preston Crow, Dartmouth College"); move( 5, 2); addstr("Report bugs/comments to: Lists@Dartmouth.Edu"); move( 7, 3); addstr("This program will allow you to conveniently search through the list"); move( 8, 3); addstr("of hundreds of mailing lists and subscribe to ones that interest you."); move(10, 5); addstr("Copyright 1992 by the Trustees of Dartmouth College"); move(11, 5); addstr("All rights reserved."); move(12, 5); addstr("Permission to use, copy, modify and distribute these programs and"); move(13, 5); addstr("their documentation for any purpose and without fee is hereby"); move(14, 5); addstr("granted, provided that this copyright notice and permission ap-"); move(15, 5); addstr("pear on all copies and supporting documentation. The name of the"); move(16, 5); addstr("Trustees of Dartmouth College may not be used in advertising or"); move(17, 5); addstr("publicity relating to distribution of these programs without"); move(18, 5); addstr("specific prior permission. Neither the Trustees of Dartmouth"); move(19, 5); addstr("College nor the author make representations about the suitability"); move(20, 5); addstr("of this software for any purpose. It is provided \"as is\" without"); move(21, 5); addstr("expressed or implied warranty."); center(stdscr,LINES-2,"Press any key to begin"); refresh(); noecho(); getch(); echo(); } /************************************************************************/ /* begin() */ /* Begin the search process--let the user make a selection, display the */ /* results, if any, and repeat. */ /************************************************************************/ #ifdef ANSI void begin(char *lists,char *tmpfile) #else void begin(lists,tmpfile) char *lists; char *tmpfile; #endif { int found; /* Number of lists found */ while (selection()) { strcpy(tmpfile,TMP_FILE); mktemp(tmpfile); found=search(lists,tmpfile); if (found) { if(!browse(tmpfile,found)) break; /* returns 0 to Quit */ } else { errwin("ERROR: No matches","Try another search"); } unlink(tmpfile); } unlink(tmpfile); } /************************************************************************/ /* selection() */ /* Enter information to narrow down the search. */ /* Builds an expression for grep to use in finding the desired lists. */ /************************************************************************/ int selection() { char cin; /* character input */ int y; /* temporary vertical position */ int field; /* field currently accepting input */ int retvalue=1; /* value to return, zero indicates exit */ WINDOW *cat; /* category input window */ WINDOW *title; /* title input window */ WINDOW *desc; /* description input window */ WINDOW *menu; /* category help window */ WINDOW *inwin; /* stdscr without border */ WINDOW *bmenu; /* menu window with border */ WINDOW *hmenu; /* menu window hidden */ WINDOW *thelp; /* title help window */ WINDOW *thelph; /* title help hidden */ /* Clear previous selection */ c='.'; *d=0; *t=0; /* Set up the display */ clear(); standout(); box(stdscr,SQUARE,SQUARE); standend(); inwin=subwin(stdscr,LINES-2,COLS-2,2,2); center(stdscr,2,"Search Criteria"); center(stdscr,LINES-3,"TAB between fields, ENTER to perform search"); /* Category selection display */ y=LINES/3-2; /* location of category window */ move(y-1,3); addstr("Category:"); cat=subwin(inwin,1,20,y,5); wstandout(cat); wmove(cat,0,0); waddstr(cat,"All"); /* Category help menu */ bmenu=newwin(12,38,y-2,30); hmenu=newwin(12,38,y-2,30); wclear(hmenu); wclear(bmenu); menu=subwin(bmenu,10,35,y-1,31); wstandout(bmenu); box(bmenu,SQUARE,SQUARE); wstandend(bmenu); center(menu,0,"Valid choices:"); center(menu,1,"Academia "); center(menu,2,"Computing "); center(menu,3,"Humanities"); center(menu,4,"Personal "); center(menu,5,"Sciences "); wmove(menu,7,0); waddstr(menu," Enter the first letter of a choice"); wmove(menu,8,0); waddstr(menu," or press space for all categories"); center(menu,9,"Select Q to quit"); /* Title selection display */ y*=2; /* location of the title search window */ move(y-1,3); addstr("Title:"); title=subwin(inwin,1,0,y,5); wstandout(title); /* Title help window */ thelp=newwin(5,36,y-5,40); thelph=newwin(5,36,y-5,40); wclear(thelp); wclear(thelph); wstandout(thelp); box(thelp,SQUARE,SQUARE); wstandend(thelp); wmove(thelp,1,1); waddstr(thelp,"For a list to be selected, it must"); wmove(thelp,2,1); waddstr(thelp,"contain exactly what you enter."); wmove(thelp,3,1); waddstr(thelp,"(Case is ignored)"); /* Description selection display */ y=y/2*3; move(y-1,3); addstr("Description:"); desc=subwin(inwin,1,0,y,5); wstandout(desc); refresh(); *d = *t = 0; /* Now find out what the user wants */ field=1; while (field) { switch (field) { case 1: touchwin(bmenu); touchwin(hmenu); wrefresh(bmenu); wmove(cat,0,0); wrefresh(cat); /* move physical cursor into position */ noecho(); cin=getch(); echo(); if (cin>'Z') cin-= ('z'-'Z'); /* Upper case */ switch (cin) { case ' ': cin='.'; /* Change to . to signify any */ case 'A': case 'C': case 'H': case 'P': case 'S': c=cin; waddstr(cat,catstring(c)); wstandend(cat); waddstr(cat," "); wstandout(cat); case '\t': /* Next field */ ++field; break; case '\n': /* Perform search */ field=0; break; case 'Q': retvalue=0; field=0; break; } wrefresh(cat); wrefresh(hmenu); break; case 2: touchwin(thelp); wrefresh(thelp); wmove(title,0,0); wrefresh(title); ++field; if(wgetstrn(title,t,sizeof(t))) field=0; touchwin(thelph); wrefresh(thelph); break; case 3: touchwin(thelp); wrefresh(thelp); wmove(desc,0,0); wrefresh(desc); field=1; if (wgetstrn(desc,d,sizeof(d))) field=0; touchwin(thelph); wrefresh(thelph); break; } } delwin(inwin); delwin(menu); delwin(desc); delwin(title); delwin(cat); delwin(hmenu); delwin(bmenu); delwin(thelp); delwin(thelph); return(retvalue); } /************************************************************************/ /* search() */ /* Searches the specified file for matches according to the global */ /* search criteria variables. Saves matching records in another file. */ /************************************************************************/ #ifdef ANSI int search(char *inname,char *outname) #else int search(inname,outname) char *inname; char *outname; #endif { FILE *in,*out; char record[MAX_SIZE]; char fields[MAX_SIZE]; char *next_field; WINDOW *cur; WINDOW *cont; int percent,old_percent=0; int count=0, oldcount=0; long size; char temp[30]; /* for sprintf() */ char inbuf[32*BUFSIZ]; /* BZS */ char outbuf[32*BUFSIZ]; /* BZS */ in=fopen(inname,"r"); out=fopen(outname,"w"); if (in==NULL || out==NULL) { mvcur(0,COLS-1,LINES-1,0); endwin(); printf("\n\nFile I/O error\n"); if (!in) printf("Unable to open file: %s\n",inname); if (!out) printf("Unable to open file: %s\n",outname); exit(1); } setbuffer(in,inbuf,sizeof(inbuf)); /* BZS */ setbuffer(out,outbuf,sizeof(outbuf)); /* BZS */ fseek(in,0l,2); size=ftell(in); fseek(in,0l,0); /* Current status subwindow */ cur=subwin(stdscr,5,22,LINES/2-3,COLS/2-11); wstandout(cur); box(cur,SQUARE,SQUARE); wstandend(cur); center(cur,1,"Searching..."); center(cur,2,"0% complete"); center(cur,3,"0 matches found"); wrefresh(cur); /* Continue window */ cont=newwin(5,40,LINES/2+1,COLS/2-20); wstandout(cont); box(cont,SQUARE,SQUARE); wstandend(cont); center(cont,1,"100 matches found"); center(cont,2,"Press Y to continue searching or"); center(cont,3,"any other key to abort."); strupr(d); strupr(t); fgets(record,MAX_SIZE-1,in); while (!feof(in)) { if (c=='.' || c==record[1]) { next_field=index(record+3,'\t')+1; next_field=index(next_field,'\t')+1; next_field=index(next_field,'\t')+1; strupr(strcpy(fields,next_field)); *index(fields,'\t')=0; /* Just the title */ if (strstr(fields,t)) { next_field=rindex(next_field,'\t')+1; if (strstr(next_field,d)) { fputs(record,out); ++count; } } } percent = (int)((ftell(in)*100)/size); if(percent != old_percent) { sprintf(temp,"%d%% complete",percent=(int)((ftell(in)*100)/size)); center(cur,2,temp); } if(count != oldcount) { sprintf(temp,"%d matches found",count); center(cur,3,temp); oldcount = count; } /* Only refresh a max. of 100 times--Otherwise it will */ /* be unusable on slow (e.g. 1200 baud) terminals. */ if (percent != old_percent) { wrefresh(cur); old_percent=percent; } if (count==100) { char c; wrefresh(cont); c=getch(); if (c!='y' && c!='Y') { delwin(cur); delwin(cont); fclose(out); fclose(in); return(count); } touchwin(stdscr); refresh(); } fgets(record,MAX_SIZE-1,in); } delwin(cur); delwin(cont); fclose(out); fclose(in); return(count); } /************************************************************************/ /* browse() */ /* Allow the user to browse through the lists that were found. */ /* Return non-zero unless the user selects "Quit." */ /************************************************************************/ #ifdef ANSI int browse(char *inname,int maxn) #else int browse(inname,maxn) char *inname; int maxn; #endif { FILE *in; long *pos; /* file position for each record */ char *mark; /* Which entries are marked */ int marked=0; /* Number of marked entries */ int currec=0; /* current record being displayed */ char inc; /* keyboard input */ char *lf; /* last field--used in splitting up the record into fields */ char *fields[7]; /* pointers to each field */ char record[MAX_SIZE]; int i,j; WINDOW *menu; /* What to do with marked entries */ WINDOW *file; /* Ask for a file name */ WINDOW *filesub; /* Input subwindow of file window */ WINDOW *namewin; /* Verify the user's real name for suscribing */ char temp[250]; /* for sprintf() */ char name[250]; /* Real name for suscribing to lists */ char maddr[250]; /* BZS - and address */ char path[50]; /* file to save marked entries in */ FILE *save; /* Try to figure out the user's real name from /etc/passwd */ #ifdef MSDOS *name=0; #else strcpy(name,(getpwnam(getlogin()))->pw_gecos); *index(name,',')=0; getmailaddress(maddr); #endif /* Name window */ namewin=newwin(5,40,7,15); wstandout(namewin); box(namewin,SQUARE,SQUARE); wstandend(namewin); center(namewin,1,"Please enter your real name"); #ifdef MSDOS *temp=0; #else sprintf(temp,"(Press ENTER for: %s)",name); center(namewin,2,temp); #endif /* Prepare menu window */ menu=newwin(12,30,LINES/2-5,COLS/2-15); wstandout(menu); box(menu,SQUARE,SQUARE); wstandend(menu); center(menu,1,"Marked Entries Menu"); center(menu,3,"S Subscribe "); center(menu,4,"! Un-subscribe "); center(menu,5,"F save to a File"); center(menu,6,"M Mark all "); center(menu,7,"U Unmark all "); file=newwin(4,60,LINES/2+4,COLS/2-25); filesub=subwin(file,1,48,LINES/2+4+2,COLS/2-25+1); werase(file); werase(filesub); wstandout(file); box(file,SQUARE,SQUARE); wstandend(file); wmove(file,1,2); waddstr(file,"Save marked lists in what file?"); /* Prepare to display entries */ pos=(long *)malloc(sizeof(long) * (maxn+1)); mark=(char *)malloc(sizeof(char)*maxn); for(i=0;i'Z') inc-= ('z'-'Z'); switch(inc) { case 'N': case 'P': (inc=='N')?++currec:--currec; if (currec==maxn) --currec; if (currec<0) currec=0; fseek(in,pos[currec],0); fgets(record,MAX_SIZE-1,in); strcat(record,"\t\t\t\t\t\t\t"); /* Make corrupt records acceptable */ if (*record!='\t') { move(LINES-1,0); refresh(); endwin(); printf("\n\nError reading temporary file\n"); exit(1); } pos[currec+1]=ftell(in); lf=record; for(i=0;i<7;++i) { fields[i]=index(lf,'\t')+1; *index(lf,'\t')=0; lf=fields[i]; } break; case '*': ++mark[currec]; ++marked; if (mark[currec]>1) { mark[currec]=0; marked-=2; } break; case '\n': sprintf(temp," (%d marked lists) ",marked); center(menu,menu->MAXY-2,temp); center(menu,menu->MAXY-3,"Choice: "); /* position cursor and clear previous choice */ touchwin(menu); wrefresh(menu); echo(); switch(wgetch(menu)) { case 'M': case 'm': for(i=0;iMAX_SUB) { sprintf(temp,"Error: You may only subscribe to %d lists at a time",MAX_SUB); errwin(temp,""); break; } */ touchwin(namewin); wmove(namewin,3,2); wrefresh(namewin); *temp=0; wgetstrn(namewin,temp,sizeof(name)); if (*temp) strcpy(name,temp); fseek(in,0l,0); for(i=0;i-menu"); } else { center(stdscr,LINES-2,"S-new search Q-quit P-previous N-next *-mark -menu"); } move(LINES-4,3); addstr("Owned by: "); addstr(fields[5]); /* Owner field */ move(10,3); addstr("De"); cur=subwin(stdscr,LINES-14,COLS-8,10,5); wmove(cur,0,0); waddstr(cur,"scription: "); wwaddstr(cur,fields[6]); /* Description */ touchwin(stdscr); move(LINES-1,0); refresh(); delwin(cur); } /************************************************************************/ /* fdisplay() */ /* Like display() only saved to a file. */ /************************************************************************/ #ifdef ANSI void fdisplay(FILE *file,char *fields[]) #else void fdisplay(file,fields) FILE *file; char *fields[]; #endif { if (fields[1]) fprintf(file,"Title: %s\n",fields[1]); if (fields[4]) fprintf(file," %s\n",fields[4]); fprintf(file,"\nCategory: %s\n\n",catstring(*fields[0])); if (fields[3]) fprintf(file,"Subscribe: %s\n\n",fields[3]); if (fields[2]) fprintf(file,"Post to: %s\n\n",fields[2]); if (fields[5]) fprintf(file,"Owned by: %s\n\n",fields[5]); if (fields[6]) fprintf(file,"Description: %s\n",fields[6]); fprintf(file,"\f\n"); /* Form feed */ } /************************************************************************/ /* die() */ /* Signal handler to abort the program nicely */ /************************************************************************/ void die() { signal(SIGINT, SIG_IGN); mvcur(0,COLS-1,LINES-1,0); endwin(); #ifdef MSDOS system("cls"); #endif exit(0); } /************************************************************************/ /* strupr() */ /* Convert a string to uppercase. */ /************************************************************************/ #ifndef MSDOS #ifdef ANSI char * strupr(char *str) #else char * strupr(str) char *str; #endif { register char *sp; for(sp=str; *sp; sp++) if(islower(*sp)) *sp = toupper(*sp); return(str); } #endif /************************************************************************/ /* center() */ /* Displays a string centered on the line */ /************************************************************************/ #ifdef ANSI void center(WINDOW *win,int y,char *str) #else void center(win,y,str) WINDOW *win; int y; char *str; #endif { wmove(win,y,(win->MAXX-strlen(str))/2); waddstr(win,str); } /************************************************************************/ /* wwaddstr() */ /* Word waddstr(): repeatedly calls waddstr() on single words of the */ /* string, placing newlines when the word won't fit. */ /************************************************************************/ #ifdef ANSI void wwaddstr(WINDOW *win,char *str) #else void wwaddstr(win,str) WINDOW *win; char *str; #endif { char word[81]; /* holds each word sequentially over time */ while (*str) { /* Isolate a single word */ strncpy(word,str,sizeof(word)-1)[sizeof(word)-1]=0; if (index(word,' ')) *index(word,' ')=0; str+=strlen(word); if (*str) ++str; /* skip over the space */ /* Now display the word */ if (strlen(word) >= win->MAXX) waddstr(win,word); else if (strlen(word) <= (win->MAXX - win->CURX)) waddstr(win,word); else { waddch(win,'\n'); waddstr(win,word); } if (win->CURX != 0) waddch(win,' '); } } /************************************************************************/ /* wgetstrn() */ /* Get string from a window with at most n characters. */ /* Specialized to terminate on newline or tab and does not alter */ /* the string if no new information is entered. */ /* Assumes standout is on and echo is on. */ /* Assumes current possition is the beginning of the string. */ /* Returns true if the string was terminated by . */ /************************************************************************/ #ifdef ANSI int wgetstrn(WINDOW *win,char *str,int n) #else int wgetstrn(win,str,n) WINDOW *win; char *str; int n; #endif { int i=0; /* current index into str[] */ char c; /* character read in */ int j; /* looping variable */ int x,y; /* save position */ while(1) { noecho(); x=win->CURX; y=win->CURY; switch(c=getch()) { case '\t': echo(); return(0); case '\n': echo(); return(1); case '\b': /* '^H' */ #ifndef MSDOS case 127: /* '^?' is often backspace */ #endif wstandend(win); if(i) { str[i]=0; --i; wmove(win,y,x-1); waddch(win,' '); wmove(win,y,x-1); } else { /* zap entire line */ for(j=0;j=n-1) { /* don't overflow str */ echo(); return(0); } } /* end switch */ } } /************************************************************************/ /* catstring() */ /* Returns a string describing a category. */ /************************************************************************/ #ifdef ANSI char *catstring(char c) #else char *catstring(c) char c; #endif { switch (c) { case 'A': return("Academia"); case 'C': return("Computing"); case 'H': return("Humanities"); case 'P': return("Personal"); case 'S': return("Sciences"); case '.': return("All"); default: return("Unknown"); } } /************************************************************************/ /* errwin() */ /* Displays a diagnostic message and waits for a keypress. */ /************************************************************************/ #ifdef ANSI void errwin(char *line1,char *line2) #else void errwin(line1,line2) char *line1,*line2; #endif { WINDOW *error; error=newwin(5, imax(40,imax(strlen(line1),strlen(line2))), LINES/2-6, (COLS-imax(40,imax(strlen(line1),strlen(line2))))/2 ); wstandout(error); box(error,SQUARE,SQUARE); wstandend(error); center(error,1,line1); center(error,2,line2); center(error,3,"Press any key to continue"); wrefresh(error); noecho(); getch(); echo(); delwin(error); } /************************************************************************/ /* imax() */ /* Returns the maximum of 2 integers. */ /************************************************************************/ #ifdef ANSI int imax(int x,int y) #else int imax(x,y) int x,y; #endif { return((xh_name); /* official name of host */ else strcat(p,h); /* local name */ return(1); }