This is Controller.m in view mode; [Download] [Up]
// // This is the Compiler's Companion a program to integrate make's and Edit // more cleanly. Version 2.0 // // Copyright(C) 1992 Daryll Strauss // // This program is shareware; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 1, or (at your option) // any later version as long as you leave all the references to the fact // that it is shareware and covered by the GNU General Public License in // tact. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // Please see the README.rtf file for more details on the shareware // distribution and the GNU General Public License. // #import "Controller.h" #import <stdio.h> #import <stdlib.h> #import <strings.h> #import <mach_init.h> #import <mach_interface.h> #import <streams/streams.h> #import <sys/file.h> #import <dpsclient/dpsclient.h> #import <appkit/nextstd.h> #import <appkit/ScrollView.h> #import <appkit/Text.h> #import <appkit/Application.h> #import <appkit/Listener.h> #import <appkit/Speaker.h> #import <appkit/Panel.h> #import <appkit/Form.h> #import <appkit/Pasteboard.h> #import <appkit/Panel.h> #import <appkit/OpenPanel.h> #import "Defaults.h" #define DISPLAY_ERROR(msg) [self sysError:msg :__FILE__ :__LINE__] @implementation Controller static char *directory; static char *command; static char *good_cmd; static char *bad_cmd; static BOOL pref_services; static BOOL pref_pref_dir; static BOOL hide_on_success; static char *file; static BOOL prompt_User=TRUE; static BOOL Aux_Loaded=FALSE; static int end_pos; static BOOL Make_In_Progress=FALSE; Full_Defaults_Vector CompilerDefaults[] = { {default_string, "directory", "", &directory}, {default_const_string, "command", "make -k", &command}, {default_bool, "services", "Yes", &pref_services}, {default_bool, "usePrefDir", "No", &pref_pref_dir}, {default_bool, "hideOnSuccess", "No", &hide_on_success}, {default_string, "executeGood", "sndplay ~/Apps/Compiler.app/good.snd &", &good_cmd}, {default_string, "executeBad", "sndplay ~/Apps/Compiler.app/bad.snd &", &bad_cmd}, {default_end, 0, 0, 0} }; // // Basic support functions // void set_directory(char *new_dir) { if (directory) free(directory); directory=malloc(strlen(new_dir)+1); strcpy(directory, new_dir); } void set_file(char *new_file) { if (file) free(file); file=malloc(strlen(new_file)+1); strcpy(file, new_file); } int Find_Newline(NXStream *data, int direction) { int pos; if (direction==1) { while (!NXAtEOS(data)) if (NXGetc(data)=='\n') return(1); return(0); } else { pos=NXTell(data); while (pos>0) { NXSeek(data, pos, NX_FROMSTART); if (NXGetc(data)=='\n') return(1); pos--; } return(0); } } int parse_error(NXStream *data, char **file, int *line) { int file_pos, line_pos, i; char *filename, c=0; file_pos=NXTell(data); while (!NXAtEOS(data)) { c=NXGetc(data); if (c=='\n') return(0); if (c==' ') return(0); if (c==':') break; } if (c!=':') return(0); line_pos=NXTell(data); filename=*file=malloc(line_pos-file_pos); NXSeek(data, file_pos, NX_FROMSTART); for (i=0; i<line_pos-file_pos-1; i++) { *filename=NXGetc(data); filename++; } *filename=0; NXGetc(data); *line=(-1); while (!NXAtEOS(data)) { c=NXGetc(data); if (c==':' || c=='\n') break; if (c<'0' || c>'9') { free(*file); Find_Newline(data, 1); return(0); } else { if (*line==-1) *line=0; *line=10*(*line)+c-'0'; } } if ((c=='\n') || (*line==-1)) { free(*file); return(0); } return(1); } // // Object support functions // - (void)sysError:(char *)msg :(char *)file :(int)line { NXRunAlertPanel("System Error", "A system error occurred.\nThis should never happen.\nPlease include this in your bug report:\nVersion %s -- %s at %s:%d", "Sorry", 0, 0, __DATE__, msg, file, line); } - (const char *)Find_Lost_File:(const char *)file; { OpenPanel *op; op = [[OpenPanel new] allowMultipleFiles:FALSE]; [op setAccessoryView:locate]; if ([op runModal]) return([op filename]); return(0); } - (void)positionOnFile:(const char *)filename Line:(int)line { port_t edit_port; int completed; char position[100]; if ((edit_port=NXPortFromName("Edit", 0))==PORT_NULL) { DISPLAY_ERROR("Finding port"); return; } if (access(filename, R_OK)<0) { /* We can't find or open the given file */ filename=[self Find_Lost_File:filename]; if (!filename) { NXRunAlertPanel(0, "Couldn't find the file from the error message", 0, 0, 0); return; } } [[NXApp appSpeaker] setSendPort:edit_port]; if (![[NXApp appSpeaker] sendOpenFileMsg:filename ok:&completed andDeactivateSelf:TRUE]) { if (!completed) { NXRunAlertPanel(0, "Edit couldn't open file %s\n", 0, 0, 0, filename); return; } } else { DISPLAY_ERROR("Sending open"); return; } sprintf(position, "%d:%d", line, line); if (![[NXApp appSpeaker] msgSetPosition:position posType:NX_LINENUMPOSTYPE andSelect:TRUE ok:&completed]) { if (!completed) { NXRunAlertPanel(0, "Edit couldn't position the file at line %d\n", 0, 0, 0, line); return; } } else { DISPLAY_ERROR("Sending position"); return; } } - (void)loadAux { if (!Aux_Loaded) { [NXApp loadNibSection:"Auxillary.nib" owner:self]; Aux_Loaded=TRUE; } } - appDidInit:sender { Register_Full_Defaults("Compiler", CompilerDefaults); directory=0; Get_Full_Defaults("Compiler", CompilerDefaults); [cmd_form setStringValue:directory at:0]; [cmd_form setStringValue:command at:1]; [[NXApp appListener] setServicesDelegate:self]; NXSetServicesMenuItemEnabled("Compiler/Make", pref_services); NXSetServicesMenuItemEnabled("Compiler/Show Error", pref_services); return(self); } // // Services activated functions // - doMake:(id)pasteboard userData:(const char *)user error:(char **)error { char *data, *ptr; int len; const NXAtom *types; types=[pasteboard types]; while (types) if (*types==NXFilenamePboardType) break; if (!*types) DISPLAY_ERROR("Wrong pasteboard type"); if ([pasteboard readType:NXFilenamePboardType data:(void*)&data length:&len]) { if (pref_pref_dir) Get_Default_By_Name("Compiler", "directory", CompilerDefaults); else { ptr=data+strlen(data); while (*ptr!='/') ptr--; set_file(ptr+1); *ptr=0; if (strcmp(data, directory)) { set_directory(data); prompt_User=TRUE; } } vm_deallocate(task_self(), (vm_address_t)data, len); } [self doMake:self]; return(self); } - nextError:(id)pasteboard userData:(const char *)user error:(char **)error { [self nextError:self]; return(self); } // // Delegate methods for the subprocess object // - subprocessOutput:(char *)text { int cnt; NXSelPt start, end; cnt=strlen(text); if (cnt) { [[textfield docView] setAutodisplay:FALSE]; [[textfield docView] getSel:&start :&end]; [[textfield docView] setSel:end_pos :end_pos]; [[textfield docView] replaceSel:text]; [[textfield docView] setSel:start.cp :end.cp]; [[textfield docView] display]; [[textfield docView] setAutodisplay:TRUE]; end_pos+=cnt; } return(self); } - subprocessDone:(int)status { NXStream *data; char buf[10], c; BOOL result=TRUE, more; int pos; [process free]; process=0; data=[[textfield docView] stream]; NXSeek(data, 0, NX_FROMEND); Find_Newline(data, 0); do { pos=NXTell(data)-2; NXRead(data, buf, 9); buf[9]=0; if (!strcmp(buf, "*** Exit ")) { do { c=NXGetc(data); } while ((c>='0') && (c<='9')); if (c=='\n') { result=FALSE; break; } } NXSeek(data, pos, NX_FROMSTART); more=Find_Newline(data, 0); } while (more); if (result && !status) { [[textfield window] setTitle:"Compile Done -- SUCCESS"]; if (good_cmd && *good_cmd) system(good_cmd); if (hide_on_success) [NXApp hide:self]; } else { [[textfield window] setTitle:"Compile Done -- FAILURE"]; if (bad_cmd && *bad_cmd) system(bad_cmd); } Make_In_Progress=FALSE; return(self); } - subprocessError:(char *)msg { DISPLAY_ERROR(msg); return(self); } // // User interface activated functions // -doMake:(id)sender { char *shell, *ptr; if (Make_In_Progress) { NXRunAlertPanel("Busy", "Compilation in progress. Please start your compilation when the current one finishes", "OK", 0, 0); return(self); } if (prompt_User) { [[cmd_form window] makeKeyAndOrderFront:self]; [cmd_form setStringValue:directory at:0]; [cmd_form setStringValue:command at:1]; return(self); } Make_In_Progress=TRUE; [[textfield window] makeKeyAndOrderFront:self]; [[textfield docView] setSel:0 :0]; shell=getenv("SHELL"); if (!shell) shell="/bin/csh"; process=[[Subprocess alloc] init:shell withDelegate:self andPtySupport:FALSE andStdErr:TRUE]; if (!process) { DISPLAY_ERROR("Failed to create child process"); Make_In_Progress=FALSE; return(self); } if (file) { [process send:"set file=" withNewline:FALSE]; [process send:file withNewline:TRUE]; ptr=file+strlen(file); while (--ptr>=file) if (*ptr=='.') { *ptr=0; break; } [process send:"set stripped=" withNewline:FALSE]; [process send:file withNewline:TRUE]; if (ptr>=file) *ptr='.'; } if (directory) { [process send:"set dir=" withNewline:FALSE]; [process send:directory withNewline:TRUE]; } [process send:"echo cd " withNewline:FALSE]; [process send:directory withNewline:TRUE]; [process send:"cd " withNewline:FALSE]; [process send:directory withNewline:TRUE]; [process send:"echo " withNewline:FALSE]; [process send:command withNewline:TRUE]; [process send:"exec " withNewline:FALSE]; [process send:command withNewline:TRUE]; [process terminateInput]; [[textfield window] setTitle:"Compile¼Running"]; end_pos=0; [[textfield docView] setText:""]; [[textfield docView] setSel:0 :0]; return(self); } - nextError:(id)sender { NXSelPt start, end; NXStream *data; char *file, *path; int line; [[textfield docView] getSel:&start :&end]; data=[[textfield docView] stream]; if (start.cp<0) start.cp=0; NXSeek(data, end.cp, NX_FROMSTART); Find_Newline(data, 0); while (!NXAtEOS(data)) { start.cp=NXTell(data); if (parse_error(data, &file, &line)) { Find_Newline(data, 1); end.cp=NXTell(data); [[textfield docView] setSel:start.cp :end.cp]; [[textfield docView] scrollSelToVisible]; path=malloc(strlen(directory)+strlen(file)+2); sprintf(path, "%s/%s", directory, file); [self positionOnFile:path Line:line]; free(path); free(file); break; } } return(self); } - stopMake:(id)sender { if (Make_In_Progress) { [process terminate:self]; [self subprocessOutput:"TERMINATED\n"]; } return(self); } - resetPrefs:sender { char *hold_directory, *hold_command; hold_directory=directory; hold_command=command; directory=0; command=0; Reset_Defaults(CompilerDefaults); [self show_prefs:self]; set_directory(hold_directory); command=hold_command; return(self); } - setPrefs:sender { set_directory((char *)[pref_form stringValueAt:0]); command=(char *)[pref_form stringValueAt:1]; good_cmd=(char *)[pref_form stringValueAt:2]; bad_cmd=(char *)[pref_form stringValueAt:3]; pref_services=[service_switch intValue]; pref_pref_dir=[pref_dir_switch intValue]; hide_on_success=[hide_switch intValue]; Put_Full_Defaults("Compiler", CompilerDefaults); NXSetServicesMenuItemEnabled("Compiler/Make", pref_services); NXSetServicesMenuItemEnabled("Compiler/Show Error", pref_services); prompt_User=FALSE; [[pref_form window] orderOut:self]; return(self); } - setValues:sender { prompt_User=FALSE; set_directory((char *)[cmd_form stringValueAt:0]); command=(char *)[cmd_form stringValueAt:1]; [[cmd_form window] orderOut:self]; [self doMake:self]; return(self); } - show_help:sender { [self loadAux]; [NXGetNamedObject("Help", self) makeKeyAndOrderFront:self]; return(self); } - show_info:sender { [self loadAux]; [NXGetNamedObject("Info", self) makeKeyAndOrderFront:self]; return(self); } - show_license:sender { [self loadAux]; [NXGetNamedObject("License", self) makeKeyAndOrderFront:self]; return(self); } - show_prefs:sender { [self loadAux]; [pref_form setStringValue:directory at:0]; [pref_form setStringValue:command at:1]; [pref_form setStringValue:good_cmd at:2]; [pref_form setStringValue:bad_cmd at:3]; [service_switch setIntValue:pref_services]; [pref_dir_switch setIntValue:pref_pref_dir]; [hide_switch setIntValue:hide_on_success]; [NXGetNamedObject("Preferences", self) makeKeyAndOrderFront:self]; return(self); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.