mikew@wyse.wyse.com (Mike Wexler) (01/10/89)
Submitted-by: jim@expo.lcs.mit.edu (Jim Fulton) Posting-number: Volume 2, Issue 81 Archive-name: x11.3/patch5 Created on Monday, 9 January 1989 PART 1 of 3 Fixes 5, 6, and 7 are part of a single update to the xman program. Together they affect the following files: clients/xman/CHANGES clients/xman/README clients/xman/ScrollByL.c clients/xman/TODO clients/xman/buttons.c clients/xman/defs.h clients/xman/globals.c clients/xman/globals.h clients/xman/handler.c clients/xman/help.c clients/xman/main.c clients/xman/man.c clients/xman/man.h clients/xman/menu.c clients/xman/misc.c clients/xman/pages.c clients/xman/search.c clients/xman/tkfuncs.c clients/xman/version.h clients/xman/xman.help clients/xman/xman.man To apply these fixes, concatenate all three files and pipe them to patch -p0 from the top of your X sources: % cat fix5 fix6 fix7 | patch -p0 The following is fix5 (you will also need fix6 and fix7): *** /tmp/,RCSt1a17149 Fri Jan 6 18:56:33 1989 --- clients/xman/buttons.c Fri Jan 6 18:41:55 1989 *************** *** 1,8 **** /* * xman - X window system manual page display program. * ! * $XConsortium: buttons.c,v 1.2 88/09/04 20:27:16 swick Exp $ ! * $oHeader: buttons.c,v 4.0 88/08/31 22:11:26 kit Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * --- 1,8 ---- /* * xman - X window system manual page display program. * ! * $XConsortium: buttons.c,v 1.3 89/01/06 18:41:51 kit Exp $ ! * $Header: buttons.c,v 1.3 89/01/06 18:41:51 kit Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * *************** *** 21,27 **** */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: buttons.c,v 4.0 88/08/31 22:11:26 kit Exp $"; #endif #include "globals.h" --- 21,27 ---- */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: buttons.c,v 4.5 88/12/19 13:46:34 kit Exp $"; #endif #include "globals.h" *************** *** 45,53 **** #define TOPARGS 5 void ! MakeTopMenuWidget(top) ! Widget top; { Widget menu; /* Top Box and menu. */ Menu topbox; /* The menu structure for this box. */ Button topbuttons[TOPBUTTONS]; /* The button structure for these buttons. */ --- 45,53 ---- #define TOPARGS 5 void ! MakeTopMenuWidget() { + Widget top; /* top box widget. */ Widget menu; /* Top Box and menu. */ Menu topbox; /* The menu structure for this box. */ Button topbuttons[TOPBUTTONS]; /* The button structure for these buttons. */ *************** *** 60,65 **** --- 60,80 ---- "Manual Page" }; + /* create the top icon. */ + + num_args = 0; + XtSetArg(arglist[num_args], XtNiconPixmap, + XCreateBitmapFromData( XtDisplay(initial_widget), + XtScreen(initial_widget)->root, + iconclosed_bits, iconclosed_width, + iconclosed_height)); + num_args++; + XtSetArg(arglist[num_args], XtNallowShellResize, TRUE); + num_args++; + + top = XtCreatePopupShell(TOPBOXNAME, topLevelShellWidgetClass, + initial_widget, arglist, num_args); + /* Set up the manual structure. */ topbox.number = TOPBUTTONS; *************** *** 73,79 **** topbox.buttons = topbuttons; topbox.callback = TopCallback; ! /* Set up the button structures, by assiging each one a name and a * width, this puts either one button on a line or two depending on * the length of the string that will go into the buttons. See Menu.c for * details. --- 88,95 ---- topbox.buttons = topbuttons; topbox.callback = TopCallback; ! /* ! * Set up the button structures, by assiging each one a name and a * width, this puts either one button on a line or two depending on * the length of the string that will go into the buttons. See Menu.c for * details. *************** *** 91,105 **** menu = MakeMenu(top,&topbox, NULL); /* Create the menu. */ XtManageChild(menu); /* Manage the menu. */ ! /* create the top icon. */ ! ! num_args = 0; ! XtSetArg(arglist[num_args], XtNiconPixmap, ! XCreateBitmapFromData( XtDisplay(top), XtScreen(top)->root, ! iconclosed_bits, iconclosed_width, ! iconclosed_height)); ! num_args++; ! XtSetValues(top,arglist,num_args); } /* Function Name: CreateManpage --- 107,115 ---- menu = MakeMenu(top,&topbox, NULL); /* Create the menu. */ XtManageChild(menu); /* Manage the menu. */ ! XtRealizeWidget(top); ! XtMapWidget(top); ! AddCursor(top, resources.cursors.top); } /* Function Name: CreateManpage *************** *** 136,142 **** /* Initialize the number of screens that will be shown */ ! man_globals->both_shown = both_shown_initial; for ( i = 0 ; i < sections ; i++) man_globals->manpagewidgets.box[i] = NULL; --- 146,152 ---- /* Initialize the number of screens that will be shown */ ! man_globals->both_shown = resources.both_shown_initial; for ( i = 0 ; i < sections ; i++) man_globals->manpagewidgets.box[i] = NULL; *************** *** 174,181 **** XtSetArg(arglist[num_args], XtNheight, default_height); num_args++; ! top = XtCreateApplicationShell(name, topLevelShellWidgetClass, ! arglist, num_args); man_globals->This_Manpage = top; /* pointer to root widget of Manualpage. */ num_args = 0; --- 184,191 ---- XtSetArg(arglist[num_args], XtNheight, default_height); num_args++; ! top = XtCreatePopupShell(name, topLevelShellWidgetClass, initial_widget, ! arglist, num_args); man_globals->This_Manpage = top; /* pointer to root widget of Manualpage. */ num_args = 0; *************** *** 215,230 **** mpw->directory = XtCreateWidget(DIRECTORY_NAME, viewportWidgetClass, pane, arglist, num_args); ! man_globals->current_directory = 1; MakeDirectoryBox(man_globals, mpw->directory, ! mpw->box + man_globals->current_directory, 1); XtManageChild(mpw->box[man_globals->current_directory]); } /* Create Manpage */ ! font_height = (fonts.normal->max_bounds.ascent + ! fonts.normal->max_bounds.descent); num_args = 0; XtSetArg(arglist[num_args], XtNallowVert, TRUE); --- 225,241 ---- mpw->directory = XtCreateWidget(DIRECTORY_NAME, viewportWidgetClass, pane, arglist, num_args); ! man_globals->current_directory = INITIAL_DIR; MakeDirectoryBox(man_globals, mpw->directory, ! mpw->box + man_globals->current_directory, ! man_globals->current_directory ); XtManageChild(mpw->box[man_globals->current_directory]); } /* Create Manpage */ ! font_height = (resources.fonts.normal->max_bounds.ascent + ! resources.fonts.normal->max_bounds.descent); num_args = 0; XtSetArg(arglist[num_args], XtNallowVert, TRUE); *************** *** 285,291 **** if (man_globals->both_shown) { XtManageChild(dir); man_globals->dir_shown = TRUE; ! XtPanedSetMinMax(dir, directory_height, directory_height); XtSetSensitive(man_globals->put_up_manpage,FALSE); XtSetSensitive(man_globals->put_up_directory,FALSE); ChangeLabel(man_globals->both_shown_button, SHOW_ONE); --- 296,303 ---- if (man_globals->both_shown) { XtManageChild(dir); man_globals->dir_shown = TRUE; ! XtPanedSetMinMax(dir, resources.directory_height, ! resources.directory_height); XtSetSensitive(man_globals->put_up_manpage,FALSE); XtSetSensitive(man_globals->put_up_directory,FALSE); ChangeLabel(man_globals->both_shown_button, SHOW_ONE); *************** *** 320,326 **** */ XtRealizeWidget( man_globals->This_Manpage ); ! AddCursor( man_globals->This_Manpage, cursors.manpage); XtPanedSetMinMax(dir, 1, 10000); } --- 332,340 ---- */ XtRealizeWidget( man_globals->This_Manpage ); ! XtMapWidget( man_globals->This_Manpage ); ! ! AddCursor( man_globals->This_Manpage, resources.cursors.manpage); XtPanedSetMinMax(dir, 1, 10000); } *************** *** 467,473 **** MakeLong((Widget) pupwidget); XtRealizeWidget(popup_shell); /* Realize it and change its cursor. */ ! AddCursor(popup_shell,cursors.top); } /* Function Name: MakeDirPopUpWidget --- 481,487 ---- MakeLong((Widget) pupwidget); XtRealizeWidget(popup_shell); /* Realize it and change its cursor. */ ! AddCursor(popup_shell,resources.cursors.top); } /* Function Name: MakeDirPopUpWidget *************** *** 494,513 **** Arg args[1]; /* The argument list. */ int i; /* A counter. */ Cardinal num_args = 0; /* The number of arguments. */ - static char * name[MAXSECT]; /*the names of of the popups */ - /* Get the names from the manual structure. */ - - for ( i = 1; i < sections; i++) - name[i - 1] = manual[i].blabel; - popup_shell = XtCreatePopupShell( SPOPUPNAME, overrideShellWidgetClass, widget, NULL, (Cardinal) 0); XtSetArg(args[num_args],XtNjustify,XtJustifyLeft); num_args++; ! popup.number = sections - 1; /* We ignore section (0) even though it is ! in the manual structure. */ popup.name = "Manual Sections"; popup.label_args = NULL; popup.label_num = (Cardinal) 0; --- 508,520 ---- Arg args[1]; /* The argument list. */ int i; /* A counter. */ Cardinal num_args = 0; /* The number of arguments. */ popup_shell = XtCreatePopupShell( SPOPUPNAME, overrideShellWidgetClass, widget, NULL, (Cardinal) 0); XtSetArg(args[num_args],XtNjustify,XtJustifyLeft); num_args++; ! popup.number = sections; popup.name = "Manual Sections"; popup.label_args = NULL; popup.label_num = (Cardinal) 0; *************** *** 518,525 **** popup.buttons = buttons; popup.callback = DirPopUpCallback; ! for ( i = 0 ; i < sections - 1; i ++) { ! buttons[i].name = name[i]; buttons[i].number_per_line = 0; } --- 525,532 ---- popup.buttons = buttons; popup.callback = DirPopUpCallback; ! for ( i = 0 ; i < sections; i ++) { ! buttons[i].name = manual[i].blabel; buttons[i].number_per_line = 0; } *************** *** 529,566 **** XtManageChild(pupwidget); (void) MakeLong(pupwidget); XtRealizeWidget(popup_shell); ! AddCursor(popup_shell,cursors.top); } /* Function Name: CreateManpageName * Description: Creates the manual page name for a given item. ! * Arguments: filename - the filename to convert. * Returns: the manual page properly allocated. */ /* ! * If the filename is foo.c - Create an entry of the form: foo ! * If the filename is foo.cX - Create an entry of the form: foo(X) */ char * ! CreateManpageName(filename) ! char * filename; { ! char * cp, temp[BUFSIZ]; ! strcpy(temp, filename); ! cp = rindex(temp, '.'); ! if (cp[2] != '\0') { ! *cp++ = '('; ! *cp++ = *(cp + 1); *cp++ = ')'; *cp = '\0'; } else *cp = '\0'; ! ! return(StrAlloc(temp)); } /* Function Name: CreateList --- 536,578 ---- XtManageChild(pupwidget); (void) MakeLong(pupwidget); XtRealizeWidget(popup_shell); ! AddCursor(popup_shell,resources.cursors.top); } /* Function Name: CreateManpageName * Description: Creates the manual page name for a given item. ! * Arguments: entry - the entry to convert. * Returns: the manual page properly allocated. */ /* ! * If the filename is foo.3 - Create an entry of the form: foo ! * If the filename is foo.3X11 ! * or foo.cX11.stuff - Create an entry of the form: foo(X11) */ char * ! CreateManpageName(entry) ! char * entry; { ! char * cp; ! char page[BUFSIZ]; ! ParseEntry(entry, NULL, NULL, page); ! ! cp = index(page, '.'); ! if ( (cp[2] != '\0') && (cp[2] != '.') ) { ! *cp++ = '('; ! while( (cp[1] != '\0') && (cp[1] != '.') ) { ! *cp = cp[1]; cp++; ! } *cp++ = ')'; *cp = '\0'; } else *cp = '\0'; ! ! return(StrAlloc(page)); } /* Function Name: CreateList *************** *** 581,587 **** for (current = ret_list, count = 0 ; count < manual[section].nentries ; count++, current++) ! *current = CreateManpageName(manual[section].entries[count].label); *current = NULL; /* NULL terminate the list. */ return(ret_list); --- 593,599 ---- for (current = ret_list, count = 0 ; count < manual[section].nentries ; count++, current++) ! *current = CreateManpageName(manual[section].entries[count]); *current = NULL; /* NULL terminate the list. */ return(ret_list); *************** *** 618,624 **** num_args++; XtSetArg(arglist[num_args], XtNborderWidth, 0); num_args++; ! XtSetArg(arglist[num_args], XtNfont, fonts.directory); num_args++; *dir_disp = XtCreateWidget(DIRECTORY_NAME, listWidgetClass, parent, --- 630,636 ---- num_args++; XtSetArg(arglist[num_args], XtNborderWidth, 0); num_args++; ! XtSetArg(arglist[num_args], XtNfont, resources.fonts.directory); num_args++; *dir_disp = XtCreateWidget(DIRECTORY_NAME, listWidgetClass, parent, *************** *** 669,675 **** arglist,num_args); XtManageChild(box); XtRealizeWidget(shell); ! AddCursor(shell,cursors.top); num_args = 0; shell = XtCreatePopupShell("likeToSave",transientShellWidgetClass, --- 681,687 ---- arglist,num_args); XtManageChild(box); XtRealizeWidget(shell); ! AddCursor(shell,resources.cursors.top); num_args = 0; shell = XtCreatePopupShell("likeToSave",transientShellWidgetClass, *************** *** 727,731 **** XtManageChild(box); XtRealizeWidget(shell); ! AddCursor(shell,cursors.top); } --- 739,743 ---- XtManageChild(box); XtRealizeWidget(shell); ! AddCursor(shell,resources.cursors.top); } *** /tmp/,RCSt1a17205 Fri Jan 6 18:56:49 1989 --- clients/xman/man.c Fri Jan 6 18:42:17 1989 *************** *** 1,7 **** /* * xman - X window system manual page display program. * ! * $XConsortium: man.c,v 1.2 88/09/06 17:48:10 jim Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * --- 1,7 ---- /* * xman - X window system manual page display program. * ! * $XConsortium: man.c,v 1.3 89/01/06 18:42:14 kit Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * *************** *** 20,49 **** */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: man.c,v 4.0 88/08/31 22:12:33 kit Exp $"; #endif #include "globals.h" - static void SetSectionNames(); - static int GetSectNumber(); - static void CheckMandesc(); - static char error_buf[BUFSIZ]; /* The buffer for error messages. */ ! /* Function Name: CmpEntryLabel - used in qsort(). ! * Description: compares to elements by using their labels. ! * Arguments: e1, e2 - two elements to compare by label. ! * Returns: an integer >, < or = 0. ! */ ! static int ! CmpEntryLabel(e1, e2) ! struct entry *e1, *e2; ! { ! return(strcmp(e1->label, e2->label)); ! } /* Function Name: Man * Description: Builds a list of all manual directories and files. * Arguments: none. --- 20,46 ---- */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: man.c,v 4.5 88/12/19 13:47:35 kit Exp $"; #endif #include "globals.h" static char error_buf[BUFSIZ]; /* The buffer for error messages. */ ! static void SortList(), ReadMandescFile(), SortAndRemove(), InitManual(); ! static void AddToCurrentSection(), AddNewSection(), AddStandardSections(); ! static int CmpEntryLabel(); ! #define SECT_ERROR -1 ! #define streq(a, b) ( strcmp((a), (b)) == 0 ) + typedef struct _SectionList { + struct _SectionList * next; /* link to next elem in list. */ + char * label, *directory; /* The label and directory that this + section represents. */ + Boolean standard; /* Is this one of the standard sections? */ + } SectionList; + /* Function Name: Man * Description: Builds a list of all manual directories and files. * Arguments: none. *************** *** 53,351 **** int Man() { ! char *man_nomatch[MAXSECT + 1]; /* allow NULL termination. */ ! char *manptr, manualdir[BUFSIZ], *local_ptr; ! int i,current[MAXSECT],nsect; ! nsect = FIXEDSECT; ! for (i = 0 ; i < MAXSECT ; i ++) { ! current[i] = 0; /* set current entries = 0. */ ! if ( (manual[i].entries = ! (struct entry *) malloc(MAXENTRY * sizeof(struct entry))) == NULL ) ! PrintError("Could not allocate memory, while building manpage list."); ! ! manual[i].blabel = "Dummy Section Label"; ! manual[i].longest = 1; ! } ! SetManNames(manual); ! manptr = getenv("MANPATH"); ! if (manptr == NULL || strcmp(manptr,"") == 0) { ! #ifdef DEBUG /* Since man does not complain we had better not either. */ ! sprintf(error_buf,"Could not find MANPATH searching only, %s.",MANDIR); ! PrintWarning(error_buf); ! #endif ! strcpy(manualdir,MANDIR); } ! else ! strcpy(manualdir,manptr); ! local_ptr = manualdir; ! do { ! char *man[MAXSECT]; ! char *curmandir; ! if ( (manptr = index(local_ptr,':')) != NULL) { ! *manptr = '\0'; ! curmandir = local_ptr; ! local_ptr = manptr + 1; ! } ! else ! curmandir = local_ptr; ! /* if (!Preformatted(curmandir, manual, current, nsect)) { */ ! if (GetEntry(curmandir,man_nomatch)) { ! MatchEntries(curmandir,manual,man_nomatch,man,&nsect); ! AddStruct(manual,curmandir,man,current,nsect); } ! /* } */ ! } while (manptr != NULL); ! ! SetSectionNames(manual); ! SortAndRemove(manual, nsect); ! #ifdef notdef ! DumpManual(nsect); #endif ! return(nsect); /* return the number of man sections. */ } ! /* Function Name: GetEntry ! * Description: This function gets the names of the manual page ! * directories, then closes the directory. ! * Arguments: path - the path to this directory. ! * man - The directries of unformatted manual pages. ! * Returns: FALSE if directory could not be opened. */ ! static Boolean ! GetEntry(path, man) ! char * path; ! char * man[MAXSECT]; { ! DIR * dir; ! struct stat sb; ! register struct direct *dp; ! int numberman; ! char full_path[BUFSIZ]; ! numberman = 0; ! /* ! * Read through this directory and save up any directory name ! * which begins with "man". ! */ ! ! if((dir = opendir(path)) == NULL) { ! sprintf(error_buf,"Can't open directory %s", path); ! PrintWarning(error_buf); ! return(FALSE); ! } ! while((dp = readdir(dir)) != NULL) { ! if((dp->d_namlen >= LSEARCHDIR) && ! (strncmp(dp->d_name, SEARCHDIR, LSEARCHDIR) == 0)) { ! if(numberman == MAXSECT) ! PrintError( ! "Too many manual sections, recompile with larger allocations"); ! sprintf(full_path, "%s/%s", path, dp->d_name); ! if((stat(full_path, &sb) >= 0) && (sb.st_mode & S_IFDIR)) ! man[numberman++] = StrAlloc(dp->d_name); } } - - man[numberman] = NULL; /* NULL terminate this list. */ - closedir(dir); - return(TRUE); - } ! /* Function Name: MatchEntries ! * Description: This fucntion gives the correct number to the ! * directory, so that all manl entries will be ! * in the same place. ! * Arguments: path - path name if the current searched directory. ! * manual - a pointer to the manual structure. ! * manin - the unmatched states of the directories. ! * manout - the new wonderfully matched directories. ! * number - a pointer to the current number of sections. ! * Returns: manout. */ ! void ! MatchEntries(path,manual,manin,manout,number) ! char * path; ! Manual * manual; ! char **manin; ! char **manout; ! int *number; ! { ! int sect; ! ! bzero((char *) manout, MAXSECT * sizeof(char *)); ! ! for ( ; *manin != NULL ; manin++) { ! if ( (sect = GetSectNumber( (*manin)[LMAN] )) >= 0) ! manout[sect] = *manin; } ! CheckMandesc(path, manout, manual, number); ! } ! ! /* Function Name: CheckMandesc * Description: Reads the mandesc file, and adds more sections as * nescessary. ! * Arguments: path - path name if the current searched directory. ! * manual - a pointer to the manual structure. ! * man - directories, now sorted by order. ! * number - a pointer to the current number of sections. ! * Returns: none */ static void ! CheckMandesc(path, manout, manual, number) ! int *number; char * path; - char ** manout; - Manual * manual; { char mandesc_file[BUFSIZ]; /* full path to the mandesc file. */ FILE * descfile; ! char character; ! char string[BUFSIZ]; ! int sectnum; ! register int j; sprintf(mandesc_file, "%s/%s", path, MANDESC); ! if ( (descfile = fopen(mandesc_file, "r")) == NULL) ! return; /* if no description file we are done. */ ! while ( (character = getc(descfile)) != EOF) { ! Boolean flag = TRUE; ! fgets(string, 100, descfile); ! string[strlen(string)-1] = '\0'; /* Strip off the CR. */ ! if ( (sectnum = GetSectNumber(character)) >= 0) { ! if (manout[sectnum] == NULL) { ! sprintf(error_buf, "Error in file: %s.", mandesc_file); ! PrintWarning(error_buf); ! sprintf(error_buf, "Could not find the directory %s/man%c.", ! path, character); ! PrintWarning(error_buf); continue; } ! for (j = FIXEDSECT ; j < *number ; j++) { ! /* ! * If this section exists then do not create a new one for it. ! */ ! if ( (!strcmp(manual[j].blabel , string)) ) { ! manout[j] = manout[sectnum]; ! flag = FALSE; ! } ! } ! if (flag) { ! manual[*number].blabel = StrAlloc(string); ! manual[*number].sect = StrAlloc(manout[sectnum]); ! manout[*number] = StrAlloc(manout[sectnum]); ! if ( ++(*number) >= MAXSECT) { ! sprintf(error_buf,"Number of sections exceeded %d recompile %s", ! MAXSECT,"with larger MAXSECT."); ! PrintError(error_buf); ! } ! } ! manout[sectnum][0] = '\0'; /* remove it's name for the prev place */ } ! else { /* (sectnum = GetSectNumber(character)) >= 0) */ ! sprintf(error_buf, "Unknown man directory 'man%s'.", character); ! PrintWarning(error_buf); ! } } ! fclose(descfile); } ! /* Function Name: AddStruct ! * Description: add the new entries to the manual structure. ! * Arguments: manual - the manual structure to add them to. ! * path - the man path for these entires. ! * man - a pointer to the man directory names. ! * current - a pointer to the number of the current entry. ! * Returns: current - new current pointer numbers and changes manual */ ! void ! AddStruct(manual,path,man,current,number) ! Manual * manual; char * path; - char * man[MAXSECT]; - int current[MAXSECT]; - int number; { ! int i; ! DIR * dir; ! register struct direct *dp; ! char section[BUFSIZ]; ! /* ! * Go through each manual directory saving up the individual ! * page entries. ! * Demand that a page entry not start with a '.' but have ! * a dot somewhere. ! */ ! for(i=0; i < number; i++,man++) { ! register int j, k; ! int longest, lpixels; ! longest = lpixels = 1; /* prevents division by zero. */ ! k = current[i]; ! path = StrAlloc(path); /* allocate a space to save the path. */ ! /* ! * Use the man directories to get the file names 'cause they should be ! * more complete. ! */ ! if (*man == NULL) ! continue; ! sprintf(section,"%s/%s",path, *man); ! if ( (dir = opendir(section)) == NULL) { ! sprintf(error_buf, "Could not open directory %s.", section); ! PrintWarning(error_buf); ! continue; ! } ! while((dp = readdir(dir)) != NULL) { ! if( k >= MAXENTRY) { ! sprintf(error_buf,"Too many manual pages in %s %s", section, ! "Try recompiling with larger allocations"); ! PrintError(error_buf); ! } ! /* starts with a dot? no dot in name? */ ! if( (dp->d_name[0] == '.') || (rindex(dp->d_name,'.') == NULL) ) ! continue; ! manual[i].entries[k].label = StrAlloc(dp->d_name); ! manual[i].entries[k].path = path; ! k++; ! /* ! * This sets the value of the longest string in characters and pixels, I have ! * to play a few games since the longest string in characters is not ! * nescessarily the longest string in pixels, and XTextWidth is not very fast. */ ! if ((j = strlen(dp->d_name)) >= longest - 2) { ! longest = j; ! if ( (j = XTextWidth(fonts.directory,dp->d_name,strlen(dp->d_name))) > ! lpixels) ! lpixels = j; ! } } ! closedir(dir); ! /* ! * Yes, this check is needed, because we may add to the structure more ! * than once, depending on the MANPATH. ! */ ! if ( (lpixels + 5) > manual[i].longest) ! manual[i].longest = lpixels+5; ! current[i] = manual[i].nentries = k; } } /* Function Name: SortAndRemove --- 50,348 ---- int Man() { ! SectionList *list = NULL; ! char *ptr, manpath[BUFSIZ], *path, *current_label; ! int sect; ! /* ! * Get the environment variable MANPATH, and if it doesn't exist then back ! * up to MANDIR. ! */ ! ptr = getenv("MANPATH"); ! if (ptr == NULL || streq(ptr , "") ) ! ptr = MANDIR; ! strcpy(manpath, ptr); ! /* ! * Get the list of manual directories in the users MANPATH that we should ! * open to look for manual pages. The ``mandesc'' file is read here. ! */ ! ! for ( path = manpath ; (ptr = index(path , ':')) != NULL ; path = ++ptr) { ! *ptr = '\0'; ! ReadMandescFile(&list, path); } ! ReadMandescFile(&list, path); ! SortList(&list); ! sect = 0; ! InitManual( &(manual[sect]), list->label ); ! current_label = NULL; ! while ( list != NULL ) { ! SectionList * old_list; ! ! if ( current_label == NULL || streq(list->label, current_label) ) ! AddToCurrentSection( &(manual[sect]), list->directory); ! else { ! if (manual[sect].nentries == 0) { /* empty section, re-use it. */ ! free(manual[sect].blabel); ! manual[sect].blabel = list->label; } ! else { ! if ( ++sect >= MAXSECT ) { ! sprintf(error_buf, "%s %s", "Too many manual sections, recompile", ! "with a larger value for MAXSECT."); ! PrintError(error_buf); ! } ! InitManual( &(manual[sect]), list->label ); ! } ! AddToCurrentSection( &(manual[sect]), list->directory); ! } ! /* Save label to see if it matches next entry. */ ! current_label = list->label; ! old_list = list; ! list = list->next; ! free(old_list); /* free what you allocate. */ ! } ! if (manual[sect].nentries != 0) ! sect++; /* don't forget that last section. */ ! ! SortAndRemove(manual, sect); ! #ifdef notdef /* dump info. */ ! DumpManual(sect); #endif ! return(sect); /* return the number of man sections. */ } ! /* Function Name: SortList ! * Description: Sorts the list of sections to search. ! * Arguments: list - a pointer to the list to sort. ! * Returns: a sorted list. ! * ! * This is the most complicated part of the entire operation. ! * all sections with the same label must by right next to each other, ! * but the sections that are in the standard list have to come first. */ ! static void ! SortList(list) ! SectionList ** list; { ! SectionList * local; ! SectionList *head, *last, *inner, *old; ! ! if (*list == NULL) ! PrintError("No manual sections to read, exiting."); ! /* ! * First step ! * ! * Look for standard list items, and more them to the top of the list. ! */ ! last = NULL; /* keep Saber happy. */ ! for ( local = *list ; local->next != NULL ; local = local->next) { ! if ( local->standard ) { ! if ( local == *list ) /* top element is already standard. */ ! break; ! head = local; ! /* Find end of standard block */ ! for ( ; (local->next != NULL) && (local->standard) ! ; old = local, local = local->next); ! ! last->next = old->next; /* Move the block. */ ! old->next = *list; ! *list = head; ! ! break; /* First step accomplished. */ } + last = local; } ! /* ! * Second step ! * ! * Move items with duplicate labels right next to each other. */ ! local = *list; ! for ( local = *list ; local->next != NULL ; local = local->next) { ! inner = local->next; ! while ( inner != NULL) { ! if ( streq(inner->label, local->label) && (inner != local->next)) { ! last->next = inner->next; /* Move it to directly follow local. */ ! inner->next = local->next; ! local->next = inner; ! inner = last; /* just so that we keep marching down the ! tree (this keeps us from looping). */ ! } ! last = inner; ! inner = inner->next; ! } } + } ! /* Function Name: ReadMandescFile * Description: Reads the mandesc file, and adds more sections as * nescessary. ! * Arguments: path - path name if the current search directory. ! * section_list - pointer to the list of sections. ! * Returns: TRUE in we should use default sections */ static void ! ReadMandescFile( section_list, path ) ! SectionList ** section_list; char * path; { char mandesc_file[BUFSIZ]; /* full path to the mandesc file. */ FILE * descfile; ! char string[BUFSIZ], local_file[BUFSIZ]; ! Boolean use_defaults = TRUE; sprintf(mandesc_file, "%s/%s", path, MANDESC); ! if ( (descfile = fopen(mandesc_file, "r")) != NULL) { ! while ( fgets(string, BUFSIZ, descfile) != NULL) { ! string[strlen(string)-1] = '\0'; /* Strip off the CR. */ ! if ( streq(string, NO_SECTION_DEFAULTS) ) { ! use_defaults = FALSE; continue; } ! ! sprintf(local_file, "%s%c", MAN, string[0]); ! AddNewSection(section_list, path, local_file, (string + 1), FALSE ); } ! fclose(descfile); } ! if (use_defaults) ! AddStandardSections(section_list, path); } ! /* Function Name: AddStandardSections ! * Description: Adds all the standard sections to the list for this path. ! * Arguments: list - a pointer to the section list. ! * path - the path to these standard sections. ! * Returns: none. */ ! static void ! AddStandardSections(list, path) ! SectionList **list; char * path; { ! static char * names[] = { ! "User Commands (1)", ! "System Calls (2)", ! "Subroutines (3)", ! "Devices (4)", ! "File Formats (5)", ! "Games (6)", ! "Miscellaneous (7)", ! "Sys. Administration (8)", ! "Local (l)", ! "New (n)", ! "Old (o)", ! }; ! register int i; ! char file[BUFSIZ]; ! for (i = 1 ; i <= 8 ; i++) { ! sprintf(file, "%s%d", MAN, i); ! AddNewSection(list, path, file, names[i-1], TRUE); ! } ! i--; ! sprintf(file, "%sl", MAN); ! AddNewSection(list, path, file, names[i++], TRUE); ! sprintf(file, "%sn", MAN); ! AddNewSection(list, path, file, names[i++], TRUE); ! sprintf(file, "%so", MAN); ! AddNewSection(list, path, file, names[i], TRUE); ! } ! /* Function Name: AddNewSection ! * Description: Adds the new section onto the current section list. ! * Arguments: list - pointer to the section list. ! * path - the path to the current manual section. ! * file - the file to save. ! * label - the current section label. ! * standard - one of the standard labels? ! * Returns: none. ! */ ! static void ! AddNewSection(list, path, file, label, standard) ! SectionList **list; ! char * path, * label, * file; ! Boolean standard; ! { ! SectionList * local_list, * end; ! char full_path[BUFSIZ]; ! /* Allocate a new list element */ ! if ( (local_list = (SectionList *) malloc(sizeof(SectionList)) ) == NULL) ! PrintError("Could not allocate Memory in AddNewSection."); ! if (*list != NULL) { ! for ( end = *list ; end->next != NULL ; end = end->next ); ! end->next = local_list; ! } ! else ! *list = local_list; ! local_list->next = NULL; ! local_list->label = StrAlloc(label); ! sprintf(full_path, "%s/%s", path, file); ! local_list->directory = StrAlloc(full_path); ! local_list->standard = standard; ! } ! ! /* Function Name: AddToCurrentSection ! * Description: This function gets the names of the manual page ! * directories, then closes the directory. ! * Arguments: local_manual - a pointer to a manual pages structure. ! * path - the path to this directory. ! * Returns: FALSE if directory could not be opened. */ ! ! static void ! AddToCurrentSection(local_manual, path) ! Manual * local_manual; ! char * path; ! { ! DIR * dir; ! register struct direct *dp; ! register int nentries; ! char full_name[BUFSIZ]; ! ! if((dir = opendir(path)) == NULL) { ! #ifdef DEBUG ! sprintf(error_buf,"Can't open directory %s", path); ! PrintWarning(NULL, error_buf); ! #endif DEBUG ! return; ! } ! ! nentries = local_manual->nentries; ! ! while( (dp = readdir(dir)) != NULL ) { ! char * name = dp->d_name; ! if( (name[0] == '.') || (index(name, '.') == NULL) ) ! continue; ! if ( nentries >= MAXENTRY ) { ! sprintf(error_buf, "%s %s %s", "Too many manual pages in directory", ! path, "recompile with A larger value for MAXENTRY."); ! PrintError(error_buf); } ! sprintf(full_name, "%s/%s", path, name); ! local_manual->entries[nentries++] = StrAlloc(full_name); } + local_manual->nentries = nentries; } /* Function Name: SortAndRemove *************** *** 356,386 **** * Returns: an improved manual stucure */ ! void SortAndRemove(manual, number) Manual *manual; int number; { int i; for ( i = 0; i < number; i++) { /* sort each section */ register int j = 0; Manual * man = &(manual[i]); ! qsort(man->entries, man->nentries, sizeof(struct entry), CmpEntryLabel); while (j < (man->nentries - 1) ) { ! if (!strcmp(man->entries[j].label, man->entries[j+1].label)) { ! register int k = 0; ! for( k = j; k < (man->nentries -1); k++) ! man->entries[j] = man->entries[j+1]; (man->nentries)--; } ! j++; } } } /* Function Name: StrAlloc * Description: this function allocates memory for a character string * pointed to by sp and returns its new pointer. --- 353,424 ---- * Returns: an improved manual stucure */ ! static void SortAndRemove(manual, number) Manual *manual; int number; { int i; + char *l1, *l2; for ( i = 0; i < number; i++) { /* sort each section */ register int j = 0; Manual * man = &(manual[i]); ! #ifdef DEBUG ! printf("sorting section %d - %s\n", i, man->blabel); ! #endif DEBUG + qsort(man->entries, man->nentries, sizeof( char * ), CmpEntryLabel); + + #ifdef DEBUG + printf("removing from section %d.\n", i); + #endif DEBUG + + if ( (l1 = rindex(man->entries[j], '/')) == NULL) + PrintError("Internal error while removing duplicate manual pages."); + j++; + while (j < (man->nentries - 1) ) { ! l2 = l1; ! if ( (l1 = rindex(man->entries[j], '/')) == NULL) ! PrintError("Internal error while removing duplicate manual pages."); ! if ( streq(l1, l2) ) { ! register int k; ! for( k = j; k < (man->nentries); k++) ! man->entries[k - 1] = man->entries[k]; (man->nentries)--; } ! else ! j++; } } } + /* Function Name: CmpEntryLabel - used in qsort(). + * Description: compares to elements by using their labels. + * Arguments: e1, e2 - two items to compare. + * Returns: an integer >, < or = 0. + */ + + static int + CmpEntryLabel(e1, e2) + char **e1, **e2; + { + char *l1, *l2; + + /* + * What we really want to compare is the actual names of the manual pages, + * and not the full path names. + */ + + if ( (l1 = rindex(*e1, '/')) == NULL) + PrintError("Internal error while sorting manual pages."); + if ( (l2 = rindex(*e2, '/')) == NULL) + PrintError("Internal error while sorting manual pages."); + return( strcmp(l1, l2) ); + } + /* Function Name: StrAlloc * Description: this function allocates memory for a character string * pointed to by sp and returns its new pointer. *************** *** 401,493 **** return(ret); } ! /* Function Name: SetManNames ! * Description: This function give a name to manual.sect ! * Arguments: manual - pointer to the manual structure. ! * Returns: NONE. ! */ ! ! void ! SetManNames(manual) ! Manual *manual; ! { ! int i; ! char string[40]; ! ! for (i = 0; i < 9; i++) { ! sprintf(string,"%s%d",MAN,i); ! manual[i].sect = StrAlloc(string); ! } ! sprintf(string,"%s%c",MAN,'l'); ! manual[9].sect = StrAlloc(string); ! sprintf(string,"%s%c",MAN,'n'); ! manual[10].sect = StrAlloc(string); ! } ! ! /* Function Name: GetSectNumber ! * Description: this gets a section number of a fixed section. ! * Arguments: character - the character representing the section. ! * Returns: the number of that section. ! */ ! ! static int ! GetSectNumber(c) ! char c; ! { ! ! switch (c) { ! case '0': ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! case '7': ! case '8': ! return(c - '0'); ! case 'l': ! return(9); ! case 'n': ! return(10); ! default: ! break; /* ignore others, and return -1. */ ! } ! return(-1); ! } ! ! /* Function Name: SetSectNames ! * Description: Sets the section names. ! * Arguments: manual - the manual structure. * Returns: none. */ static void ! SetSectionNames(manual) ! Manual * manual; { ! ! /* These are the names for the first 10 sections. */ ! ! static char * names[] = { ! "foo bar (0)", ! "User Commands (1)", ! "System Calls (2)", ! "Subroutines(3)", ! "Devices (4)", ! "File Formats (5)", ! "Games (6)", ! "Miscellaneous (7)", ! "Sys. Administration (8)", ! "Local (l)", ! "New (n)" ! }; ! register int i; ! ! for (i = 1; i < FIXEDSECT; i++) ! manual[i].blabel = names[i]; } ! #if defined(DEBUG) /* Function Name: DumpManual --- 439,463 ---- return(ret); } ! /* Function Name: InitManual ! * Description: Initializes this manual section. ! * Arguments: l_manual - local copy of the manual structure. ! * label - the button label for this section. * Returns: none. */ static void ! InitManual(l_manual, label) ! Manual * l_manual; ! char * label; { ! bzero( l_manual, sizeof(Manual) ); /* clear it. */ ! l_manual->blabel = label; /* set label. */ ! l_manual->entries = (char **) malloc( sizeof(char *) * MAXENTRY); ! if (l_manual->entries == NULL) ! PrintError("Could not allocate memory in InitManual()."); } ! #if defined(DEBUG) /* Function Name: DumpManual *************** *** 502,510 **** register int i,j; for ( i = 0; i < number; i++) { for (j = 0; j < manual[i].nentries; j++) ! printf("path %-10s label %-20s\n", manual[i].entries[j].path, ! manual[i].entries[j].label); } } --- 472,480 ---- register int i,j; for ( i = 0; i < number; i++) { + printf("label: %s\n", manual[i].blabel); for (j = 0; j < manual[i].nentries; j++) ! printf("%s\n", manual[i].entries[j]); } } *** /tmp/,RCSt1a17235 Fri Jan 6 18:56:59 1989 --- clients/xman/misc.c Fri Jan 6 18:42:26 1989 *************** *** 1,7 **** /* * xman - X window system manual page display program. * ! * $XConsortium: misc.c,v 1.3 88/10/07 17:19:53 jim Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * --- 1,7 ---- /* * xman - X window system manual page display program. * ! * $XConsortium: misc.c,v 1.4 89/01/06 18:42:24 kit Exp $ * * Copyright 1987, 1988 Massachusetts Institute of Technology * *************** *** 20,26 **** */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: misc.c,v 4.0 88/08/31 22:13:01 kit Exp $"; #endif #include "globals.h" --- 20,26 ---- */ #if ( !defined(lint) && !defined(SABER)) ! static char rcs_version[] = "$Athena: misc.c,v 4.6 88/12/19 13:48:01 kit Exp $"; #endif #include "globals.h" *************** *** 37,46 **** */ void ! PrintWarning(string) char * string; { ! fprintf(stderr,"Xman Warning: %s\n",string); } /* Function Name: PrintError --- 37,54 ---- */ void ! PrintWarning(man_globals, string) ! ManpageGlobals * man_globals; char * string; { ! char buffer[BUFSIZ]; ! ! sprintf( buffer, "Xman Warning: %s", string); ! ! if (man_globals != NULL) ! ChangeLabel(man_globals->label, buffer); ! ! fprintf(stderr, "%s\n", buffer); } /* Function Name: PrintError *************** *** 63,88 **** /* Function Name: FindFilename * Description: Opens the entry file given the entry struct. * Arguments: man_globals - the globals info for this manpage. - * name - name of the current manpage. * entry - the structure containg the info on the file to open. * Returns: fp - the file pointer */ FILE * ! FindFilename(man_globals, name, section, entry) ManpageGlobals * man_globals; ! char * name; ! int section; ! struct entry * entry; { FILE * file; ! char local_filename[BUFSIZ]; /* local filename. */ ! sprintf(man_globals->manpage_title, ! "The current manual page is: %s.", name); ! sprintf(man_globals->filename, "%s/%s%c/%s", ! entry->path, CAT, manual[section].sect[LCAT], entry->label); /* if we find the formatted manpage then return it */ --- 71,94 ---- /* Function Name: FindFilename * Description: Opens the entry file given the entry struct. * Arguments: man_globals - the globals info for this manpage. * entry - the structure containg the info on the file to open. * Returns: fp - the file pointer */ FILE * ! FindFilename(man_globals, entry) ManpageGlobals * man_globals; ! char * entry; { FILE * file; ! char path[BUFSIZ], page[BUFSIZ], section[BUFSIZ], *temp; ! temp = CreateManpageName(entry); ! sprintf(man_globals->manpage_title, "The current manual page is: %s.", temp); ! free(temp); ! ParseEntry(entry, path, section, page); ! sprintf(man_globals->filename, "%s/%s%c/%s", path, CAT, section[LCAT], page); /* if we find the formatted manpage then return it */ *************** *** 89,109 **** if ( (file = fopen(man_globals->filename,"r")) != NULL) return(file); ! /* If not then look for the unformatted man page, format it and ! * write access is allowed to the cat directory, then ask if we ! * want to save it. ! */ ! ! sprintf(local_filename,"%s/%s/%s", ! entry->path, manual[section].sect, entry->label); ! if ( (file = fopen(local_filename,"r")) == NULL) { ! char error_buf[BUFSIZ]; ! /* We Really could not find it, this should never happen, yea right. */ ! sprintf(error_buf, "Could open manual page file, %s", local_filename); ! PrintError(error_buf); ! } ! else ! return(Format(man_globals,file,local_filename, entry, section)); } /* Function Name: Format --- 95,101 ---- if ( (file = fopen(man_globals->filename,"r")) != NULL) return(file); ! return(Format(man_globals, entry)); } /* Function Name: Format *************** *** 111,118 **** * with the user. * Arguments: man_globals - the psuedo globals * file - the file pointer to use and return - * local_filename - the name of the file that is - * being formatted. * entry - the current entry struct. * current_box - The current directory being displayed. * Returns: none. --- 103,108 ---- *************** *** 121,138 **** /* ARGSUSED */ FILE * ! Format(man_globals, file, local_filename, entry, current_box) ManpageGlobals * man_globals; ! FILE * file; ! char * local_filename; ! struct entry * entry; ! int current_box; /* The current directory being displayed. */ { Widget w = man_globals->manpagewidgets.directory; ! char cmdbuf[256]; ! char tmp[25]; ! char catdir[100]; ! int x,y; /* location to pop up whould you like to save widget. */ strcpy(tmp,MANTEMP); /* get a temp file. */ --- 111,126 ---- /* ARGSUSED */ FILE * ! Format(man_globals, entry) ManpageGlobals * man_globals; ! char * entry; { + FILE * file; Widget w = man_globals->manpagewidgets.directory; ! char cmdbuf[BUFSIZ], tmp[BUFSIZ], catdir[BUFSIZ]; ! char path[BUFSIZ], section[BUFSIZ], error_buf[BUFSIZ]; ! ! Position x,y; /* location to pop up whould you like to save widget. */ strcpy(tmp,MANTEMP); /* get a temp file. */ *************** *** 157,187 **** XFlush(XtDisplay(w)); */ /* End replacement. */ ! /* ! ChangeLabel(man_globals->label, "Formatting Manpage, Please Stand by..."); ! */ #ifdef macII ! sprintf(cmdbuf,"cd %s;/usr/bin/pcat %s | /usr/bin/col | /usr/bin/ul -t dumb > %s", ! entry->path, local_filename, man_globals->tmpfile); #else ! sprintf(cmdbuf,"cd %s;%s %s > %s", ! entry->path, ! FORMAT, local_filename, man_globals->tmpfile); #endif ! if(system(cmdbuf) != 0) /* execute search. */ ! PrintError("Something went wrong trying to run the command"); if ((file = fopen(man_globals->tmpfile,"r")) == NULL) { ! PrintWarning("Something went wrong in retrieving the temp file"); ! PrintError("Try cleaning up /tmp"); } /* if the catdir is writeable the ask the user if he/she wants to write the man page to it. */ ! sprintf(catdir,"%s/%s%c", ! entry->path,CAT, manual[current_box].sect[LCAT], entry->label); if( (access(catdir,W_OK)) == 0) { x = Width(man_globals->manpagewidgets.manpage)/2; --- 145,187 ---- XFlush(XtDisplay(w)); */ /* End replacement. */ ! ! if ( (file = fopen( entry , "r")) == NULL) { ! /* We Really could not find it, this should never happen, yea right. */ ! sprintf(error_buf, "Could open manual page file, %s", entry); ! PrintWarning(man_globals, error_buf); ! return(NULL); ! } ! ! ParseEntry(entry, path, section, NULL); ! #ifdef macII ! sprintf(cmdbuf, ! "cd %s;/usr/bin/pcat %s | /usr/bin/col | /usr/bin/ul -t dumb > %s %s", ! path, entry, man_globals->tmpfile, "2> /dev/null"); #else ! sprintf(cmdbuf,"cd %s ; %s %s > %s %s", path, ! FORMAT, entry, man_globals->tmpfile, "2> /dev/null"); #endif ! if(system(cmdbuf) != 0) { /* execute search. */ ! sprintf(error_buf, ! "Something went wrong trying to run the command: %s", cmdbuf); ! PrintWarning(man_globals, error_buf); ! return(NULL); ! } if ((file = fopen(man_globals->tmpfile,"r")) == NULL) { ! sprintf(error_buf, "Something went wrong in retrieving the temp file, %s", ! "Try cleaning up /tmp"); ! PrintWarning(man_globals, error_buf); ! return(NULL); } /* if the catdir is writeable the ask the user if he/she wants to write the man page to it. */ ! sprintf(catdir,"%s/%s%c", path, CAT, section[LCAT]); if( (access(catdir,W_OK)) == 0) { x = Width(man_globals->manpagewidgets.manpage)/2; *************** *** 188,194 **** y = Height(man_globals->manpagewidgets.manpage)/2; XtTranslateCoords(man_globals->manpagewidgets.manpage, x, y, &x, &y); PositionCenter( PopupChild(man_globals->manpagewidgets.manpage, 0), ! x,y,0,0,0,0); XtPopup( PopupChild(man_globals->manpagewidgets.manpage, 0), XtGrabExclusive); } --- 188,194 ---- y = Height(man_globals->manpagewidgets.manpage)/2; XtTranslateCoords(man_globals->manpagewidgets.manpage, x, y, &x, &y); PositionCenter( PopupChild(man_globals->manpagewidgets.manpage, 0), ! (int) x, (int) y,0,0,0,0); XtPopup( PopupChild(man_globals->manpagewidgets.manpage, 0), XtGrabExclusive); } *************** *** 232,238 **** { if (!XtIsRealized(w)) { ! PrintWarning("Widget is not realized, no cursor added.\n"); return; } XDefineCursor(XtDisplay(w),XtWindow(w),cursor); --- 232,238 ---- { if (!XtIsRealized(w)) { ! PrintWarning(NULL, "Widget is not realized, no cursor added.\n"); return; } XDefineCursor(XtDisplay(w),XtWindow(w),cursor); *************** *** 316,318 **** --- 316,352 ---- XtMoveWidget(widget,x_temp,y_temp); } + /* Function Name: ParseEntry(entry, path, sect, page) + * Description: Parses the manual pages entry filenames. + * Arguments: str - the full path name. + * path - the path name. RETURNED + * sect - the section name. RETURNED + * page - the page name. RETURNED + * Returns: none. + */ + + void + ParseEntry(entry, path, sect, page) + char *entry, *path, *page, *sect; + { + char *c, temp[BUFSIZ]; + + strcpy(temp, entry); + + c = rindex(temp, '/'); + if (c == NULL) + PrintError("index failure in ParseEntry."); + *c++ = '\0'; + if (page != NULL) + strcpy(page, c); + + c = rindex(temp, '/'); + if (c == NULL) + PrintError("index failure in ParseEntry."); + *c++ = '\0'; + if (sect != NULL) + strcpy(sect, c); + + if (path != NULL) + strcpy(path, temp); + } -- Mike Wexler(wyse!mikew) Phone: (408)433-1000 x1330 Moderator of comp.sources.x