ftp.nice.ch/pub/next/text/tex/apps/Bibliography.1.2a.s.tar.gz#/Bibliography.1.2a/TeXClass.m

This is TeXClass.m in view mode; [Download] [Up]


//	Copyright H. Giesen, University of Koblenz-Landau 1996


#import "Controller.h"
#import "TeXClass.h"
#import "BibTeXObject.h"
#import "BibliographicFile.h"
#import "MyBrowserCell.h"
#import "Preferences.h"
#import "Subprocess.h"
#import "Bbl2rtf.h"

static	char	*fName = "Bib";

char	buf[1024];

static	char *texType[] = 
	{	"tex",
		NULL
	};

//	special entryNames
static	int	STRING = -1;
static	int	PREAMBLE = -1;


@implementation TeXClass


- (void)alert:(char *)txt :(char *)para
{
	NXRunAlertPanel("Bibliography",
				txt,
				"  OK ",	// 1: default button
				NULL,		// 0: alternate
				NULL, 		//-1: other
				para
				);
}


- init
/*
	creates the popUpList as pushDownList
*/

{
	[super init];
	if( !myPanel ){
		[NXApp loadNibSection:"TeX.nib" owner:self];
	}
	[splitView addSubview:upperView];	// default template view
	[splitView addSubview:lowerView];

	[texText setDelegate:self];

	popUpList = [[PopUpList alloc] init];
	[popUpList changeButtonTitle:NO];	// is now a pullDownMenu
	[popUpButton setTitle:"open file"];
	[popUpButton setEnabled:NO];

	filesExist = NO;
	[myPanel setFrameUsingName:"TeXWindow"];
	[myPanel setFrameAutosaveName:"TeXWindow"];
	[myPanel setMiniwindowIcon:"multiBook"];
	//[myPanel orderFront:self];
	//[myPanel display];

	return self;
}


- (void) setup
{
	preferences = [Preferences new];
	//	get temporary directory name from preferences
	bibDir = [preferences tempDirectory];
	sprintf( buf, "TeXfiles are in directory: %s", bibDir );
	[directoryTextField setStringValue:buf];
	// load the templatefile (if it exists)
	[self loadTemplateFile:[preferences templateFile]];
	STRING = [preferences indexOfEntryname:"STRING"];
	PREAMBLE = [preferences indexOfEntryname:"PREAMBLE"];

	[self buildPreviewMenuFor:preViewButton];
}


- (void)showPanel	// called from mainmenu
{
	if( preferences==nil ) [self setup];
	[myPanel orderFront:self];
}


- (void)copyObject:(BibTeXObject*)obj ofType:(int)type
{
	if( [obj entryType]==type ){ 
		NXPutc( texStream, '\n');
		[obj copyToStream:texStream];
		NXPutc( texStream, '\n');
	}
}


- (void)copy:(List *)aList toFile:(const char *)aFile
//	'aList' is the list of browsercells of class MyBrowserCell
{
	int	i, j;
	id	fileList = [[List alloc] init];

	if( !texStream )
		texStream = NXOpenMemory(NULL, 0, NX_READWRITE);

	NXSeek(texStream, 0, NX_FROMSTART);

	// how many files are involved ?
	for( i=0; i<[aList count]; i++ ){
		[fileList addObjectIfAbsent:[[aList objectAt:i] fileObject]];
	}
	//	copy all entries to the desired file

	//		first copy PREAMBLE from ALL source files
	for( j=0; j<[fileList count]; j++ ){
		BibliographicFile *theFile = [fileList objectAt:j];
		for( i=0; i<[theFile entries]; i++ ){
			[self copyObject:[theFile objectAt:i] ofType:PREAMBLE];
		}
	}

	// we need ALL STRINGs from ALL source files
	for( j=0; j<[fileList count]; j++ ){
		BibliographicFile *theFile = [fileList objectAt:j];
		for( i=0; i<[theFile entries]; i++ ){
			[self copyObject:[theFile objectAt:i] ofType:STRING];
		}
	}

	//		and now the rest
	for( i=0; i<[aList count]; i++ ){
		id	entryObj = [[aList objectAt:i] object];
		if( !( ([entryObj entryType]==PREAMBLE)
			|| ([entryObj entryType]==STRING)) ){ 
			NXPutc( texStream, '\n');
			[entryObj copyToStream:texStream];
			NXPutc( texStream, '\n');
		}
	}

	NXFlush( texStream );
	NXSaveToFile( texStream, aFile );
	NXCloseMemory( texStream, NX_FREEBUFFER );
	texStream = NULL;
	[fileList free];
}


- (PopUpList *)buildPreviewMenuFor:aButton
{
	PopUpList	*previewList = [[PopUpList alloc] init];
	Menu		*subMenu;
	Matrix		*menuList;
	MenuCell	*menuCell, *popUpCell;
	int			i;

	subMenu = [[[NXApp mainMenu] findCellWithTag:6] target];
	menuList = [subMenu itemList];

	for( i=1; i<=4; i++ ){
		menuCell = [menuList cellAt:i :0];
		popUpCell = [previewList addItem:[menuCell title]];
		[popUpCell setTarget:[menuCell target]];
		[popUpCell setAction:[menuCell action]];
		[popUpCell setTag:[menuCell tag]];
	}

	NXAttachPopUpList( aButton, previewList );
	[aButton setTitle:"preview..."];
	//[previewList sizeButton:aButton];
	[aButton setEnabled:YES];
	[previewList changeButtonTitle:NO];	// is now a pullDownMenu
	//[aButton display];
	return previewList;
}


#include <sys/dir.h>	/* POSIX applications #include <dirent.h> */

- (void)popUpAllFiles
{
	DIR	*dirp;
	struct direct *dp;

	dirp = opendir( bibDir );
	if( dirp==NULL ){
		sprintf( buf, "%s\n%s", bibDir, strerror(errno) );
		[self alert:"  %s" :buf];
		return;
	}
	for( dp = readdir(dirp); dp != NULL; dp = readdir(dirp) ) {
		char *fn = dp->d_name;	// filename
		if( fn[0]=='_' ) continue;
		if( fn[0]=='.' && fn[1]=='\0' ) continue;
		if( fn[0]=='.' && fn[1]=='.' && fn[2]=='\0' ) continue;
		[popUpList addItem:fn];
	}
	closedir(dirp);
	NXAttachPopUpList( popUpButton, popUpList );
	[[popUpList setAction:@selector(bibPopup:)] setTarget:self];
	[popUpList sizeButton:popUpButton];
	[popUpButton setEnabled:YES];
	[[popUpButton window] display];
}


- (void)bibPopup:sender	// sender is Matrix
{
	int	 isCmd = [sender mouseDownFlags]&(NX_COMMANDMASK|NX_CONTROLMASK);
	BOOL rtn;

	if( [sender selectedRow]==0 ) return;


#ifdef SomeKeyBoardMasks
#define	NX_ALPHASHIFTMASK	(1 << 16)	/* if alpha lock is on */
#define	NX_SHIFTMASK		(1 << 17)	/* if shift key is down */
#define NX_CONTROLMASK		(1 << 18)	/* if control key is down */
#define NX_ALTERNATEMASK	(1 << 19)	/* if alt key is down */
#define NX_COMMANDMASK		(1 << 20)	/* if command key is down */
#define NX_NUMERICPADMASK	(1 << 21)	/* if key on numeric pad */
#define NX_HELPMASK			(1 << 22)	/* if help key is down */
#endif

	sprintf( buf, "%s/%s", bibDir, [[sender selectedCell] title] );

	if(isCmd)
		rtn = [[Application workspace] openFile:buf withApplication:"Edit"];
	else
		rtn = [[Application workspace] openFile:buf];

	if( rtn==NO )
		NXRunAlertPanel ("Can't open file",
			"The file %s could not be opened",
			NULL, NULL, NULL, buf);

}

//	the subprocess has come to an end
- (void)showFormatted:sender
{
	char	*data;
	int	length;
	BOOL	rtn;
	pboard = [Pasteboard newName:NXDragPboard];
	
	[[theView setSel:0 :[theView textLength]] replaceSel:NULL];	// clear

	if( previewType==RUNRTF ){
		[self createRtf:sender];
		return;
	}
	if( previewType==RUNHTML ){
		[self createHTML:sender];
		return;
	}
	sprintf( buf, "%s/%s.eps", bibDir, fName );
/*  place the name of the file on the pasteboard. */
	[pboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
	[pboard writeType:NXFilenamePboardType
		data:buf length:strlen( buf )+1];
	[pboard readType:NXFilenamePboardType data:&data length:&length];
	[theView draggingEntered:(id <NXDraggingInfo>)self];
	rtn = [theView prepareForDragOperation:(id <NXDraggingInfo>)self];
	if( rtn==YES ){
		rtn = [theView performDragOperation:(id <NXDraggingInfo>)self];
	}

	if( rtn==YES ){
		[theView concludeDragOperation:(id <NXDraggingInfo>)self];
	}
}


- (BOOL)saveFile:(const char *)theFile from:view
{
	int			fd;
	NXStream	*stream;

	fd = open(theFile, O_CREAT | O_WRONLY | O_TRUNC, 0666);
	stream = NXOpenFile(fd, NX_WRITEONLY);
	if( stream==NULL ) return NO;
	[view writeText:stream];
	NXFlush(stream);
	NXClose(stream);
	close(fd);

	return YES;
}


- (BOOL)loadFile:(const char *)theFile to:view
{
	NXStream *memStream;
	 
	if( access(theFile, R_OK)==0 ){	// read from file
		memStream = NXMapFile([preferences templateFile], NX_READONLY);
		[view readText:memStream];
		NXCloseMemory( memStream, NX_FREEBUFFER );
		return YES;
	}
	return NO;
}


// saves the content of the scrollView = texText to 'theFile'
- saveTextToFile:(const char *)theFile
{
	if( [self saveFile:theFile from:texText] ){
		[myPanel setDocEdited:NO];
		return self;
	}

	NXRunAlertPanel ("Bibliography", 		// title
			"The file %s could not be opened",	// message
			"  OK ",		// 1: default button
			NULL,			// 0: alternate
			NULL,			//-1: other
			theFile
		);
	return nil;
}


- (BOOL)restoreFromTeXfile:(const char *)theFile
{
	NXStream *memStream;
	 
	if( access(theFile, W_OK)==0 ){	// read from file
		memStream = NXMapFile(theFile, NX_READONLY);
		[texText readText:memStream];
		NXCloseMemory( memStream, NX_FREEBUFFER );
		return YES;	// file exists
	}
	//	load template ???
	return NO;	// not .tex - file found
}


- placeStopButton
{
	NXRect frame, stopFrame;

	[popUpButton getFrame:&frame];
	[stopButton getFrame:&stopFrame];
	stopFrame.X= frame.X + 11.0;
	stopFrame.Y= frame.Y - 34.0;
	[stopButton setFrame:&stopFrame];
	[[myPanel contentView] replaceSubview:popUpButton with:stopButton];
	[myPanel display];
	return self;
}


- removeStopButton
{
	isRunning = NO;
	[[myPanel contentView] replaceSubview:stopButton with:popUpButton];
	[self popUpAllFiles];
	//[myPanel display];
	return self;
}


- stopRunning:sender
{
	isRunning = NO;
	cancelled = YES;
	[theSubprocess terminate:self];
	return self;
}


static	char* auxText= 
	"\\relax\n"
	"\\bibdata{Bib}\n"
	"\\bibstyle{%s}\n"
	"\\citation{*}\n";
	

//	creates an .aux-file and runs bibtex
- runRTFfor:aList
{
	int			fd;
	const char	*shell;

	sprintf( buf, "%s/%s.bbl", bibDir, fName );
	if(0)if( access(buf, R_OK)==0 ){
		[self showFormatted:self];	// ??? maybe the style€changed !!!
		return self;
	}
	unlink( buf );
	//sprintf( buf, "%s/%s.aux", bibDir, fName );	unlink( buf );

	sprintf( buf,	"%s/%s.aux", bibDir, fName );
	fd = open( buf, O_CREAT | O_WRONLY | O_TRUNC, 0666 );
	sprintf( buf, auxText, [preferences theStyle] );
	write( fd, buf, strlen( buf ) );
	close(fd);

	if( aList ){
		sprintf( buf, "%s/%s.bib", bibDir, fName );
		[self copy:aList toFile:(const char *)buf];
	}

	if( preferences==nil ) [self setup];
	shell = [preferences theShell];
	sprintf( buf,	"(cd %s; %s -c 'bibtex %s'\n)",
					bibDir, shell, fName );

	if( theSubprocess ) [theSubprocess free];

	[upperView setDocView:logText];
	[logText clearText];
	[logText setEditable:NO];
	[switchMatrix selectCellAt:1 :0];

	isRunning = YES;
	[self placeStopButton];
	cancelled = NO;
	theSubprocess = [[Subprocess alloc]
		init:buf withDelegate:self];

	return self;
}


//	aList is the list of browserCells of class MyBrowserCell
//	it's not really TeX !
- runTeXfor:aList tag:(int)tag
{
	int	rtn;
	const char *shell;

	if( preferences==nil ) [self setup];
	shell = [preferences theShell];

	previewType = tag;

	if( theSubprocess ) [theSubprocess terminate:self];
	[myPanel orderFront:self];

	if( tag==RUNRTF ){
		[self runRTFfor:aList];
		return self;
	}

	if( tag==RUNHTML ){
		[self runRTFfor:aList];
		return self;
	}

	sprintf( buf, "%s/%s.tex", bibDir, fName );
	if( [myPanel isDocEdited]==YES ){
		rtn = NXRunAlertPanel("Bibliography",
				"TeX text did change, use changed text ?",
				"  YES  ",	// 1: default button
				"  NO  ",	// 0: alternate
				NULL 		//-1: other
				);
		if( rtn==NX_ALERTDEFAULT ){	// use changed text
			[self saveTextToFile:buf];
		}
		else if( [self restoreFromTeXfile:buf]==NO ){
			NXRunAlertPanel("Bibliography",
				"no .tex - file found",
				"  OK  ",	// 1: default button
				NULL,		// 0: alternate
				NULL 		//-1: other
				);
			return self;
		}
	}
	else	[self saveTextToFile:buf];

	if( aList ){
		sprintf( buf, "%s/%s.bib", bibDir, fName );
		[self copy:aList toFile:(const char *)buf];
	}
	//	else: use the already existing .bib - file
	
	// rm *.dvi *.eps *.bbl
	sprintf( buf, "%s/%s.dvi", bibDir, fName );	unlink( buf );
	sprintf( buf, "%s/%s.eps", bibDir, fName );	unlink( buf );
	sprintf( buf, "%s/%s.bbl", bibDir, fName );	unlink( buf );
	sprintf( buf, "%s/%s.aux", bibDir, fName );	unlink( buf );

	sprintf( buf,	"(cd %s; %s -c 'latex %s'\n"
					"%s -c 'bibtex %s'\n"
					"%s -c 'latex %s'\n"
					"%s -c 'latex %s'\n"
					"%s -c 'dvips -E -o %s.eps %s.dvi'\n) 2>&1",
					bibDir, shell, fName,	// cd ... latex
					shell, fName,			// bibtex
					shell, fName,			// latex
					shell, fName,			// latex
					shell, fName, fName		// dvips
			);

	if( theSubprocess ) [theSubprocess free];

	[upperView setDocView:logText];
	[logText clearText];
	[logText setEditable:NO];
	[switchMatrix selectCellAt:1 :0];

	isRunning = YES;
	[self placeStopButton];
	cancelled = NO;
	theSubprocess = [[Subprocess alloc]
		init:buf withDelegate:self];
	return self;
}


 - subprocess:sender done:(int)exitStatus
{
	filesExist = YES;
	[self removeStopButton];
	if( cancelled ) return self;
	//[self popUpAllFiles];
	cancelled = NO;
	[self showFormatted:self];

	return self;
}


 - subprocess:sender output:(char *)buffer;
{
	//fprintf( stderr, "%s\n", buffer );
	[logText addText:buffer];
	[logText addText:"\n"];
	return self;
}


 - subprocess:sender stderrOutput:(char *)buffer;
{
	fprintf( stderr, "%s\n", buffer );
	//[texText addText:buffer];
	return self;
}


 - subprocess:sender error:(const char *)errorString;
{
	fprintf( stderr, "%s\n", errorString );
	//[texText addText:buffer];
	return self;
}


- (BOOL)isRunning
{
	return isRunning;
}


- showUpperView:sender
{
	switch( [sender selectedRow] ){
		case 0: [upperView setDocView:texText]; break;
		case 1: [upperView setDocView:logText]; break;
		default: break;
	}
	return self;
}


- prepareLaTeX:(int)tag
{
	[self runTeXfor:nil tag:tag];
	return self;
}


- createLaTeX:sender
{
	if( [self isRunning] ){
		[self alert:"bibtex is still running, please wait\n": NULL ];
		return self;
	}

	[self prepareLaTeX:RUNLATEX];
	return self;
}


- printDvi:sender
{
	[theView printPSCode:sender];
	return self;
}


- textDidGetKeys:sender isEmpty:(BOOL)flag
{
	[myPanel setDocEdited:YES];
	return self;
}


- saveTemplate:sender	// called from 'save' button
{
	[self saveTextToFile:[preferences templateFile]];
	return self;
}


- loadTemplateFile:(const char *)template
{
	NXStream *memStream;
	 
	if( access(template, W_OK)==0 ){	// read from file
		memStream = NXMapFile(template, NX_READONLY);
		[texText readText:memStream];
		NXCloseMemory( memStream, NX_FREEBUFFER );
	}
	else
		[self loadDefault:self];
	[myPanel setDocEdited:NO];
	return self;
}


- loadTemplate:sender	// called from 'load' button
{
	int	rtn;
	const char* fileName = {NULL};
	id openPanel = [OpenPanel new];

	if ( (rtn=[openPanel runModalForTypes:texType] )
		&& (fileName = [openPanel filename]) ) {
		[self loadTemplateFile:fileName];
		
	}
	else{
		if( rtn==NX_OKTAG )
			[self alert:"cannot not open\n\n      %s\n" :(char *)fileName ];
	}	
	[myPanel setDocEdited:NO];
	return self;
}


- loadDefault:sender	// called from 'default' button
{
	char buf[MAXPATHLEN];
	NXStream  *input;
	id	m = [NXBundle mainBundle];

	// load TeXtemplate from the bundle
	if( [m getPath:buf forResource:"TeXtemplate" ofType:""] ){
		input = NXMapFile(buf, NX_READONLY);
		[texText readText:input];
		NXCloseMemory(input, NX_FREEBUFFER);
	}
	else {
		[self alert:"cannot load default file" :"TeXtemplate"];
		return self;
	}

	[myPanel setDocEdited:NO];

	return self;
}


//	returns the new state of the menuCell
	// YES = enabled
	//	NO = disabled

- (BOOL)updateMenuFor:menuCell
{
	BOOL	newState=NO;	// .. and the compiler keeps silent

	switch( [menuCell tag] ){
		case CUT			:
		case COPY			:
		case PASTE			:
		case SELECTALL		:
		case ENTERSELECTION : newState = YES; break;

		case PRVWINDOW		: newState = YES; break;
		case RUNLATEX		:
		case RUNRTF			:
		case RUNHTML		: newState = filesExist; break;	// ????
		case PRINT			: newState = filesExist; break;	// ????
		default : newState = [[NXApp delegate]updateMenuFor:menuCell];
				  break;
		}

	return newState;
}


// copy selected text to findPasteBoard

- enterSelection:sender
{
	[[NXApp delegate] enterSelectionFor:[myPanel firstResponder]];

	return self;
}


//	creates rtf-text (and a file!) from a .bbl-file
- createRtf:sender
{
	id	rtfObject;
	NXStream *textStream;

	if(0)if( [self isRunning] ){
		[self alert:"bibtex is still running, please wait\n": NULL ];
		return self;
	}

	sprintf( buf, "%s/%s.bbl", bibDir, fName );
	rtfObject = [[Bbl2rtf alloc] initFromFile:buf];
	if( rtfObject ){
		[rtfObject convert2Rtf];	
		sprintf( buf, "%s/%s.rtf", bibDir, fName );
		if( previewType==RUNRTF ){
			textStream = [rtfObject stream];
			NXSeek(textStream, 0, NX_FROMSTART);
			[theView readRichText:textStream];	// CRASH
		}
		[rtfObject saveTo:buf];
		[rtfObject free];
		[self popUpAllFiles];
	}
	return self;
}



- createHTML:sender
{
	id	rtfObject;
	NXStream *textStream;

	if(0)if( [self isRunning] ){
		[self alert:"bibtex is still running, please wait\n": NULL ];
		return self;
	}

	sprintf( buf, "%s/%s.bbl", bibDir, fName );
	rtfObject = [[Bbl2rtf alloc] initFromFile:buf];
	if( rtfObject ){
		[rtfObject convert2HTML];	
		sprintf( buf, "%s/%s.html", bibDir, fName );
		if( previewType==RUNHTML ){
			textStream = [rtfObject stream];
			NXSeek(textStream, 0, NX_FROMSTART);
			[theView readText:textStream];
		}

		[rtfObject saveTo:buf];
		[rtfObject free];
		[self popUpAllFiles];
	}
	return self;
}



//	========= dragging

- (BOOL)isDraggingSourceLocal
{
	//fprintf( stderr, "isDraggingSourceLocal\n" );
	return YES;
}

- draggingSource
{
	//fprintf( stderr, "draggingSource\n" );
	return self;
}

- (NXDragOperation)draggingSourceOperationMask
{
	//fprintf( stderr, "draggingSourceOperationMask\n" );
	return    NX_DragOperationGeneric
			| NX_DragOperationCopy
			| NX_DragOperationPrivate;
}


- draggingDestinationWindow
{
	//fprintf( stderr, "draggingDestinationWindow\n" );
	return nil;
}


- (Pasteboard *)draggingPasteboard
{
	char	*data;
	int		length;
	[pboard readType:NXFilenamePboardType data:&data length:&length];
	return pboard;
}


- (int)draggingSequenceNumber
{
	return 77;
}


- (NXPoint)draggingLocation
{
	NXPoint pnt = {50.0, 50.0};
	return pnt;
}


- (NXImage *)draggedImage
{
	return nil;
}


- (NXImage *)draggedImageCopy
{
	return nil;
}


- (NXPoint)draggedImageLocation
{
	NXPoint pnt = {50.0, 50.0};
	return pnt;
}

- slideDraggedImageTo:(NXPoint *)screenPoint
{	
	return self;
}


- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{	
	return NX_DragOperationCopy;
}

- draggedImage:(NXImage *)image 
		endedAt:(NXPoint *)screenPoint
		deposited:(BOOL)didDeposit
{	
	return nil;
}

		

- saveTexText:sender
{
	return self;
}


@end


These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.