[comp.sources.amiga] setpref

ain@j.cc.purdue.edu (Patrick White) (08/11/88)

Submitted by:	peter@sugar.UUCP (Peter da Silva)
Summary:	Dump and load preferences settings from a file.
Poster Boy:	Patrick White	(ain@j.cc.purdue.edu)
Archive Name:	sources/amiga/volume5/setpref.sh.Z
untested.
 
NOTES:
   I had to shar it -- the 'README' file is really just the explanation
Peter sent me on the beginning of the submission.
   This will not compile without the 1.3 preferences.h include file (Peter
claimed it was 1.2, but I think he made a mistake).  I can't post the
include file, but I have been told that the new includes will be distributed
with the release of 1.3.. if not, you can always buy them from CATS :-)
.
 
 
-- Pat White   (co-moderator comp.sources/binaries.amiga)
ARPA/UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM  PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906
[archives at: j.cc.purdue.edu.ARPA]
 
========================================
 
#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	pref.c
# This archive created: Mon Aug  8 09:52:48 1988
# By:	Patrick White (PUCC Land, USA)
cat << \SHAR_EOF > README
The following program isn't sharred, because it's just one file. It's a
handy little program that you can use to selectively save, edit, and
reload all or part of your Preferences in text format. For example,
suppose you had a file with this in it:

1> type pointer
PointerMatrix
                
       2        
       2        
      2 2       
      2 2       
     1   1      
     1   1      
    1     1     
    1     1     
    333 333     
      3 3       
      3 3       
      3 3       
      333       
                


                
XOffset -8
YOffset 0
1>

Then you could type:

1> prefs <pointer set
1>

Or if you have a decent shell:

% prefs set <pointer
%

The only prefs entry I go to any pains about is the pointer, because it's
the hardest to get right. The rest are dumped an an appropriate format for
their data type. You really need preferences.h to make the most of this
program, and you need to be a bit of a guru to do anything with the odder
entries.

One problem comes for people who use setfont: when you set preferences the
font gets reset to topaz. &^%&^$^%$&$
SHAR_EOF
cat << \SHAR_EOF > pref.c
/* Prefs.c
 *
 * Author: Peter da Silva
 *
 * Usage:
 *   To save preferences into a file:
 *     prefs >filename
 *   To restore (presumably edited) preferences from a file:
 *     prefs <filename set
 *
 * Distribution: this program is public domain. Please be cool and leave
 *   my name on it. It makes me feel good.
 *
 * Modification history:
 *   Release: 28 April 1988, the day Max Headroom returned.
 *
 * Joke:
 *   How many IBM programmers does it take to screw in a lightbulb?
 *   None -- the marketing department claims the dead bulb is a feature.
 */
#include <stdio.h>
#include <intuition/intuition.h>
#include <ctype.h>

struct Preferences prefs;

/* Internal tags for feilds. Add new prefs feilds (1.3?) after these. They
 * Have to be in the same order in flds.
 */
#define P_FontHeight 0
#define P_PrinterPort 1
#define P_BaudRate 2
#define P_KeyRptSpeed 3
#define P_KeyRptDelay 4
#define P_DoubleClick 5
#define P_PointerMatrix 6
#define P_XOffset 7
#define P_YOffset 8
#define P_color17 9
#define P_color18 10
#define P_color19 11
#define P_PointerTicks 12
#define P_color0 13
#define P_color1 14
#define P_color2 15
#define P_color3 16
#define P_ViewXOffset 17
#define P_ViewYOffset 18
#define P_ViewInitX 19
#define P_ViewInitY 20
#define P_EnableCLI 21
#define P_PrinterType 22
#define P_PrinterFilename 23
#define P_PrintPitch 24
#define P_PrintQuality 25
#define P_PrintSpacing 26
#define P_PrintLeftMargin 27
#define P_PrintRightMargin 28
#define P_PrintImage 29
#define P_PrintAspect 30
#define P_PrintShade 31
#define P_PrintThreshold 32
#define P_PaperSize 33
#define P_PaperLength 34
#define P_PaperType 35
#define P_SerRWBits 36
#define P_SerStopBuf 37
#define P_SerParShk 38
#define P_LaceWB 39
#define P_WorkName 40
#define P_RowSizeChange 41
#define P_ColumnSizeChange  42
#define P_PrintFlags 43
#define P_PrintMaxWidth 44
#define P_PrintMaxHeight 45
#define P_PrintDensity 46
#define P_PrintXOffset 47

/* Symbol table. Add new feilds just before where it says "aliases".
 */
struct {
	char *Name;
	int ID;
} flds[] = {
	"FontHeight", P_FontHeight,
	"PrinterPort", P_PrinterPort,
	"BaudRate", P_BaudRate,
	"KeyRptSpeed", P_KeyRptSpeed,
	"KeyRptDelay", P_KeyRptDelay,
	"DoubleClick", P_DoubleClick,
	"PointerMatrix", P_PointerMatrix,
	"XOffset", P_XOffset,
	"YOffset", P_YOffset,
	"color17", P_color17,
	"color18", P_color18,
	"color19", P_color19,
	"PointerTicks", P_PointerTicks,
	"color0", P_color0,
	"color1", P_color1,
	"color2", P_color2,
	"color3", P_color3,
	"ViewXOffset", P_ViewXOffset,
	"ViewYOffset", P_ViewYOffset,
	"ViewInitX", P_ViewInitX,
	"ViewInitY", P_ViewInitY,
	"EnableCLI", P_EnableCLI,
	"PrinterType", P_PrinterType,
	"PrinterFilename", P_PrinterFilename,
	"PrintPitch", P_PrintPitch,
	"PrintQuality", P_PrintQuality,
	"PrintSpacing", P_PrintSpacing,
	"PrintLeftMargin", P_PrintLeftMargin,
	"PrintRightMargin", P_PrintRightMargin,
	"PrintImage", P_PrintImage,
	"PrintAspect", P_PrintAspect,
	"PrintShade", P_PrintShade,
	"PrintThreshold", P_PrintThreshold,
	"PaperSize", P_PaperSize,
	"PaperLength", P_PaperLength,
	"PaperType", P_PaperType,
	"SerRWBits", P_SerRWBits,
	"SerStopBuf", P_SerStopBuf,
	"SerParShk", P_SerParShk,
	"LaceWB", P_LaceWB,
	"WorkName", P_WorkName,
	"RowSizeChange", P_RowSizeChange,
	"ColumnSizeChange", P_ColumnSizeChange ,
	"PrintFlags", P_PrintFlags,
	"PrintMaxWidth", P_PrintMaxWidth,
	"PrintMaxHeight", P_PrintMaxHeight,
	"PrintDensity", P_PrintDensity,
	"PrintXOffset", P_PrintXOffset,
/* Aliases */
	"Pointer", P_PointerMatrix,
	"PointerSpeed", P_PointerTicks,
	0, 0
};

#define SET 1
#define SAVE 2

struct IntuitionBase *IntuitionBase, *OpenLibrary();

/* Symbol table routines :->
 */
Match(s1, s2)
char *s1;
char *s2;
{
	char c1, c2;

	c1 = *s1;
	c2 = *s2;
	while(*s1 && *s2) {
		if(islower(c1)) c1 = toupper(c1);
		if(islower(c2)) c2 = toupper(c2);
		if(c1!=c2) return 0;
		s1++;
		s2++;
		c1 = *s1;
		c2 = *s2;
	}
	return c1 == c2;
}

Lookup(s)
char *s;
{
	int i;

	for(i = 0; flds[i].Name; i++)
		if(Match(s, flds[i].Name))
			return flds[i].ID;
}

Usage()
{
	printf("Prefs [SET]\n");
}

/* Check options, and do the dirty work.
 */
main(ac, av)
int ac;
char **av;
{
	int mode = 0;
	int ret;

	mode = SAVE;
	if(av[1]) {
		if(Match(av[1], "SET"))
			mode = SET;
		else {
			Usage();
			exit(5);
		}
	}

	if(!(IntuitionBase = OpenLibrary("intuition.library", 33))) {
		printf("Can't open intuition.library.\n");
		exit(20);
	}
	GetPrefs(&prefs, sizeof(prefs));

	ret = DoPrefs(mode);

	CloseLibrary(IntuitionBase);
	return ret;
}

DoPrefs(mode)
{
	if(mode==SET) {
		if(ReadPrefs())
			SetPrefs(&prefs, sizeof(prefs), 1);
		else
			return 20;
	} else {
		ShowPrefs();
	}
	return 0;
}

/* Dump all prefs. This could probably be made selective, but that's what
 * delete line is for in your editor :->.
 */
ShowPrefs()
{
	DumpBYTE(flds[P_FontHeight].Name, prefs.FontHeight);
	DumpUBYTE(flds[P_PrinterPort].Name, prefs.PrinterPort);
	DumpUSHORT(flds[P_BaudRate].Name, prefs.BaudRate);
	Dumptimeval(flds[P_KeyRptSpeed].Name, &prefs.KeyRptSpeed);
	Dumptimeval(flds[P_KeyRptDelay].Name, &prefs.KeyRptDelay);
	Dumptimeval(flds[P_DoubleClick].Name, &prefs.DoubleClick);
	DumpPointer(flds[P_PointerMatrix].Name, &prefs.PointerMatrix);
	DumpBYTE(flds[P_XOffset].Name, prefs.XOffset);
	DumpBYTE(flds[P_YOffset].Name, prefs.YOffset);
	DumpUSHORT(flds[P_color17].Name, prefs.color17);
	DumpUSHORT(flds[P_color18].Name, prefs.color18);
	DumpUSHORT(flds[P_color19].Name, prefs.color19);
	DumpUSHORT(flds[P_PointerTicks].Name, prefs.PointerTicks);
	DumpUSHORT(flds[P_color0].Name, prefs.color0);
	DumpUSHORT(flds[P_color1].Name, prefs.color1);
	DumpUSHORT(flds[P_color2].Name, prefs.color2);
	DumpUSHORT(flds[P_color3].Name, prefs.color3);
	DumpBYTE(flds[P_ViewXOffset].Name, prefs.ViewXOffset);
	DumpBYTE(flds[P_ViewYOffset].Name, prefs.ViewYOffset);
	DumpWORD(flds[P_ViewInitX].Name, prefs.ViewInitX);
	DumpWORD(flds[P_ViewInitY].Name, prefs.ViewInitY);
	DumpBOOL(flds[P_EnableCLI].Name, prefs.EnableCLI);
	DumpUSHORT(flds[P_PrinterType].Name, prefs.PrinterType);
	DumpString(flds[P_PrinterFilename].Name, prefs.PrinterFilename);
	DumpUSHORT(flds[P_PrintPitch].Name, prefs.PrintPitch);
	DumpUSHORT(flds[P_PrintQuality].Name, prefs.PrintQuality);
	DumpUSHORT(flds[P_PrintSpacing].Name, prefs.PrintSpacing);
	DumpUWORD(flds[P_PrintLeftMargin].Name, prefs.PrintLeftMargin);
	DumpUWORD(flds[P_PrintRightMargin].Name, prefs.PrintRightMargin);
	DumpUSHORT(flds[P_PrintImage].Name, prefs.PrintImage);
	DumpUSHORT(flds[P_PrintAspect].Name, prefs.PrintAspect);
	DumpUSHORT(flds[P_PrintShade].Name, prefs.PrintShade);
	DumpWORD(flds[P_PrintThreshold].Name, prefs.PrintThreshold);
	DumpUSHORT(flds[P_PaperSize].Name, prefs.PaperSize);
	DumpUWORD(flds[P_PaperLength].Name, prefs.PaperLength);
	DumpUSHORT(flds[P_PaperType].Name, prefs.PaperType);
	DumpUBYTE(flds[P_SerRWBits].Name, prefs.SerRWBits);
	DumpUBYTE(flds[P_SerStopBuf].Name, prefs.SerStopBuf);
	DumpUBYTE(flds[P_SerParShk].Name, prefs.SerParShk);
	DumpUBYTE(flds[P_LaceWB].Name, prefs.LaceWB);
	DumpString(flds[P_WorkName].Name, prefs.WorkName);
	DumpBYTE(flds[P_RowSizeChange].Name, prefs.RowSizeChange );
	DumpBYTE(flds[P_ColumnSizeChange].Name, prefs.ColumnSizeChange );
	DumpUWORD(flds[P_PrintFlags].Name, prefs.PrintFlags);
	DumpUWORD(flds[P_PrintMaxWidth].Name, prefs.PrintMaxWidth);
	DumpUWORD(flds[P_PrintMaxHeight].Name, prefs.PrintMaxHeight);
	DumpUBYTE(flds[P_PrintDensity].Name, prefs.PrintDensity);
	DumpUBYTE(flds[P_PrintXOffset].Name, prefs.PrintXOffset);
}

/* Dump stuff
 */
DumpBYTE(name, value)
char *name;
BYTE value;
{
	printf("%s %d\n", name, value);
}

DumpUBYTE(name, value)
char *name;
UBYTE value;
{
	printf("%s 0x%02x\n", name, value);
}

DumpUSHORT(name, value)
char *name;
USHORT value;
{
	printf("%s 0x%04x\n", name, value);
}

Dumptimeval(name, value)
char *name;
struct timeval *value;
{
	printf("%s (%d:%06d)\n", name, value->tv_secs, value->tv_micro);
}

/* This one is a trifle hairy. I don't do anything special about the first
 * and last lines of the pointer. See the docs on Sprites when you go through
 * here.
 */
DumpPointer(name, value)
char *name;
USHORT value[POINTERSIZE];
{
	int i, j, w1, w2, c;
	printf("%s\n", name);
	for(i = 0; i < POINTERSIZE; i+=2) {
		w1=value[i];
		w2=value[i+1];
		for(j = 0; j < 16; j++) {
			c = '0';
			if(w1&0x8000) c += 1;
			if(w2&0x8000) c += 2;
			putchar(c);
			w1<<=1;
			w2<<=1;
		}
		putchar('\n');
	}
}

DumpWORD(name, value)
char *name;
WORD value;
{
	printf("%s %ld\n", name, value);
}

DumpBOOL(name, value)
char *name;
BOOL value;
{
	printf("%s %c\n", name, value?'T':'F');
}

DumpString(name, value)
char *name;
UBYTE *value;
{
	printf("%s \"%s\"\n", name, value);
}

DumpUWORD(name, value)
char *name;
UWORD value;
{
	printf("%s 0x%08x\n", name, value);
}

char inputbuffer[255];	/* Where to read data */
int virgin;	/* Used when pointer has been truncated to indicate that the
		stuff in "inputbuffer" hasn't had its cherry popped. */

/* This routine reads numbers in hex or decimal.
 * Almost worthy of getting stuck in a library.
 */
char *ReadNum(s, n)
char *s;
long *n;
{
	long num;
	int digit;
	int negate;
	int base;

	while(isspace(*s)) s++;
	if(*s=='-') {
		negate = -1;
		s++;
	} else
		negate = 1;
	if(!isdigit(*s)) {
		printf("Not a number: %s\n", s);
		return 0;
	}
	if(*s=='0') {
		s++;
		if(*s=='x' || *s=='X') {
			s++;
			base=16;
		} else
			base = 10;
	} else
		base = 10;

	num = 0;
	while(1) {
		if(*s<'0')
			break;
		else if(*s<='9')
			digit = *s-'0';
		else if(*s<'A')
			break;
		else if(*s<='F')
			digit = *s-'A'+10;
		else if(*s<'a')
			break;
		else if(*s,'f')
			digit = *s-'a'+10;
		else
			break;
		if(digit >= base)
			break;
		num = num * base + digit;
		s++;
	}
	*n = num * negate;
	return s;
}

/* Time value is (secs:micros)
 */
char *Readtimeval(s, t)
char *s;
struct timeval *t;
{
	char *s1;
	int secs, micro;
	int defsecs;

	if(*s=='(')
		s++;
	if(*s==':') {
		secs = 0;
		defsecs = 1;
	} else {
		s = ReadNum(s, &secs);
		defsecs = 0;
	}
	if(!s) return 0;
	if(*s==':') {
		s++;
		s1 = ReadNum(s, &micro);
		if(s1)
			s=s1;
		else {
			if(defsecs) {
				error();
				printf("Must specify either secs or microsecs\n");
				return 0;
			} else
				micro = 0;
		}
	} else
		micro = 0;
	if(*s==')')
		s++;
	t->tv_secs = secs;
	t->tv_micro = micro;
	return s;
}

/* See comments on DumpPointer. Note that this code doesn't care whether you
 * use "0123", "@ABC", " 123", or any other combination of characters, just
 * so long as the low two bits are right. Each line must start with a digit
 * or space, though.
 */
char *ReadPointer(p)
USHORT p[POINTERSIZE];
{
	int i, j, mask;
	for(i = 0; i < POINTERSIZE; i += 2) {
		gets(inputbuffer);
		virgin = 1;
		if(!isdigit(*inputbuffer) && *inputbuffer!=' ')
			break;
		virgin = 0;
		for(j = 0; j < 16; j++)
			if(!inputbuffer[j])
				break;
		for(; j < 16; j++)
			inputbuffer[j] = 0;
		mask = 0x8000;
		p[i] = p[i+1] = 0;
		for(j = 0; j < 16; j++) {
			if(inputbuffer[j]&0x01)
				p[i] |= mask;
			if(inputbuffer[j]&0x02)
				p[i+1] |= mask;
			mask >>= 1;
		}
	}
	for(; i < POINTERSIZE; i += 2)
		p[i] = p[i+1] = 0;
	return inputbuffer;
}

/* Uses shell-like quoting. Either '' or "" can be used to delimit strings,
 * and you can concatenate them by butting them together. A bit of overkill,
 * but what the hell.
 */
char *ReadString(s, t, max)
char *s;
char *t;
int max;
{
	char target;

	while(isspace(*s))
		s++;
	if(*s == '"' || *s == '\'') {
		while(*s == '"' || *s == '\'') {
			target = *s;
			s++;

			while(*s!=target && *s) {
				if(max>0) {
					*t++ = *s++;
					max--;
				} else
					s++;
			}

			if(*s==target)
				s++;
		}
		if(max>0)
			*t = 0;
		return s;
	} else {
		error();
		printf("Not a string: %s\n", s);
		return 0;
	}
}

char *ReadWord(s, t)
char *s;
char *t;
{
	if(!isalpha(*s) && *s != '_') {
		error();
		printf("Not an identifier: %s\n", s);
		return 0;
	}
	while(isalnum(*s) || *s=='_')
		*t++ = *s++;
	*t = 0;
	return s;
}

char *ReadBYTE(s, v)
char *s;
BYTE *v;
{
	ULONG n;
	if(s = ReadNum(s, &n))
		*v = n;
	return s;
}

char *ReadUBYTE(s, v)
char *s;
UBYTE *v;
{
	ULONG n;
	if(s = ReadNum(s, &n))
		*v = n;
	return s;
}

char *ReadUSHORT(s, v)
char *s;
USHORT *v;
{
	ULONG n;
	if(s = ReadNum(s, &n))
		*v = n;
	return s;
}

char *ReadWORD(s, v)
char *s;
WORD *v;
{
	ULONG n;
	if(s = ReadNum(s, &n))
		*v = n;
	return s;
}

char *ReadBOOL(s, v)
char *s;
BOOL *v;
{
	while(isdigit(*s))
		s++;
	if(*s=='t' || *s=='T')
		*v = 1;
	else if(*s=='f' || *s=='F')
		*v = 0;
	else {
		error();
		printf("Not T or F: %s\n", s);
		return 0;
	}
	while(isalpha(*s))
		s++;
	return s;
}

char *ReadUWORD(s, v)
char *s;
UWORD *v;
{
	ULONG n;
	if(s = ReadNum(s, &n))
		*v = n;
	return s;
}

/* The big bopper. Note that "end" is a special case alias for end-of-file.
 */
ReadPrefs()
{
	char t[255];
	char *s;

	virgin = 0;
	while(1) {
		if(!virgin) {
			if(!gets(inputbuffer))
				break;
		}
		virgin = 0;
		s = inputbuffer;
		while(isspace(*s)) s++;
		if(!*s || *s=='#') continue;

		s = ReadWord(s, t);
		if(Match(t, "END"))
			break;
		if(!s)
			continue;
		switch(Lookup(t)) {
			case P_FontHeight: s = ReadBYTE(s, &prefs.FontHeight); break;
			case P_PrinterPort: s = ReadUBYTE(s, &prefs.PrinterPort); break;
			case P_BaudRate: s = ReadUSHORT(s, &prefs.BaudRate); break;
			case P_KeyRptSpeed: s = Readtimeval(s, &prefs.KeyRptSpeed); break;
			case P_KeyRptDelay: s = Readtimeval(s, &prefs.KeyRptDelay); break;
			case P_DoubleClick: s = Readtimeval(s, &prefs.DoubleClick); break;
			case P_PointerMatrix: s = ReadPointer(&prefs.PointerMatrix); break;
			case P_XOffset: s = ReadBYTE(s, &prefs.XOffset); break;
			case P_YOffset: s = ReadBYTE(s, &prefs.YOffset); break;
			case P_color17: s = ReadUSHORT(s, &prefs.color17); break;
			case P_color18: s = ReadUSHORT(s, &prefs.color18); break;
			case P_color19: s = ReadUSHORT(s, &prefs.color19); break;
			case P_PointerTicks: s = ReadUSHORT(s, &prefs.PointerTicks); break;
			case P_color0: s = ReadUSHORT(s, &prefs.color0); break;
			case P_color1: s = ReadUSHORT(s, &prefs.color1); break;
			case P_color2: s = ReadUSHORT(s, &prefs.color2); break;
			case P_color3: s = ReadUSHORT(s, &prefs.color3); break;
			case P_ViewXOffset: s = ReadBYTE(s, &prefs.ViewXOffset); break;
			case P_ViewYOffset: s = ReadBYTE(s, &prefs.ViewYOffset); break;
			case P_ViewInitX: s = ReadWORD(s, &prefs.ViewInitX); break;
			case P_ViewInitY: s = ReadWORD(s, &prefs.ViewInitY); break;
			case P_EnableCLI: s = ReadBOOL(s, &prefs.EnableCLI); break;
			case P_PrinterType: s = ReadUSHORT(s, &prefs.PrinterType); break;
			case P_PrinterFilename: s = ReadString(s, &prefs.PrinterFilename, FILENAME_SIZE); break;
			case P_PrintPitch: s = ReadUSHORT(s, &prefs.PrintPitch); break;
			case P_PrintQuality: s = ReadUSHORT(s, &prefs.PrintQuality); break;
			case P_PrintSpacing: s = ReadUSHORT(s, &prefs.PrintSpacing); break;
			case P_PrintLeftMargin: s = ReadUWORD(s, &prefs.PrintLeftMargin); break;
			case P_PrintRightMargin: s = ReadUWORD(s, &prefs.PrintRightMargin); break;
			case P_PrintImage: s = ReadUSHORT(s, &prefs.PrintImage); break;
			case P_PrintAspect: s = ReadUSHORT(s, &prefs.PrintAspect); break;
			case P_PrintShade: s = ReadUSHORT(s, &prefs.PrintShade); break;
			case P_PrintThreshold: s = ReadWORD(s, &prefs.PrintThreshold); break;
			case P_PaperSize: s = ReadUSHORT(s, &prefs.PaperSize); break;
			case P_PaperLength: s = ReadUWORD(s, &prefs.PaperLength); break;
			case P_PaperType: s = ReadUSHORT(s, &prefs.PaperType); break;
			case P_SerRWBits: s = ReadUBYTE(s, &prefs.SerRWBits); break;
			case P_SerStopBuf: s = ReadUBYTE(s, &prefs.SerStopBuf); break;
			case P_SerParShk: s = ReadUBYTE(s, &prefs.SerParShk); break;
			case P_LaceWB: s = ReadUBYTE(s, &prefs.LaceWB); break;
			case P_WorkName: s = ReadString(s, &prefs.WorkName, FILENAME_SIZE); break;
			case P_RowSizeChange: s = ReadBYTE(s, &prefs.RowSizeChange ); break;
			case P_ColumnSizeChange: s = ReadBYTE(s, &prefs.ColumnSizeChange ); break;
			case P_PrintFlags: s = ReadUWORD(s, &prefs.PrintFlags); break;
			case P_PrintMaxWidth: s = ReadUWORD(s, &prefs.PrintMaxWidth); break;
			case P_PrintMaxHeight: s = ReadUWORD(s, &prefs.PrintMaxHeight); break;
			case P_PrintDensity: s = ReadUBYTE(s, &prefs.PrintDensity); break;
			case P_PrintXOffset: s = ReadUBYTE(s, &prefs.PrintXOffset); break;
			default: error(); printf("Undefined: %s\n", t); return 0;
		}
		if(!s)
			return 0;
	}
	return 1;
}

error()
{
	printf("Error in [%s]\n", inputbuffer);
}
SHAR_EOF
#	End of shell archive
exit 0