This is MacroDB.m in view mode; [Download] [Up]
// Copyright H. Giesen, University of Koblenz-Landau 1996
#import "MacroDB.h"
#import "Controller.h"
#import "BibliographicFile.h"
#import "Preferences.h"
#import "BibTexView.h"
#import "TabMatrix.h"
#import <dbkit/dbkit.h>
static id macroDB = nil;
#define STRING_MODE 301
#define MACRO_MODE 302
#define STYLE_MODE 303
@implementation MacroDB
+ new
{
if( macroDB==nil ){
macroDB = [[super alloc] init];
}
return macroDB;
}
+ alloc
{
return [self notImplemented:_cmd];
}
- (void)alert:(const char *)txt :(const char *)para
{
NXRunAlertPanel("Bibliography",
txt,
" OK ", // 1: default button
NULL, // 0: alternate
NULL, //-1: other
para
);
}
- makeTabMatrix
{
NXRect backgroundRect,matrixRect;
TabSelectionCell *aCell;
unsigned int entryFormMask = [tabCellView autosizing]; //€as set in IB
/* Set tabCellView to be flipped ('cause Matrices are flipped) */
[tabCellView setFlipped:YES];
/* Get the tabCellView's dimensions */
[tabCellView getBounds:&backgroundRect];
/* Set up the matrix bounds */
matrixRect = backgroundRect;
matrixRect.origin.y = NX_MAXY(&matrixRect) - 17.0;
/* Prepare a matrix to go inside the tabCellView */
tabMatrix = [[Matrix allocFromZone:[self zone]] initFrame:&matrixRect
mode:NX_RADIOMODE
cellClass:[TabSelectionCell class]
numRows:1
numCols:3];
/* Set the background gray of tabMatrix to NX_DKGRAY */
[tabMatrix setBackgroundGray:NX_DKGRAY];
/* Set the autosizing and autoscrolling attributes of the matrix */
[tabMatrix setAutosizing:entryFormMask];
//[tabMatrix setAutoscroll:YES];
[tabMatrix setAutosizeCells:YES];
/* Stick the matrix in our scrollView */
[tabCellView addSubview:tabMatrix];
[tabCellView setAutoresizeSubviews:YES];
[tabCellView setAutosizing:entryFormMask];
/* Set our target and single-click actions */
[tabMatrix setTarget:self];
[tabMatrix setAction:@selector(tabMatrixAction:)];
aCell = [tabMatrix cellAt:0 :0];
[aCell initTextCell:"strings"];
aCell = [tabMatrix cellAt:0 :1];
[aCell initTextCell:"macros"];
aCell = [tabMatrix cellAt:0 :2];
[aCell initTextCell:"styles"];
/* Size tabMatrix to its cells and display it */
[tabMatrix sizeToCells];
[tabMatrix display];
return self;
}
- tabMatrixAction:sender
{
[[mainBox window] disableDisplay];
displayMode = [sender selectedCol] + STRING_MODE;
switch( displayMode ){
case STRING_MODE:
case MACRO_MODE:
[mainBox setContentView:stringView];
[self show:self];
break;
case STYLE_MODE:
[mainBox setContentView:styleBrowserBox];
break;
default : break;
}
[[mainBox window] reenableDisplay];
[mainBox display];
return self;
}
- awakeFromNib
{
[[mainBox window] setFrameUsingName:"MacroWindow"];
[[mainBox window] setFrameAutosaveName:"MacroWindow"];
[stringView setRowHeadingVisible:NO];
[stringView setColumnHeadingVisible:YES];
[stringView allowVectorReordering:YES];
[stringView allowVectorResizing:YES];
[stringView setDataSource:self];
[stringView setTarget:self];
[stringView setDelegate:self];
[stringView setAction:@selector(tableViewSingleClick:)];
[stringView setDoubleAction:@selector(tableViewDoubleClick:)];
[stringView setGridVisible:YES];
preferences = [Preferences new];
STRING = [preferences indexOfEntryname:"STRING"];
NOTE = [preferences indexOfFieldname:"NOTE"];
[mainBox setContentView:stringView];
displayMode = STRING_MODE;
// style browser
[styleBrowser setDelegate:self];
[styleBrowser setTarget:self];
[styleBrowser setAction:@selector(styleSingleClick:)];
[styleBrowser setDoubleAction:@selector(styleDoubleClick:)];
[styleBrowser setMinColumnWidth:22];
[styleBrowser setMaxVisibleColumns:2];
[styleBrowser setTitle:"TEXINPUTS" ofColumn:0];
styleFile = NXCopyStringBuffer( "no style file selected" );
[self makeTabMatrix];
return self;
}
- fileDidChangeTo:theFile
{
if( dbWindow && [dbWindow isVisible] && (displayMode==STRING_MODE) ){
[self show:self file:theFile];
}
return self;
}
/*======================================================================
* methods (delegate methods and others) for the style browser
*======================================================================*/
// browser delegate methods
#include <sys/dir.h> /* POSIX applications #include <dirent.h> */
- (BOOL)isDirectory:(const char *)path
{
struct stat fBuf;
int rtn = stat(path, &fBuf);
if( rtn<0 ){
perror("stat error");
return NO;
}
return (S_IFDIR & fBuf.st_mode) != 0;
}
- styleSingleClick:sender
{
//NXRect aRect;
//NXStream *localStream = NXOpenMemory( NULL, 0, NX_READWRITE );
return self;
//fprintf( stderr, "styleSingleClick\n" );
//[stringButton printPSCode:self]; // TEST
//[stringButton getFrame:&aRect];
//[stringButton convertRect:&aRect fromView:nil];
//[stringButton copyPSCodeInside:&aRect to:localStream];
//NXSaveToFile(localStream, "/tmp/abcde.eps");
//return self;
}
- (char *)nextFunctionName:(NXStream *)aStream
{
char buf[1024];
int i = 0;
while( (mc!=EOF) && NXIsAlpha(mc) ){
buf[i++] = mc;
mc = NXGetc( aStream );
}
buf[i] = '\0';
//fprintf( stderr, ">%s<\n", buf );
return buf;
}
- skipEmptyText:(NXStream *)aStream
{
while( (mc!=EOF) && (NXIsSpace(mc) || (mc=='%')) ){
if( mc=='%' ){
mc = NXGetc( aStream ); // skip '%'
while( (mc!=EOF) && (mc!='\n') ) mc = NXGetc( aStream );
// mc == '\n' || mc==EOF
}
else mc = NXGetc( aStream );
}
return self;
}
- skipString:(NXStream *)aStream
{
if( mc!='"' ) return self; // internal error
mc = NXGetc( aStream ); // skip stringquote
while( YES ){
if( (mc=='"') || (mc==EOF) ) return self;
mc = NXGetc( aStream );
}
return self;
}
- skipParameter:(NXStream *)aStream
{
int braceLevel = 1;
// mc == LBRACE
while( braceLevel && (mc!=EOF) ){
mc = NXGetc( aStream );
if( mc=='%' ) [self skipEmptyText:aStream];
if( mc=='"' ) [self skipString:aStream];
if( mc==RBRACE ) braceLevel--;
if( mc==LBRACE ) braceLevel++;
}
mc = NXGetc( aStream ); // skip RBRACE
return self;
}
- readMacro:(NXStream *)aStream
{
// we need a stream for the definitions
if( !texStream ){
texStream = NXOpenMemory(NULL, 0, NX_READWRITE);
NXSeek(texStream, 0, NX_FROMSTART);
NXPrintf( texStream, "macros "); // we may not start with index 0 !
}
[self skipEmptyText:aStream];
// mc must now be LBRACE
mc = NXGetc( aStream ); // skip LBRACE
[self skipEmptyText:aStream];
// collect the macro name
[macroList addObject:(id)NXTell( texStream )]; // here starts the macro
while( NXIsAlpha(mc) ){
NXPutc( texStream, mc);
mc = NXGetc( aStream );
}
NXPutc( texStream, '\0');
[self skipEmptyText:aStream];
mc = NXGetc( aStream ); // skip RBRACE
[self skipEmptyText:aStream];
// mc must be LBRACE
mc = NXGetc( aStream ); // skip LBRACE
// collect the macro text
while( mc!=RBRACE ){
NXPutc( texStream, mc);
mc = NXGetc( aStream );
}
NXPutc( texStream, '\0');
mc = NXGetc( aStream ); // skip RBRACE
return self;
}
- initFromStream:(NXStream *)aStream
{
char *theName;
styleStream = aStream;
if( styleStream==NULL ){
//[self alert:"cannot open %s" :fname];
return self;
}
// we need a stream for the macro definitions
if( !texStream ){
texStream = NXOpenMemory(NULL, 0, NX_READWRITE);
}
NXSeek(texStream, 0, NX_FROMSTART);
NXPrintf( texStream, "macros "); // we may not start with index 0 !
if( macroList==nil ) macroList = [[List alloc] initCount:50];
[macroList empty];
mc = NXGetc( styleStream );
while( (mc!=EOF) ){
[self skipEmptyText:styleStream];
theName = [self nextFunctionName:styleStream];
if( strcasecmp( theName, "macro" )==0 ){
[self readMacro:styleStream];
}
[self skipEmptyText:styleStream];
while( mc==LBRACE ){ // skip a parameter list
[self skipParameter:styleStream];
}
}
return self;
}
- (BOOL) initFromFile:(const char *)fname
{
NXStream *fileStream = NXMapFile(fname, NX_READONLY);
if( fileStream==NULL ){
[self alert:"cannot open file %s" :fname];
return NO;
}
if( styleFile ) free( styleFile );
styleFile = NXCopyStringBuffer( fname );
[self initFromStream:fileStream];
NXCloseMemory( fileStream, NX_FREEBUFFER );
return YES;
}
- styleDoubleClick:sender
{
char path[1024];
int selCol = [sender selectedColumn];
//fprintf( stderr, "styleDoubleClick\n" );
if( selCol==0 ) return self;
[styleBrowser getPath:path toColumn:selCol+1]; // starts with //
if( [self initFromFile:(path+1)]==NO ) return self;
if(0)[[Application workspace] openFile:(path+1)
withApplication:[preferences theEditor]];
//[popUpButton setTitle:"macros"];
[tabMatrix selectCellAt:0 :1];
[dbWindow disableDisplay];
[mainBox setContentView:stringView];
displayMode = MACRO_MODE;
[self show:self];
return self;
}
- (int)fillColZero:locMatrix
{
int i=0, row=0;
id newCell;
char buffer[1024];
List *args = [preferences shellArgsOf:"TEXINPUTS"
toBuffer:buffer size:1024];
if (args==nil ){
//fprintf( stderr, "Erorr: no variable TEXINPUTS\n" );
args = [[List alloc] init];
[args addObject:(id)"."];
[args addObject:(id)"/usr/lib/tex/inputs"]; // default
}
for( i=0; i<[args count]; i++ ){
const char *para = (const char *)[args objectAt:i];
if( para[0]=='\0' ) continue; // (empty string)
[locMatrix addRow];
newCell = [locMatrix cellAt:row :0];
row++;
if( strcmp(para, ".")==0 ){
[newCell setStringValue:[preferences tempDirectory]];
//[newCell setStringValue:NXHomeDirectory()];
}
else{
[newCell setStringValue:para];
}
[newCell setLeaf:NO];
[newCell setLoaded:YES];
}
[args free];
return row;
}
- (int)fillMatrix:locMatrix
{
DIR *dirp;
struct direct *dp;
int length;
int count = 0;
id newCell;
char path[1024];
char buffer[1024];
[styleBrowser getPath:path
toColumn:[styleBrowser selectedColumn]+1];
// path starts with "//", do not use the first character
dirp = opendir( path+1 );
if( dirp==NULL ){
sprintf( buffer, "%s\n%s", path+1, strerror(errno) );
[self alert:" %s" :buffer];
return 0;
}
for( dp = readdir(dirp); dp != NULL; dp = readdir(dirp) ) {
length = strlen( dp->d_name );
if( length<=4 ) continue;
// show also directories
sprintf( buffer, "%s/%s", path+1, dp->d_name );
if( NO && [self isDirectory:buffer] ){
[locMatrix addRow];
newCell = [locMatrix cellAt:count :0];
[newCell setStringValue:dp->d_name];
[newCell setLeaf:NO];
[newCell setLoaded:YES];
count++;
continue;
}
if( dp->d_name[length-4]=='.' &&
dp->d_name[length-3]=='b' &&
dp->d_name[length-2]=='s' &&
dp->d_name[length-1]=='t'
){
[locMatrix addRow];
newCell = [locMatrix cellAt:count :0];
[newCell setStringValue:dp->d_name];
[newCell setLeaf:YES];
[newCell setLoaded:YES];
count++;
}
}
closedir(dirp);
return count;
}
- (int)browser:sender fillMatrix:locMatrix inColumn:(int)column
{
//id matrix = [theBrowser matrixInColumn:column-1];
//int index = [matrix selectedRow];
if( column==0 ){
return [self fillColZero:locMatrix];
}
return [self fillMatrix:locMatrix];
}
/*======================================================================*/
- tableViewSingleClick:sender
{
int col = [sender selectedColumn];
int row = [sender selectedRow];
View *colHead = [sender columnHeading];
NXRect aRect;
[colHead getVisibleRect:&aRect];
if( row<0 ){
[stringButton setEnabled:NO];
[expndStrButton setEnabled:NO];
}
else{
[stringButton setEnabled:YES];
[expndStrButton setEnabled:YES];
}
if(0)fprintf( stderr, "selection is row(%d/%d) col(%d/%d)\n",
[sender selectedRow], [sender rowCount],
col, [sender columnCount] );
return self;
}
- tableViewDoubleClick:sender
{
//fprintf( stderr, "tableViewDoubleClick %s\n", [sender name] );
return self;
}
- insertString:sender
{
id <DBTableVectors> vector;
id rowIdentifier;
int here;
int row = [stringView selectedRow];
char buf[1024];
if( row<0 ) return self;
vector = [stringView rowAt:row];
rowIdentifier = [vector identifier];
switch( displayMode ){
case STRING_MODE :
[rowIdentifier parseSelf];
[rowIdentifier copyRange:[rowIdentifier key] toBuffer:(buf+1)];
break;
case MACRO_MODE :
here = (int)[macroList objectAt:(int)rowIdentifier];
sprintf( (buf+1), ¯oBuffer[here] );
break;
default : return self;
}
buf[0] = '@';
[[BibTexView new] insertMacro:buf isRaw:NO];
return self;
}
- insertExpandedString:sender
{
int here;
id <DBTableVectors> vector;
id rowIdentifier;
int row = [stringView selectedRow];
char buf[1024];
if( row<0 ) return self;
vector = [stringView rowAt:row];
rowIdentifier = [vector identifier];
switch( displayMode ){
case STRING_MODE :
[rowIdentifier parseSelf];
[rowIdentifier
convertRawField:[rowIdentifier fieldFor:NOTE] to:buf];
[[BibTexView new] insertMacro:buf isRaw:NO];
break;
case MACRO_MODE :
here = (int)[macroList objectAt:(int)rowIdentifier];
while( macroBuffer[here++] ); // skip the definition
[[BibTexView new] insertMacro:¯oBuffer[here] isRaw:YES];
break;
default : return self;
}
return self;
}
- show:sender file:selFile
{
int i;
char buffer[128];
id <DBTableVectors> vector;
///id selFile = [[NXApp delegate] selectedFile];
id anObj;
id typedList;
if( !dbWindow ){ // first call
[NXApp loadNibSection:"macroWindow.nib" owner:self];
}
if( sender!=self )[dbWindow orderFront:self];
if( displayMode==STYLE_MODE ) return self;
if(0)fprintf( stderr, "show obj %08x\n", (unsigned)selFile );
if(0)fprintf( stderr, "show file %s\n", [selFile fullPath] );
[stringButton setEnabled:NO];
[expndStrButton setEnabled:NO];
//if( selFile==nil ) return self;
if( [dbWindow isDisplayEnabled] ) [dbWindow disableDisplay];
for(i=[stringView rowCount]-1; i>=0; i-- ){
id row = [stringView rowAt:i];
[stringView removeRowAt:i]; // remove from display
[row free];
}
for(i=[stringView columnCount]-1; i>=0; i-- ){
id col = [stringView columnAt:i];
[stringView removeColumnAt:i]; // remove from display
[col free];
}
if( displayMode==MACRO_MODE ){ //show MACRO
[stringButton setTitle:"insert macro"];
[expndStrButton setTitle:"insert expanded macro"];
[stringView addColumn:(id)0 withTitle:"Macro"];
[stringView addColumn:(id)1 withTitle:styleFile ];
if( macroList && texStream ){
NXGetMemoryBuffer( texStream, ¯oBuffer, &len, &maxLength);
for( i=0; i<[macroList count]; i++ ){
[stringView addRow:(id)i withTitle:
¯oBuffer[(int)[macroList objectAt:i]] ];
}
}
}
else{ //show @STRING
[stringButton setTitle:"insert string"];
[expndStrButton setTitle:"insert expanded string"];
[stringView addColumn:(id)0 withTitle:"String"];
if( selFile==nil ){
[stringView addColumn:(id)1 withTitle:"no or multiple selection" ];
}
else {
[stringView addColumn:(id)1 withTitle:[selFile fullPath] ];
typedList = [selFile listForType:STRING sorted:YES];
for( i=0; i<[typedList count]; i++ ){
anObj = [typedList objectAt:i];
[anObj copyRange:[anObj key] toBuffer:buffer];
[stringView addRow:anObj withTitle:buffer];
//[stringView addRow:anObj at:i+1];
}
}
}
vector = [stringView columnAt:0];
[vector setMaxSize:100.0];
[stringView layoutChanged:self];
if( sender!=self )[dbWindow orderFront:self];
[dbWindow reenableDisplay];
[dbWindow display];
[stringView setEditable:YES];
return self;
}
- show:sender
{
return [self show:sender file:[[NXApp delegate] selectedFile]];
}
/*======================================================================
* DBTableView data source (pseudo-delegate) methods
*======================================================================*/
- tableViewDidChangeSelection:aTableView
{
[self tableViewSingleClick:aTableView];
return self;
}
- (unsigned int)rowCount
{
//fprintf( stderr, "rowCount\n" );
return 0;
}
- (unsigned int)columnCount
{
fprintf( stderr, "columnCount\n" );
return 2;
}
/* DBTV sends this message when it needs to know what to display */
- getValueFor:identifier at:(unsigned int)aPosition into:aValue
{
//fprintf( stderr, "getValueFor %d at %d\n", (int)identifier, aPosition );
[aValue setIntValue:5*aPosition];
return nil;
}
/* DBTV sends this message when it needs to know what to display */
- getValueFor:rowIdentifier :colIdentifier into:aValue
{
int here;
if(0)fprintf( stderr, "getValueFor row(%d)/col(%d)\n",
(unsigned)rowIdentifier, (unsigned)colIdentifier );
if( displayMode==STRING_MODE ){
// show @STRING
// rowIdentifier is an entryObject
// colIdentifier is the column number
[rowIdentifier parseSelf];
if( (int)colIdentifier==0 ){ //String
[rowIdentifier setStringOf: [rowIdentifier key] to:aValue];
}
if( (int)colIdentifier==1 ){ //Expansion
[rowIdentifier setStringOf:
[rowIdentifier fieldFor:NOTE] to:aValue];
}
return nil;
}
// displayMode==MACRO_MODE
// rowIdentifier is the row number ( = index in macroList)
// colIdentifier is the column number
here = (int)[macroList objectAt:(int)rowIdentifier];
if( (int)colIdentifier==0 ){ // macro name
[aValue setStringValue: ¯oBuffer[here]];
//fprintf( stderr, "0: %s\n", ¯oBuffer[here] );
}
if( (int)colIdentifier==1 ){ //Expansion
while( macroBuffer[here++] ); // skip the definition
//fprintf( stderr, "0: %s\n", ¯oBuffer[here] );
[aValue setStringValue: ¯oBuffer[here]];
}
return nil;
}
/* DBTV sends this message when data in a cell has changed */
- setValueFor:identifier at:(unsigned int)aPosition from:aValue
{
fprintf( stderr, "setValueFor at %d\n", aPosition );
return nil;
}
- setValueFor:rowIdentifier :columnIdentifier from:aValue
{
fprintf( stderr, "setValueFor row=%d col=%d\n",
(int)rowIdentifier, (int)columnIdentifier );
return nil;
}
/*======================================================================
* end of DBTableView data
*======================================================================*/
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.