This is NickSpaceView.m in view mode; [Download] [Up]
#import "NickSpaceView.h"
#import "NickSpaceWraps.h"
#import <appkit/appkit.h>
#import <dpsclient/wraps.h>
#import <ansi/string.h>
#import <bsd/libc.h>
#import <stdio.h>
@implementation NickSpaceView
- calcNext
{
int i, j;
BOOL tryingLeft, tryingRight; // with respect to the CURRENT ORIENTATION!!
for (i=0;i<trailCount;i++) {
if ((!trails[i].dead && trails[i].maxLength > trails[i].currentLength) ||
trails[i].currentLength<=1)
continue;
if (trails[i].tailOrient == UP || trails[i].tailOrient == DOWN)
VERTEDGE(trails[i].tailEdge.row,trails[i].tailEdge.col) = 0;
else
HOREDGE(trails[i].tailEdge.row,trails[i].tailEdge.col) = 0;
trails[i].currentLength--;
/* update tail edges */
switch (trails[i].tailOrient) {
case UP:
if (VERTEDGE(trails[i].tailEdge.row+1,trails[i].tailEdge.col))
trails[i].tailEdge.row++;
else if (HOREDGE(trails[i].tailEdge.row,trails[i].tailEdge.col))
trails[i].tailOrient = LEFT;
else if (HOREDGE(trails[i].tailEdge.row,trails[i].tailEdge.col+1)) {
trails[i].tailEdge.col++;
trails[i].tailOrient = RIGHT;
}
break;
case DOWN:
if (VERTEDGE(trails[i].tailEdge.row-1,trails[i].tailEdge.col))
trails[i].tailEdge.row--;
else if (HOREDGE(trails[i].tailEdge.row-1,trails[i].tailEdge.col)) {
trails[i].tailEdge.row--;
trails[i].tailOrient = LEFT;
}
else if (HOREDGE(trails[i].tailEdge.row-1,trails[i].tailEdge.col+1)) {
trails[i].tailEdge.row--;
trails[i].tailEdge.col++;
trails[i].tailOrient = RIGHT;
}
break;
case RIGHT:
if (HOREDGE(trails[i].tailEdge.row,trails[i].tailEdge.col+1))
trails[i].tailEdge.col++;
else if (VERTEDGE(trails[i].tailEdge.row,trails[i].tailEdge.col))
trails[i].tailOrient = DOWN;
else if (VERTEDGE(trails[i].tailEdge.row+1,trails[i].tailEdge.col)) {
trails[i].tailEdge.row++;
trails[i].tailOrient = UP;
}
break;
case LEFT:
if (HOREDGE(trails[i].tailEdge.row,trails[i].tailEdge.col-1))
trails[i].tailEdge.col--;
else if (VERTEDGE(trails[i].tailEdge.row,trails[i].tailEdge.col-1)) {
trails[i].tailEdge.col--;
trails[i].tailOrient = DOWN;
}
else if (VERTEDGE(trails[i].tailEdge.row+1,trails[i].tailEdge.col-1)) {
trails[i].tailEdge.row++;
trails[i].tailEdge.col--;
trails[i].tailOrient = UP;
}
break;
}
}
/* update head edges */
for (i=0;i<trailCount;i++) {
if (firstTime) {
trails[i].headEdge = trails[i].tailEdge;
trails[i].tailOrient = trails[i].headOrient;
} else {
trails[i].dead = NO;
switch (trails[i].headOrient) {
case UP:
if (trails[i].headEdge.row < horCount - 1 &&
!VERTEDGE(trails[i].headEdge.row + 2,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row + 1,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row + 1,trails[i].headEdge.col + 1))
trails[i].headEdge.row++; /* continue UP */
else {
tryingLeft = (BOOL)random()%2;
for (j=0;j<2;j++) {
if (tryingLeft) {
if (trails[i].headEdge.col > 0 &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col-1) &&
!VERTEDGE(trails[i].headEdge.row+1,trails[i].headEdge.col-1) &&
!HOREDGE(trails[i].headEdge.row,trails[i].headEdge.col-1)) {
trails[i].headOrient = LEFT;
break;
}
} else {
if (trails[i].headEdge.col < vertCount - 1 &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col+1) &&
!VERTEDGE(trails[i].headEdge.row+1,trails[i].headEdge.col+1) &&
!HOREDGE(trails[i].headEdge.row,trails[i].headEdge.col+2)) {
trails[i].headEdge.col++;
trails[i].headOrient = RIGHT;
break;
}
}
if (j==1)
trails[i].dead = YES;
else
tryingLeft = 1 - tryingLeft;
}
}
break;
case DOWN:
if (trails[i].headEdge.row > 1 &&
!VERTEDGE(trails[i].headEdge.row - 2,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row - 2,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row - 2,trails[i].headEdge.col + 1))
trails[i].headEdge.row--; /* continue DOWN */
else {
tryingRight = (BOOL)random()%2;
for (j=0;j<2;j++) {
if (tryingRight) {
if (trails[i].headEdge.col > 0 &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col-1) &&
!VERTEDGE(trails[i].headEdge.row-1,trails[i].headEdge.col-1) &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col-1)) {
trails[i].headEdge.row--;
trails[i].headOrient = LEFT;
break;
}
} else {
if (trails[i].headEdge.col < vertCount - 1 &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col+1) &&
!VERTEDGE(trails[i].headEdge.row-1,trails[i].headEdge.col+1) &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col+2)) {
trails[i].headEdge.col++;
trails[i].headEdge.row--;
trails[i].headOrient = RIGHT;
break;
}
}
if (j==1)
trails[i].dead = YES;
else
tryingRight = 1 - tryingRight;
}
}
break;
case RIGHT:
if (trails[i].headEdge.col < vertCount - 1 &&
!HOREDGE(trails[i].headEdge.row,trails[i].headEdge.col+2) &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col + 1) &&
!VERTEDGE(trails[i].headEdge.row + 1,trails[i].headEdge.col + 1))
trails[i].headEdge.col++; // continue RIGHT
else {
tryingRight = (BOOL)random()%2;
for (j=0;j<2;j++) {
if (tryingRight) {
if (trails[i].headEdge.row > 0 &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col+1) &&
!VERTEDGE(trails[i].headEdge.row-1,trails[i].headEdge.col)) {
trails[i].headOrient = DOWN;
break;
}
} else {
if (trails[i].headEdge.row < horCount - 1 &&
!HOREDGE(trails[i].headEdge.row+1,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row+1,trails[i].headEdge.col+1) &&
!VERTEDGE(trails[i].headEdge.row+2,trails[i].headEdge.col)) {
trails[i].headEdge.row++;
trails[i].headOrient = UP;
break;
}
}
if (j==1)
trails[i].dead = YES;
else
tryingRight = 1 - tryingRight;
}
}
break;
case LEFT:
if (trails[i].headEdge.col > 1 &&
!HOREDGE(trails[i].headEdge.row,trails[i].headEdge.col-2) &&
!VERTEDGE(trails[i].headEdge.row+1,trails[i].headEdge.col-2) &&
!VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col-2))
trails[i].headEdge.col--; // continue LEFT
else {
tryingLeft = (BOOL)random()%2;
for (j=0;j<2;j++) {
if (tryingLeft) {
if (trails[i].headEdge.row > 0 &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row-1,trails[i].headEdge.col-1) &&
!VERTEDGE(trails[i].headEdge.row-1,trails[i].headEdge.col-1)) {
trails[i].headEdge.col--;
trails[i].headOrient = DOWN;
break;
}
} else {
if (trails[i].headEdge.row < horCount - 1 &&
!HOREDGE(trails[i].headEdge.row+1,trails[i].headEdge.col) &&
!HOREDGE(trails[i].headEdge.row+1,trails[i].headEdge.col-1) &&
!VERTEDGE(trails[i].headEdge.row+2,trails[i].headEdge.col-1)) {
trails[i].headEdge.row++;
trails[i].headEdge.col--;
trails[i].headOrient = UP;
break;
}
}
if (j==1)
trails[i].dead = YES;
else
tryingLeft = 1 - tryingLeft;
}
}
}
if (!trails[i].dead)
trails[i].currentLength++;
}
if (!trails[i].dead) {
if (trails[i].headOrient == UP || trails[i].headOrient == DOWN)
VERTEDGE(trails[i].headEdge.row,trails[i].headEdge.col) = 1;
else
HOREDGE(trails[i].headEdge.row,trails[i].headEdge.col) = 1;
}
}
firstTime = 0;
return self;
}
- oneStep
{
int i, level, currCol;
/* if window level changed, reinitialize and decide whether to buffer or not */
getWindowLevel([[self window] windowNum],&level);
if (level != lastLevel) {
lastLevel = level;
if (level < NX_NORMALLEVEL) {
[self newSize:YES];
image = [[NXImage alloc] initSize:&(bounds.size)];
[image lockFocus];
PSsetgray(0);
NXRectFill(&bounds);
[image unlockFocus];
} else {
[self newSize:YES];
if (image) {
[image free];
image = nil;
}
}
}
/* erase tail edges, as needed (calc'ed last time through */
PSsetgray(0);
for (i=0;i<trailCount;i++) {
if ((!trails[i].dead && trails[i].maxLength > trails[i].currentLength) ||
trails[i].currentLength<=1)
continue;
if (trails[i].tailOrient == UP || trails[i].tailOrient == DOWN) {
doSeg((float)((trails[i].tailEdge.col + 1) * spacing),
(float)(trails[i].tailEdge.row * spacing),
(float)((trails[i].tailEdge.col + 1) * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing));
} else {
doSeg((float)(trails[i].tailEdge.col * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing),
(float)((trails[i].tailEdge.col + 1) * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing));
}
}
PSstroke();
if (image) {
[image lockFocus];
/* erase tail edges, as needed (calc'ed last time through) */
PSsetgray(0);
for (i=0;i<trailCount;i++) {
if ((!trails[i].dead && trails[i].maxLength > trails[i].currentLength) ||
trails[i].currentLength<=1)
continue;
if (trails[i].tailOrient == UP || trails[i].tailOrient == DOWN) {
doSeg((float)((trails[i].tailEdge.col + 1) * spacing),
(float)(trails[i].tailEdge.row * spacing),
(float)((trails[i].tailEdge.col + 1) * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing));
} else {
doSeg((float)(trails[i].tailEdge.col * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing),
(float)((trails[i].tailEdge.col + 1) * spacing),
(float)((trails[i].tailEdge.row + 1) * spacing));
}
}
PSstroke();
[image unlockFocus];
}
[self calcNext];
/* draw head edges, as needed */
currCol = 0; // historical accident--careful not to confuse with currColor
PSsetrgbcolor(colors[currCol].red, colors[currCol].green, colors[currCol].blue);
for(i = 0;i<trailCount; i++) {
if (i==(trailCount*(currCol+1))/numColors) {
currCol++;
PSstroke();
PSsetrgbcolor(colors[currCol].red, colors[currCol].green, colors[currCol].blue);
}
if (trails[i].dead)
continue;
if (trails[i].headOrient == UP || trails[i].headOrient == DOWN) {
PSmoveto((float)((trails[i].headEdge.col + 1) * spacing),
(float)(trails[i].headEdge.row * spacing));
PSlineto((float)((trails[i].headEdge.col + 1) * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
} else {
PSmoveto((float)(trails[i].headEdge.col * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
PSlineto((float)((trails[i].headEdge.col + 1) * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
}
}
PSstroke();
if (image) {
[image lockFocus];
currCol = 0;
PSsetrgbcolor(colors[currCol].red, colors[currCol].green, colors[currCol].blue);
for(i = 0;i<trailCount; i++) {
if (i==(trailCount*(currCol+1))/3) {
currCol++;
PSstroke();
PSsetrgbcolor(colors[currCol].red, colors[currCol].green,
colors[currCol].blue);
}
if (trails[i].dead)
continue;
if (trails[i].headOrient == UP || trails[i].headOrient == DOWN) {
PSmoveto((float)((trails[i].headEdge.col + 1) * spacing),
(float)(trails[i].headEdge.row * spacing));
PSlineto((float)((trails[i].headEdge.col + 1) * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
} else {
PSmoveto((float)(trails[i].headEdge.col * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
PSlineto((float)((trails[i].headEdge.col + 1) * spacing),
(float)((trails[i].headEdge.row + 1) * spacing));
}
}
PSstroke();
[image unlockFocus];
}
return self;
}
- initFrame:(NXRect *)frameRect
{
char nibPath[MAXPATHLEN];
NXDefaultsVector defaults = {
{ "spacing", "" },
{ "tcRatio", "" },
{ "tlRatio", "" },
{ "grays", "" },
{ "reds", "" },
{ "greens", "" },
{ "blues", "" },
{ NULL } };
char scratch[128], scratch2[64];
int i;
srandom(time(0));
[super initFrame:frameRect];
/* these are preserved from bezierView--I don't know if they're doing any good */
[self allocateGState]; // For faster lock/unlockFocus
[self setClipping:NO]; // even faster...
/* Miscellaneous initializations */
image = nil;
lastLevel = 0;
sprintf(nibPath,[[NXApp delegate] moduleDirectory:"NickSpace"]);
strcat(nibPath,"/NickSpace.nib");
[NXApp loadNibFile:nibPath owner:self];
/* Set target/action for each control */
[[spaceControl setTarget:self] setAction:@selector(getSpacingFrom:)];
[[countControl setTarget:self] setAction:@selector(getNumberFrom:)];
[[lengthControl setTarget:self] setAction:@selector(getMaxLenFrom:)];
[[colorWell setTarget:self] setAction:@selector(updateCurrColor:)];
[[colorScrollers setTarget:self] setAction:@selector(scrollColor:)];
[[[addRemoveButtons cellAt:0 :0] setTarget:self] setAction:@selector(addColor:)];
[[[addRemoveButtons cellAt:1 :0] setTarget:self] setAction:@selector(removeColor:)];
/* Check the first default; if it hasn't been written before, get all
* parameters from the controls; else, read all defaults and set the controls
*/
NXRegisterDefaults("NickSpace",defaults);
if (strlen(NXGetDefaultValue("NickSpace","spacing"))==0) {
// Some empirically determined initial settings:
spacing = 8;
tcRatio = .6;
tlRatio = 1.0;
numColors = 10;
currColor = 0;
colors = (rgbColor *)malloc(sizeof(rgbColor)*numColors);
sprintf(scratch,"%d",spacing);
NXWriteDefault("NickSpace","spacing",scratch);
sprintf(scratch,"%f",tcRatio);
NXWriteDefault("NickSpace","tcRatio",scratch);
sprintf(scratch,"%f",tlRatio);
NXWriteDefault("NickSpace","tlRatio",scratch);
sprintf(scratch,"%i",numColors);
NXWriteDefault("NickSpace","numColors",scratch);
// randomize an initial set of colors:
for (i=0;i<numColors;i++) {
colors[i].red = (float)random()/(float)MAXLONG;
colors[i].green = (float)random()/(float)MAXLONG;
colors[i].blue = (float)random()/(float)MAXLONG;
sprintf(scratch,"%f %f %f",colors[i].red, colors[i].green, colors[i].blue);
sprintf(scratch2,"color%d",i);
NXWriteDefault("NickSpace",scratch2,scratch);
}
} else {
spacing = atoi(NXGetDefaultValue("NickSpace","spacing"));
tcRatio = atof(NXGetDefaultValue("NickSpace","tcRatio"));
tlRatio = atof(NXGetDefaultValue("NickSpace","tlRatio"));
numColors = atoi(NXGetDefaultValue("NickSpace","numColors"));
currColor = 0;
colors = (rgbColor *)malloc(sizeof(rgbColor)*numColors);
for (i=0;i<numColors;i++) {
sprintf(scratch2,"color%d",i);
sprintf(scratch,"%s",NXGetDefaultValue("NickSpace",scratch2));
sscanf(scratch,"%f %f %f",&(colors[i].red),&(colors[i].green),&(colors[i].blue));
}
}
[spaceControl setIntValue:spacing];
[countControl setFloatValue:tcRatio];
[lengthControl setFloatValue:tlRatio];
[colorWell setColor:NXConvertRGBToColor(colors[currColor].red,colors[currColor].green,
colors[currColor].blue)];
sprintf(scratch,"%d/%d",currColor+1,numColors);
[numColorsField setStringValue:scratch];
[self newSize:NO];
return self;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[self newSize:YES];
return self;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
int i;
if (!rects || !rectCount) return self;
for (i=0;i<rectCount;i++)
[image composite:NX_COPY fromRect:&(rects[i]) toPoint:&(rects[i].origin)];
return self;
}
/* next two methods do initializations */
- newSize:(BOOL)freeOld;
{
if (freeOld) {
free(horEdges);
free(vertEdges);
free(trails);
}
horCount = (int)((bounds.size.height - 5.0) / spacing);
vertCount = (int)((bounds.size.width - 5.0) / spacing);
horEdges = (char *)malloc(HORSIZE);
vertEdges = (char *)malloc(VERTSIZE);
bzero(horEdges,HORSIZE);
bzero(vertEdges,VERTSIZE);
trailCount = (int)((vertCount + horCount) * tcRatio);
trailCount = trailCount ? trailCount : 1;
trails = (trail *)malloc(sizeof(trail)*trailCount);
maxTrailLen = (vertCount + horCount) * 4 * tlRatio;
minTrailLen = maxTrailLen/40;
maxTrailLen = maxTrailLen < 2 ? 2 : maxTrailLen;
minTrailLen = minTrailLen < 2 ? 2 : minTrailLen;
firstTime = YES;
[self startTrails];
if ([self window]) {
[self lockFocus];
PSsetgray(0);
NXRectFill(&bounds);
[self unlockFocus];
}
if (image){
[image lockFocus];
PSsetgray(0);
NXRectFill(&bounds);
[image unlockFocus];
}
return self;
}
- startTrails
{
int i,j;
BOOL dup;
int initPos[trailCount];
/* This could potentially take arbitrarily long--should tighten up;
*/
for (i=0;i<trailCount;) {
dup = NO;
if (trailCount < vertCount + horCount) {
initPos[i] = (random() % (vertCount + horCount))*2;
for (j=0;j<i;j++) {
if (initPos[j] == initPos[i]) {
dup = YES;
break;
}
}
} else
initPos[i] = i * 2;
if (!dup)
i++;
}
for (i=0;i<trailCount;i++) {
trails[i].currentLength = 1;
if (tlRatio == 1.0)
trails[i].maxLength = MAXINT;
else
trails[i].maxLength = (random() % ((maxTrailLen - minTrailLen) + 1) + minTrailLen);
trails[i].dead = NO;
if (initPos[i] < vertCount) {
trails[i].tailEdge.row = 0;
trails[i].tailEdge.col = initPos[i];
trails[i].headOrient = UP;
continue;
}
if (vertCount <= initPos[i] && initPos[i] < vertCount + horCount) {
trails[i].tailEdge.row = initPos[i] - vertCount;
trails[i].tailEdge.col = vertCount;
trails[i].headOrient = LEFT;
continue;
}
if (vertCount + horCount <= initPos[i] && initPos[i] < (2*vertCount + horCount)) {
trails[i].tailEdge.row = horCount;
trails[i].tailEdge.col = initPos[i] - (vertCount + horCount);
trails[i].headOrient = DOWN;
continue;
}
trails[i].tailEdge.row = initPos[i] - (2*vertCount + horCount);
trails[i].tailEdge.col = 0;
trails[i].headOrient = RIGHT;
}
return self;
}
- inspector:sender
{
return inspector;
}
- updateCurrColor:sender
{
char scratch[128],scratch2[16];;
NXConvertColorToRGB([sender color],&(colors[currColor].red),
&(colors[currColor].green),
&(colors[currColor].blue));
sprintf(scratch2,"color%d",currColor);
sprintf(scratch,"%f %f %f",colors[currColor].red,colors[currColor].green,
colors[currColor].blue);
NXWriteDefault("NickSpace",scratch2,scratch);
return self;
}
- scrollColor:sender
{
char scratch[32];
if ([sender selectedRow]==1)
currColor = currColor==0 ? numColors-1 : currColor-1;
else
currColor = (currColor + 1)%numColors;
[colorWell setColor:NXConvertRGBToColor(colors[currColor].red,
colors[currColor].green,
colors[currColor].blue)];
sprintf(scratch,"%d/%d",currColor+1,numColors);
[numColorsField setStringValue:scratch];
return self;
}
- addColor:sender
{
char scratch[128],scratch2[32];
numColors++;
colors = (rgbColor *)realloc(colors,sizeof(rgbColor)*numColors);
currColor = numColors-1;
colors[currColor].red = (float)random()/(float)MAXLONG;
colors[currColor].green = (float)random()/(float)MAXLONG;
colors[currColor].blue = (float)random()/(float)MAXLONG;
sprintf(scratch2,"color%d",currColor);
sprintf(scratch,"%f %f %f",colors[currColor].red,
colors[currColor].green,
colors[currColor].blue);
NXWriteDefault("NickSpace",scratch2,scratch);
sprintf(scratch,"%d",numColors);
NXWriteDefault("NickSpace","numColors",scratch);
[colorWell setColor:NXConvertRGBToColor(colors[currColor].red,
colors[currColor].green,
colors[currColor].blue)];
sprintf(scratch,"%d/%d",currColor+1,numColors);
[numColorsField setStringValue:scratch];
return self;
}
- removeColor:sender
{
int i;
char scratch2[128],scratch[32];
if (numColors==1)
return self;
for (i=currColor;i<numColors-1;i++) {
colors[i] = colors[i+1];
sprintf(scratch2,"color%d",i);
sprintf(scratch,"%f %f %f",colors[i].red,
colors[i].green,
colors[i].blue);
NXWriteDefault("NickSpace",scratch2,scratch);
}
numColors--;
sprintf(scratch2,"color%d",numColors);
NXRemoveDefault("NickSpace",scratch2);
sprintf(scratch,"%d",numColors);
NXWriteDefault("NickSpace","numColors",scratch);
currColor %= numColors;
[colorWell setColor:NXConvertRGBToColor(colors[currColor].red,
colors[currColor].green,
colors[currColor].blue)];
sprintf(scratch,"%d/%d",currColor+1,numColors);
[numColorsField setStringValue:scratch];
return self;
}
- getSpacingFrom:sender;
{
char scratch[128];
spacing = [sender intValue];
sprintf(scratch,"%d",spacing);
NXWriteDefault("NickSpace","spacing",scratch);
[self newSize:YES];
return self;
}
- getNumberFrom:sender
{
char scratch[128];
tcRatio = [sender floatValue];
sprintf(scratch,"%f",tcRatio);
NXWriteDefault("NickSpace","tcRatio",scratch);
[self newSize:YES];
return self;
}
- getMaxLenFrom:sender
{
char scratch[128];
tlRatio = [sender floatValue];
sprintf(scratch,"%f",tlRatio);
NXWriteDefault("NickSpace","tlRatio",scratch);
[self newSize:YES];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.