|
/*ScianPreferences.c
Eric Pepke
June 15, 1991
Preferences in SciAn
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianMethods.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianStyle.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianDialogs.h"
#include "ScianControls.h"
#include "ScianButtons.h"
#include "ScianTextBoxes.h"
#include "ScianErrors.h"
#include "ScianPreferences.h"
#include "ScianScripts.h"
typedef union pv
{
char *string; /*String value*/
Bool truth; /*Expression true or false*/
long integer; /*Numeric value*/
} PrefValue;
typedef struct
{
char *shortName; /*Short name of the preference*/
char *longName; /*Long name of the preference*/
int type; /*Type of the preference*/
char *helpString; /*String of the help*/
} PrefInfo;
typedef struct
{
Bool exists; /*True iff the preference exists*/
Bool changed; /*True iff the preference has been changed*/
PrefValue value; /*Value of the preference*/
} PrefState;
PrefInfo prefInfo[NPREFERENCES] =
{
{"DEFDIR", "Data File Directory", PT_STRING,
"This controls the default directory that will be used when you choose NewFileWindow from the File menu. \
Edit the string in the text box to change it."},
{"ROTINERTIA", "Rotation Inertia", PT_YNBOOL,
"This controls the inertia when you rotate objects within a space. \
If Yes is selected, the space will continue to rotate it when you give it a spin and release the mouse button while moving the mouse. \
You can stop the rotation by clicking in the space again."},
{"NEWWINPLACE", "New Window Placement", PT_AMBOOL,
"This controls how new windows will be placed on the screen. If Automatic is \
selected, windows will be created with a fixed size and automatically staggered. \
If Manual is selected, you will need to drag out the outline of new windows \
before they appear on the screen."},
{"DRAWMOVING", "Interactive Drawing", PT_AFFINT,
"This controls how visualization objects are drawn when you are interactively \
changing them. If Full Quality is selected, objects will always be drawn in full \
quality. If Faster is selected, objects will be drawn with only a skeleton while you are \
interactively moving them, which is much faster. This can provide better feedback \
on slower computers. If Automatic is selected, SciAn will automatically choose whether \
objects are to be drawn fully or faster depending on how much time they take to draw."},
{"STAGGERICONS", "Stagger Icons", PT_YNBOOL,
"This controls whether icons will be staggered in icon corrals. If Yes is selected, \
the vertical position of the icons will be staggered so that long icon names have \
less chance of overlapping. If No is selected, icons will not be staggered."}
,
{"SCREENSAVE", "Screen Save", PT_RPINT,
"This controls whether screen snapshots are saved as IRIS rgb files or as PostScript files. \
If PostScript is selected they will be saved as embedded PostScript files with a file extension \
of .eps. If IRIS RGB is selected, they will be saved as IRIS RGB files with a file \
extension of .rgb. Screen saving is done using the recorder drivers, and the \
parameters are set within the recorder driver control panels."},
{"IDLENAP", "Nap When Idle", PT_YNBOOL,
"This controls whether SciAn naps when it is idle. When No is checked, SciAn will \
constantly run housekeeping functions. This will ensure that interaction is quick, but \
it may slow down other processes running on the computer. When Yes is checked, SciAn will \
nap for one-second intervals five seconds after the last window change. This will \
release time for use by other processes, but the first interaction when it is napping \
may take up to a second to respond."},
{"GARBAGECOLLECT", "Garbage Collection", PT_SFBOOL,
"This controls whether garbage collection is absolutely safe or a little bit \
faster."}
};
PrefState prefState[NPREFERENCES];
#define PREFCELLHEIGHT 40 /*Height of a cell in preferences*/
#define PREFNAMEWIDTH 200 /*Width of the name of a preference*/
#define PREFFIELDWIDTH 400 /*Width of a field of a preference*/
Bool PrefExists(whichPref)
int whichPref;
/*Returns true iff whichPref exists*/
{
return prefState[whichPref] . exists;
}
char *GetPrefString(whichPref)
int whichPref;
/*Gets the string for preference whichPref*/
{
if (prefInfo[whichPref] . type != PT_STRING) return 0;
return prefState[whichPref] . value . string;
}
Bool GetPrefTruth(whichPref)
int whichPref;
/*Gets the truth for preference whichPref*/
{
if (prefInfo[whichPref] . type != PT_YNBOOL &&
prefInfo[whichPref] . type != PT_AMBOOL &&
prefInfo[whichPref] . type != PT_SFBOOL)
{
return false;
}
return prefState[whichPref] . value . truth;
}
long GetPrefInteger(whichPref)
int whichPref;
/*Gets the integer for preference whichPref*/
{
if (prefInfo[whichPref] . type != PT_AFFINT &&
prefInfo[whichPref] . type != PT_RPINT)
{
return false;
}
return prefState[whichPref] . value . integer;
}
static void MakePrefFromString(whichPref, string)
int whichPref;
char *string;
/*Makes a preference whichPref from string*/
{
prefState[whichPref] . exists = true;
switch(prefInfo[whichPref] . type)
{
case PT_STRING:
prefState[whichPref] . value . string = Alloc(strlen(string) + 1);
strcpy(prefState[whichPref] . value . string, string);
break;
case PT_YNBOOL:
if (strcmp2(string, "yes") == 0 || strcmp2(string, "true") == 0)
{
prefState[whichPref] . value . truth = true;
}
else
{
prefState[whichPref] . value . truth = false;
}
break;
case PT_AMBOOL:
if (strcmp2(string, "auto") == 0 || strcmp2(string, "automatic") == 0)
{
prefState[whichPref] . value . truth = true;
}
else
{
prefState[whichPref] . value . truth = false;
}
break;
case PT_SFBOOL:
if (strcmp2(string, "fast") == 0 || strcmp2(string, "reckless") == 0)
{
prefState[whichPref] . value . truth = true;
}
else
{
prefState[whichPref] . value . truth = false;
}
break;
case PT_AFFINT:
if (strcmp2(string, "auto") == 0 || strcmp2(string, "automatic") == 0)
{
prefState[whichPref] . value . integer = 2;
}
else if (strcmp2(string, "fast") == 0 || strcmp2(string, "faster") == 0)
{
prefState[whichPref] . value . integer = 1;
}
else
{
prefState[whichPref] . value . integer = 0;
}
break;
case PT_RPINT:
if (strcmp2(string, "post") == 0 || strcmp2(string, "postscript") == 0)
{
prefState[whichPref] . value . integer = 1;
}
else
{
prefState[whichPref] . value . integer = 0;
}
break;
}
}
static ObjPtr ChangePrefString(object)
ObjPtr object;
/*Changed value for a text box object that controls a string preference*/
{
ObjPtr var, value;
int whichPref;
var = GetIntVar("ChangePrefString", object, WHICHPREF);
if (!var)
{
return ObjFalse;
}
whichPref = GetInt(var);
value = GetValue(object);
if (!value || !IsString(value))
{
return ObjFalse;
}
if (prefState[whichPref] . value . string)
{
Free(prefState[whichPref] . value . string);
}
prefState[whichPref] . value . string = Alloc(strlen(GetString(value)) + 1);
strcpy(prefState[whichPref] . value . string, GetString(value));
prefState[whichPref] . changed = true;
prefState[whichPref] . exists = true;
return ObjTrue;
}
static ObjPtr ChangePrefBoolean(object)
ObjPtr object;
/*Changed value for a text box object that controls a boolean preference*/
{
ObjPtr var, value;
int whichPref;
var = GetIntVar("ChangePrefBoolean", object, WHICHPREF);
if (!var)
{
return ObjFalse;
}
whichPref = GetInt(var);
value = GetValue(object);
if (!value || !IsInt(value))
{
return ObjFalse;
}
prefState[whichPref] . value . truth = GetInt(value);
prefState[whichPref] . changed = true;
prefState[whichPref] . exists = true;
return ObjTrue;
}
static ObjPtr ChangePrefInteger(object)
ObjPtr object;
/*Changed value for a text box object that controls an integer preference*/
{
ObjPtr var, value;
int whichPref;
var = GetIntVar("ChangePrefInteger", object, WHICHPREF);
if (!var)
{
return ObjFalse;
}
whichPref = GetInt(var);
value = GetValue(object);
if (!value || !IsInt(value))
{
return ObjFalse;
}
prefState[whichPref] . value . integer = GetInt(value);
prefState[whichPref] . changed = true;
prefState[whichPref] . exists = true;
return ObjTrue;
}
void DoShowPreferences()
/*Shows the preferences dialog*/
{
WinInfoPtr dialogExists, newDialog;
ObjPtr whichDialog;
int nPreferences;
if (logging)
{
Log("show preferences\n");
InhibitLogging(true);
}
whichDialog = NewString("Preferences");
#ifdef RELEASE
nPreferences = NRELEASEPREFERENCES;
#else
nPreferences = NPREFERENCES;
#endif
dialogExists = DialogExists(0, whichDialog);
newDialog = GetDialog(0, whichDialog, "Preferences",
PREFNAMEWIDTH + PREFFIELDWIDTH + 3 * MAJORBORDER,
PREFCELLHEIGHT * nPreferences + MAJORBORDER * 2,
PREFNAMEWIDTH + PREFFIELDWIDTH + 3 * MAJORBORDER,
PREFCELLHEIGHT * nPreferences + MAJORBORDER * 2,
WINUI + WINFIXEDSIZE);
if (!dialogExists)
{
/*Fill the dialog with stuff*/
ObjPtr contents, panel, radio, button, textBox;
int left, right, bottom, top;
int k;
/*Set the help string*/
SetVar((ObjPtr) newDialog, HELPSTRING,
NewString("This window shows your personal preferences for using \
SciAn. The preferences are saved in a file named \".scianPrefs\" in your home \
directory when you exit SciAn normally. \
Use Help In Context and click on the various controls to find out what they do."));
contents = GetListVar("DoShowPreferences", (ObjPtr) newDialog, CONTENTS);
if (!contents) return;
panel = NewPanel(greyPanelClass,
0, PREFNAMEWIDTH + PREFFIELDWIDTH + 3 * MAJORBORDER,
0, PREFCELLHEIGHT * nPreferences + MAJORBORDER * 2
);
if (!panel)
{
return;
}
PrefixList(contents, panel);
contents = GetListVar("DoShowPreferences", panel, CONTENTS);
if (!contents) return;
SetVar(panel, PARENT, (ObjPtr) newDialog);
for (k = 0; k < nPreferences; ++k)
{
char objName[200], longName[300];
int median;
/*Calculate a median line*/
median = MAJORBORDER + PREFCELLHEIGHT / 2 + PREFCELLHEIGHT * (nPreferences - 1 - k);
/*Add a text box for this preference*/
sprintf(objName, "%s name", prefInfo[k] . shortName);
if (prefInfo[k] . type == PT_YNBOOL)
{
sprintf(longName, "%s?", prefInfo[k] . longName);
}
else
{
sprintf(longName, "%s:", prefInfo[k] . longName);
}
textBox = NewTextBox(MAJORBORDER, MAJORBORDER + PREFNAMEWIDTH,
median - TEXTBOXHEIGHT / 2, median + TEXTBOXHEIGHT / 2,
0, objName, longName);
PrefixList(contents, textBox);
SetVar(textBox, PARENT, panel);
SetVar(textBox, HELPSTRING, NewString(prefInfo[k] . helpString));
SetTextFont(textBox, "Helvetica-Bold");
/*Add the field based on the type of preference*/
switch(prefInfo[k] . type)
{
case PT_STRING:
sprintf(objName, "%s field", prefInfo[k] . shortName);
textBox = NewTextBox(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH,
median - PITBOXHEIGHT / 2, median + PITBOXHEIGHT / 2,
EDITABLE + WITH_PIT + ONE_LINE, objName,
prefState[k] . value . string);
PrefixList(contents, textBox);
SetVar(textBox, HELPSTRING, NewString(prefInfo[k] . helpString));
SetVar(textBox, PARENT, panel);
SetVar(textBox, WHICHPREF, NewInt(k));
SetMethod(textBox, CHANGEDVALUE, ChangePrefString);
break;
case PT_YNBOOL:
sprintf(objName, "%s radio", prefInfo[k] . shortName);
radio = NewRadioButtonGroup(objName);
PrefixList(contents, radio);
SetVar(radio, PARENT, panel);
SetVar(radio, HELPSTRING, NewString(prefInfo[k] . helpString));
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"No");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Yes");
AddRadioButton(radio, button);
SetValue(radio, NewInt(prefState[k] . value . truth));
SetVar(radio, WHICHPREF, NewInt(k));
SetMethod(radio, CHANGEDVALUE, ChangePrefBoolean);
break;
case PT_AMBOOL:
sprintf(objName, "%s radio", prefInfo[k] . shortName);
radio = NewRadioButtonGroup(objName);
PrefixList(contents, radio);
SetVar(radio, PARENT, panel);
SetVar(radio, HELPSTRING, NewString(prefInfo[k] . helpString));
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Manual");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Automatic");
AddRadioButton(radio, button);
SetValue(radio, NewInt(prefState[k] . value . truth));
SetVar(radio, WHICHPREF, NewInt(k));
SetMethod(radio, CHANGEDVALUE, ChangePrefBoolean);
break;
case PT_SFBOOL:
sprintf(objName, "%s radio", prefInfo[k] . shortName);
radio = NewRadioButtonGroup(objName);
PrefixList(contents, radio);
SetVar(radio, PARENT, panel);
SetVar(radio, HELPSTRING, NewString(prefInfo[k] . helpString));
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Safer");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Faster");
AddRadioButton(radio, button);
SetValue(radio, NewInt(prefState[k] . value . truth));
SetVar(radio, WHICHPREF, NewInt(k));
SetMethod(radio, CHANGEDVALUE, ChangePrefBoolean);
break;
case PT_AFFINT:
sprintf(objName, "%s radio", prefInfo[k] . shortName);
radio = NewRadioButtonGroup(objName);
PrefixList(contents, radio);
SetVar(radio, PARENT, panel);
SetVar(radio, HELPSTRING, NewString(prefInfo[k] . helpString));
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Full Quality");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Faster");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"Automatic");
AddRadioButton(radio, button);
SetValue(radio, NewInt(prefState[k] . value . integer));
SetVar(radio, WHICHPREF, NewInt(k));
SetMethod(radio, CHANGEDVALUE, ChangePrefInteger);
break;
case PT_RPINT:
sprintf(objName, "%s radio", prefInfo[k] . shortName);
radio = NewRadioButtonGroup(objName);
PrefixList(contents, radio);
SetVar(radio, PARENT, panel);
SetVar(radio, HELPSTRING, NewString(prefInfo[k] . helpString));
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH,
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"IRIS RGB");
AddRadioButton(radio, button);
button = NewRadioButton(
MAJORBORDER * 2 + PREFNAMEWIDTH + PREFFIELDWIDTH / 3,
MAJORBORDER * 2 + PREFNAMEWIDTH + 2 * PREFFIELDWIDTH / 3,
median - CHECKBOXHEIGHT / 2, median + CHECKBOXHEIGHT / 2,
"PostScript");
AddRadioButton(radio, button);
SetValue(radio, NewInt(prefState[k] . value . integer));
SetVar(radio, WHICHPREF, NewInt(k));
SetMethod(radio, CHANGEDVALUE, ChangePrefInteger);
break;
}
}
}
if (logging)
{
InhibitLogging(false);
}
}
void InitPreferences()
/*Initialize the preferences*/
{
int k;
FILE *prefFile;
/*Avoid a core dump if I forget to handle all preferences*/
for (k = 0; k < NPREFERENCES; ++k)
{
prefState[k] . value . string = 0;
prefState[k] . changed = false;
}
/*Set up default values for all preferences*/
prefState[PREF_DEFDIR] . value . string = Alloc(2);
strcpy(prefState[PREF_DEFDIR] . value . string, ".");
prefState[PREF_ROTINERTIA] . value . truth = true;
prefState[PREF_NEWWINPLACE] . value . truth = true;
prefState[PREF_DRAWMOVING] . value . integer = DM_FULL;
/*Try to read all preferences from environment variables*/
for (k = 0; k < NPREFERENCES; ++k)
{
char *envString;
prefState[k] . exists = false;
/*See if it can be read from an environment variable*/
strcpy(tempStr, "SCIAN_");
strcat(tempStr, prefInfo[k] . shortName);
envString = getenv(tempStr);
if (envString)
{
MakePrefFromString(k, envString);
}
}
/*If a preferences file exists, open it and read it*/
sprintf(tempStr, "%s/%s", getenv("HOME"), ".scianPrefs");
prefFile = fopen(tempStr, "r");
if (prefFile)
{
char *s1, *s2, *s3;
while (fgets(tempStr, TEMPSTRSIZE, prefFile))
{
s1 = tempStr;
while (*s1 && *s1 == ' ') ++s1;
s2 = s1;
while (*s2 && *s2 != ' ') ++s2;
*s2++ = 0;
while (*s2 && *s2 == ' ') ++s2;
s3 = s2;
while (*s3 && *s3 != '\n') ++s3;
*s3 = 0;
for (k = 0; k < NPREFERENCES; ++k)
{
if (0 == strcmp2(s1, prefInfo[k] . shortName))
{
MakePrefFromString(k, s2);
break;
}
}
}
fclose(prefFile);
}
}
void KillPreferences()
/*Kills the preferences*/
{
int k;
Bool savePreferences;
savePreferences = false;
/*Determine if preferences should be saved*/
for (k = 0; k < NPREFERENCES; ++k)
{
if (prefState[k] . changed)
{
savePreferences = true;
}
}
if (savePreferences)
{
/*Save the preferences*/
FILE *prefFile;
sprintf(tempStr, "%s/%s", getenv("HOME"), ".scianPrefs");
prefFile = fopen(tempStr, "w");
if (prefFile)
{
for (k = 0; k < NPREFERENCES; ++k)
{
if (prefState[k] . exists)
{
fprintf(prefFile, "%s ", prefInfo[k] . shortName);
switch (prefInfo[k] . type)
{
case PT_STRING:
fprintf(prefFile, "%s\n", prefState[k] . value . string);
break;
case PT_YNBOOL:
fprintf(prefFile, "%s\n", prefState[k] . value . truth ? "yes" : "no");
break;
case PT_AMBOOL:
fprintf(prefFile, "%s\n", prefState[k] . value . truth ? "auto" : "manual");
break;
case PT_SFBOOL:
fprintf(prefFile, "%s\n", prefState[k] . value . truth ? "fast" : "safe");
break;
case PT_AFFINT:
fprintf(prefFile, "%s\n", prefState[k] . value . integer ? (prefState[k] . value . integer == 2 ? "auto" : "faster") : "full");
break;
case PT_RPINT:
fprintf(prefFile, "%s\n", prefState[k] . value . integer ? "PostScript" : "RGB");
break;
}
}
}
fclose(prefFile);
}
}
/*Get rid of the preferences*/
for (k = 0; k < NPREFERENCES; ++k)
{
if ((prefInfo[k] . type == PT_STRING) && (prefState[k] . value . string))
{
Free(prefState[k] . value . string);
prefState[k] . value . string = 0;
}
}
}
|