This is ScoreKeeper.m in view mode; [Download] [Up]
#import <appkit/defaults.h> #import <appkit/Matrix.h> #import <appkit/TextField.h> #import <appkit/TextFieldCell.h> #import <appkit/Window.h> #import <pwd.h> #import <strings.h> #import <sys/types.h> #import <ctype.h> #import "ScoreKeeper.h" #import "TetApp.h" #define SCORE_FILE ".TetrisScores" #define NUM_SCORES 10 #define BEZEL_SIZE 2.0 #define FIELD_X_OFFSET 2.0 extern void setpwent(); extern void endpwent(); extern uid_t getuid(); extern void chmod(char *path, int mode); @implementation ScoreKeeper #ifdef FOO - (int) fileFoundProc(char *)path { strcpy(self->path, path); return 0; } #endif - (NXStream *)findScoresFile:(int) mode { NXStream *result; char *appName; strcpy(path, NXArgv[0]); if ((appName = rindex(path, '/'))) appName++; else appName = path; strcpy(appName, SCORE_FILE); if (!(result = NXMapFile(path, mode))) { strcat(strcat(strcpy(path, NXHomeDirectory()), "/"), SCORE_FILE); result = (mode == NX_READONLY) ? NXMapFile(path, NX_READONLY) : NXOpenMemory(NULL, 0, mode); } return result; } - init { [super init]; nameField = nil; return self; } - (void) readHighScores:(NXStream *)stream { int c; char name[BUFSIZ]; char level[5]; char myScore[10]; for (c = 0; c < NUM_SCORES; c++) { name[0] = level[0] = myScore[0] = '\0'; NXScanf(stream, "%[^\7]\7%[^\7]\7%[^\7]\7", name, level, myScore); [[names cellAt:c :0] setStringValue:name], [[levels cellAt:c :0] setStringValue:level], [[scores cellAt:c :0] setStringValue:myScore]; } } - setScoresWindow:anObject { NXStream *inStream; scoresWindow = anObject; [scoresWindow setDelegate:self]; if ((inStream = [self findScoresFile: NX_READONLY])) { [self readHighScores: inStream]; NXCloseMemory(inStream, NX_FREEBUFFER); } return self; } - setZero { [score setIntValue:0]; return self; } - addScore:(int)amount { [score setIntValue:[score intValue] + amount]; return self; } static char *username() { static char *username = (char *)0; struct passwd *pwdentry; static char ubuf [128]; if (!username) { char * pc; setpwent(); pwdentry = getpwuid(getuid()); endpwent(); username = ((pwdentry) ? pwdentry->pw_gecos : ""); /* extended GECOS field handling added by Detlev Droege, * droege@infko.uni-koblenz.de, December 1991 */ if (pc = index (username, ',')) *pc = 0; /* strip ','-part of gecos field */ if (index (username, '&')) { /* do '&' expansion */ pc = ubuf; while (*username) { if (*username == '&') { strcpy (pc, pwdentry->pw_name); *pc = toupper (*pc); while (*pc) pc++; } else *pc++ = *username; username++; } *pc = 0; username = ubuf; } } return username; } - (int) findrank:(int) myScore { id window = [names window]; int myRank; int c; [window disableFlushWindow]; for (myRank = 0; myRank < NUM_SCORES; myRank++) if (myScore >= [[scores cellAt:myRank :0] intValue]) break; for (c = NUM_SCORES - 1; c > myRank; c--) { [[names cellAt:c :0] setStringValue: [[names cellAt:(c - 1) :0] stringValue]]; [[levels cellAt:c :0] setStringValue: [[levels cellAt:(c - 1) :0] stringValue]]; [[scores cellAt:c :0] setStringValue: [[scores cellAt:(c - 1) :0] stringValue]]; } [window reenableFlushWindow]; return myRank; } - updateHighScores:(int)level { id window = [names window]; int scoreValue = [score intValue]; NXRect nRect; if ((rank = [self findrank: scoreValue]) < NUM_SCORES) { [scoresWindow makeKeyAndOrderFront:self]; [[levels cellAt:rank :0] setIntValue:level]; [[scores cellAt:rank :0] setIntValue:scoreValue]; [[names getCellFrame:&nRect at:rank :0] convertRect:&nRect toView:nil]; NXInsetRect(&nRect, -BEZEL_SIZE, -BEZEL_SIZE); nRect.origin.x -= FIELD_X_OFFSET; if (!nameField) { nameField = [[TextField alloc] initFrame:&nRect]; [nameField setEditable:YES]; [[nameField setTarget:self] setAction:@selector(nameFieldEnd:)]; } else [nameField moveTo:nRect.origin.x :nRect.origin.y]; [nameField setStringValue:username()]; [[window contentView] addSubview:nameField]; [[nameField display] selectText:self]; while ([NXApp peekAndGetNextEvent:NX_KEYUPMASK | NX_KEYDOWNMASK]) ; [NXApp runModalFor:window]; } return self; } - nameFieldEnd:sender { id window = [names window]; [window disableFlushWindow]; [[names cellAt:rank :0] setStringValue:[nameField stringValue]]; [nameField removeFromSuperview]; [window display]; [[window reenableFlushWindow] flushWindow]; [NXApp stopModal]; return self; } - windowWillClose:sender { if (nameField && [nameField currentEditor]) { [self nameFieldEnd:sender]; return nil; } else return self; } - writeHighScores:(NXStream *)stream { int c; for (c = 0; c < NUM_SCORES; c++) NXPrintf(stream, "%s\7%s\7%s\7", [[names cellAt:c :0] stringValue], [[levels cellAt:c :0] stringValue], [[scores cellAt:c :0] stringValue]); NXFlush(stream); return self; } - writeScores { NXStream *outStream; if ((outStream = [self findScoresFile: NX_WRITEONLY])) { [self writeHighScores: outStream]; NXSaveToFile(outStream, path); NXCloseMemory(outStream, NX_FREEBUFFER); chmod(path, 0666); } return self; } - free { if (nameField) [nameField free]; return [super free]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.