This is Help.m in view mode; [Download] [Up]
/***************************************************************************** * * Help.h * * Author: Denise Howard (not really) Julie Zelenski * * Desc: This is a stripped down version of the Help object from * the NeXT BusyBox example code. * * Modified by Tsutomu_Eguchi@ns.saga-med.ac.jp April 1998 * support localization * *****************************************************************************/ /* * Help.m, a help object to manage and display RTF and RTFD help files. * The help object owns its own nib section "Help.nib" which has a * Help panel - with an NXBrowser to display the help topics, and * a scrolling text view to display the help files. The help files are * all stored as RTF and RTFD text files in a directory called Help within the * app wrapper. At init time, the Help object loads the browser with * names of all the files found in the Help directory. When a name is * chosen from the browser, the help object opens a stream on that file * and read the rich text into the text object. * */ #import "Help.h" @implementation Help:Object static Help *theHelpInstance = NULL; + new { if (!theHelpInstance) { theHelpInstance = [[self alloc] init]; } return (id)theHelpInstance; } - init /* For newly created help object, loads the nib section with the Help * panel which has the topics browser and a scrolling text view for * displaying help files. Gets the appDirectory from NXApp, finds help * directory in app wrapper. */ { [[NXBundle mainBundle] getPath:helpDirectory forResource:"HelpOpener" ofType:""]; //TE // sprintf(helpDirectory, "%s/%s", [[NXBundle mainBundle] directory], // "HelpOpener"); sprintf(noHelpFile, "%s/%s", helpDirectory, "NoHelp.rtf"); [NXApp loadNibSection:"Help.nib" owner:self]; [helpBrowser setDelegate:self]; [helpBrowser setTarget:self]; [helpBrowser acceptArrowKeys:YES andSendActionMessages:YES]; [helpBrowser loadColumnZero]; return self; } /* TARGET/ACTION METHODS */ - generalHelp:sender; /* This is the target/action method for the "Help" menu item. This method * will show the "general help" file. */ { [self showHelpFile:"General"]; return self; } - browserHit:sender /* This is the target/action method from the help topics browser. When * a help topic is selected, this method will show the help file for that * topic. */ { [self showHelpFile:[[[sender matrixInColumn:0] selectedCell] stringValue]]; return self; } /* HELP METHODS */ - showHelpFile:(const char*)filename; /* Tries to open a stream for the specified RTF or RTFD text file in the Help * directory so the text object can readRichText. Also selects the * filename in the browser of help topics. If the filename doesn't exist, * it will select and display the "nohelp" file. It also brings the * help panel to the front. */ { NXStream *stream; char tFileName[MAXPATHLEN]; char helpFile[MAXPATHLEN]; char *p; static NXPoint origin = {0.0,0.0}; if (!filename) return self; // change ' ' to '_' strcpy(tFileName, filename); for (p=(char*)tFileName; *p!='\0'; p++) if (*p==' ') *p='_'; if (![self browser:helpBrowser selectCell:filename inColumn:0]) [self browser:helpBrowser selectCell:"NoHelp" inColumn:0]; sprintf(helpFile, "%s/%s.rtf", helpDirectory, tFileName); if ((stream = NXMapFile(helpFile, NX_READONLY)) == NULL) { sprintf(helpFile, "%s/%s.rtfd", helpDirectory, tFileName); [[helpScrollView docView] openRTFDFrom:helpFile]; } else { [helpPanel disableFlushWindow]; [[helpScrollView docView] readRichText:stream]; [[helpScrollView docView] scrollPoint:&origin]; [[helpPanel reenableFlushWindow] flushWindow]; NXCloseMemory(stream,NX_FREEBUFFER); } [helpPanel orderFront:self]; return self; } /* BROWSER DELEGATE METHODS */ static char ** addFile(const char *file, int length, char **list, int count) /* Adds the specified filename to the list of filenames. It allocates * more memory in chunks as needed. */ { char *suffix; char *p; if (!list) list = (char **)malloc(CHUNK*sizeof(char *)); if ((suffix = rindex(file,'.')) != NULL) *suffix = '\0'; /* strip rtf or rtfd suffix */ // change ' ' to '_' for (p=(char*)file; *p!='\0'; p++) if (*p=='_') *p=' '; list[count] = (char *)malloc((length+1)*sizeof(char)); strcpy(list[count], file); count++; if (!(count% CHUNK)) { list = (char **)realloc(list,(((count/CHUNK)+1)*CHUNK)*sizeof(char *)); } list[count] = NULL; return list; } static void freeList(char **list) /* Frees the array of filenames */ { char **strings; if (list) { strings = list; while (*strings) free(*strings++); free(list); } } static BOOL isOk(const char *s) { BOOL result; char *p; result = (!s[0] || s[0] == '.') ? NO : YES; if (result) { result = NO; if ((p = rindex(s, '.')) != NULL) { if ((!strcmp(p+1, "rtf")) || (!strcmp(p+1, "rtfd"))) if (!strstr(s, "NoHelp")) result = YES; } } return result; } static int caseInsensitiveCompare(const void *arg1, const void *arg2) /* Compares the two arguments without regard for case using strcasecmp(). */ { char *string1, *string2; string1 = *((char **)arg1); string2 = *((char **)arg2); return strcasecmp(string1,string2); } static char **fileList; - (int)browser:sender fillMatrix:matrix inColumn:(int)column /* This delegate method goes out to the help directory and gets a list * of all the files in that directory. It creates a list of file names * for the static variable fileList, and will load the filenames into the * browser on demand (lazy loading). */ { long basep; char *buf; struct direct *dp; char **list = NULL; int cc, fd, fileCount = 0; char dirbuf[8192]; if ((fd = open(helpDirectory, O_RDONLY, 0644)) > 0) { cc = getdirentries(fd, (buf = dirbuf), 8192, &basep); while (cc) { dp = (struct direct *)buf; if (isOk(dp->d_name)) { list = addFile(dp->d_name, dp->d_namlen, list, fileCount++); } buf += dp->d_reclen; if (buf >= dirbuf + cc) { cc = getdirentries(fd, (buf = dirbuf), 8192, &basep); } } close(fd); if (list) qsort(list,fileCount,sizeof(char *), caseInsensitiveCompare); } freeList(fileList); fileList = list; return fileCount; } - browser:sender loadCell:cell atRow:(int)row inColumn:(int)column /* This delegate method loads the cell for a given row. The stringValue * for that row comes from the fileList. */ { if (fileList) { [cell setStringValueNoCopy:fileList[row]]; [cell setLeaf:YES]; } return self; } - (BOOL)browser:sender selectCell:(const char *)title inColumn:(int)column /* This delegate method selects the cell with the given title. If it finds * a cell with that title, it verifies that it has a file entry in the * fileList, forces the loading of the cell, selects it (highlights) and * scrolls the browser so the cell is visible. It returns a boolean value * which indicates whether the cell was found. */ { int row; id matrix; if (title) { matrix = [sender matrixInColumn:column]; if (!fileList) return NO; for (row = [matrix cellCount]-1; row >= 0; row--) { if (fileList[row] && !strcmp(title, fileList[row])) { [sender getLoadedCellAtRow:row inColumn:column]; [matrix selectCellAt:row :0]; [matrix scrollCellToVisible:row :0]; return YES; } } } return NO; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.