This is Preferences.m in view mode; [Download] [Up]
/* -*-C-*-
*******************************************************************************
*
* File: Preferences.m
* RCS: $Header: /usr/local/lib/cvs/EnhanceMail/Preferences.m,v 1.1.1.30 1996/07/01 01:10:26 cedman Exp $
* Description:
* Author: Carl Edman
* Created: Wed Nov 1 09:58:01 1995
* Modified: Thu Jun 27 20:06:19 1996 (Carl Edman) cedman@capitalist.princeton.edu
* Language: C
* Package: N/A
* Status: Experimental (Do Not Distribute)
*
* (C) Copyright 1995, but otherwise this file is perfect freeware.
*
*******************************************************************************
*/
#define PREFEXTERN
#import "Preferences.h"
#undef PREFEXTERN
#import "EnhanceMail.h"
#import "XFace.h"
#import "XImageURL.h"
#import "regexp.h"
#import <ctype.h>
#import <math.h>
#import <netdb.h>
#define MSG_OK NXLoadLocalizedStringFromTableInBundle("Buttons", nil, "OK", NULL)
#define MSG_BAD_XFACE NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "%s does not contain monochrome 48x48 image.", NULL, Error message for bad XFace)
#define MSG_BAD_REGEXP NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "%s is not a valid regular expression.", NULL, Error message for bad Regexp)
#define DEFAULT_QUOTE_INTRO NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "You wrote:", NULL, Default introduction to quotes in replies)
static struct PrefDefault
{
struct PrefDefault *next;
enum { bool=1, string, integer, color } type;
union
{
BOOL *bool;
const char **string;
int *integer;
NXColor *color;
} location;
id control;
char name[0];
} *prefroot=0;
static HashTable *PanelHash=nil;
static NXImage *delete_image=nil;
static id XImageURLButton=nil;
static id XFaceButton=nil;
@implementation EnhancePreferences
+ finishLoading:(struct mach_header *)header
{
id pref;
char path[MAXPATHLEN+1];
if (EnhanceBundle==0) EnhanceBundle=[NXBundle bundleForClass:[self class]];
[self poseAs:[self superclass]];
if ([EnhanceBundle getPath:path forResource:"delete" ofType:"tiff"])
delete_image=[[NXImage alloc] initFromFile:path];
pref=[Preferences new];
if ([EnhanceBundle getPath:path forResource:"EnhancePreferences" ofType:"nib"])
[NXApp loadNibFile:path owner:pref];
[pref addPanel:NXGetNamedObject("Quoting_Box2",pref)];
[pref addPanel:NXGetNamedObject("Images_Box2",pref)];
[pref addPanel:NXGetNamedObject("PGP_Box2",pref)];
[pref addPanel:NXGetNamedObject("Options_Box2",pref)];
[pref registerBool:"QuoteReplies"
location:&EnhanceQuoteReplies
control:"Quoting_Box2_Quoting_Quote Replies"
default:NO];
[pref registerString:"QuoteIntro"
location:&EnhanceQuoteIntro
control:"Quoting_Box2_Quoting_Form_Introduction"
default:DEFAULT_QUOTE_INTRO];
[pref registerString:"QuotePrefix"
location:&EnhanceQuotePrefix
control:"Quoting_Box2_Quoting_Form_Prefix"
default:"> %0"];
[pref registerString:"QuoteRegex"
location:&EnhanceQuoteRegex
control:"Quoting_Box2_Quoting_Form_Regex"
default:"^[>:# ]*[>:#] ?"];
[pref registerBool:"QuoteColoring"
location:&EnhanceQuoteColoring
control:"Quoting_Box2_Quoting_Color Quotes"
default:NO];
[pref registerColor:"QuoteColor"
location:&EnhanceQuoteColor
control:"Quoting_Box2_Quoting_Color"
default:NX_COLORBLACK];
[pref registerBool:"InsertSignature"
location:&EnhanceInsertSignature
control:"Quoting_Box2_Signatures_Insert Signatures"
default:NO];
[pref registerString:"SignatureFilename"
location:&EnhanceSignatureFilename
control:"Quoting_Box2_Signatures_Form_Filename"
default:".signature"];
[pref registerString:"SignatureSeparator"
location:&EnhanceSignatureSeparator
control:"Quoting_Box2_Signatures_Form_Separator"
default:"---\n"];
[pref registerBool:"InsertXFace"
location:&EnhanceInsertXFace
control:"Images_Box2_XFace_Form_Send XFace"
default:NO];
[pref registerBool:"ShowXFace"
location:&EnhanceShowXFace
control:"Images_Box2_XFace_Form_Show XFace"
default:NO];
XFaceButton=NXGetNamedObject("Images_Box2_XFace_Box_Image",pref);
[pref registerString:"XFace"
location:&EnhanceXFace
control:"Images_Box2_XFace_Path"
default:""];
[pref registerBool:"InsertXImageURL"
location:&EnhanceInsertXImageURL
control:"Images_Box2_XImageURL_Form_Send XImageURL"
default:NO];
[pref registerBool:"ShowXImageURL"
location:&EnhanceShowXImageURL
control:"Images_Box2_XImageURL_Form_Show XImageURL"
default:NO];
XImageURLButton=NXGetNamedObject("Images_Box2_XImageURL_Box_Image",pref);
[pref registerString:"XImageURL"
location:&EnhanceXImageURL
control:"Images_Box2_XImageURL_Path"
default:""];
[pref registerBool:"UsePGP"
location:&EnhanceUsePGP
control:"PGP_Box2_PGP_Use PGP"
default:NO];
[pref registerInteger:"PGPPassTimeout"
location:&EnhancePGPPassTimeout
control:"PGP_Box2_PGP_Pass Timeout"
default:0];
[pref registerBool:"RetrievePGPKeys"
location:&EnhanceRetrievePGPKeys
control:"PGP_Box2_PGP_Buttons_Retrieve PGP Keys"
default:NO];
[pref registerBool:"PGPSign"
location:&EnhancePGPSign
control:"PGP_Box2_PGP_Buttons_Sign"
default:NO];
[pref registerBool:"PGPEncrypt"
location:&EnhancePGPEncrypt
control:"PGP_Box2_PGP_Buttons_Encrypt"
default:NO];
[pref registerString:"PGPPath"
location:&EnhancePGPPath
control:"PGP_Box2_PGP_Texts_PGP Path"
default:"/usr/local/bin/pgp"];
[pref registerString:"KeyServerURL"
location:&EnhanceKeyServerURL
control:"PGP_Box2_PGP_Texts_Key Server URL"
default:"http://pgp.ai.mit.edu/htbin/pks-extract-key.pl?op=get&search="];
[pref registerBool:"RepliesWithOriginals"
location:&EnhanceRepliesWithOriginals
control:"Options_Box2_Other_Form_Keep Replies with Originals"
default:NO];
[pref registerBool:"AutoSpellCheck"
location:&EnhanceAutoSpellCheck
control:"Options_Box2_Other_Form_Automatically spell check messages"
default:NO];
[pref registerBool:"AutoCompact"
location:&EnhanceAutoCompact
control:"Options_Box2_Other_Form_Automatically compact mailboxes"
default:NO];
[pref registerBool:"LaunchMailboxes"
location:&EnhanceLaunchMailboxes
control:"Options_Box2_Other_Form_Open Mailboxes Window on Launch"
default:NO];
[pref registerBool:"LaunchAddresses"
location:&EnhanceLaunchAddresses
control:"Options_Box2_Other_Form_Open Addresses Window on Launch"
default:NO];
[pref registerBool:"FlagReplies"
location:&EnhanceFlagReplies
control:"Options_Box2_Other_Form_Flag Replies"
default:NO];
[pref registerBool:"ExpandSmilies"
location:&EnhanceExpandSmilies
control:"Options_Box2_Other_Form_Expand Smilies"
default:NO];
[pref registerBool:"RestoreDeletesDraft"
location:&EnhanceRestoreDeletesDraft
control:0
default:NO];
[pref registerBool:"BackSpaceBackPages"
location:&EnhanceBackSpaceBackPages
control:0
default:NO];
[pref registerString:"HTTPProxy"
location:&EnhanceHTTPProxy
control:0
default:""];
[pref registerString:"Smilies"
location:&EnhanceSmilies
control:0
default:
":-*\\]\nFaceGrinning.tiff\n\
:-*[oO]\nFaceStartled.tiff\n\
:-*[)>]\nFaceHappy.tiff\n\
;-*[>)]\nFaceWinking.tiff\n\
:-[/\\\\]\nFaceIronic.tiff\n\
:-*|\nFaceStraight.tiff\n\
:-[(<]\nFaceAngry.tiff\n\
:-*d\nFaceTasty.tiff\n\
:-*[pP]\nFaceYukky.tiff\n\
8-*|\nFaceKOed.tiff"
];
[pref upLoad];
return self;
}
- (void)downLoad
{
struct PrefDefault *pd;
const char *appname, *tmp;
char buf[10240];
appname=[NXApp appName];
for(pd=prefroot;pd;pd=pd->next) if (pd->control!=nil) switch (pd->type)
{
case bool:
*pd->location.bool=[pd->control state];
break;
case string:
*pd->location.string=[pd->control stringValue];
break;
case integer:
*pd->location.integer=[pd->control intValue];
break;
case color:
*pd->location.color=[pd->control color];
break;
}
for(pd=prefroot;pd;pd=pd->next) switch (pd->type)
{
case bool:
NXWriteDefault(appname,pd->name,*(pd->location.bool) ? "YES" : "NO");
break;
case string:
NXWriteDefault(appname,pd->name,*(pd->location.string));
break;
case integer:
sprintf(buf,"%d",*(pd->location.integer));
NXWriteDefault(appname,pd->name,buf);
break;
case color:
if (tmp=NXColorName(*(pd->location.color)))
NXWriteDefault(appname,pd->name,tmp);
else
{
float red,green,blue;
NXConvertColorToRGB(*(pd->location.color),&red,&green,&blue);
sprintf(buf,"RGB%02x%02x%02x",(int)rint(red*0xff),(int)rint(green*0xff),(int)rint(blue*0xff));
NXWriteDefault(appname,pd->name,buf);
}
break;
}
[super downLoad];
}
- (void)upLoad
{
int i;
struct PrefDefault *pd;
const char *appname, *value, *c;
id colorlistlist=[NXColorList availableColorLists];
[super upLoad];
NXUpdateDefaults();
appname=[NXApp appName];
for(pd=prefroot;pd;pd=pd->next) if (value=NXReadDefault(appname,pd->name)) switch (pd->type)
{
case bool:
if (strcasecmp(value,"YES")==0)
*(pd->location.bool)=YES;
else if (strcasecmp(value,"NO")==0)
*(pd->location.bool)=NO;
else
[self logWarning:"Boolean default %s given bad value \"%s\".",appname,pd->name,value];
break;
case string:
*(pd->location.string)=value;
break;
case integer:
for(c=value;isspace(*c);c++);
for(i=0;isdigit(*c);c++) i=i*10+(*c-'0');
while(isspace(*c)) c++;
if (*c=='\0')
*(pd->location.integer)=i;
else
[self logWarning:"Integer default %s given bad value \"%s\".",appname,pd->name,value];
break;
case color:
i=-1;
if ((strncmp(value,"RGB",3)==0)&&(strlen(value)==9))
{
for(c=value+3,i=0;*c;c++)
{
if (*c>='0' && *c<='9') i=16*i+*c-'0';
else if (*c>='a' && *c<='f') i=16*i+*c-('a'-10);
else if (*c>='A' && *c<='F') i=16*i+*c-('A'-10);
else break;
}
if (*c)
i=-1;
else
{
*(pd->location.color)=NXConvertRGBToColor(((i>>16)&0xff)/255.0,((i>>8)&0xff)/255.0,(i&0xff)/255.0);
i=0;
}
}
if (i<0) for(i=[colorlistlist count]-1;i>=0;i--)
{
if (NXFindColorNamed([[colorlistlist objectAt:i] name],value,pd->location.color))
break;
}
if (i<0)
[self logWarning:"Color default %s given bad value \"%s\".",appname,pd->name,value];
break;
}
for(pd=prefroot;pd;pd=pd->next) if (pd->control!=nil)
{
switch (pd->type)
{
case bool:
[pd->control setState:*(pd->location.bool)];
break;
case string:
[pd->control setStringValue:*(pd->location.string)];
break;
case integer:
[pd->control setIntValue:*(pd->location.integer)];
break;
case color:
[pd->control setColor:*(pd->location.color)];
break;
}
if (pd->control)
{
id con;
if ([pd->control respondsTo:@selector(sendAction:to:)])
[pd->control sendAction:[pd->control action] to:[pd->control target]];
else if ([pd->control respondsTo:@selector(controlView)]
&& ((con=[pd->control controlView])!=nil)
&& [con respondsTo:@selector(sendAction:to:)])
[con sendAction:[pd->control action] to:[pd->control target]];
}
}
[prefPanel setDocEdited:NO];
}
- controlFor:(const void *)location
{
struct PrefDefault *pd;
for(pd=prefroot;pd;pd=pd->next)
if ((pd->location.string)==location) return pd->control;
return nil;
}
- addPanel:panel
{
id cell;
id popuplist;
int tag;
if (panel==nil) return nil;
popuplist=[[viewButton cell] target];
for(tag=0;[popuplist findCellWithTag:tag]!=nil;tag++);
cell=[popuplist addItem:[[panel window] title]];
[cell setTarget:self];
[cell setAction:@selector(changeView:)];
[cell setTag:tag];
if (PanelHash==nil) PanelHash=[[HashTable alloc] initKeyDesc:"i" valueDesc:"@"];
[PanelHash insertKey:(const void *)tag value:panel];
return self;
}
- registerBool:(const char *)name location:(BOOL *)loc control:(const char *)con default:(BOOL)def
{
struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
pd->next=prefroot;
pd->type=bool;
pd->location.bool=loc;
*loc=def;
pd->control=con ? NXGetNamedObject(con,self) : nil;
if ((pd->control!=nil)
&& ([pd->control respondsTo:@selector(setEnabled:)]))
[pd->control setEnabled:YES];
strcpy(pd->name,name);
prefroot=pd;
return self;
}
- registerString:(const char *)name location:(const char **)loc control:(const char *)con default:(const char *)def
{
struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
pd->next=prefroot;
pd->type=string;
pd->location.string=loc;
*loc=def;
pd->control=con ? NXGetNamedObject(con,self) : nil;
if ((pd->control!=nil)
&& ([pd->control respondsTo:@selector(setEnabled:)]))
[pd->control setEnabled:YES];
strcpy(pd->name,name);
prefroot=pd;
return self;
}
- registerInteger:(const char *)name location:(int *)loc control:(const char *)con default:(int)def
{
struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
pd->next=prefroot;
pd->type=integer;
pd->location.integer=loc;
*loc=def;
pd->control=con ? NXGetNamedObject(con,self) : nil;
if ((pd->control!=nil)
&& ([pd->control respondsTo:@selector(setEnabled:)]))
[pd->control setEnabled:YES];
strcpy(pd->name,name);
prefroot=pd;
return self;
}
- registerColor:(const char *)name location:(NXColor *)loc control:(const char *)con default:(NXColor)def
{
struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
pd->next=prefroot;
pd->type=color;
pd->location.color=loc;
*loc=def;
pd->control=con ? NXGetNamedObject(con,self) : nil;
if ((pd->control!=nil)
&& ([pd->control respondsTo:@selector(setEnabled:)]))
[pd->control setEnabled:YES];
strcpy(pd->name,name);
prefroot=pd;
return self;
}
- changeView:sender
{
id ret,item,panel,ogeneralview;
int tag;
if (((item=[viewButton selectedPopUpItem])==nil)
||((tag=[item tag])==0)
||(PanelHash==nil)
||((panel=[PanelHash valueForKey:(const void *)tag])==nil))
return [super changeView:sender];
ogeneralview=generalView;
generalView=panel;
[item setTag:0];
ret=[super changeView:sender];
[item setTag:tag];
generalView=ogeneralview;
return ret;
}
- noteChangeXFace:sender
{
id XFace=[self controlFor:&EnhanceXFace];
const char *val;
NXRect r;
NXImage *image;
if (!XFace || !XFaceButton) return nil;
val=[XFace stringValue];
[XFaceButton getBounds:&r];
image=[[NXImage alloc] initFromFile:val xFaceSize:&r.size];
if (image==nil) image=delete_image;
[XFaceButton setImage:image];
return [self noteChange:sender];
}
- noteChangeXImageURL:sender
{
id XImageURL=[self controlFor:&EnhanceXImageURL];
NXRect r;
NXImage *image;
const char *val;
if (!XImageURL || !XImageURLButton) return nil;
val=[XImageURL stringValue];
[XImageURLButton getBounds:&r];
image=[[NXImage alloc] initURL:val];
if (image==nil) image=delete_image;
[image setScalable:YES];
[image setSize:&r.size];
[XImageURLButton setImage:image];
return [self noteChange:sender];
}
- setXFace:sender
{
id open;
const char *const types[] = { "tiff", 0 };
id XFaceC=[self controlFor:&EnhanceXFace];
if (((XFaceC=[self controlFor:&EnhanceXFace])==nil)
|| ((open=[OpenPanel new])==nil)
|| ([open allowMultipleFiles:NO]==nil)
|| ([open runModalForDirectory:[XFaceC stringValue] file:0 types:types]!=NX_OKTAG)
|| ([open filename]==0))
return nil;
[XFaceC setStringValue:[open filename]];
return [self noteChangeXFace:sender];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.