This is Controller.m in view mode; [Download] [Up]
/* $Id: Controller.m,v 1.2 1996/10/12 14:30:34 vkyr Exp vkyr $ */
#import <streams/streams.h>
#import <objc/typedstream.h>
#import <objc/NXStringTable.h>
#import <strings.h>
#import "Controller.h"
#import "DragImageView.h"
#import "PrefsController.h"
#import "Text_Fmt.h"
@implementation Controller
char linelen[100];
char str[100],str2[100];
static char *info_array[50];
int inf_cnt;
/*==========================================================
* initialisation methods
*==========================================================*/
- appDidInit:sender
{
[super init];
[myWindow setDelegate: self];
openReq = [OpenPanel new];
dragImage = [[NXImage alloc] initFromSection:"man.tiff"];
[dragImageView setScaleState:YES];
[dragImageView setImage:dragImage];
[myWindow getFrame: &initViewSize];
[myUnits setTitle:[prefsController whatUnit]]; // Set to DefaultsDB value
if ([prefsController shouldShowWin] == YES) // Startup window?
[[myWindow display] makeKeyAndOrderFront:self];
[self setDummyWindow];
[self setFontsScrollView];
[self setDummyScrollView];
return self;
}
/*==========================================================
* Supporting methods for accessing objects
*==========================================================*/
- getMyWindow
{
return myWindow;
}
- getFonts
{
return fontsScrollView;
}
- getPages
{
return pagesField;
}
- getHeight
{
return heightField;
}
- getWidth
{
return widthField;
}
- getMyUnits
{
return myUnits;
}
- getOpenButton
{
return openButton;
}
/*============================================================
* Update units to be conform to the actual user selection
*============================================================*/
- setMyUnits
{
const char *itemtitle = [[myUnits selectedCell] title];
if (strcasecmp(itemtitle, "Inches") == 0)
[self inches:self];
if (strcasecmp(itemtitle, "Cms") == 0)
[self cms:self];
if (strcasecmp(itemtitle, "Points") == 0)
[self points:self];
if (strcasecmp(itemtitle, "Picas") == 0)
[self picas:self];
return self;
}
- setDummyWindow
{
// Create an invisible dummy window
NXSetRect(&aRect, 0.0, 0.0, 350.0, 150.0);
dummyWindow = [ [Window alloc] initContent: &aRect
style: NX_TITLEDSTYLE backing:NX_BUFFERED
buttonMask:NX_MINIATURIZEBUTTONMASK defer:YES];
return self;
}
- setFontsScrollView
{
// Create a text scrollview that holds the list of used fonts
NXSetRect(&aRect, 0, 0, 293, 180); // Don't change these sizes!!!
fontsScrollView = [ [ScrollView alloc] initFrame: &aRect];
[fontsScrollView setVertScrollerRequired:YES];
[fontsScrollView setHorizScrollerRequired:NO];
[fontsScrollView setBorderType: NX_BEZEL];
//[[dummyWindow contentView] addSubview: fontsScrollView];
[fontsScrollView getContentSize: &aSize];
// create the text object for the fontsScrollView
NXSetRect(&aRect, 2.0, 2.0, aSize.width-2.0, aSize.height-2.0);
fontsText = [ [Text alloc] initFrame: &aRect text: NULL
alignment: NX_LEFTALIGNED];
[fontsText setOpaque:YES];
// notify superview when frame rectangle changes -- allows scroller updates
[fontsText notifyAncestorWhenFrameChanged:YES];
[fontsText setEditable: NO];
[fontsText setVertResizable:YES];
[fontsText setHorizResizable:NO];
// create min and max size of text
aSize.width = 0.0; [fontsText setMinSize: &aSize];
aSize.height = 1000000; [fontsText setMaxSize: &aSize];
// set the text as docview of scrollview
[fontsScrollView setDocView: fontsText];
[[dummyWindow contentView] addSubview: fontsScrollView];
return self;
}
- setDummyScrollView
{
// Create another text scrollview to hold formated stuff for printing
NXSetRect(&aRect, 200.0, 300.0, 350.0, 150.0);
dummyScrollView = [ [ScrollView alloc] initFrame: &aRect];
[dummyScrollView setVertScrollerRequired:YES];
[dummyScrollView setHorizScrollerRequired:NO];
//[[dummyWindow contentView] addSubview: dummyScrollView];
[dummyScrollView getContentSize:&aSize];
// Create another text object for this scrollview
NXSetRect(&aRect, 0.0, 0.0, aSize.width, aSize.height);
dummyText = [ [Text alloc] initFrame:&aRect text: NULL
alignment: NX_LEFTALIGNED];
// notify superview when frame rectangle changes -- allows scroller updates
[dummyText notifyAncestorWhenFrameChanged: YES];
[dummyText setVertResizable: YES];
[dummyText setHorizResizable: NO];
[dummyText setMonoFont:NO];
// create min and max size of text
aSize.width = 0.0;
[dummyText setMinSize: &aSize];
aSize.height = 1000000;
[dummyText setMaxSize: &aSize];
// set the text as docview of scrollview
[dummyScrollView setDocView: dummyText];
[[dummyWindow contentView] addSubview: dummyScrollView];
return self;
}
/*==========================================================
* load InfoPanel
*==========================================================*/
- infoPanel:sender
{
if (infoPanel == nil) {
[NXApp loadNibSection:"Info.nib" owner:self];
}
[infoPanel orderFront:sender];
return self;
}
/*==========================================================
* Handle Error-Messages via stringSet
*==========================================================*/
- showError: (const char *)errorMessage
{
NXRunAlertPanel(NULL, errorMessage,
[stringSet valueForStringKey:"OK"], NULL, NULL);
return self;
}
- selectAll:sender
{
int currentLength = [[fontsScrollView docView] textLength];
[[fontsScrollView docView] setSel:0 :currentLength];
return self;
}
// appAcceptsAnotherFile is an application delegate method which
// returns whether it is OK for the application to try to open more files
// with the appOpenFile:type: method. DviInfo needs this to open dvi-files
// by double-clicking in the WM, so we return YES.
-(BOOL) appAcceptsAnotherFile:sender
{
return (YES);
}
- openInTexview: sender
{
[[Application workspace] openFile: [myWindow title]];
return self;
}
/*=======================================================================
* appOpenFile:type: is called to open the specified file. It is normally
* called by the Application object in response to open requests from the
* Workspace. Here we also route the open requests from the OpenPanel
* to this method (see openRequest:).
*=======================================================================*/
-(int) appOpenFile:(char *)fileName type:(char *)fileType
{
return [self openDviFile:fileName];
}
/*=======================================================================
* openRequest: opens a new file. It puts up a open panel, and, if the user
* doesn't cancel, it reads the specified dvi file. If the selected file
* is not a proper dvi file, then openRequest: will complain.
*=======================================================================*/
- openRequest:sender
{
const char *fileName;
const char *const types[2] = {[stringSet valueForStringKey:"extension"],
NULL};
if ([openReq runModalForTypes:types] && (fileName = [openReq filename])) {
[self openDviFile:fileName];
}
else
[self showError:[stringSet valueForStringKey:"errorOnOpenRequest"]];
return self;
}
/*==========================================================
* The main openDviFile action-method
*==========================================================*/
-(int) openDviFile:(const char *)fileName
{
FILE *dvi_file;
int i;
inf_cnt = 0;
dvi_file = fopen(fileName, "rb");
if (dvi_file == NULL)
{
[self showError:[stringSet valueForStringKey:"errorOnOpen"]];
return NO;
}
else
{
[[fontsScrollView docView] setText:""];
[self process_dvi_file: dvi_file];
fclose(dvi_file);
[myWindow setTitle:fileName];
[self setMyUnits]; // Setup correct values for the selected Unit
[myUnits setEnabled: YES]; // Enable Units popupbutton
[openButton setEnabled: YES]; // Enable TeXview pushbutton
for (i = 0; i < inf_cnt; i++)
[[fontsScrollView docView] printf: info_array[i]];
[[myWindow display] makeKeyAndOrderFront:self];
for (i = 0; i < inf_cnt; i++)
free(info_array[i]);
return YES;
}
}
/*=================================================
*** PLAIN DVI-FILE-FORMAT STUFF BEGINS HERE ...***
*================================================*/
#define post 248
#define post_post 249
#define dvi_id 2
#define nop 138
#define fnt_def1 243
#define fnt_def2 244
#define fnt_def3 245
#define fnt_def4 246
typedef unsigned long four_bytes;
int cur_command;
double unity;
double val, val2;
void print_dimen(four_bytes x)
{
val = unity*x / 10000.0;
if (val > 10)
{
val /= 10;
}
}
void print_dimen2(four_bytes x)
{
val2 = unity*x / 10000.0;
if (val2 > 10)
{
val2 /= 10;
}
}
four_bytes read_unsigned(df, bytes)
FILE *df;
int bytes;
{
four_bytes x;
x = getc(df);
while (bytes-- >1)
{
x *= 256;
x += getc(df);
}
return(x);
}
int reverse_getc(df)
FILE *df;
{
fseek(df, -2, SEEK_CUR);
return(getc(df));
}
- process_dvi_file:(FILE *)df
{
four_bytes design_size, at_size;
four_bytes num, den, magnification;
four_bytes page_width, page_height;
int a, l, pages;
double font_size;
fpos_t post_loc;
fseek(df,0,SEEK_END); /* File-end */
/* Ignore fillbytes i*/
while ((cur_command = reverse_getc(df)) == 223)
;
if (cur_command != dvi_id) {
[self showError:[stringSet valueForStringKey:"wrongIdByte"]];
return self;
}
/* Read backwards till post_post */
reverse_getc(df); reverse_getc(df); reverse_getc(df);
reverse_getc(df); cur_command = reverse_getc(df);
if (cur_command != post_post) {
[self showError:[stringSet valueForStringKey:"noPostamblefound"]];
return self;
}
post_loc = (fpos_t)read_unsigned(df,4);
/* Jump to postamble */
if (fseek(df,post_loc,SEEK_SET) != 0) {
[self showError:[stringSet valueForStringKey:"seekError"]];
return self;
}
if ((cur_command = (int) read_unsigned(df,1)) != post) {
[self showError:[stringSet valueForStringKey:"noPostamblefound"]];
return self;
}
read_unsigned(df,4);
/* Pointer to the begin of the last page */
num = read_unsigned(df,4); den = read_unsigned(df,4);
magnification = read_unsigned(df,4);
unity = (num*((double) magnification/1000))/den;
page_height = read_unsigned(df,4);
page_width = read_unsigned(df,4);
read_unsigned(df,2); /* Ignore stacksize */
pages = (int) read_unsigned(df,2);
[pagesField setIntValue: pages];
print_dimen(page_width);
[widthField setDoubleValue: val];
print_dimen2(page_height);
[heightField setDoubleValue: val2];
info_array[inf_cnt] = (char *)malloc(sizeof(linelen));
while (cur_command != post_post)
{
int lc = 0;
char ftemp[100];
cur_command = (int) read_unsigned(df,1);
switch (cur_command)
{
case nop:
case post_post : break;
case fnt_def1 :
case fnt_def2 :
case fnt_def3 :
case fnt_def4 :
read_unsigned(df,cur_command-fnt_def1+1);
read_unsigned(df,4); /* throw away checksum */
at_size = read_unsigned(df,4);
design_size = read_unsigned(df,4);
a = (int) read_unsigned(df,1);
l = (int) read_unsigned(df,1);
while (a-- > 0)
info_array[inf_cnt][lc++] = getc(df);
while (l-- > 0)
info_array[inf_cnt][lc++] = getc(df);
font_size = (at_size*((double)magnification/1000))/design_size;
info_array[inf_cnt][lc] = '\0';
sprintf(ftemp, "\t\t at magnification \t %5.3f \n", font_size);
strcat(info_array[inf_cnt++], ftemp);
info_array[inf_cnt] = (char *)malloc(sizeof(linelen));
break;
}
}
return self;
}
/*================================================
*** PLAIN DVI-FILE-FORMAT STUFF ENDS HERE ... ***
*===============================================*/
/*=======================================================================
* Print the invisibleView (textview) via printPSCode:
*=======================================================================*/
- printRequest:sender
{
if ([[fontsScrollView docView] textLength] == 0)
[self showError:[stringSet valueForStringKey:"errorOnPrintRequest"]];
else {
[self copytext:self];
[[[NXApp printInfo] setHorizCentered:NO] setVertCentered:NO];
[[dummyScrollView docView] printPSCode:self];
}
return self;
}
/*====================================================================
* copy formated text to invisibleView (activated from printRequest)
*====================================================================*/
- copytext:sender
{
NXStream *stream;
int pagecount, txtlen;
double pagewidth, pageheight;
const char *unitstr;
pagecount = [pagesField intValue];
pagewidth = [widthField doubleValue];
pageheight = [heightField doubleValue];
unitstr = [[myUnits selectedCell] title];
// clear dummyScrollView
[[dummyScrollView docView] setText:""];
[[dummyScrollView docView] printf:"Generated by DviInfo\n\n"];
[[dummyScrollView docView] printf: "File: %s\n\n", [myWindow title]];
[[dummyScrollView docView] printf:"Pages:\t\t%d\n", pagecount];
[[dummyScrollView docView] printf: "Page width:\t%5.3f %s\n", pagewidth, unitstr];
[[dummyScrollView docView] printf: "Page height:\t%5.3f %s\n\n", pageheight, unitstr];
txtlen = [[fontsScrollView docView] textLength];
if (txtlen != 0)
[[dummyScrollView docView] printf: "Used fonts are:\n\n"];
/* Get the entire text, using the rich RTF format */
stream = NXOpenMemory(NULL, 0, NX_READWRITE);
if (stream)
[[fontsScrollView docView] writeRichText: stream]; // write to stream
/* Stick the text from the fontsText into the dummyScrollView */
if (stream)
{
int currentLength = [[dummyScrollView docView] textLength];
[[dummyScrollView docView] setSel:currentLength :currentLength];
NXSeek(stream, 0L, NX_FROMSTART);
[[dummyScrollView docView] replaceSelWithRichText: stream];
[[dummyScrollView docView] scrollSelToVisible];
NXCloseMemory(stream, NX_FREEBUFFER);
}
return self;
}
/*======================================================
* Methods which calculate the dvi-page units
*======================================================*/
double unitval, newval, newval2;
- cms:sender
{
unitval = 1;
[widthField setDoubleValue: val];
[heightField setDoubleValue: val2];
return self;
}
- inches:sender
{
unitval = 0.3937;
[widthField setDoubleValue: val*unitval];
[heightField setDoubleValue: val2*unitval];
return self;
}
- points:sender
{
unitval = 28.346;
if ([prefsController shouldRoundUnit] == YES)
{
newval = rint(val*unitval);
newval2 = rint(val2*unitval);
}
else
{
newval = val*unitval;
newval2 = val2*unitval;
}
[widthField setDoubleValue: newval];
[heightField setDoubleValue: newval2];
return self;
}
- picas:sender
{
unitval = 2.3623;
if ([prefsController shouldRoundUnit] == YES)
{
newval = rint(val*unitval);
newval2 = rint(val2*unitval);
}
else
{
newval = val*unitval;
newval2 = val2*unitval;
}
[widthField setDoubleValue: newval];
[heightField setDoubleValue: newval2];
return self;
}
/*=============================================================
* Window resizing method which adds/hides the fonts scrollview
*=============================================================*/
- resizeWindow:sender
{
NXRect fontsTextFrame, newWinFrame;
[fontsScrollView getFrame: &fontsTextFrame];
NX_HEIGHT(&newWinFrame) = NX_HEIGHT(&initViewSize) +
NX_HEIGHT(&fontsTextFrame);
if ([resizeButton state] == 1)
{
[[myWindow contentView] addSubview: fontsScrollView];
[myWindow sizeWindow:NX_WIDTH(&initViewSize)
:NX_HEIGHT(&newWinFrame) byCorner:3];
}
else
{
[fontsScrollView removeFromSuperview];
[myWindow sizeWindow:NX_WIDTH(&initViewSize)
:NX_HEIGHT(&initViewSize) byCorner:3];
}
return self;
}
@end
@implementation Window(Sizing)
#define CORNER_UPPER_LEFT 0
#define CORNER_LOWER_LEFT 1
#define CORNER_UPPER_RIGHT 2
#define CORNER_LOWER_RIGHT 3
// Keep 'a' between x and y
#define CLAMP(a,x,y) (MAX((x), MIN((y), (a))))
/*=====================================================================
* This Method resizes the receiving window as if it was dragged with
* the given corner. This method is useful when you want the window to
* resize by a corner other that the default upper right.
*=====================================================================*/
- sizeWindow:(NXCoord)width :(NXCoord)height byCorner:(int)corner
{
NXRect newFrame;
NXSize minSize, maxSize;
// Clamp width and height to their respective minimum and maximum values
[self getMinSize:&minSize]; [self getMaxSize:&maxSize];
width = CLAMP(width, minSize.width, maxSize.width);
height = CLAMP(height, minSize.height, maxSize.height);
// Set newFrame from the old frame and the new sizes
NXSetRect(&newFrame, NX_X(&frame), NX_Y(&frame), width, height);
// Move the respective corner by the amount of growth and set newFrame
switch(corner) {
case CORNER_UPPER_LEFT:
NX_X(&newFrame) -= width - NX_WIDTH(&frame);
break;
case CORNER_LOWER_LEFT:
NX_X(&newFrame) -= width - NX_WIDTH(&frame);
NX_Y(&newFrame) -= height - NX_HEIGHT(&frame);
break;
case CORNER_UPPER_RIGHT:
break;
case CORNER_LOWER_RIGHT:
NX_Y(&newFrame) -= height - NX_HEIGHT(&frame);
break;
}
[self placeWindowAndDisplay:&newFrame];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.