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.