This is Controller.m in view mode; [Download] [Up]
/*****************************************************************************
* Controller.m
*
* Authors:
* Denise Howard
* howardd@swissbank.com
*
* Michael Hawley
* mike@media.mit.edu
*
* Copyright (c) MIT Media Laboratory, 1991-1995.
*
* Description:
* This is the app delegate for Opener.
*
* Revisions:
* See Revision_History.rtfd in project directory HelpOpener.
*
* To add new filetypes:
* See Modifying.rtfd in project directory HelpOpener.
*
* Modified by Tsutomu_Eguchi@ns.saga-med.ac.jp April 1998
* Add bzip2, bunzip2, binhex support
* See Modifying.rtfd in project directory HelpOpener.
*
*****************************************************************************/
#import "Controller.h"
#import "Help.h"
#import "ComposeSuggestion.h"
@interface Speaker(ObsoleteMethods)
- (int)registerWindow:(int)windowNum toPort:(port_t)aPort;
- (int)unregisterWindow:(int)windowNum;
@end
@implementation Controller
static NXDefaultsVector OpenerDefaults = {
{"TmpDir", "/tmp"},
{"ArchiveFormat", ".tar.Z"},
{"FirstUsed", ""},
{NULL}
};
#define MaxLen 256
#define MaxSuf 64
#define MaxTab 64
#define MaxPend 512
#define LS_MSG_YES NXLocalizedString("Yes", NULL, "LS_MSG_YES") //TE
#define LS_MSG_NO NXLocalizedString("No", NULL, "LS_MSG_NO") //TE
#define LS_MSG_COULDNT_OPEN \
NXLocalizedString("Couldn't open file: %s",NULL,"LS_MSG_COULDNT_OPEN") //TE
char TmpDir[1024] = "/tmp";
char *iconPathList = (char *)0;
char MoreFiles[8192] = "";
int Reset = 1;
char Suffix[MaxTab][MaxSuf],
Command[MaxTab][MaxLen];
int NT = 0;
char PSuffix[MaxTab][MaxSuf],
PCommand[MaxTab][MaxLen];
int PNT = 0;
char *Pending[MaxPend];
int NP = 0;
static id me, pb2;
static char Files[8192];
/*****************************************************************************/
/* Functions start here */
/*****************************************************************************/
int
err(a,b,c,d)
char *a,*b,*c,*d;
{
char t[1024];
extern id NXApp;
sprintf(t,a,b,c,d);
return NXRunAlertPanel([NXApp appName],t,0,0,0)==1;
}
char *
tmp(char *s, char *suffix, int isDir)
{
/*
* return a path for a temporary file
* named "/tmp/O_[n_]file", where 'file' is 's';
* e.g., /a/b/foo.bar, .bar => /tmp/O_foo
* if 'isDir', map a "." in the suffix to "_" to ensure that
* the directory wrapper will open properly.
*/
static char t[1024];
char *p, u[1024];
int k = 1;
strcpy(u,s);
if (*suffix) u[strlen(u) - strlen(suffix)] = '\0';
if (p = rindex(u,'/')) p++;
else p = s;
if (isDir) {
char *x = rindex(p,'.');
if (x) *x = '_';
}
sprintf(t,"%s/O_%s", TmpDir, p);
while (access(t,0)==0) sprintf(t, "%s/O_%d_%s", TmpDir, k++, p);
return t;
}
char *
path(char *s)
/*
* if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
* (for looking up internal commands and files in .../Opener.app/...).
*/
{
char t[1024], *q, *r;
static char p[1024];
extern char **NXArgv;
*t = '\0';
sscanf(s,"%s",t);
if (!*t || *t=='(') return s;
r = s + strlen(t);
strcpy(p,*NXArgv);
if (q=rindex(p,'/'))
strcpy(q+1,t);
else
strcpy(p,t);
if (access(p,0)==0){
strcpy(p+strlen(p),r);
return p;
}
return s;
}
char *
skipsp(char *s)
{
while (*s==' ' || *s=='\t' || *s == '\n') ++s;
return s;
}
int
blank(char *s)
{ /* true if 's' is blank */
while (*s == ' ' || *s=='\t' || *s == '\n') ++s;
return !*s;
}
char *
save(char *s)
{
char *p = (char *)malloc(strlen(s)+1);
if (p) strcpy(p,s);
return p;
}
void
stripcomment(char *s)
{ /* truncate 's' at a comment character ('#') */
char *p = index(s,'#');
if (p && (p==s || p[-1] != '\\')) *p = '\0';
}
char *
strindex(char *s, char *t)
{ /* return ptr to first match of 't' in 's' */
int n = strlen(t);
if (s)
while (*s)
if (!strncmp(s, t, n)) return s;
else s++;
return (char *)0;
}
// Case-insensitive version of equal().
// Commented out by Denise Howard 08/93 Opener 3.1.1.
// int
// equal(char *s, char *t)
// { /* true if 's' & 't' are equal (case-insens.) */
// char a, b;
// while (*s && *t){
// a = isupper(*s)? tolower(*s) : *s;
// b = isupper(*t)? tolower(*t) : *t;
// s++, t++;
// if (a != b) return 0;
// }
// return (*s || *t)? 0 : 1;
// }
/* Case-sensitive version of equal(). */
/* Added by Howard 08/93 Opener 3.1.1. */
int
equal(char *s, char *t)
{ /* true if 's' & 't' are equal (case-sens.) */
char a, b;
while (*s && *t){
a = *s;
b = *t;
s++, t++;
if (a != b) return 0;
}
return (*s || *t)? 0 : 1;
}
int
tailmatch(char *s, char *t)
{ /* true if t appears at end of s */
int tn = strlen(t), sn = strlen(s);
if (tn > sn) return 0;
return equal(s+(sn-tn), t);
}
char *
shstrcat(char *s, char *t)
{ // strcat, but quote shell metachars
register char *p;
while (*s) s++;
p=t;
if (*p=='~') *s++='\\'; // csh "feature"
while (*p) {
if (*p<=' '||*p>'~'||index(";&()|<>\\'\"$*?[]^!", *p)) *s++='\\';
*s++=*p++;
}
*s='\0';
return t;
}
void
subfname(char *s, char *a, char *b)
{ /* like 'substr', but assumes the "b" string is a filename that may need
special-to-shell characters quoted */
char q[8192], quoted_b[2048];
char *p = s;
int n = strlen(a);
quoted_b[0] = '\0';
shstrcat(quoted_b, b);
for (;*p;p++){
if (*p == *a && strncmp(p,a,n)==0){
strcpy(q,p+n);
strcpy(p,quoted_b);
strcpy(p+strlen(quoted_b),q);
p += strlen(quoted_b)-1;
}
}
}
int
fdTime(int f)
{ /* return size of file 'f' */
struct stat b;
fstat(f, &b);
return b.st_mtime;
}
void
clearPackItems()
{
int i, n = [[pb2 target] count];
for (i=0;i<n;i++){
[[pb2 target] removeItemAt:i];
}
}
void
addPackItem(char *s)
{
// What this function does: add a cell to the pb2 matrix with title 's',
// and assign it a selector so that when someone selects it the title
// becomes the new default pack suffix.
id c;
c = [[pb2 target] addItem:s];
[c setTarget:me];
[c setAction:@selector(setPackSuffix:)];
}
void
resetPackItems()
{
int i;
clearPackItems();
for (i=0;i<PNT;i++)
addPackItem(PSuffix[i]);
}
void
addUnpackItem(char *s)
{
id c;
c = [[pb2 target] addItem:s];
[c setTarget:me];
[c setAction:@selector(setUnpackSuffix:)];
}
void
loadTable()
{
/*
* Unpacking files is table-driven.
* The file "Opener.table" is of the form
* suffix command
* like
* .Z uncompress < $f > $t
* When opening files, the table is checked to
* find a matching command for the given suffix.
*/
char s[1024];
FILE *f;
static int first = 1;
static int t = 0;
int pack = 0;
strcpy(s,path("Opener.table"));
if (!first){
if (f=fopen(s,"r")){
int tt = fdTime(fileno(f));
fclose(f);
if (tt == t) return;
t = tt; // table has changed -- reread it
NT=PNT=0;
clearPackItems();
printf("rereading table\n");
} else
return;
}
first = 0;
if (f = fopen(s,"r")){
char *p, *q;
t = fdTime(fileno(f));
while (fgets(s,sizeof s,f)){
stripcomment(s);
if (blank(s)) continue;
if (strncmp(s,"Unpack:",7)==0) continue;
if (strncmp(s,"Pack:",5)==0){ pack++; continue; }
if (pack){
for (p=skipsp(s), q=PSuffix[PNT];
*p && *p != ' ' && *p != '\t' && (q-PSuffix[PNT])<(MaxSuf-1);
*q++ = *p++) ;
*q = '\0';
for (p = skipsp(p), q=PCommand[PNT];
*p && (*p != '\n') && (q-PCommand[PNT])<(MaxLen-1);
*q++ = *p++) ;
*q='\0';
addPackItem(PSuffix[PNT]);
// printf("[%s]: %s\n",PSuffix[PNT],PCommand[PNT]);
if (!blank(PSuffix[PNT])&& !blank(PCommand[PNT]) && PNT < MaxTab)
++PNT;
} else {
for (p=skipsp(s), q=Suffix[NT];
*p && *p != ' ' && *p != '\t' && (q-Suffix[NT])<(MaxSuf-1);
*q++ = *p++) ;
*q = '\0';
for (p = skipsp(p), q=Command[NT];
*p && (*p != '\n') && (q-Command[NT])<(MaxLen-1);
*q++ = *p++) ;
*q='\0';
// printf("[%s]: %s\n",Suffix[NT],Command[NT]);
if (!blank(Suffix[NT]) && !blank(Command[NT]) && NT < MaxTab)
++NT;
}
}
fclose(f);
}
}
int
findSuffix(char *s)
{
char *p = s + strlen(s);
int i;
loadTable();
for (i=0;i<NT;i++)
if (equal(Suffix[i],p-strlen(Suffix[i])))
return i;
return -1;
}
int
findPSuffix(char *s)
{
char *p = s + strlen(s);
int i;
loadTable();
for (i=0;i<PNT;i++)
if (equal(PSuffix[i],p-strlen(PSuffix[i])))
return i;
return -1;
}
void
ex_unpack(char *s)
{
char t[1024];
if (strncmp(s,"unpack: ",8)) return;
strcpy(t,skipsp(s+8));
strcpy(s,"mkdir $t; cd $t; "); strcat(s,t);
}
void
substr(char *s, char *a, char *b)
{ /* like 'sub', but with strings */
char q[8192];
char *p = s;
int n = strlen(a);
for (;*p;p++){
if (*p == *a && strncmp(p,a,n)==0){
strcpy(q,p+n);
strcpy(p,b);
strcpy(p+strlen(b),q);
p += strlen(b)-1;
}
}
}
void
expand(char *s, int i, char *c)
{
/*
* 's' is the current filename.
* 'i' is the index in the Suffix/Command table.
* 'c' is the command to fill;
* Replace "unpack: ..." with the standard unpack command
* $f with the filename,
* $g => $f without the path
* $r => $f without any extensions
* $R => $f without any extensions and without the path
* $e => all the extensions (including the dot)
* $t with the temp
*/
char *T, *p, S[MaxSuf], q[1024], *r;
int isDir = 0;
strcpy(c,Command[i]);
strcpy(S,s+strlen(s)-strlen(Suffix[i]));
if (strindex(c,"mkdir $t") || strindex(c,"unpack: ")) isDir = 1;
T = tmp(s,Suffix[i],isDir);
ex_unpack(c); /* rewrite "unpack: ..." */
p = c; /* prepend the $p/... paths */
while (p = strindex(p,"$p/")){
sscanf(p,"%s",q);
r = path(q+3);
substr(p,q,r);
}
if (!strindex(c,"open ")){
if (isDir) strcat(c,"; (cd $t; open . )"); // make sure directory opens
else strcat(c,"; open $t");
}
subfname(c,"$f",s); /* expand the abbreviations */
subfname(c,"$t",T);
subfname(c,"$s",S);
/*******************************************************/
/* The following chunk handles the $r abbreviation */
/*******************************************************/
{
char root[1024];
int index=0;
while(s[index]!='\0' && index<1024 && s[index]!='.'){
root[index] = s[index];
index++;
}
root[index]='\0';
subfname(c,"$r",root);
}
/*******************************************************/
/* The following chunk handles the $e abbreviation */
/*******************************************************/
{
char ext[1024];
int index=0,ptr=0;
ext[0]='\0';
while(s[index]!='\0' && index<1024 && s[index]!='.'){
index++;
}
if(s[index]=='.'){
ptr = index;
while(s[index]!='\0' && index<1024){
ext[index-ptr]=s[index]; index++;
}
ext[index-ptr]='\0';
}
subfname(c,"$e",ext);
}
/*******************************************************/
/* The following chunk handles the $R abbreviation */
/*******************************************************/
{
char rroot[1024];
int index=0;
rroot[0]='\0';
while(s[index]!='\0'){index++;}
while(index>-1 && s[index]!='/'){index--;}
if(s[index]=='/'){
index++;
while(s[index]!='\0' && index<1024 && s[index]!='.'){
rroot[index] = s[index];
index++;
}
}
subfname(c,"$R",rroot);
}
/*******************************************************/
/* The following chunk handles the $g abbreviation */
/*******************************************************/
{
char sroot[1024];
int index=0;
sroot[0]='\0';
while(s[index]!='\0'){index++;}
while(index>-1 && s[index]!='/'){index--;}
if(s[index]=='/'){
index++;
while(s[index]!='\0' && index<1024){
sroot[index] = s[index];
index++;
}
}
subfname(c,"$g",sroot);
}
}
void
getTmpName(char *s, char *t)
{
/*
* Copy a /tmp name for the comp.sources archive into 't'.
* if 's' is ...comp.sources/.../foo/part00.Z ==> /tmp/O_foo
* ...comp.sources/.../foo.Z ==> /tmp/O_foo
*/
char *p = rindex(s,'/'), q[1024], c;
int n;
if (!p) return (void)strcpy(t,s);
strcpy(q,p+1);
c = q[4]; q[4]='\0';
if (equal(q,"part") && isdigit(c)){ /* skip to previous */
*p='\0';
p = rindex(s,'/');
if (!p) p=s;
else p++;
} else p++;
strcpy(t,p);
n = findSuffix(t);
p = (n== -1)? ".Z" : Suffix[n];
if (t[strlen(t)-strlen(p)]=='.')
t[strlen(t)-strlen(p)] = '\0';
strcpy(t,tmp(t,p,0));
}
int
System(fmt, a,b,c,d,e,f,g)
char *fmt,*a,*b,*c,*d,*e,*f,*g;
{
char t[8192];
sprintf(t,fmt,a,b,c,d,e,f,g);
printf("! %s\n",t);
return system(t);
}
void
openFile(char *s)
{ /* open 's' in workspace */
int ok = 0;
id p = [NXApp appSpeaker];
[p setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
[p openTempFile:s ok:&ok];
if (!ok) err(LS_MSG_COULDNT_OPEN,s);
}
void
previewFile(char *s)
{ /* open 's' in the default PostScript previewer */
/* This function worked over for 3.1.1 by Howard; it never worked before
* but it does now. */
char *a = (char *)0;
char *index;
char head[1024];
int ok = 0;
id p = [NXApp appSpeaker];
/* get handle on the user's favorite Preview application */
if (!a) a = "Preview";
[p setSendPort:NXPortFromName(a, NULL)];
getTmpName(s, head);
index = rindex(&head[0], '.');
if (tailmatch(s, ".PS"))
strcpy(index+1, "ps");
else
strcpy(index+1, "eps");
System("cp %s %s", s, head);
[p openFile: head ok:&ok];
if (!ok) err(LS_MSG_COULDNT_OPEN,s);
}
int
confirm(a,b,c,d)
char *a,*b,*c,*d;
{
char t[1024];
extern id NXApp;
sprintf(t,a,b,c,d);
return NXRunAlertPanel([NXApp appName],t,LS_MSG_YES,LS_MSG_NO,NULL)==1; //TE
}
int
unpackFile(char *s)
{
int i;
char c[2048];
i = findSuffix(s);
if (i != -1){ /* we found a suffix and command in the table */
expand(s,i,c);
[me system:c]; // System("(%s)&",c);
} else
if (tailmatch(s,".PS" ) || tailmatch(s,".EPS")) /* catch some PS files */
previewFile(s);
else
err("Couldn't open '%s'",s);
return 1;
}
int
isCompSourceArchive(char *s)
{
return ((strindex(s,"comp.sources") || strindex(s,"mod.sources") ||
strindex(s,"net.sources")) &&
equal(s+strlen(s)-2,".z") &&
!strindex(s,"index") && !strindex(s,"Index") && !strindex(s,"INDEX") &&
!strindex(s,"files") && !strindex(s,"Files") && !strindex(s,"FILES"));
}
void
reap(DPSTimedEntry n, double now, char *userData)
{
int i, np;
char x[1024], head[1024], c[8192], *p, q[1024], *r;
DPSRemoveTimedEntry(n);
np = NP;
if (!NP) return;
NP = 0;
if (confirm("Try to build %s...?",Pending[0])){
strcpy(x,Pending[0]);
getTmpName(x,head);
sprintf(c,"(mkdir $t; cp ");
for (i=0; i<np; i++)
strcat(c,Pending[i]), strcat(c," ");
sprintf(c+strlen(c)," $t; $p/builder $t; open $t $t/errors)&");
p = c; /* prepend the $p/... paths */
while (p = strindex(p,"$p/")){
sscanf(p,"%s",q);
r = path(q+3);
substr(p,q,r);
}
substr(c,"$t",head);
System("%s",c);
} else {
for (i=0;i<np;i++)
unpackFile(Pending[i]);
}
for (i=0;i<np;i++)
free(Pending[i]);
}
void
pending(char *s)
{
/*
* One or more files from a comp.sources archive are being selected.
* Put them on a queue -- reap() will unpack them specially.
*/
if (NP == MaxPend)
return (void)err("Too many pending files! Try quitting.");
Pending[NP++] = save(s);
DPSAddTimedEntry(4.0, (DPSTimedEntryProc)reap, 0, 10);
}
void
stot(char *s, char **t, char c)
{ /* split 's' into a table 't' */
char *p;
while (p = index(s,c)){
*p++ = '\0';
*t++ = s;
s = p;
}
*t++ = s;
*t = (char *)0;
}
void
trimdir(char *d, char **t)
{ /* put longest leading directory of t into d */
int i, n;
char *p,*q;
*d = '\0';
p = rindex(t[0],'/');
if (p){
*p='\0';
strcpy(d,t[0]); strcat(d,"/");
*p='/';
} else return ;
if (t[1]){
for (i=0;t[i];i++){
for (p=d,q=t[i]; *p && *q && *p == *q; p++, q++);
if (!*p) continue;
*p = '\0';
}
}
n = strlen(d);
for (i=0;t[i];i++) t[i] += n;
}
void
pexpand(i,c,d,f,F,t)
char *c, *d, *f, *F, *t;
int i;
/*
* like expand, but for packing:
* 'i' is the index in the Suffix/Command table.
* 'c' is the command to fill;
* 'd' is the prefix directory
* 'F' is the files without 'd' removed
* 'f' is the files with 'd' removed
* 't' is the files with 'd' removed
*/
{
char *p, q[1024], *r;
strcpy(c,PCommand[i]);
p = c; /* prepend the $p/... paths */
while (p = strindex(p,"$p/")){
sscanf(p,"%s",q);
r = path(q+3);
substr(p,q,r);
}
substr(c,"$F",F);
substr(c,"$f",f);
substr(c,"$d",d);
substr(c,"$t",t);
}
void
expand_files(char *s, char *p, char *dir)
{
char *t[1024], x[8192];
int i;
strcpy(x,s);
stot(x,t,'\t');
if (dir) trimdir(dir,t);
*p = '\0';
for (i=0;t[i];i++){
if (i > 0) strcat(p," ");
shstrcat(p,t[i]);
p += strlen(p);
}
}
char *
getText(id t, char *s)
{
id d = [t docView];
int n = [d textLength];
char *p;
*s = '\0';
[d getSubstring:s start:0 length:[d textLength]];
s[n] = '\0';
for (p=s; *p; p++) if (*p == '\n') *p = ' ';
return s;
}
void
setText(id t, char *s)
{
id w = [t window], d = [t docView];
static NXPoint origin = {0.0,0.0};
[w disableFlushWindow];
[d setMonoFont:YES];
[d setText:s];
[d setSel:0:999999];
[d setSelGray:0.0];
[d selectNull];
[d scrollPoint:&origin];
[t display];
[[w reenableFlushWindow] flushWindow];
NXPing();
}
int
setSuffixes(char *s)
{
char *p = s + strlen(s);
int i, r = -1;
loadTable();
clearPackItems();
for (i=0;i<NT;i++)
if (equal(Suffix[i],p-strlen(Suffix[i]))){
if (r == -1) r = i;
addUnpackItem(Suffix[i]);
}
if (r >= 0) [[pb2 selectedCell] setTitle:Suffix[r]];
return r;
}
/*****************************************************************************/
/* Action methods start here */
/*****************************************************************************/
- appWillInit:sender
{
me = self;
return self;
}
- appDidInit:sender
{
// char subj[512] = "Opener-";
unsigned int wn;
id s = [NXApp appSpeaker];
NXRegisterDefaults("Opener", OpenerDefaults);
strcpy(TmpDir, ((char *)NXGetDefaultValue("Opener", "TmpDir")));
[tmpDirTF setStringValue:TmpDir];
[versionTF setStringValue:[self version]];
// This new-user monitoring feature now obsolete (2/95) DJH
// strcat(subj, [self version]);
// strcat(subj, "-newuser");
// OpenerMonitor(subj);
NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &wn);
[s setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
[s registerWindow:wn toPort:[[NXApp appListener] listenPort]];
pb2 = packButton2;
return self;
}
- appWillTerminate:sender
{
unsigned int wn;
NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &wn);
[self removeTmpFiles:sender];
[[NXApp appSpeaker] unregisterWindow:wn];
[helpObject free];
return self;
}
- (BOOL)appAcceptsAnotherFile:sender
{
return YES;
}
#define LS_MSG_REMOVE_SCRATCH_FILE \
NXLocalizedString("Remove the scratch files in %s?",NULL,"LS_MSG_REMOVE_SCRATCH_FILE") //TE
- removeTmpFiles:sender
{
if ([self scratchFiles] &&
confirm(LS_MSG_REMOVE_SCRATCH_FILE, TmpDir)) { //TE
if (strcmp(TmpDir,"/tmp"))
System("rm -rf /tmp/O_* %s/O_* &", TmpDir);
else
System("rm -rf /tmp/O_* &");
}
return self;
}
- setTmp:sender
{
char *s = (char *)[sender stringValueAt:0];
if (!s || !*s || access(s,0)){
if (s && *s) err("Couldn't access '%s'",s);
s = (char *)[sender stringValueAt:0];
NXWriteDefault("Opener", "TmpDir", s);
strcpy(TmpDir, s);
[tmpDirTF setStringValue:s];
}
return self;
}
#define LS_MSG_UNPACK_FILES_IN \
NXLocalizedString("Unpack files in:", NULL, "LS_MSG_UNPACK_FILES_IN") //TE
- setDirectory:sender
{
id p = [SavePanel new];
char *s;
[[[p contentView] findViewWithTag:NX_OPTITLEFIELD]
setStringValue:LS_MSG_UNPACK_FILES_IN]; //TE
if ([p dirPanelRunModal] && (s = (char *)[p directory])){
NXWriteDefault("Opener", "TmpDir", s);
strcpy(TmpDir,s);
[tmpDirTF setStringValue:s];
}
return self;
}
- (int)appOpenFile:(const char *)filename type:(const char *)aType
{
if (isCompSourceArchive((char *)filename))
pending((char *)filename);
else
unpackFile((char *)filename);
return 1;
}
- openRequest:sender
{
const char *directory, *const *files;
static const char *const types[] = {
"tar", "TAR", "tar.z", "tar.Z", "TAR.Z", "tar-z", "tar-Z", "TAR-Z",
"taz", "TAZ",
"tar.gz", "tar.GZ", "TAR.GZ", "tar-gz", "tar-GZ", "TAR-GZ",
"tgz", "TGZ",
"shar","SHAR","shar.z","shar.Z","SHAR.Z","shar-z","shar-Z","SHAR-Z",
"shar.gz", "shar.GZ", "SHAR.GZ", "shar-gz", "shar-GZ", "SHAR-GZ",
"PS", "EPS", "PS-Z", "ps-Z", "ps-z", "EPS-Z", "eps-Z", "eps-z",
"PS-GZ", "ps-GZ", "ps-gz", "EPS-GZ", "eps-GZ", "eps-gz",
"tar.bz2", "tar.BZ2","TAR.BZ2","bz2","BZ2", //TE
"uu", "UU",
"lha", "Lha", "LHA",
"lzh", "Lzh", "LZH",
"arc", "Arc", "ARC",
"arj", "Arj", "ARJ",
"sit", "Sit", "SIT",
"cpt", "Cpt", "CPT",
"bin", "Bin", "BIN",
"hqx", "Hqx", "HQX",
"zip", "Zip", "ZIP",
"zoo", "Zoo", "ZOO",
"mime", "Mime", "MIME",
"gz", "Gz", "GZ",
"z", "Z",
"compressed", "Compressed", "COMPRESSED",
"gsm", "Gsm", "GSM",
"au", "Au", "AU",
NULL};
id p = [[OpenPanel new] allowMultipleFiles:YES];
char name[512];
if ([p runModalForTypes:types]){
files = [p filenames]; // list of multiple files
directory = [p directory];
while (files && *files) {
strcpy(name, directory );
strcat(name, "/" );
strcat(name, *files );
files++;
unpackFile(name);
}
}
return self;
}
- (BOOL)scratchFiles
{
char t[1024];
FILE *p;
char s[1024];
BOOL b = NO;
if (strcmp(TmpDir,"/tmp"))
sprintf(t,"ls /tmp/O_* %s/O_*", TmpDir);
else
sprintf(t,"ls /tmp/O_*");
p = popen(t,"r");
if (p){
if (fgets(s,sizeof s,p) && strncmp(s,"No match",8)) b = YES;
pclose(p);
}
return b;
}
- (int)iconEntered:(int)windowNum at:(double)x :(double)y
iconWindow:(int)iconWindowNum
iconX:(double)iconX iconY:(double)iconY
iconWidth:(double)iconWidth
iconHeight:(double)iconHeight
pathList:(char *)pathList
{
if (!iconPathList || strcmp(iconPathList, pathList)) {
free(iconPathList);
iconPathList = save(pathList);
}
return 0;
}
- processOutput:(char *)s
{
err("%s",s);
return self;
}
- system:(char *)s
{ // exec 's' and processOutput pops up a panel with output
[Process new:s delegate:self];
return self;
}
- setPackCommand
{
char t[1024], f[4096], F[4096], dir[1024], *p, files[8192];
char c[8192], *curSuffix, *curCmd;
int i;
Again:
curSuffix = (char *)[[packButton2 selectedCell] title];
curCmd = (char *)[[packButton selectedCell] title];
strcpy(files,Files);
if (strcmp(curCmd,"create")==0){ // curCmd == "unpack"
if (Reset) resetPackItems();
Reset = 1;
curSuffix = (char *)[[packButton2 selectedCell] title];
i = findPSuffix(curSuffix);
if (i == -1){
[packPanel orderOut:self];
err("Unknown archive format: %s",curSuffix);
return 0;
}
expand_files(files,f,dir);
expand_files(files,F,0);
sscanf(f,"%s",t); stripnl(t);
if (p = rindex(t,'/')) strcpy(t,p+1);
strcat(t,curSuffix);
p = tmp(t,"",0); strcpy(t,p);
pexpand(i,c,dir,f,F,t);
setText(packCmdText,c);
} else { // curCmd = "create" rather than "unpack"
if (index(files,'\t')){
char *p;
p = index(files,'\t');
*p = '\0';
strcpy(MoreFiles,p+1);
stripnl(files);
} else {
*MoreFiles = '\0';
}
expand_files(files,f,0);
i = setSuffixes(files);
if (i == -1){
extern void NXBeep();
[[packButton selectedCell] setTitle:"create"];
NXBeep();
resetPackItems();
NXPing();
goto Again;
}
expand(f,i,c);
setText(packCmdText,c);
}
return self;
}
#define LS_TITLE_MAKE_NEW_ARCHIVE \
NXLocalizedString("Make new archive", NULL, "LS_TITLE_MAKE_NEW_ARCHIVE") //TE
#define LS_TITLE_UNPACK_ARCHIVE \
NXLocalizedString("Unpack archive", NULL, "LS_TITLE_UNPACK_ARCHIVE") //TE
- setPackOrUnpack:sender
{
char *s = (char *)[[sender selectedCell] title];
[[packButton selectedCell] setTitle:s];
if (strcmp(s,"create")==0)
[packPanel setTitle:LS_TITLE_MAKE_NEW_ARCHIVE]; //TE
else
[packPanel setTitle:LS_TITLE_UNPACK_ARCHIVE]; //TE
NXPing();
resetPackItems();
[self setPackCommand];
return self;
}
- setUnpackSuffix:sender
{
char *s = (char *)[[sender selectedCell] title];
[[packButton2 selectedCell] setTitle:s];
NXPing();
resetPackItems();
[self setPackCommand];
return self;
}
- setPackSuffix:sender
{
// Change the default pack suffix in the Opener defaults to match the title
// on the selected cell. Then use the title to build a pack command.
char *s = (char *)[[sender selectedCell] title];
NXWriteDefault("Opener", "ArchiveFormat", s);
[[packButton2 selectedCell] setTitle:s];
Reset = 0; // bandaid
NXPing();
[self setPackCommand];
return self;
}
- packFiles:(char *)files
{
strcpy(Files,files);
if (!*MoreFiles){
if (index(Files,'\t') || findSuffix(Files) == -1){
[packPanel setTitle:LS_TITLE_MAKE_NEW_ARCHIVE]; //TE
[[packButton selectedCell] setTitle:"create"];
} else {
[packPanel setTitle:LS_TITLE_UNPACK_ARCHIVE]; //TE
[[packButton selectedCell] setTitle:"unpack"];
}
}
[packPanel makeKeyAndOrderFront:self];
[[packButton2 selectedCell] setTitle:((char *)NXGetDefaultValue("Opener",
"ArchiveFormat"))];
NXPing();
resetPackItems();
[self setPackCommand];
return self;
}
- cancelPack:sender
{
[packPanel orderOut:sender];
*MoreFiles = '\0';
return self;
}
- pack:sender
{
char c[8192];
getText(packCmdText,c);
if (!blank(c)) [self system:c];
[packPanel orderOut:sender];
if (*MoreFiles) [self packFiles:MoreFiles];
return self;
}
- (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag {
[self packFiles:iconPathList];
*flag = YES;
return 0;
}
- help:sender
{
if (!helpObject)
helpObject = [Help new];
[helpObject generalHelp:sender];
return self;
}
#define LS_MSG_CONFIRM_EDIT_TABLE \
NXLocalizedString("Edit the command table that controls Opener?\n(Unix experts only)", NULL, "LS_MSG_CONFIRM_EDIT_TABLE") //TE
- editTable:sender
{
char s[1024];
strcpy(s,path("open"));
if (confirm(LS_MSG_CONFIRM_EDIT_TABLE)) //TE
// System("open -a Edit %s",path("Opener.table"));
System("%s -a Edit %s", s, path("Opener.table")); //TE
return self;
}
- suggestion:sender
{
ComposeSuggestion();
return self;
}
/*****************************************************************************/
/* Access methods start here */
/*****************************************************************************/
- (char *)version
{
return "Version 3.4b Jun 1998"; //TE
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.