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.