This is Controller.m in view mode; [Download] [Up]
// Copyright H. Giesen, University of Koblenz-Landau 1996 #import "Controller.h" #import "BibliographicFile.h" #import "BibTexView.h" #import "DragView.h" #import "MyBrowserCell.h" #import "Preferences.h" #import "TeXClass.h" #import "FindClass.h" #import "BrowserController.h" #import "Shelf.h" #import "BufferClass.h" #import "MacroDB.h" #import "HTML_Stuff.h" #import <ansi/time.h> #import <stdarg.h> #import <mach-o/arch.h> #define ON YES #define OFF NO #define DRAGVIEWTAG 7 #define ui unsigned int #define sameFile(a,b) \ ( !NXOrderStrings( a, b, YES, -1, NULL ) ) char *aFileName = NULL; static int semaphore = 1; // see windowDidBecomeKey: const char *Bib_Version = "1.2a"; /*************** category for the PopUpList class ***********/ @implementation PopUpList(sizeTheButton) - sizeButton:button { NXRect menuRect; [self sizeToFit]; // the itemlist is the matrix of menucells [[self itemList] getCellFrame:&menuRect at:0 :0]; [button sizeTo:menuRect.W :menuRect.H]; return self; } @end /*========= category for the Textclass ===========*/ @implementation Text(printf) - (void) addText:(char *)theText { int length = [self textLength]; [self setSel:length :length]; [self replaceSel:theText]; [self scrollSelToVisible]; } - (void) clearText { [self setSel:0 :[self textLength]]; [self replaceSel:NULL]; } - (void) clearAndWriteText:(char *)theText // never used { [self setSel:0 :[self textLength]]; [self replaceSel:theText]; [self scrollSelToVisible]; } - (void) printf:(const char *)format, ... // never used { va_list ap; int length = [self textLength]; char locBuffer[512]; va_start( ap, format ); vsprintf( locBuffer, format, ap ); va_end( ap ); [self setSel:length :length]; [self replaceSel:locBuffer]; [self scrollSelToVisible]; } @end /*^^^^^^^^^^^^ category for the Textclass ^^^^^^^^^^^^*/ @implementation Controller char buffer[512]; // global textbuffer int fileSeqNumber = 0; - (void) prRect:(const char *)txt :(NXRect)r { fprintf( stderr, "%s x=%d y=%d w=%d h=%d\n", txt, (int)r.X, (int)r.Y, (int)r.W, (int)r.H ); } - (void)alert:(char *)txt :(char *)para { NXRunAlertPanel("Bibliography", txt, " OK ", // 1: default button NULL, // 0: alternate NULL, //-1: other para ); } - (void) clearButton:button { [[button findViewWithTag:DRAGVIEWTAG] clear]; } - (BOOL)appAcceptsAnotherFile:sender { return YES; } - (int)app:sender openFile:(const char *)filename type:(const char *)aType { if( aFileName==NULL ){ // appDidInit not yet invoked aFileName = NXCopyStringBuffer( filename ); return YES; } if( [self openFile:filename] ){ [browserController resetBrowser:self]; return YES; } return NO; } - initMenuCellsIn:(int)menuTag from:(int)first to:(int)last { int i; Menu *subMenu; if( menuTag<10 ) subMenu = [[[NXApp mainMenu] findCellWithTag:menuTag] target]; else{ subMenu = [[[NXApp mainMenu] findCellWithTag:menuTag/10] target]; subMenu = [[subMenu findCellWithTag:menuTag] target]; } if( subMenu ) for( i=first; i<=last; i++ ){ // Document menu [[subMenu findCellWithTag:i] setUpdateAction:@selector(menuActive:) forMenu:subMenu]; } //else fprintf( stderr, "menutag %d not found\n", menuTag ); return self; } - initMenus { [self initMenuCellsIn:DOCUMENT from:OPEN to:CLOSE]; [self initMenuCellsIn:EDIT from:CUT to:SELECTALL]; [self initMenuCellsIn:FIND from:FINDPANEL to:JUMPTOSELECTION]; [self initMenuCellsIn:PREVIEW from:PRVWINDOW to:PRINT]; [NXApp setAutoupdate:YES]; return self; } static const char * dragTypes[3]; - appDidInit:sender { openPanel = [OpenPanel new]; [openPanel allowMultipleFiles:YES]; listOfFiles = [[List alloc] initCount:10]; if( BIBTEST==NO ){ int row, col; MenuCell *cell = [[NXApp mainMenu] findCellWithTag:1111]; Matrix *matrix = [[NXApp mainMenu] itemList]; [matrix getRow:&row andCol:&col ofCell:cell]; [matrix removeRowAt:row andFree:YES]; [[NXApp mainMenu] sizeToFit]; [[NXApp mainMenu] display]; [[bufferedButton removeFromSuperview] free]; } [bibWindow setMiniwindowIcon:"multiBook"]; [bibWindow registerForDraggedTypes:&NXFilenamePboardType count:1]; //[bibWindow registerForDraggedTypes:&NXAsciiPboardType count:1]; [bibWindow setFrameUsingName:"MainWindow"]; [bibWindow setFrameAutosaveName:"MainWindow"]; [browserController setUp]; [browserController setUpIcons:[fileDragBox findViewWithTag:DRAGVIEWTAG] :[entryDragBox findViewWithTag:DRAGVIEWTAG]]; [[NXApp appListener] setServicesDelegate:browserController]; litBrowser = [browserController theBrowser]; [bibWindow makeKeyAndOrderFront:self]; [bibWindow useOptimizedDrawing:YES]; [betweenButton setIcon:"NXmenuArrow"]; inspector = [BibTexView new]; MyListPboardType = NXUniqueString( "My List Pboard Type" ); dragTypes[0] = MyListPboardType; dragTypes[1] = NXAsciiPboardType; dragTypes[2] = NULL; [[fileDragBox findViewWithTag:DRAGVIEWTAG] registerForDraggedTypes:dragTypes count:2]; preferences = [Preferences new]; [deleteButton setEnabled:NO]; [newEntryButton setEnabled:NO]; // prepare the shelf [bibWindow disableDisplay]; shelfController = [iconScrollView docView]; [shelfController setBoxPrototype:fileDragBox]; [shelfController loadShelfFromFile:[preferences shelfFile]]; [[bibWindow reenableDisplay] displayIfNeeded]; if( aFileName ){ // lazy evaluation if( [self openFile:aFileName] ) [browserController resetBrowser:self]; } else aFileName = "X"; // must not be NULL [self initMenus]; preViewPushDown = [[self texObject] buildPreviewMenuFor:preViewButton]; [preViewButton setEnabled:NO]; [bibWindow makeFirstResponder:litBrowser]; return self; } - (DragView *)viewFor:button { return [button findViewWithTag:DRAGVIEWTAG]; } - (BOOL) canCiteFromColumn:(int)col // never used but useful { int theType = [browserController displayTypeInCol:col]; return ( (theType==D_KEY_SORTED) || (theType==D_KEY_AS_READ) ); } // returns the new state of the menuCell // YES = enabled // NO = disabled - (BOOL)updateMenuFor:menuCell { BOOL isEnabled = [menuCell isEnabled]; BOOL newState = NO; // .. and the compiler keeps silent int cnt = [[browserController selectedFiles] count]; switch( [menuCell tag] ){ case OPEN : newState = YES; break; case NEW : newState = YES; break; case SAVE : newState = (cnt>0); break; case SAVEAS : newState = (cnt>0); break; case SAVETO : newState = NO; break; // not yet implemented case SAVEALL: newState = NO; break; case REVERT : newState = (cnt>0); break; case CLOSE : newState = (cnt>0); break; case CUT : newState = NO; break; case COPY : newState = NO; break; case COPYCITE : newState = [[[self viewFor:entryDragBox] getList] count]>0; break; case PASTE : newState = NO; break; case SELECTALL : newState = [listOfFiles count]?YES:NO; break; case FINDNEXT : newState = (cnt>0); break; case ENTERSELECTION : newState = NO; break; case PRVWINDOW : newState = YES; break; case RUNLATEX : case RUNRTF : case RUNHTML : newState = ([[[self viewFor:entryDragBox] getList] count]>0) && ([texObject isRunning]==NO); break; case PRINT : newState = texObject!=nil; break; default : newState = isEnabled; // do not change } return newState; } - (BOOL)menuActive:menuCell { id delegate = [[NXApp keyWindow] delegate]; BOOL isEnabled = [menuCell isEnabled]; BOOL newState=NO; // .. and the compiler keeps silent if( [delegate respondsTo:@selector(updateMenuFor:)] ){ newState = [delegate updateMenuFor:menuCell]; if( isEnabled!=newState ){ [menuCell setEnabled:newState]; return YES; } return NO; } return NO; } - info:sender { const NXArchInfo *architecture; char hostNameStr[MAXHOSTNAMELEN]; const NXScreen *screen; const char *dTxt; NXRect screenBounds; NXWindowDepth depth; char locBuf[64]; if( !infoPanel ){ [NXApp loadNibSection:"info.nib" owner:self]; [infoPanel setFrameUsingName:"InfoPanel"]; [infoPanel setFrameAutosaveName:"InfoPanel"]; sprintf( locBuf, "Version %s", Bib_Version ); [versionText setStringValue: locBuf]; gethostname(hostNameStr, MAXHOSTNAMELEN); [hostNameText setStringValue: hostNameStr]; //[hostNameText setStringValue: [NXApp hostName]]; architecture = NXGetLocalArchInfo(); [procTypeText setStringValue: architecture->description]; screen = [[NXApp mainMenu] screen]; screenBounds = screen->screenBounds; depth = screen->depth; switch( depth ){ case NX_DefaultDepth : dTxt = "default"; break; case NX_TwoBitGrayDepth : dTxt = "2 bit gray"; break; case NX_EightBitGrayDepth : dTxt = "8 bit gray"; break; case NX_TwelveBitRGBDepth : dTxt = "12 bit RGB"; break; case NX_TwentyFourBitRGBDepth : dTxt = "24 bit RGB"; break; case 514 : dTxt = "8 bit RGB"; break; default : dTxt = "unknown screentype"; break; } [screenTypeText setStringValue: dTxt]; sprintf( locBuf, "%d x %d", (int)screenBounds.W, (int)screenBounds.H ); [screenSizeText setStringValue: locBuf]; } [infoPanel orderFront:self]; return self; } - (void) insertFile:(BibliographicFile *)theFile { int j = [listOfFiles count] - 1; while( j>=0 ){ if( strcasecmp( [[listOfFiles objectAt:j] fileName], [theFile fileName] ) > 0 ) j--; else break; } [listOfFiles insertObject:theFile at:j+1]; } - newFile:sender { BibliographicFile *fileObj; sprintf( buffer, "%s/UNTITLED-%d.bib", NXHomeDirectory(), (++fileSeqNumber) ); fileObj = [[BibliographicFile alloc] initNewFile:buffer]; if( fileObj ){ [self insertFile:(BibliographicFile *)fileObj]; [fileObj setDirty]; } else{ [self alert:"cannot create file\n\n %s\n": buffer ]; } [browserController resetBrowser:self]; [browserController selectFile:fileObj]; [bibWindow makeKeyAndOrderFront:self]; return self; } - (BOOL) openFile:(const char *)fullName { int i; BibliographicFile *fileObj; if( ![BibliographicFile canLoadFromFile:fullName] ){ [self alert: "file >%s<\n is not a bib-file" :(char *)fullName ]; return NO; } // check if file is already loaded for( i=0; i<[listOfFiles count]; i++ ){ if( sameFile( fullName, [[listOfFiles objectAt:i] fullPath] ) ){ [self alert: "file >%s<\n is already loaded" :(char *)fullName ]; return NO; } } fileObj = [[BibliographicFile alloc] initFromFile:fullName]; if( fileObj ){ [self insertFile:(BibliographicFile *)fileObj]; // update icon on the shelf [shelfController attachFile:fullName toObject:fileObj]; return YES; } [self alert: "cannot open >%s<" :(char *)fullName ]; return NO; } - (BOOL) openFile:(const char *)dir :(const char *)fName { sprintf( buffer, "%s/%s", dir, fName ); return [self openFile:buffer]; } - open:sender // multiple files allowed (type is 'bib') { int rtn; const char* const* fileName = {NULL}; const char* dir; // directory dir = [openPanel directory]; if ( (rtn=[openPanel runModalForTypes:[BibliographicFile fileTypes]] ) && (fileName = [openPanel filenames]) ) { int i=0; dir = [openPanel directory]; while( fileName[i] != NULL ){ [self openFile:dir :fileName[i]]; i++; } [browserController resetBrowser:self]; } else{ if( rtn==NX_OKTAG ) [self alert:"cannot not open\n\n %s\n" :(char *)fileName ]; } [bibWindow makeKeyAndOrderFront:self]; return self; } // saveFile returns -1 on error, otherwise: // NX_CANCELTAG or NX_OKTAG - (int)saveFile:(BibliographicFile *) theFile { char buffer[1024]; char *fName; BOOL isNew = NO; filenameChanged = NO; if( (isNew=[theFile isNewFile]) ){ int rtn; SavePanel *savePanel = [SavePanel new]; fName = NXCopyStringBuffer( [theFile fullPath] ); // save old name [savePanel setRequiredFileType:"bib"]; rtn = [savePanel runModalForDirectory:[theFile fullPath] file:[theFile fileName]]; // Returns NX_OKTAG (if the user clicks the OK button) // or NX_CANCELTAG (if the user clicks the Cancel button) if( rtn == NX_CANCELTAG ) return NX_CANCELTAG; filenameChanged = YES; [theFile changeFilenameTo:[savePanel filename]]; rtn = [theFile save]; if( rtn<0 ){; [theFile changeFilenameTo:fName]; // rename } else [browserController resetBrowser:self]; // show the new file free( fName ); return rtn; } else{ // save backup // did someone else change the file ?? struct stat fBuf; int last = [theFile lastModified]; int rtn = stat([theFile fullPath], &fBuf); if( rtn<0 ) perror("stat error"); if( fBuf.st_mtime>last ){ [self alert:"%s has been edited by someone else." "Do you want to overwrite?" :[theFile fullPath]]; } // instead of "system mv . . . " use: // performFileOperation:source:destination:files:options: /***** [[Application workspace] performFileOperation:WSM_MOVE_OPERATION source:"/tmp" destination:NULL files:(const char *)(fff + 1) options:NULL]; ****/ sprintf( buffer, " mv %s %s~", [theFile fullPath], [theFile fullPath] ); system( buffer ); } return [theFile save]; } - close:sender { List *closeList = [browserController selectedFiles]; BibliographicFile *fileObj; int i; if( [closeList count]==0 ){ // should never occur fprintf( stderr, "systemerror in close\n" ); return self; } for( i=0; i<[closeList count]; i++ ){ fileObj = [[closeList objectAt:i] fileObject]; if( [fileObj isDirty]==YES ){ int rtn = NXRunAlertPanel("Bibliography", // title "file >%s<\n did change", // message " save and close ", // 1: default button " close anyway ", // 0: alternate " cancel ", //-1: other [fileObj fullPath] ); if( rtn==NX_ALERTDEFAULT ){// save and close [self saveFile:fileObj]; } if( rtn==NX_ALERTOTHER ) break; // cancel } if( fileObj==lastMainFile ){ lastMainObject = nil; lastMainFile = nil; } [findObject deleteFile:fileObj]; // delete one by one [shelfController detachObject:fileObj]; [listOfFiles removeObject:fileObj]; [fileObj free]; } [[MacroDB new] fileDidChangeTo:nil]; [browserController resetBrowser:self]; return self; } - revertToSaved:sender { BibliographicFile *fileObj; List *closeList = [browserController selectedFiles]; int i, rtn; if( [closeList count]==0 ){ // should never occur fprintf( stderr, "SystemError in revertToSaved\n" ); return self; } for( i=0; i<[closeList count]; i++ ){ fileObj = [[closeList objectAt:i] fileObject]; //if( [fileObj isDirty]==NO ) continue; // ????? if( [fileObj isNewFile]==YES ) continue; if( fileObj==lastMainFile ){ lastMainObject = nil; lastMainFile = nil; } rtn = NXRunAlertPanel("Bibliography", // title "revert %s ?", // message " OK ", // 1: default button " NO ", // 0: alternate NULL, //-1: other [fileObj fullPath] ); if( rtn==NX_ALERTALTERNATE ) continue; // NO [findObject deleteFile:fileObj]; // delete one by one [listOfFiles removeObject:fileObj]; [shelfController detachObject:fileObj]; [self openFile:[fileObj fullPath]]; // insert in listOfFiles [fileObj free]; } [browserController resetBrowser:self]; return self; } - (void) fileNameOf:(BibliographicFile *)aFile didChangeTo:(const char *)aName { [aFile changeFilenameTo:aName]; // sets 'isDirty' to YES // remove fileobj and insert it at the right (sorted) place [listOfFiles removeObject:aFile]; [self insertFile:aFile]; [browserController resetBrowser:self]; // file could be in the find window [findObject showFindList]; [shelfController detachObject:aFile]; } - (void) shelfText:(const char *)txt { [fileOnShelfText setStringValue:txt]; } - save:sender { int rtn, i; SavePanel *savePanel = [SavePanel new]; List *saveList = [browserController selectedFiles]; BibliographicFile *fileObj; BOOL isNew; if( [saveList count]==0 ) return self; [savePanel setAccessoryView:saveAccessoryView]; for( i=0; i<[saveList count]; i++ ){ fileObj = [[saveList objectAt:i] fileObject]; //fprintf( stderr, "save %s\n", [fileObj fullPath] ); isNew = [fileObj isNewFile]; if( (rtn = [self saveFile:fileObj])<0 ){ [self alert:"cannot not save\n\n %s\n" :[fileObj fullPath] ]; continue; } if( rtn==NX_CANCELTAG ) continue; // rtn is NX_OK // did the name change ? if( filenameChanged==NO ) continue; if( (isNew==NO) && sameFile( [savePanel filename], [fileObj fullPath] ) ){ continue; } // filename did change //[shelfController detachObject:fileObj]; [self fileNameOf:fileObj didChangeTo:[savePanel filename]]; } return self; } - saveAs:sender { int rtn, i; char *fName; SavePanel *savePanel = [SavePanel new]; BibliographicFile *fileObj = [browserController selectedFile]; [savePanel setRequiredFileType:"bib"]; [savePanel setAccessoryView:saveAccessoryView]; rtn = [savePanel runModalForDirectory:[fileObj fullPath] file:[fileObj fileName]]; // Returns NX_OKTAG (if the user clicks the OK button) // or NX_CANCELTAG (if the user clicks the Cancel button) if( rtn == NX_CANCELTAG ) return self; // exists another file with this name? for( i=0; i<[listOfFiles count]; i++ ){ if( sameFile( [savePanel filename], [[listOfFiles objectAt:i] fullPath] ) ){ [self alert: "filename >%s<\n already exists\ncannot SaveAs..." :(char *)[savePanel filename] ]; return self; } } // the new filename is ok fName = NXCopyStringBuffer( [fileObj fullPath] ); // save old name [fileObj changeFilenameTo:[savePanel filename]]; rtn = [fileObj save]; if( rtn<0 ){ [self alert:"cannot not save\n\n %s\n" :[fileObj fullPath] ]; [fileObj changeFilenameTo:fName]; } else [self fileNameOf:fileObj didChangeTo:[savePanel filename]]; free( fName ); return self; } - appWillTerminate:sender { int i; BOOL review = YES; if( [texObject isRunning] ) [texObject stopRunning:self]; // are there some changed files ? for( i=0; i<[listOfFiles count]; i++ ){ BibliographicFile *fileObj = [listOfFiles objectAt:i]; if( [fileObj isDirty]==YES ){ int rtn = NXRunAlertPanel("Bibliography", // title "There are edited windows", // message " Review Unsaved ", // 1: default button " Quit anyway ", // 0: alternate " Cancel " //-1: other ); if( rtn==NX_ALERTDEFAULT ){ // Review Unsaved review = YES; break; } if( rtn==NX_ALERTALTERNATE ){ // Quit anyway review = NO; break; } if( rtn==NX_ALERTOTHER ) return nil; // cancel } } if( review==YES ) for( i=0; i<[listOfFiles count]; i++ ){ BibliographicFile *fileObj = [listOfFiles objectAt:i]; if( [fileObj isDirty]==YES ){ int rtn = NXRunAlertPanel("Bibliography", // title "changed file:\n%s", // message " save ", // 1: default button " close anyway ", // 0: alternate " cancel ", //-1: other [fileObj fullPath] ); if( rtn==NX_ALERTDEFAULT ){ // save if( [self saveFile:fileObj]<0 ){ [self alert: "cannot not save\n\n %s\n" :[fileObj fullPath] ]; return nil; } } if( rtn==NX_ALERTOTHER ) return nil; // cancel } } // remove the temporary directory if( [preferences shallRemoveTempFiles] ){ char *fff = strrchr( [preferences tempDirectory], '/' ); if( fff==NULL ) return self; [[Application workspace] performFileOperation:WSM_DESTROY_OPERATION source:"/tmp" destination:NULL files:(const char *)(fff + 1) options:NULL]; } return self; } - app:sender fileOperationCompleted:(int)tag { //fprintf( stderr, "fileOperationCompleted %d\n", tag ); return self; } - app:sender powerOffIn:(int)ms andSave:(int)aFlag { return [self appWillTerminate:self]; } - preferences:sender { [preferences show]; return self; } - setFiledataFor:(BibliographicFile *)fileObject { int cpuTime; if( fileObject==NULL ){ [fileNameText setStringValue:""]; [fileSizeText setStringValue:""]; [fileTimeText setStringValue:""]; [numberOfEntriesText setStringValue:""]; return self; } [fileNameText setStringValue:[fileObject fullPath]]; sprintf( buffer, "filesize: %d byte", [fileObject fileSize] ); [fileSizeText setStringValue:buffer]; if( [fileObject entries]==1 ) sprintf( buffer, "1 entry" ); else sprintf( buffer, "%d entries", [fileObject entries] ); [numberOfEntriesText setStringValue:buffer]; cpuTime = [fileObject uTime] + [fileObject sTime]; sprintf( buffer, "%d.%03d sec", cpuTime/1000, cpuTime%1000 ); [fileTimeText setStringValue:buffer]; return self; } // returns a list of all loaded files - (List *) listOfFiles { return listOfFiles; } - selectedFile { return [browserController selectedFile]; } - (void)colZeroIsFilled { [inspector setEntry:(lastMainObject = nil) inFile:(lastMainFile = nil)]; [self setFiledataFor:NULL]; [newEntryButton setEnabled:NO]; [findButton setEnabled:YES]; [preViewButton setEnabled:NO]; } - browserDidChange:sender // sender is BrowserController { DragView *fileView = [self viewFor:fileDragBox]; DragView *entryView = [self viewFor:entryDragBox]; BibliographicFile *fileObj; int cnt; cnt = [[entryView getList] count]; if( cnt>0 ){ // there are selected entries [deleteButton setEnabled:YES]; [preViewButton setEnabled:YES]; if( cnt==1 ) lastMainObject = [[[entryView getList] objectAt:0] object]; else lastMainObject = nil; } else { [deleteButton setEnabled:NO]; [preViewButton setEnabled:NO]; lastMainObject = nil; } // is exactly one file selected ? if( [fileView count]==1 ){ // exactly one file selected [newEntryButton setEnabled:YES]; fileObj = [[[fileView getList] objectAt:0] fileObject]; if( lastMainObject==nil ) [[MacroDB new] fileDidChangeTo:fileObj]; } else{ [[MacroDB new] fileDidChangeTo:nil]; [newEntryButton setEnabled:NO]; fileObj = nil; } // are some entries selected? [self setFiledataFor:fileObj]; lastMainFile = fileObj; [inspector setEntry:lastMainObject inFile:lastMainFile]; return self; } // let this the browserController do !!!! - deleteEntry:sender // (only) called from delete-button { Matrix *matrix = [litBrowser matrixInColumn:[litBrowser lastColumn]]; List *selList = [matrix getSelectedCells:nil]; BibliographicFile *theFile = nil; // makes the compiler happy int i, row, col; if( [selList count]==0 ){ [selList free]; return self; } [findObject deleteEntries:selList]; // delete all in findpanel theFile = [[selList objectAt:0] fileObject]; [theFile setDirty]; //for( i=0; i<[selList count]; i++ ){ for( i=[selList count]-1; i>=0; i-- ){ MyBrowserCell *cell = [selList objectAt:i]; if( lastMainObject==[cell object] ) lastMainObject=nil; [theFile deleteBibObject:[cell object]]; // delete in file [matrix getRow:&row andCol:&col ofCell:cell]; [matrix removeRowAt:row andFree:NO]; } [deleteButton setEnabled:NO]; [matrix sizeToCells]; [matrix sendAction]; [matrix display]; [selList free]; return self; } - newEntry:sender // of predefined type !!!! { [browserController deselectColumn:-1]; [deleteButton setEnabled:NO]; lastMainObject = nil; [inspector newEntryFor:lastMainFile]; return self; } // semaphore - operations - (void) P:sender { semaphore--; } - (void) V:sender { semaphore++; } - (int)semaphore:sender; { return semaphore; } - theShelf { return shelfController; } - (void) getFrameOfFileIcon:(NXRect *)frame { [fileDragBox getFrame:frame]; } - (BrowserController *)browserController { return browserController; } - (DragView *)fileDragView { return [fileDragBox findViewWithTag:DRAGVIEWTAG]; } - (TeXClass *)texObject { if( !texObject ) texObject = [[TeXClass alloc] init]; return texObject; } - macro:sender { id macro; macro = [[MacroDB new] show:sender]; return self; } /************ dragging ************/ // includesType() returns YES if type is included within types. static BOOL includesType (const NXAtom *types, NXAtom type) { if (types) while (*types){ //fprintf( stderr, "%s\n", *types ); if (*types++ == type) return YES; } return NO; } - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender { return [self draggingUpdated:sender]; } - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender { Pasteboard *pboard; char *data, *lastDot, *file, *tab; int length; if( [sender isDraggingSourceLocal]==YES ){ //fprintf( stderr, "it's local\n" ); return NX_DragOperationNone; } if( [sender draggingSourceOperationMask] & NX_DragOperationGeneric) { pboard = [sender draggingPasteboard]; if( includesType([pboard types], NXFilenamePboardType) ){ [pboard readType:NXFilenamePboardType data:&data length:&length]; // is it a list of files ? file = data; while (file) { if (tab = strchr(file, '\t')) { *tab = '\0'; } lastDot = rindex( file, '.' ); if( lastDot==0 ) return NX_DragOperationNone; if ( (strcmp( lastDot, ".bib" ) && strcmp( lastDot, ".bib~" )) ) { // use types !!! return NX_DragOperationNone; } file = (tab) ? ++tab : NULL; } return NX_DragOperationGeneric; } if( includesType( [pboard types], NXAsciiPboardType) ){ return NX_DragOperationGeneric; } } return NX_DragOperationNone; } - draggingExited:sender { //fprintf( stderr, "draggingExited\n" ); return self; } - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender { char *data, *file, *tab; int length; Pasteboard *pboard = [sender draggingPasteboard]; if( includesType([pboard types], NXFilenamePboardType) ){ [pboard readType:NXFilenamePboardType data:&data length:&length]; file = data; while (file) { if (tab = strchr(file, '\t')) { *tab = '\0'; } [self openFile:file]; file = (tab) ? ++tab : NULL; } [browserController resetBrowser:self]; return YES; } return NO; } - windowDidMove:sender { return self; } - update:obj for:aFile isNew:(BOOL)q shiftLit:(BOOL)sl { List *aList = [browserController selectedFiles]; if( [aList count]!=1 ){ // more than one file selected return self; } if( [[aList objectAt:0] fileObject]!=aFile ){ // is this file selected ? return self; } [bibWindow disableDisplay]; [browserController entryObjectChanged:obj]; [deleteButton setEnabled:YES]; [preViewButton setEnabled:YES]; [self setFiledataFor:aFile]; lastMainObject = obj; lastMainFile = aFile; [[bibWindow reenableDisplay] displayIfNeeded]; return self; } - objectForFileNamed:(const char *)fName { int i; for(i=0; i<[listOfFiles count]; i++ ){ if( sameFile( fName, [[listOfFiles objectAt:i] fullPath] ) ){ return [listOfFiles objectAt:i]; } } return nil; } - setBacking:sender { if(0)fprintf( stderr, "state is %d ", [sender state] ); [bibWindow setBackingType: ([sender state]==1) ? NX_BUFFERED :NX_RETAINED]; if(0)fprintf( stderr, " backingType is %d\n", [bibWindow backingType] ); return self; } - windowDidBecomeKey:sender { if( [self semaphore:self] <= 0 ) return self; [self P:self]; if( sender==bibWindow ){ if( lastMainObject==nil ) [inspector setEntry:lastMainObject inFile:lastMainFile]; else{ [inspector setEntry:lastMainObject inFile:lastMainFile ]; } [bibWindow makeFirstResponder:litBrowser]; [findObject setFindText]; } [self V:self]; return self; } - windowDidResize:sender { [browserController windowDidResize:sender]; [shelfController windowDidResize:sender]; return self; } - didFileSystemChange // never used { fprintf( stderr, "fSys changed %d\n", [[Application workspace]didFileSystemChange]); return self; } - LaTeXFromList:(List *)aList tag:(int)tag { if( [aList count]<=0 ) return self; if( !texObject ) texObject = [[TeXClass alloc] init]; [texObject runTeXfor:aList tag:tag]; return self; } - prepareLaTeX:(int)tag { if( [texObject isRunning] ){ [self alert:"bibtex is still running, please wait\n": NULL ]; return self; } [self LaTeXFromList:[[self viewFor:entryDragBox] getList] tag:tag]; return self; } - LaTeX:sender // from menu LaTeX -> RUNLATEX/RUNRTF/RUNHTML { id delegate = [[NXApp mainWindow] delegate]; if( [delegate respondsTo:@selector(prepareLaTeX:)] ) [delegate prepareLaTeX:[[sender selectedCell] tag]]; return self; } - HTML:sender { [[HTML_Stuff new] writeHTMLfor:[listOfFiles objectAt:0]]; return self; } - showPanel:sender { if( !texObject ) texObject = [[TeXClass alloc] init]; [texObject showPanel]; return self; } - printDvi:sender { [texObject printDvi:sender]; return self; } // copy selected entries to copyPasteBoard - copyCitationForEdit { [[self viewFor:entryDragBox] copyCitation:self]; return self; } - copyCitation:sender //€sender is a menu-button { id main = [NXApp mainWindow]; if( [[main delegate] respondsTo:@selector(copyCitationForEdit)] ) [[main delegate] copyCitationForEdit]; return self; } - (int) entryDragMethod { // 0 : drag as citation // 1 : drag as citation return [entryDragButton selectedRow]; } // copy selected text to findPasteBoard - enterSelectionFor:responder { NXSelPt start, end; Pasteboard *pboard; int length; static BufferClass *viewBuffer = nil; // local buffer [responder getSel:&start :&end]; if( (length=end.cp-start.cp)==0 ) return self; if( viewBuffer==nil ) viewBuffer = [[BufferClass alloc] initBufferSize:length+1]; else [viewBuffer setMinSizeTo:length+1]; [responder getSubstring:[viewBuffer buffer] start:start.cp length:length]; // copy selection [viewBuffer setLength:length]; // write to NXFindPboard pboard = [Pasteboard newName:NXFindPboard]; [pboard declareTypes:&NXAsciiPboardType num:1 owner:nil]; [pboard writeType:NXAsciiPboardType data:[viewBuffer buffer] length:length]; [findObject setFindText]; return self; } /* ********* suggestions ******** */ // The following code was send to me by Michael Hawley (c) // Carefully modified by Sven Lehmann to fit at Zoom.app /* * Implement the "suggestion" box, to catch user's comments, * and also a simple tracking mechanism, to send a blip of * mail from the first-time user. This is akin to releasing * helium balloons with postcards that say "If you find me, * send this card back to . . ." -- it should be interesting * to the community to track the free flow of software on * the ethernet. * * If you have any concerns about this, please check with me. * * Michael Hawley * mike@media-lab.mit.edu */ static char *stripnl(char *s) { char *p; for (p=s;*p;p++) if (*p == '\n' || *p == '\r') *p = '\0'; return s; } char *execstr(s) char *s; { FILE *f = popen(s,"r"); char *p = s; *s = '\0'; if (f) { while (fgets(p,256,f)) stripnl(p), p += strlen(p); pclose(f); } return s; } - suggestion: sender { #define call(a,b) [s performRemoteMethod: a with: b length: strlen(b) + 1] char subj[256], w[256] = "whoami"; char body[4096]= "\n\n" " I have these electronic comments:\n\n\n" " <insert comments & suggestions here>\n\n\n" " best regards,\n" " "; id s = [NXApp appSpeaker]; NXPortFromName("Mail", NULL); // make sure app is launched [s setSendPort: NXPortFromName("MailSendDemo", NULL)]; sprintf(subj, "Comments and suggestions for BibTeXfrontend (%s)", Bib_Version); strcat(body, execstr(w)); strcat(body, "\n"); call("setTo:", "giesen@informatik.uni-koblenz.de"); call("setSubject:", subj); call("setBody:", body); return self; } - showFile:(const char *)aFile { char buf[MAXPATHLEN]; NXBundle *m = [NXBundle mainBundle]; // load the file from the bundle if( [m getPath:buf forResource:aFile ofType:"rtf"] ){ [[Application workspace] openFile:buf withApplication:"Edit"]; } return self; } - showReadme:sender { return [self showFile:"Readme"]; } - showUsage:sender { return [self showFile:"Usage"]; } - app:sender willShowHelpPanel:panel { #ifdef PLP char path[MAXPATHLEN + 1]; fprintf( stderr,"%s willShowHelpPanel at %s\n", [sender name], [panel helpDirectory] ); sprintf (path, "%s/%s", [panel helpDirectory], "Edit/Cut.cmd.rtfd"); [panel showFile:"/tmp/Edit/Cut.cmd.rtfd" atMarker:NULL]; #endif [panel setMiniwindowIcon:"Images/help"]; return self; } - window2eps:sender { //NXStream *imageStream; //NXRect frame; id theWindow = [NXApp keyWindow]; if( theWindow==nil ){ fprintf( stderr, "there is no keyWindow\n" ); theWindow = [NXApp mainWindow]; if( theWindow==nil ){ fprintf( stderr, "there is no mainWindow\n" ); return self; } } [theWindow printPSCode:self]; // method to create a file return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.