This is Controller.m in view mode; [Download] [Up]
#import "Controller.h" @implementation Controller + initialize { static char buffer [1025]; static NXDefaultsVector MyDefaults = { {"SayAvailable", "false"}, {"SayPath", "/usr/local/bin/say"}, {"SndplayPath", "/usr/bin/sndplay"}, {"SoundPath", buffer}, {NULL} }; sprintf (buffer, "%s/Library/Sounds", NXHomeDirectory ()); NXRegisterDefaults ("FIX", MyDefaults); return self; } - init { commands = NULL; variables = [[NXStringTable alloc] init]; constants = [[NXStringTable alloc] init]; directory = NULL; filename = NULL; return [super init]; } - awakeFromNib { [self revertDefaults:self]; return self; } - defaultsOK:sender { NXWriteDefault ("FIX", "SayAvailable", [sayAvailableButton state] ? "true": "false"); NXWriteDefault ("FIX", "SayPath", [sayPathField stringValue] ? [sayPathField stringValue] : ""); NXWriteDefault ("FIX", "SoundPath", [soundPathField stringValue] ? [soundPathField stringValue] : ""); NXWriteDefault ("FIX", "SndplayPath", [sndplayPathField stringValue] ? [sndplayPathField stringValue] : ""); return self; } - revertDefaults:sender { const char * sayAvailable; const char * sayPath; const char * soundPath; const char * sndplayPath; sayAvailable = NXGetDefaultValue ("FIX", "SayAvailable"); if (sayAvailable == NULL || !*sayAvailable || strcmp (sayAvailable, "true") != 0) [sayAvailableButton setState:NO]; else [sayAvailableButton setState:YES]; sayPath = NXGetDefaultValue ("FIX", "SayPath"); if (sayPath == NULL || !*sayPath) [sayPathField setStringValue:""]; else [sayPathField setStringValue:sayPath]; soundPath = NXGetDefaultValue ("FIX", "SoundPath"); if (soundPath == NULL || !*soundPath) [soundPathField setStringValue:""]; else [soundPathField setStringValue:soundPath]; sndplayPath = NXGetDefaultValue ("FIX", "SndplayPath"); if (sndplayPath == NULL || !*sndplayPath) [sndplayPathField setStringValue:""]; else [sndplayPathField setStringValue:sndplayPath]; return self; } - setKey:(const char *)key toValue:(const char *)value inStringTable:table { [table insertKey:NXUniqueString(key) value:(char *)NXUniqueString(value)]; return self; } - setNextCommand:(command *)command { nextCommand = command; if (nextCommand != NULL) [programText setSel:nextCommand->startPosition :nextCommand->endPosition]; else [programText setSel:0 :0]; return self; } - analyseConstantLine:(const char *)line { char name [80]; char * blankPtr; blankPtr = index (line, ' '); if (blankPtr == NULL) { [self setMessage:[translation valueForStringKey: "Feste Daten mössen im Format <name> <wert> sein!"]]; return NULL; } strncpy (name, line, blankPtr - line); name[blankPtr - line] = '\0'; [self setKey:name toValue:blankPtr + 1 inStringTable:constants]; return self; } - addCommand:(commandCode)code label:(char *)label argument:(char *)arg start:(int)start end:(int)end { command * c, * n; c = malloc (sizeof (command)); c->succ = NULL; c->startPosition = start; c->endPosition = end; strcpy (c->label, label); c->code = code; strcpy (c->argument, arg); if (commands == NULL) commands = c; else { n = commands; while (n->succ != NULL) n = n->succ; n->succ = c; } return self; } - missingArgument:(char *)arg inCommand:(char *)command { char buffer[256]; sprintf (buffer, [translation valueForStringKey: "Der Befehl %s braucht %s als Argument."], command, [translation valueForStringKey:arg]); [self setMessage:buffer]; return self; } - analyseProgramLine:(const char *)line start:(int)start end:(int)end { char label [80]; char name [80]; char argument [256]; char * firstBlankPtr; char * secondBlankPtr; BOOL hasArgument; if (line[0] == ' ') while (line[1] == ' ') line++; firstBlankPtr = index (line, ' '); if (firstBlankPtr == NULL) { [self setMessage:[translation valueForStringKey: "Programmzeilen mössen im Format <nummer> <befehl> <argument> sein!"]]; return NULL; } strncpy (label, line, firstBlankPtr - line); label[firstBlankPtr - line] = '\0'; secondBlankPtr = index (firstBlankPtr + 1, ' '); if (secondBlankPtr == NULL) { hasArgument = NO; strcpy (name, firstBlankPtr + 1); strcpy (argument, ""); } else { hasArgument = YES; strncpy (name, firstBlankPtr + 1, secondBlankPtr - firstBlankPtr - 1); name[secondBlankPtr - firstBlankPtr - 1] = '\0'; strcpy (argument, secondBlankPtr + 1); } if (strcasecmp (name, "L") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"L"]; return NULL; } [self addCommand:C_L label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcasecmp (name, "S") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"B"]; return NULL; } [self addCommand:C_S label:label argument:argument start:start end:end]; if (![self addVariable:argument]) { [self setMessage:[translation valueForStringKey: "Du kannst keinen festen Wert in einem S-Befehl verwenden"]]; return NULL; } } if (strcasecmp (name, "D") == 0) { if (!hasArgument) { [self missingArgument:"einen Wert" inCommand:"D"]; return NULL; } [self addCommand:C_D label:label argument:argument start:start end:end]; } if (strcasecmp (name, "GO") == 0) { if (!hasArgument) { [self missingArgument:"eine Befehlsadresse" inCommand:"GO"]; return NULL; } [self addCommand:C_GO label:label argument:argument start:start end:end]; } if (strcasecmp (name, "IF") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"IF"]; return NULL; } [self addCommand:C_IF label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcasecmp (name, "TH") == 0) { if (!hasArgument) { [self missingArgument:"eine Befehlsadresse" inCommand:"TH"]; return NULL; } [self addCommand:C_TH label:label argument:argument start:start end:end]; } if (strcasecmp (name, "EL") == 0) { if (!hasArgument) { [self missingArgument:"eine Befehlsadresse" inCommand:"EL"]; return NULL; } [self addCommand:C_EL label:label argument:argument start:start end:end]; } if (strcasecmp (name, "E") == 0) { if (!hasArgument) [self addCommand:C_E label:label argument:"" start:start end:end]; else { [self addCommand:C_E label:label argument:argument start:start end:end]; if (![self addVariable:argument]) { [self setMessage:[translation valueForStringKey: "Du kannst keinen festen Wert in einem E-Befehl verwenden"]]; return NULL; } } } if (strcasecmp (name, "A") == 0) { if (!hasArgument) [self addCommand:C_A label:label argument:"" start:start end:end]; else { [self addCommand:C_A label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } } if (strcmp (name, "+") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"+"]; return NULL; } [self addCommand:C_PLUS label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcmp (name, "-") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"-"]; return NULL; } [self addCommand:C_MINUS label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcmp (name, "*") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"*"]; return NULL; } [self addCommand:C_MUL label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcmp (name, "/") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"/"]; return NULL; } [self addCommand:C_DIV label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcmp (name, "|") == 0) { if (!hasArgument) { [self missingArgument:"eine Datenadresse" inCommand:"|"]; return NULL; } [self addCommand:C_APP label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } if (strcasecmp (name, "P") == 0) { if (!hasArgument) { [self missingArgument:"einen Wert" inCommand:"P"]; return NULL; } [self addCommand:C_P label:label argument:argument start:start end:end]; } if (strcasecmp (name, "F") == 0) { if (!hasArgument) { [self missingArgument:"eine Frage" inCommand:"F"]; return NULL; } [self addCommand:C_F label:label argument:argument start:start end:end]; } if (strcasecmp (name, "I") == 0) { if (!hasArgument) { [self missingArgument:"eine Frage" inCommand:"I"]; return NULL; } [self addCommand:C_I label:label argument:argument start:start end:end]; } if (strcasecmp (name, "END") == 0) { [self addCommand:C_END label:label argument:"" start:start end:end]; } if (strcasecmp (name, "SAY") == 0) { if (!hasArgument) [self addCommand:C_SAY label:label argument:"" start:start end:end]; else { [self addCommand:C_SAY label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } } if (strcasecmp (name, "PLAY") == 0) { if (!hasArgument) [self addCommand:C_PLAY label:label argument:"" start:start end:end]; else { [self addCommand:C_PLAY label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } } if (strcasecmp (name, "ALERT") == 0) { if (!hasArgument) [self addCommand:C_ALERT label:label argument:"" start:start end:end]; else { [self addCommand:C_ALERT label:label argument:argument start:start end:end]; [self addVariableOrConstOrDirectValue:argument]; } } if (strcasecmp (name, "") == 0 || strcasecmp (name, "NOP") == 0) { [self addCommand:C_NOP label:label argument:"" start:start end:end]; } return self; } - showVariables { NXHashState state; char * key; char * value; char buffer [1024]; [variablesText setText:""]; [variablesText selectText:self]; state = [variables initState]; while ([variables nextState:&state key:(const void **)&key value:(void **)&value]) { sprintf (buffer, "%s %s\n", key, value); [variablesText replaceSel:buffer]; } return self; } - (command *)searchCommandWithLabel:(char *)label { command * n; for (n = commands; n != NULL; n = n->succ) if (strcasecmp (n->label, label) == 0) return n; return NULL; } - (const char *)getDirectValue:(const char *)name { static char buffer[256]; int len; if (name != NULL && (len = strlen (name)) > 1 && *name == '"') { // lets first copy the string without opening quote len--; strncpy (buffer, name+1, len); // now lets remove spaces from the end while (len > 0 && buffer[len - 1] == ' ') len--; // if len == 0, it was only one quote // if buffer[len - 1] != '"', it is not terminated with a quote if (len > 0 && buffer[len - 1] == '"') { buffer[len - 1] = '\0'; return buffer; } } return NULL; } - (const char *)getVarOrConstOrDirectValue:(const char *)name { const char * value; if ((value = [self getDirectValue:name]) != NULL) return value; value = [constants valueForStringKey:name]; if (value == NULL) value = [variables valueForStringKey:name]; return value; } - setVar:(const char *)name toValue:(const char *)value { char buffer[256]; if ([constants valueForStringKey:name] != NULL) { sprintf (buffer, [translation valueForStringKey: "Der feste Datenwert %s kann nicht öberschrieben werden"], name); [self setMessage:buffer]; return nil; } [self setKey:name toValue:value inStringTable:variables]; return self; } - addVariable:(const char *)name { if ([constants valueForStringKey:name] != NULL) return nil; [self setKey:name toValue:"0" inStringTable:variables]; return self; } - addVariableOrConstOrDirectValue:(const char *)name { if ([self getDirectValue:name] == NULL && [constants valueForStringKey:name] == NULL) [self setKey:name toValue:"0" inStringTable:variables]; // its a variable return self; } - findInputLine:(int)line start:(int *)start end:(int *)end { char buffer[2]; *start = [inputText positionFromLine:line]; if (*start == -1) return nil; *end = [inputText positionFromLine:line + 1]; if (*end == -1) *end = [inputText textLength]; if (*start == *end) return self; if ([inputText getSubstring:buffer start:(*end) - 1 length:1] != 1) return self; if (buffer[0] == '\n') (*end)--; return self; } - unselectNextInputLine { int start, end; char buffer [3]; [self findInputLine:nextInputLine start:&start end:&end]; if (start == -1) return self; if (end - start > 1 && [inputText getSubstring:buffer start:start length:2] == 2 && strncmp (buffer, "> ", 2) == 0) { [inputText setSel:start :start + 2]; [inputText replaceSel:""]; } return self; } - selectNextInputLine { int start, end; [self findInputLine:nextInputLine start:&start end:&end]; if (start == -1) return self; [inputText setSel:start :start]; [inputText replaceSel:"> "]; return self; } - (const char *) input { int start, end; static char buffer[256]; [self unselectNextInputLine]; [self findInputLine:nextInputLine start:&start end:&end]; if (start < end) [inputText getSubstring:buffer start:start length:end - start]; buffer[end - start] = '\0'; nextInputLine++; [self selectNextInputLine]; return buffer; } - output:(const char *)line { int end; end = [outputText textLength]; [outputText setSel:end :end]; [outputText replaceSel:line]; [outputText replaceSel:"\n"]; [outputText setSel:end :[outputText textLength] - 1]; [outputText scrollSelToVisible]; return self; } - (const char *)askForValue:(const char *)question { [questionField setStringValue:question? question : ""]; [answerField setStringValue:""]; [answerField selectText:self]; cancelRequested = NO; [questionPanel makeKeyAndOrderFront:self]; [NXApp runModalFor:questionPanel]; // returns with OK [questionPanel orderOut:self]; if (cancelRequested) return NULL; return [answerField stringValue]; } - answerOK:sender { cancelRequested = NO; [NXApp stopModal]; return self; } - answerCancel:sender { cancelRequested = YES; [NXApp stopModal]; return self; } - say:(const char *)value { char buffer [1000]; const char * sayAvailable; const char * sayPath; sayAvailable = NXGetDefaultValue ("FIX", "SayAvailable"); if (sayAvailable == NULL || !*sayAvailable || strcmp (sayAvailable, "true") != 0) { NXBeep (); return self; } sayPath = NXGetDefaultValue ("FIX", "SayPath"); if (sayPath == NULL || !*sayPath) { NXBeep (); return self; } if (value != NULL) { sprintf (buffer, "%s %s", sayPath, value); system (buffer); } return self; } - (BOOL)fileExists:(const char *)name { FILE * fp; if ((fp = fopen (name, "r")) != NULL) { fclose (fp); return YES; } return NO; } - (const char *)findSoundFile:(const char *)name { static char buffer [1000]; const char * soundPath; sprintf (buffer, "%s", name); if ([self fileExists:buffer]) return buffer; strcat (buffer, ".snd"); if ([self fileExists:buffer]) return buffer; if (directory != NULL) { sprintf (buffer, "%s/%s", directory, name); if ([self fileExists:buffer]) return buffer; strcat (buffer, ".snd"); if ([self fileExists:buffer]) return buffer; } soundPath = NXGetDefaultValue ("FIX", "SoundPath"); if (soundPath != NULL && *soundPath) { sprintf (buffer, "%s/%s", soundPath, name); if ([self fileExists:buffer]) return buffer; } strcat (buffer, ".snd"); if ([self fileExists:buffer]) return buffer; return NULL; } - play:(const char *)name { char msgbuffer [1000]; char buffer [1000]; const char * file = NULL; int code; const char * sndplayPath; const char * soundPath; sndplayPath = NXGetDefaultValue ("FIX", "SndplayPath"); if (sndplayPath == NULL || !*sndplayPath) { NXBeep (); return self; } soundPath = NXGetDefaultValue ("FIX", "SoundPath"); if (soundPath != NULL && !*soundPath) soundPath = NULL; if ((file = [self findSoundFile:name]) == NULL) { if (soundPath || directory) { strcpy (msgbuffer, [translation valueForStringKey:"Habe auch in "]); if (soundPath) { strcat (msgbuffer, soundPath); if (directory) strcat (msgbuffer, [translation valueForStringKey:" und "]); } if (directory) strcat (msgbuffer, directory); strcat (msgbuffer, [translation valueForStringKey:" gesucht."]); } else strcpy (msgbuffer, [translation valueForStringKey:"Es ist weder ein Sounddirectory in den Einstellungen angegeben noch ist die aktuelle Datei abgespeichert."]); code = NXRunAlertPanel ("Play", [translation valueForStringKey: "Kann die Sounddatei %s nicht finden! %s"], "OK", [translation valueForStringKey:"Abbrechen"], NULL, name, msgbuffer); if (code == NX_ALERTDEFAULT) return self; else return nil; } if (file != NULL) { sprintf (buffer, "%s %s", sndplayPath, file); system (buffer); } return self; } - alert:(const char *)value { int code; if (value == NULL) value = "nix los!"; code = NXRunAlertPanel ([translation valueForStringKey:"FIX teilt mit:"], value, "OK", [translation valueForStringKey:"Abbrechen"], NULL); if (code == NX_ALERTDEFAULT) return self; else return nil; } - performNextCommand { command * next; int ival; char buffer [1024]; const char * answer; int code; id result; if (nextCommand == NULL) return self; switch (nextCommand->code) { case C_L: [accumulator setStringValue: [self getVarOrConstOrDirectValue:nextCommand->argument]]; [self setNextCommand:nextCommand->succ]; break; case C_S: [self setVar:nextCommand->argument toValue:[accumulator stringValue]]; [self showVariables]; [self setNextCommand:nextCommand->succ]; break; case C_D: [accumulator setStringValue:nextCommand->argument]; [self setNextCommand:nextCommand->succ]; break; case C_GO: next = [self searchCommandWithLabel:nextCommand->argument]; if (next == NULL) { [self setMessage: [translation valueForStringKey:"Unbekanntes Sprungziel"]]; return nil; } [self setNextCommand:next]; break; case C_IF: if (strcasecmp ([accumulator stringValue], [self getVarOrConstOrDirectValue:nextCommand->argument]) == 0) [testResult setState:1]; else [testResult setState:0]; [self setNextCommand:nextCommand->succ]; break; case C_TH: next = [self searchCommandWithLabel:nextCommand->argument]; if (next == NULL) { [self setMessage: [translation valueForStringKey:"Unbekanntes Sprungziel"]]; return nil; } if ([testResult state] != 0) [self setNextCommand:next]; else [self setNextCommand:nextCommand->succ]; break; case C_EL: next = [self searchCommandWithLabel:nextCommand->argument]; if (next == NULL) { [self setMessage: [translation valueForStringKey:"Unbekanntes Sprungziel"]]; return nil; } if ([testResult state] != 0) [self setNextCommand:nextCommand->succ]; else [self setNextCommand:next]; break; case C_E: if (nextCommand->argument[0] == '\0') [accumulator setStringValue:[self input]]; else { [self setVar:nextCommand->argument toValue:[self input]]; [self showVariables]; } [self setNextCommand:nextCommand->succ]; break; case C_A: if (nextCommand->argument[0] == '\0') [self output:[accumulator stringValue]]; else [self output:[self getVarOrConstOrDirectValue:nextCommand->argument]]; [self setNextCommand:nextCommand->succ]; break; case C_P: [self output:nextCommand->argument]; [self setNextCommand:nextCommand->succ]; break; case C_F: code = NXRunAlertPanel ([translation valueForStringKey:"FIX fragt:"], nextCommand->argument, [translation valueForStringKey:"Nein"], [translation valueForStringKey:"Ja"], [translation valueForStringKey:"Abbrechen"]); switch (code) { case NX_ALERTDEFAULT: [testResult setState:0]; [self setNextCommand:nextCommand->succ]; break; case NX_ALERTALTERNATE: [testResult setState:1]; [self setNextCommand:nextCommand->succ]; break; case NX_ALERTOTHER: [self setNextCommand:NULL]; break; } break; case C_I: if ((answer = [self askForValue:nextCommand->argument]) == NULL) { [self setNextCommand:NULL]; break; } [accumulator setStringValue:answer]; [self setNextCommand:nextCommand->succ]; break; case C_PLUS:ival = atoi ([self getVarOrConstOrDirectValue:nextCommand->argument]); [accumulator setIntValue:[accumulator intValue] + ival]; [self setNextCommand:nextCommand->succ]; break; case C_MINUS:ival = atoi ([self getVarOrConstOrDirectValue:nextCommand->argument]); [accumulator setIntValue:[accumulator intValue] - ival]; [self setNextCommand:nextCommand->succ]; break; case C_MUL: ival = atoi ([self getVarOrConstOrDirectValue:nextCommand->argument]); [accumulator setIntValue:[accumulator intValue] * ival]; [self setNextCommand:nextCommand->succ]; break; case C_DIV: ival = atoi ([self getVarOrConstOrDirectValue:nextCommand->argument]); if (ival == 0) { [self setMessage: [translation valueForStringKey:"Division durch Null"]]; return nil; } [accumulator setIntValue:[accumulator intValue] / ival]; [self setNextCommand:nextCommand->succ]; break; case C_APP: sprintf (buffer, "%s%s", [accumulator stringValue], [self getVarOrConstOrDirectValue:nextCommand->argument]); [accumulator setStringValue:buffer]; [self setNextCommand:nextCommand->succ]; break; case C_NOP: [self setNextCommand:nextCommand->succ]; break; case C_END: [self setNextCommand:NULL]; break; case C_SAY: if (nextCommand->argument[0] == '\0') [self say:[accumulator stringValue]]; else [self say:[self getVarOrConstOrDirectValue:nextCommand->argument]]; [self setNextCommand:nextCommand->succ]; break; case C_PLAY: if (nextCommand->argument[0] == '\0') result = [self play:[accumulator stringValue]]; else result = [self play:[self getVarOrConstOrDirectValue:nextCommand->argument]]; if (result) [self setNextCommand:nextCommand->succ]; else [self setNextCommand:NULL]; break; case C_ALERT: if (nextCommand->argument[0] == '\0') result = [self alert:[accumulator stringValue]]; else result = [self alert:[self getVarOrConstOrDirectValue:nextCommand->argument]]; if (result) [self setNextCommand:nextCommand->succ]; else [self setNextCommand:NULL]; break; default: [self setMessage: [translation valueForStringKey:"Unbekannter Kommandocode"]]; return nil; } return self; } - reset:sender { NXStream * stream; char buffer[1024]; char * p; int c; int position, start; command * comm, * next; [constants empty]; [variables empty]; [self unselectNextInputLine]; // read and analyse constant lines stream = [constantsText stream]; NXSeek (stream, 0L, NX_FROMSTART); position = 0; while (1) { start = position; p = buffer; while ((c = NXGetc (stream)) != '\n' && c != EOF) { position++; *p++ = c; } *p = '\0'; if (p - buffer > 0) if (![self analyseConstantLine:buffer]) { [constantsText setSel:start :position]; return self; } position++; if (c == EOF) break; } // free commands comm = commands; while (comm != NULL) { next = comm->succ; free (comm); comm = next; } commands = NULL; // read and analyse program lines stream = [programText stream]; NXSeek (stream, 0L, NX_FROMSTART); position = 0; while (1) { start = position; p = buffer; while ((c = NXGetc (stream)) != '\n' && c != EOF) { position++; *p++ = c; } *p = '\0'; if (p - buffer > 0) if (![self analyseProgramLine:buffer start:start end:position]) { [programText setSel:start :position]; return self; } position++; if (c == EOF) break; } [self showVariables]; nextInputLine = 1; [self selectNextInputLine]; [self setNextCommand:commands]; [outputText setText:""]; [accumulator setStringValue:"0"]; [self setMessage:""]; return self; } - step:sender { if (![self performNextCommand]) return nil; if (nextCommand == NULL) [self setMessage:[translation valueForStringKey:"Fertig!"]]; return self; } /* - run:sender { int count; count = 0; while (nextCommand != NULL) { if (++count > 1000) // cycling control break; if ([self step:sender] == nil) break; } return self; } */ - run:sender { id result; if (nextCommand == NULL) return self; result = [self step:sender]; if (result == nil) return self; [self perform:@selector(run:) with:sender afterDelay:50 cancelPrevious:YES]; return self; } - stop:sender { [self perform:@selector(run:) with:sender afterDelay:-1 cancelPrevious:YES]; return self; } - toggleProgramVisibility:sender { if ([sender state]) { // on is invisible [programText setBackgroundGray:NX_DKGRAY]; [programText setTextGray:NX_DKGRAY]; [constantsText setBackgroundGray:NX_DKGRAY]; [constantsText setTextGray:NX_DKGRAY]; [variablesText setBackgroundGray:NX_DKGRAY]; [variablesText setTextGray:NX_DKGRAY]; } else { [programText setBackgroundGray:NX_WHITE]; [programText setTextGray:NX_BLACK]; [constantsText setBackgroundGray:NX_WHITE]; [constantsText setTextGray:NX_BLACK]; [variablesText setBackgroundGray:NX_LTGRAY]; [variablesText setTextGray:NX_BLACK]; } [programText update]; [constantsText update]; [variablesText update]; return self; } - setMessage:(const char *)msg { [programText scrollSelToVisible]; [messageText setStringValue:msg]; return self; } - save:sender { id savePanel; int tag; NXStream * stream; if (directory == NULL) directory = NXCopyStringBuffer ("~/Library/FIX"); if (filename == NULL) filename = NXCopyStringBuffer ([translation valueForStringKey:"OHNE_NAMEN.fix"]); savePanel = [SavePanel new]; [savePanel setTitle:[translation valueForStringKey:"FIX Abspeichern"]]; [savePanel setRequiredFileType:"fix"]; tag = [savePanel runModalForDirectory:directory file:filename]; [savePanel setTitle:[translation valueForStringKey:"Save"]]; if (tag == NX_OKTAG) { free (directory); directory = NXCopyStringBuffer ([savePanel directory]); free (filename); filename = NXCopyStringBuffer (rindex ([savePanel filename], '/') + 1); stream = NXOpenMemory (NULL, 0, NX_WRITEONLY); NXPrintf (stream, "Programm: %d\n", [programText byteLength]); [programText writeText:stream]; NXPrintf (stream, "\nFeste Daten: %d\n", [constantsText byteLength]); [constantsText writeText:stream]; [self unselectNextInputLine]; NXPrintf (stream, "\nEingaben: %d\n", [inputText byteLength]); [inputText writeText:stream]; [self selectNextInputLine]; if (NXSaveToFile (stream, [savePanel filename]) == -1) NXRunAlertPanel ([translation valueForStringKey:"Error"], [translation valueForStringKey:"Kann die Datei %s leider nicht schreiben."], NULL, NULL, NULL, [savePanel filename]); NXCloseMemory (stream, NX_FREEBUFFER); [[programText window] setTitleAsFilename:[savePanel filename]]; } return self; } - restore:sender { id openPanel; int tag; NXStream * stream; static const char * fileType[2] = {"fix", NULL}; char * buffer; int count; openPanel = [[OpenPanel new] allowMultipleFiles:NO]; if (directory == NULL) directory = NXCopyStringBuffer ("~/Library/FIX"); if (filename == NULL) filename = NXCopyStringBuffer (""); tag = [openPanel runModalForDirectory:directory file:filename types:fileType]; if (tag == NX_OKTAG) { free (directory); directory = NXCopyStringBuffer ([openPanel directory]); free (filename); filename = NXCopyStringBuffer (rindex ([openPanel filename], '/') + 1); stream = NXMapFile ([openPanel filename], NX_READONLY); if (stream == NULL) return self; count = 0; NXScanf (stream, "Programm: %d", &count); if (count == 0) [programText setText:""]; else { buffer = malloc (count + 2); if (NXRead (stream, buffer, count + 1) != count + 1) return self; buffer[count + 1] = '\0'; [programText setText:buffer + 1]; free (buffer); } count = 0; NXScanf (stream, "\nFeste Daten: %d", &count); if (count == 0) [constantsText setText:""]; else { buffer = malloc (count + 2); if (NXRead (stream, buffer, count + 1) != count + 1) return self; buffer[count + 1] = '\0'; [constantsText setText:buffer + 1]; free (buffer); } count = 0; NXScanf (stream, "\nEingaben: %d", &count); if (count == 0) [inputText setText:""]; else { buffer = malloc (count + 2); if (NXRead (stream, buffer, count + 1) != count + 1) return self; buffer[count + 1] = '\0'; [inputText setText:buffer + 1]; free (buffer); } NXCloseMemory (stream, NX_FREEBUFFER); [[programText window] setTitleAsFilename:[openPanel filename]]; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.