xref: /inferno-os/appl/lib/print/print.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Print;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsyth	draw: Draw;
7*37da2899SCharles.Forsyth	Display, Font, Rect, Point, Image, Screen: import draw;
8*37da2899SCharles.Forsythinclude "bufio.m";
9*37da2899SCharles.Forsyth	bufio: Bufio;
10*37da2899SCharles.Forsythinclude "string.m";
11*37da2899SCharles.Forsyth	str: String;
12*37da2899SCharles.Forsyth
13*37da2899SCharles.Forsythinclude "print.m";
14*37da2899SCharles.Forsyth
15*37da2899SCharles.ForsythMAXNAME: con 80;
16*37da2899SCharles.ForsythDEFMODE: con 8r664;
17*37da2899SCharles.Forsyth
18*37da2899SCharles.ForsythPAPER_CONFIG: con CONFIG_PATH + "paper.cfg";
19*37da2899SCharles.ForsythPTYPE_CONFIG: con CONFIG_PATH + "ptype.cfg";
20*37da2899SCharles.ForsythPMODE_CONFIG: con CONFIG_PATH + "pmode.cfg";
21*37da2899SCharles.ForsythPOPT_CONFIG: con CONFIG_PATH + "popt.cfg";
22*37da2899SCharles.ForsythPRINTER_CONFIG: con CONFIG_PATH + "printer.cfg";
23*37da2899SCharles.ForsythDEFPRINTER: con CONFIG_PATH + "defprinter";
24*37da2899SCharles.Forsyth
25*37da2899SCharles.Forsyth
26*37da2899SCharles.ForsythCfg: adt {
27*37da2899SCharles.Forsyth	name: string;
28*37da2899SCharles.Forsyth	pairs: list of (string, string);
29*37da2899SCharles.Forsyth};
30*37da2899SCharles.Forsyth
31*37da2899SCharles.ForsythDEBUG :=0;
32*37da2899SCharles.Forsyth
33*37da2899SCharles.Forsyth
34*37da2899SCharles.Forsythall_papers: list of ref Paper;
35*37da2899SCharles.Forsythall_pmodes: list of ref Pmode;
36*37da2899SCharles.Forsythall_ptypes: list of ref Ptype;
37*37da2899SCharles.Forsythall_popts: list of ref Popt;
38*37da2899SCharles.Forsythall_printers: list of ref Printer;
39*37da2899SCharles.Forsythdefault_printer: ref Printer;
40*37da2899SCharles.Forsythstderr: ref Sys->FD;
41*37da2899SCharles.Forsythprintfd: ref Sys->FD;
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsyth# Initialization
44*37da2899SCharles.Forsyth
45*37da2899SCharles.Forsythinit(): int
46*37da2899SCharles.Forsyth{
47*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
48*37da2899SCharles.Forsyth	stderr = sys->fildes(2);
49*37da2899SCharles.Forsyth	draw = load Draw Draw->PATH;
50*37da2899SCharles.Forsyth	bufio = load Bufio Bufio->PATH;
51*37da2899SCharles.Forsyth	str = load String String->PATH;
52*37da2899SCharles.Forsyth	all_papers = read_paper_config();
53*37da2899SCharles.Forsyth	if (all_papers == nil) return 1;
54*37da2899SCharles.Forsyth	all_pmodes = read_pmode_config();
55*37da2899SCharles.Forsyth	if (all_pmodes == nil) return 1;
56*37da2899SCharles.Forsyth	all_ptypes = read_ptype_config();
57*37da2899SCharles.Forsyth	if (all_ptypes == nil) return 1;
58*37da2899SCharles.Forsyth	all_printers = read_printer_config();
59*37da2899SCharles.Forsyth	if (all_printers == nil) return 1;
60*37da2899SCharles.Forsyth	all_popts = read_popt_config();
61*37da2899SCharles.Forsyth	for (pl:=all_printers; pl!=nil; pl=tl pl) {
62*37da2899SCharles.Forsyth		p := hd pl;
63*37da2899SCharles.Forsyth		opt := find_popt(all_popts, p.name);
64*37da2899SCharles.Forsyth		if (opt != nil) p.popt = opt;
65*37da2899SCharles.Forsyth		else {
66*37da2899SCharles.Forsyth			p.popt = ref Popt (p.name, hd all_pmodes, hd all_papers, 0, 0);
67*37da2899SCharles.Forsyth			all_popts = p.popt :: all_popts;
68*37da2899SCharles.Forsyth		}
69*37da2899SCharles.Forsyth	}
70*37da2899SCharles.Forsyth	return 0;
71*37da2899SCharles.Forsyth}
72*37da2899SCharles.Forsyth
73*37da2899SCharles.Forsyth# Set printer FD
74*37da2899SCharles.Forsyth
75*37da2899SCharles.Forsythset_printfd(fd: ref Sys->FD)
76*37da2899SCharles.Forsyth{
77*37da2899SCharles.Forsyth	printfd = fd;
78*37da2899SCharles.Forsyth}
79*37da2899SCharles.Forsyth
80*37da2899SCharles.Forsyth
81*37da2899SCharles.Forsyth# Get default printer
82*37da2899SCharles.Forsyth
83*37da2899SCharles.Forsythget_defprinter(): ref Printer
84*37da2899SCharles.Forsyth{
85*37da2899SCharles.Forsyth	if (len all_printers == 1) return hd all_printers;		# If there's only 1 printer
86*37da2899SCharles.Forsyth	df := sys->open(DEFPRINTER, Sys->OREAD);
87*37da2899SCharles.Forsyth	if (df == nil) {
88*37da2899SCharles.Forsyth		if (all_printers != nil) return hd all_printers;
89*37da2899SCharles.Forsyth		else return nil;
90*37da2899SCharles.Forsyth	}
91*37da2899SCharles.Forsyth	a := array[MAXNAME] of byte;
92*37da2899SCharles.Forsyth	nb := sys->read(df, a, MAXNAME);
93*37da2899SCharles.Forsyth	if (nb < 2) return nil;
94*37da2899SCharles.Forsyth	name := string a[:nb-1];
95*37da2899SCharles.Forsyth	def := find_printer(all_printers, name);
96*37da2899SCharles.Forsyth	if (def != nil) return def;
97*37da2899SCharles.Forsyth	else return hd all_printers;
98*37da2899SCharles.Forsyth}
99*37da2899SCharles.Forsyth
100*37da2899SCharles.Forsyth# Set default printer
101*37da2899SCharles.Forsyth
102*37da2899SCharles.Forsythset_defprinter(p: ref Printer)
103*37da2899SCharles.Forsyth{
104*37da2899SCharles.Forsyth	df := sys->create(DEFPRINTER, Sys->OWRITE, DEFMODE);
105*37da2899SCharles.Forsyth	if (df == nil) return;
106*37da2899SCharles.Forsyth	sys->fprint(df, "%s\n", p.name);
107*37da2899SCharles.Forsyth}
108*37da2899SCharles.Forsyth
109*37da2899SCharles.Forsyth# Set paper size
110*37da2899SCharles.Forsyth
111*37da2899SCharles.Forsythget_size(p: ref Printer): (int, int, int)	# dpi, xpixels, ypixels
112*37da2899SCharles.Forsyth{
113*37da2899SCharles.Forsyth	if (p == nil) return (0, 0, 0);
114*37da2899SCharles.Forsyth	load_driver(p);
115*37da2899SCharles.Forsyth	dpi := p.popt.mode.resx;
116*37da2899SCharles.Forsyth	(xpix, ypix) := p.pdriver->printable_pixels(p);	# This takes account of orientation
117*37da2899SCharles.Forsyth	return (dpi, xpix, ypix);
118*37da2899SCharles.Forsyth}
119*37da2899SCharles.Forsyth
120*37da2899SCharles.Forsyth
121*37da2899SCharles.Forsyth
122*37da2899SCharles.Forsyth# Get list of all printers
123*37da2899SCharles.Forsyth
124*37da2899SCharles.Forsythget_printers(): list of ref Printer
125*37da2899SCharles.Forsyth{
126*37da2899SCharles.Forsyth	return all_printers;
127*37da2899SCharles.Forsyth}
128*37da2899SCharles.Forsyth
129*37da2899SCharles.Forsyth# Return list of printer types
130*37da2899SCharles.Forsyth
131*37da2899SCharles.Forsythget_ptypes(): list of ref Ptype
132*37da2899SCharles.Forsyth{
133*37da2899SCharles.Forsyth	return all_ptypes;
134*37da2899SCharles.Forsyth}
135*37da2899SCharles.Forsyth
136*37da2899SCharles.Forsyth# Return list of print modes
137*37da2899SCharles.Forsyth
138*37da2899SCharles.Forsythget_pmodes(): list of ref Pmode
139*37da2899SCharles.Forsyth{
140*37da2899SCharles.Forsyth	return all_pmodes;
141*37da2899SCharles.Forsyth}
142*37da2899SCharles.Forsyth
143*37da2899SCharles.Forsyth# Return list of paper types
144*37da2899SCharles.Forsyth
145*37da2899SCharles.Forsythget_papers(): list of ref Paper
146*37da2899SCharles.Forsyth{
147*37da2899SCharles.Forsyth	return all_papers;
148*37da2899SCharles.Forsyth}
149*37da2899SCharles.Forsyth
150*37da2899SCharles.Forsyth# Return list of print options
151*37da2899SCharles.Forsyth
152*37da2899SCharles.Forsythget_popts(): list of ref Popt
153*37da2899SCharles.Forsyth{
154*37da2899SCharles.Forsyth	return all_popts;
155*37da2899SCharles.Forsyth}
156*37da2899SCharles.Forsyth
157*37da2899SCharles.Forsyth# Save option settings
158*37da2899SCharles.Forsyth
159*37da2899SCharles.Forsythsave_settings(): int
160*37da2899SCharles.Forsyth{
161*37da2899SCharles.Forsyth	return write_popt_config(all_popts);
162*37da2899SCharles.Forsyth
163*37da2899SCharles.Forsyth}
164*37da2899SCharles.Forsyth
165*37da2899SCharles.Forsyth
166*37da2899SCharles.Forsyth# Print an image
167*37da2899SCharles.Forsyth
168*37da2899SCharles.Forsythprint_image(p: ref Printer, display: ref Draw->Display, im: ref Draw->Image, pcwidth: int, cancel: chan of int): int
169*37da2899SCharles.Forsyth{
170*37da2899SCharles.Forsyth	if (p == nil || im == nil) return 1;
171*37da2899SCharles.Forsyth	load_driver(p);
172*37da2899SCharles.Forsyth	popen(p);
173*37da2899SCharles.Forsyth	(xpix, ypix) := p.pdriver->printable_pixels(p);
174*37da2899SCharles.Forsyth	imwidth := im.r.max.x - im.r.min.x;
175*37da2899SCharles.Forsyth	imheight := im.r.max.y - im.r.min.y;
176*37da2899SCharles.Forsyth	if (pcwidth > 0) pixwidth := int (real xpix * real pcwidth/100.0);
177*37da2899SCharles.Forsyth	else pixwidth = imwidth;
178*37da2899SCharles.Forsyth	lmar := (xpix - pixwidth)/2;
179*37da2899SCharles.Forsyth	fpixwidth := pixwidth;
180*37da2899SCharles.Forsyth	if (p.popt.orientation != PORTRAIT) {
181*37da2899SCharles.Forsyth		lmar += pixwidth;
182*37da2899SCharles.Forsyth		fpixwidth = pixwidth*imheight/imwidth;
183*37da2899SCharles.Forsyth	}
184*37da2899SCharles.Forsyth	if (lmar < 0) lmar = 0;
185*37da2899SCharles.Forsyth	return p.pdriver->sendimage(p, printfd, display, im, fpixwidth, lmar, cancel);
186*37da2899SCharles.Forsyth}
187*37da2899SCharles.Forsyth
188*37da2899SCharles.Forsyth# Print text
189*37da2899SCharles.Forsyth
190*37da2899SCharles.Forsythprint_textfd(p: ref Printer, fd: ref Sys->FD, ps: real, pr: int, wrap: int): int
191*37da2899SCharles.Forsyth{
192*37da2899SCharles.Forsyth	load_driver(p);
193*37da2899SCharles.Forsyth	popen(p);
194*37da2899SCharles.Forsyth	return p.pdriver->sendtextfd(p, printfd, fd, ps, pr, wrap);
195*37da2899SCharles.Forsyth
196*37da2899SCharles.Forsyth}
197*37da2899SCharles.Forsyth
198*37da2899SCharles.Forsyth
199*37da2899SCharles.Forsyth# Open printer device if necessary
200*37da2899SCharles.Forsyth
201*37da2899SCharles.Forsythpopen(p: ref Printer)
202*37da2899SCharles.Forsyth{
203*37da2899SCharles.Forsyth	if (printfd != nil) return;
204*37da2899SCharles.Forsyth	printfd = sys->create(p.device, Sys->OWRITE, DEFMODE);
205*37da2899SCharles.Forsyth}
206*37da2899SCharles.Forsyth
207*37da2899SCharles.Forsyth# Find printer item
208*37da2899SCharles.Forsyth
209*37da2899SCharles.Forsythfind_printer(all: list of ref Printer, name: string): ref Printer
210*37da2899SCharles.Forsyth{
211*37da2899SCharles.Forsyth	for (p:=all; p!=nil; p=tl p) if ((hd p).name == name) return hd p;
212*37da2899SCharles.Forsyth	return nil;
213*37da2899SCharles.Forsyth}
214*37da2899SCharles.Forsyth
215*37da2899SCharles.Forsyth# Find popt item
216*37da2899SCharles.Forsyth
217*37da2899SCharles.Forsythfind_popt(all: list of ref Popt, name: string): ref Popt
218*37da2899SCharles.Forsyth{
219*37da2899SCharles.Forsyth	for (p:=all; p!=nil; p=tl p) if ((hd p).name == name) return hd p;
220*37da2899SCharles.Forsyth	return nil;
221*37da2899SCharles.Forsyth}
222*37da2899SCharles.Forsyth
223*37da2899SCharles.Forsyth
224*37da2899SCharles.Forsyth# Find paper item
225*37da2899SCharles.Forsyth
226*37da2899SCharles.Forsythfind_paper(all: list of ref Paper, name: string): ref Paper
227*37da2899SCharles.Forsyth{
228*37da2899SCharles.Forsyth	for (p:=all; p!=nil; p=tl p) if ((hd p).name == name) return hd p;
229*37da2899SCharles.Forsyth	return nil;
230*37da2899SCharles.Forsyth}
231*37da2899SCharles.Forsyth
232*37da2899SCharles.Forsyth# Find pmode item
233*37da2899SCharles.Forsyth
234*37da2899SCharles.Forsythfind_pmode(all: list of ref Pmode, name: string): ref Pmode
235*37da2899SCharles.Forsyth{
236*37da2899SCharles.Forsyth	for (p:=all; p!=nil; p=tl p) if ((hd p).name == name) return hd p;
237*37da2899SCharles.Forsyth	return nil;
238*37da2899SCharles.Forsyth}
239*37da2899SCharles.Forsyth
240*37da2899SCharles.Forsyth# Find ptype item
241*37da2899SCharles.Forsyth
242*37da2899SCharles.Forsythfind_ptype(all: list of ref Ptype, name: string): ref Ptype
243*37da2899SCharles.Forsyth{
244*37da2899SCharles.Forsyth	for (p:=all; p!=nil; p=tl p) if ((hd p).name == name) return hd p;
245*37da2899SCharles.Forsyth	return nil;
246*37da2899SCharles.Forsyth}
247*37da2899SCharles.Forsyth
248*37da2899SCharles.Forsyth
249*37da2899SCharles.Forsyth# Read paper config file
250*37da2899SCharles.Forsyth
251*37da2899SCharles.Forsythread_paper_config(): list of ref Paper
252*37da2899SCharles.Forsyth{
253*37da2899SCharles.Forsyth	(clist, aliases) := read_config(PAPER_CONFIG);
254*37da2899SCharles.Forsyth	rlist: list of ref Paper;
255*37da2899SCharles.Forsyth	while (clist != nil) {
256*37da2899SCharles.Forsyth		this := hd clist;
257*37da2899SCharles.Forsyth		clist = tl clist;
258*37da2899SCharles.Forsyth		item := ref Paper(this.name, "", 0.0, 0.0);
259*37da2899SCharles.Forsyth		for (pairs:= this.pairs; pairs != nil; pairs = tl pairs) {
260*37da2899SCharles.Forsyth			(name, value) := hd pairs;
261*37da2899SCharles.Forsyth			case (name) {
262*37da2899SCharles.Forsyth				"hpcode" =>
263*37da2899SCharles.Forsyth					item.hpcode = value;
264*37da2899SCharles.Forsyth
265*37da2899SCharles.Forsyth				"width_inches" =>
266*37da2899SCharles.Forsyth					item.width_inches = real value;
267*37da2899SCharles.Forsyth
268*37da2899SCharles.Forsyth				"height_inches" =>
269*37da2899SCharles.Forsyth					item.height_inches = real value;
270*37da2899SCharles.Forsyth
271*37da2899SCharles.Forsyth				* =>
272*37da2899SCharles.Forsyth					sys->fprint(stderr, "Unknown paper config file option: %s\n", name);
273*37da2899SCharles.Forsyth			}
274*37da2899SCharles.Forsyth		}
275*37da2899SCharles.Forsyth		rlist =item :: rlist;
276*37da2899SCharles.Forsyth	}
277*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
278*37da2899SCharles.Forsyth		(new, old) := hd al;
279*37da2899SCharles.Forsyth		olda := find_paper(rlist, old);
280*37da2899SCharles.Forsyth		if (olda == nil) sys->fprint(stderr, "Paper alias %s not found\n", old);
281*37da2899SCharles.Forsyth		else {
282*37da2899SCharles.Forsyth			newa := ref *olda;
283*37da2899SCharles.Forsyth			newa.name = new;
284*37da2899SCharles.Forsyth			rlist = newa :: rlist;
285*37da2899SCharles.Forsyth			}
286*37da2899SCharles.Forsyth	}
287*37da2899SCharles.Forsyth	return rlist;
288*37da2899SCharles.Forsyth}
289*37da2899SCharles.Forsyth
290*37da2899SCharles.Forsyth
291*37da2899SCharles.Forsyth# Read pmode config file
292*37da2899SCharles.Forsyth
293*37da2899SCharles.Forsythread_pmode_config(): list of ref Pmode
294*37da2899SCharles.Forsyth{
295*37da2899SCharles.Forsyth	(clist, aliases)  := read_config(PMODE_CONFIG);
296*37da2899SCharles.Forsyth	rlist: list of ref Pmode;
297*37da2899SCharles.Forsyth	while (clist != nil) {
298*37da2899SCharles.Forsyth		this := hd clist;
299*37da2899SCharles.Forsyth		clist = tl clist;
300*37da2899SCharles.Forsyth		item := ref Pmode(this.name, "", 0, 0, 1, 1, 1);
301*37da2899SCharles.Forsyth		for (pairs:= this.pairs; pairs != nil; pairs = tl pairs) {
302*37da2899SCharles.Forsyth			(name, value) := hd pairs;
303*37da2899SCharles.Forsyth			case (name) {
304*37da2899SCharles.Forsyth				"desc" =>
305*37da2899SCharles.Forsyth					item.desc = value;
306*37da2899SCharles.Forsyth
307*37da2899SCharles.Forsyth				"resx" =>
308*37da2899SCharles.Forsyth					item.resx = int value;
309*37da2899SCharles.Forsyth
310*37da2899SCharles.Forsyth				"resy" =>
311*37da2899SCharles.Forsyth					item.resy = int value;
312*37da2899SCharles.Forsyth
313*37da2899SCharles.Forsyth				"coldepth" =>
314*37da2899SCharles.Forsyth					item.coldepth = int value;
315*37da2899SCharles.Forsyth
316*37da2899SCharles.Forsyth				"blackdepth" =>
317*37da2899SCharles.Forsyth					item.blackdepth = int value;
318*37da2899SCharles.Forsyth
319*37da2899SCharles.Forsyth				"blackresmult" =>
320*37da2899SCharles.Forsyth					item.blackresmult = int value;
321*37da2899SCharles.Forsyth
322*37da2899SCharles.Forsyth				* =>
323*37da2899SCharles.Forsyth					sys->fprint(stderr, "Unknown pmode config file option: %s\n", name);
324*37da2899SCharles.Forsyth
325*37da2899SCharles.Forsyth			}
326*37da2899SCharles.Forsyth		}
327*37da2899SCharles.Forsyth		rlist =item :: rlist;
328*37da2899SCharles.Forsyth	}
329*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
330*37da2899SCharles.Forsyth		(new, old) := hd al;
331*37da2899SCharles.Forsyth		olda := find_pmode(rlist, old);
332*37da2899SCharles.Forsyth		if (olda == nil) sys->fprint(stderr, "Pmode alias %s not found\n", old);
333*37da2899SCharles.Forsyth		else {
334*37da2899SCharles.Forsyth			newa := ref *olda;
335*37da2899SCharles.Forsyth			newa.name = new;
336*37da2899SCharles.Forsyth			rlist = newa :: rlist;
337*37da2899SCharles.Forsyth			}
338*37da2899SCharles.Forsyth	}
339*37da2899SCharles.Forsyth	return rlist;
340*37da2899SCharles.Forsyth}
341*37da2899SCharles.Forsyth
342*37da2899SCharles.Forsyth
343*37da2899SCharles.Forsyth
344*37da2899SCharles.Forsyth
345*37da2899SCharles.Forsyth# Readp Ptype config file
346*37da2899SCharles.Forsyth
347*37da2899SCharles.Forsythread_ptype_config(): list of ref Ptype
348*37da2899SCharles.Forsyth{
349*37da2899SCharles.Forsyth	(clist, aliases)  := read_config(PTYPE_CONFIG);
350*37da2899SCharles.Forsyth	rlist: list of ref Ptype;
351*37da2899SCharles.Forsyth	while (clist != nil) {
352*37da2899SCharles.Forsyth		this := hd clist;
353*37da2899SCharles.Forsyth		clist = tl clist;
354*37da2899SCharles.Forsyth		item := ref Ptype(this.name, "", nil, "", "");
355*37da2899SCharles.Forsyth		for (pairs:= this.pairs; pairs != nil; pairs = tl pairs) {
356*37da2899SCharles.Forsyth			(name, value) := hd pairs;
357*37da2899SCharles.Forsyth			case (name) {
358*37da2899SCharles.Forsyth				"desc" =>
359*37da2899SCharles.Forsyth					item.desc = value;
360*37da2899SCharles.Forsyth
361*37da2899SCharles.Forsyth				"driver" =>
362*37da2899SCharles.Forsyth					item.driver = value;
363*37da2899SCharles.Forsyth
364*37da2899SCharles.Forsyth				"hpmapfile" =>
365*37da2899SCharles.Forsyth					item.hpmapfile = value;
366*37da2899SCharles.Forsyth
367*37da2899SCharles.Forsyth				"modes" =>
368*37da2899SCharles.Forsyth					item.modes = make_pmode_list(value);
369*37da2899SCharles.Forsyth
370*37da2899SCharles.Forsyth				* =>
371*37da2899SCharles.Forsyth					sys->fprint(stderr, "Unknown ptype config file option: %s\n", name);
372*37da2899SCharles.Forsyth			}
373*37da2899SCharles.Forsyth		}
374*37da2899SCharles.Forsyth		if (item.modes == nil) {
375*37da2899SCharles.Forsyth			sys->fprint(stderr, "No print modes for ptype %s\n", item.name);
376*37da2899SCharles.Forsyth			continue;
377*37da2899SCharles.Forsyth		}
378*37da2899SCharles.Forsyth		rlist = item :: rlist;
379*37da2899SCharles.Forsyth	}
380*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
381*37da2899SCharles.Forsyth		(new, old) := hd al;
382*37da2899SCharles.Forsyth		olda := find_ptype(rlist, old);
383*37da2899SCharles.Forsyth		if (olda == nil) sys->fprint(stderr, "Ptype alias %s not found\n", old);
384*37da2899SCharles.Forsyth		else {
385*37da2899SCharles.Forsyth			newa := ref *olda;
386*37da2899SCharles.Forsyth			newa.name = new;
387*37da2899SCharles.Forsyth			rlist = newa :: rlist;
388*37da2899SCharles.Forsyth			}
389*37da2899SCharles.Forsyth	}
390*37da2899SCharles.Forsyth	return rlist;
391*37da2899SCharles.Forsyth}
392*37da2899SCharles.Forsyth
393*37da2899SCharles.Forsyth
394*37da2899SCharles.Forsyth# Make a list of pmodes from a string
395*37da2899SCharles.Forsyth
396*37da2899SCharles.Forsythmake_pmode_list(sl: string): list of ref Pmode
397*37da2899SCharles.Forsyth{
398*37da2899SCharles.Forsyth	pml: list of ref Pmode;
399*37da2899SCharles.Forsyth	(n, toks) := sys->tokenize(sl, " \t");
400*37da2899SCharles.Forsyth	if (n == 0) return nil;
401*37da2899SCharles.Forsyth	for (i:=0; i<n; i++) {
402*37da2899SCharles.Forsyth		pms := hd toks;
403*37da2899SCharles.Forsyth		toks = tl toks;
404*37da2899SCharles.Forsyth		pm := find_pmode(all_pmodes, pms);
405*37da2899SCharles.Forsyth		if (pm == nil) {
406*37da2899SCharles.Forsyth			sys->fprint(stderr, "unknown pmode: %s\n", pms);
407*37da2899SCharles.Forsyth			continue;
408*37da2899SCharles.Forsyth		}
409*37da2899SCharles.Forsyth		pml = pm :: pml;
410*37da2899SCharles.Forsyth	}
411*37da2899SCharles.Forsyth	return pml;
412*37da2899SCharles.Forsyth}
413*37da2899SCharles.Forsyth
414*37da2899SCharles.Forsyth
415*37da2899SCharles.Forsyth# Read popt config file
416*37da2899SCharles.Forsyth
417*37da2899SCharles.Forsythread_popt_config(): list of ref Popt
418*37da2899SCharles.Forsyth{
419*37da2899SCharles.Forsyth	(clist, aliases)  := read_config(POPT_CONFIG);
420*37da2899SCharles.Forsyth	rlist: list of ref Popt;
421*37da2899SCharles.Forsyth	while (clist != nil) {
422*37da2899SCharles.Forsyth		this := hd clist;
423*37da2899SCharles.Forsyth		clist = tl clist;
424*37da2899SCharles.Forsyth		item := ref Popt(this.name, nil, nil, 0, 0);
425*37da2899SCharles.Forsyth		for (pairs:= this.pairs; pairs != nil; pairs = tl pairs) {
426*37da2899SCharles.Forsyth			(name, value) := hd pairs;
427*37da2899SCharles.Forsyth			case (name) {
428*37da2899SCharles.Forsyth
429*37da2899SCharles.Forsyth				"mode" =>
430*37da2899SCharles.Forsyth					item.mode = find_pmode(all_pmodes, value);
431*37da2899SCharles.Forsyth					if (item.mode == nil) sys->fprint(stderr, "Config error: Pmode not found: %s\n", value);
432*37da2899SCharles.Forsyth
433*37da2899SCharles.Forsyth				"paper" =>
434*37da2899SCharles.Forsyth					item.paper = find_paper(all_papers, value);
435*37da2899SCharles.Forsyth					if (item.paper == nil) sys->fprint(stderr, "Config error: paper not found: %s\n", value);
436*37da2899SCharles.Forsyth
437*37da2899SCharles.Forsyth				"orientation" =>
438*37da2899SCharles.Forsyth					item.orientation = int value;
439*37da2899SCharles.Forsyth				"duplex" =>
440*37da2899SCharles.Forsyth					item.duplex = int value;
441*37da2899SCharles.Forsyth
442*37da2899SCharles.Forsyth				* =>
443*37da2899SCharles.Forsyth					sys->fprint(stderr, "Unknown popt config file option: %s\n", name);
444*37da2899SCharles.Forsyth			}
445*37da2899SCharles.Forsyth		}
446*37da2899SCharles.Forsyth		if (item.mode == nil) {
447*37da2899SCharles.Forsyth			sys->fprint(stderr, "No print mode for printer %s\n", item.name);
448*37da2899SCharles.Forsyth			continue;
449*37da2899SCharles.Forsyth		}
450*37da2899SCharles.Forsyth		if (item.paper == nil) {
451*37da2899SCharles.Forsyth			sys->fprint(stderr, "No paper size for printer %s\n", item.name);
452*37da2899SCharles.Forsyth			continue;
453*37da2899SCharles.Forsyth		}
454*37da2899SCharles.Forsyth		rlist = item :: rlist;
455*37da2899SCharles.Forsyth	}
456*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
457*37da2899SCharles.Forsyth		(new, old) := hd al;
458*37da2899SCharles.Forsyth		olda := find_popt(rlist, old);
459*37da2899SCharles.Forsyth		if (olda == nil) sys->fprint(stderr, "Popt alias %s not found\n", old);
460*37da2899SCharles.Forsyth		else {
461*37da2899SCharles.Forsyth			newa := ref *olda;
462*37da2899SCharles.Forsyth			newa.name = new;
463*37da2899SCharles.Forsyth			rlist = newa :: rlist;
464*37da2899SCharles.Forsyth			}
465*37da2899SCharles.Forsyth	}
466*37da2899SCharles.Forsyth	return rlist;
467*37da2899SCharles.Forsyth}
468*37da2899SCharles.Forsyth
469*37da2899SCharles.Forsyth
470*37da2899SCharles.Forsyth
471*37da2899SCharles.Forsyth
472*37da2899SCharles.Forsyth# Read printer config file
473*37da2899SCharles.Forsyth
474*37da2899SCharles.Forsythread_printer_config(): list of ref Printer
475*37da2899SCharles.Forsyth{
476*37da2899SCharles.Forsyth	(clist, aliases)  := read_config(PRINTER_CONFIG);
477*37da2899SCharles.Forsyth	rlist: list of ref Printer;
478*37da2899SCharles.Forsyth	while (clist != nil) {
479*37da2899SCharles.Forsyth		this := hd clist;
480*37da2899SCharles.Forsyth		clist = tl clist;
481*37da2899SCharles.Forsyth		item := ref Printer(this.name, nil, "", nil, nil);
482*37da2899SCharles.Forsyth		for (pairs:= this.pairs; pairs != nil; pairs = tl pairs) {
483*37da2899SCharles.Forsyth			(name, value) := hd pairs;
484*37da2899SCharles.Forsyth			case (name) {
485*37da2899SCharles.Forsyth				"ptype" =>
486*37da2899SCharles.Forsyth					item.ptype = find_ptype(all_ptypes, value);
487*37da2899SCharles.Forsyth					if (item.ptype == nil) sys->fprint(stderr, "Config error: Ptype not found: %s\n", value);
488*37da2899SCharles.Forsyth
489*37da2899SCharles.Forsyth				"device" =>
490*37da2899SCharles.Forsyth					item.device = value;
491*37da2899SCharles.Forsyth
492*37da2899SCharles.Forsyth				* =>
493*37da2899SCharles.Forsyth					sys->fprint(stderr, "Unknown printer config file option: %s\n", name);
494*37da2899SCharles.Forsyth			}
495*37da2899SCharles.Forsyth		}
496*37da2899SCharles.Forsyth		if (item.ptype == nil) {
497*37da2899SCharles.Forsyth			sys->fprint(stderr, "No printer type for printer %s\n", item.name);
498*37da2899SCharles.Forsyth			continue;
499*37da2899SCharles.Forsyth		}
500*37da2899SCharles.Forsyth		rlist = item :: rlist;
501*37da2899SCharles.Forsyth	}
502*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
503*37da2899SCharles.Forsyth		(new, old) := hd al;
504*37da2899SCharles.Forsyth		olda := find_printer(rlist, old);
505*37da2899SCharles.Forsyth		if (olda == nil) sys->fprint(stderr, "Ptype alias %s not found\n", old);
506*37da2899SCharles.Forsyth		else {
507*37da2899SCharles.Forsyth			newa := ref *olda;
508*37da2899SCharles.Forsyth			newa.name = new;
509*37da2899SCharles.Forsyth			rlist = newa :: rlist;
510*37da2899SCharles.Forsyth			}
511*37da2899SCharles.Forsyth	}
512*37da2899SCharles.Forsyth	return rlist;
513*37da2899SCharles.Forsyth}
514*37da2899SCharles.Forsyth
515*37da2899SCharles.Forsyth# Write opt config file
516*37da2899SCharles.Forsyth
517*37da2899SCharles.Forsythwrite_popt_config(plist: list of ref Popt): int
518*37da2899SCharles.Forsyth{
519*37da2899SCharles.Forsyth	cfl: list of Cfg;
520*37da2899SCharles.Forsyth	for (pl:=plist; pl!=nil; pl=tl pl) {
521*37da2899SCharles.Forsyth		po := hd pl;
522*37da2899SCharles.Forsyth		cf := Cfg(po.name, nil);
523*37da2899SCharles.Forsyth		cf.pairs = ("mode", po.mode.name) :: cf.pairs;
524*37da2899SCharles.Forsyth		cf.pairs = ("paper", po.paper.name) :: cf.pairs;
525*37da2899SCharles.Forsyth		cf.pairs = ("orientation", sys->sprint("%d", po.orientation)) :: cf.pairs;
526*37da2899SCharles.Forsyth		cf.pairs = ("duplex", sys->sprint("%d", po.duplex)) :: cf.pairs;
527*37da2899SCharles.Forsyth		cfl = cf :: cfl;
528*37da2899SCharles.Forsyth	}
529*37da2899SCharles.Forsyth	return write_config(POPT_CONFIG, cfl, nil);
530*37da2899SCharles.Forsyth}
531*37da2899SCharles.Forsyth
532*37da2899SCharles.Forsyth
533*37da2899SCharles.Forsythwrite_config(fspec: string, clist: list of Cfg, aliases: list of (string, string)): int
534*37da2899SCharles.Forsyth{
535*37da2899SCharles.Forsyth	fd := sys->create(fspec, Sys->OWRITE, DEFMODE);
536*37da2899SCharles.Forsyth	if (fd == nil) {
537*37da2899SCharles.Forsyth		sys->fprint(stderr, "Failed to write to config file %s: %r\n", fspec);
538*37da2899SCharles.Forsyth		return 1;
539*37da2899SCharles.Forsyth	}
540*37da2899SCharles.Forsyth	for (cfl:=clist; cfl!=nil; cfl=tl cfl) {
541*37da2899SCharles.Forsyth		cf := hd cfl;
542*37da2899SCharles.Forsyth		sys->fprint(fd, "%s=\n", cf.name);
543*37da2899SCharles.Forsyth		for (pl:=cf.pairs; pl!=nil; pl=tl pl) {
544*37da2899SCharles.Forsyth			(name, value) := hd pl;
545*37da2899SCharles.Forsyth			if (sys->fprint(fd, "\t%s=%s\n", name, value) < 0) return 2;
546*37da2899SCharles.Forsyth		}
547*37da2899SCharles.Forsyth	}
548*37da2899SCharles.Forsyth	for (al:=aliases; al!=nil; al=tl al) {
549*37da2899SCharles.Forsyth		(new, old) := hd al;
550*37da2899SCharles.Forsyth		if (sys->fprint(fd, "%s=%s\n", new, old)) return 2;
551*37da2899SCharles.Forsyth	}
552*37da2899SCharles.Forsyth	return 0;
553*37da2899SCharles.Forsyth}
554*37da2899SCharles.Forsyth
555*37da2899SCharles.Forsyth
556*37da2899SCharles.Forsyth# Read in a config file and return list of items and aliases
557*37da2899SCharles.Forsyth
558*37da2899SCharles.Forsythread_config(fspec: string): (list of Cfg, list of (string, string))
559*37da2899SCharles.Forsyth{
560*37da2899SCharles.Forsyth	ib := bufio->open(fspec, Bufio->OREAD);
561*37da2899SCharles.Forsyth	if (ib == nil) {
562*37da2899SCharles.Forsyth		sys->fprint(stderr, "Failed to open config file %s: %r\n", fspec);
563*37da2899SCharles.Forsyth		return (nil, nil);
564*37da2899SCharles.Forsyth	}
565*37da2899SCharles.Forsyth	clist: list of Cfg;
566*37da2899SCharles.Forsyth	plist: list of (string, string);
567*37da2899SCharles.Forsyth	section := "";
568*37da2899SCharles.Forsyth	aliases : list of (string, string);
569*37da2899SCharles.Forsyth	while ((line := bufio->ib.gets('\n')) != nil) {
570*37da2899SCharles.Forsyth		if (line[0] == '#') continue;
571*37da2899SCharles.Forsyth		if (line[len line-1] == '\n') line = line[:len line-1];
572*37da2899SCharles.Forsyth		if (len line == 0) continue;
573*37da2899SCharles.Forsyth		if (line[0] != ' ' && line[0] != '\t') {
574*37da2899SCharles.Forsyth			if (section != "") clist = Cfg (section, plist) :: clist;
575*37da2899SCharles.Forsyth			section = "";
576*37da2899SCharles.Forsyth			plist = nil;
577*37da2899SCharles.Forsyth			sspec := strip(line);
578*37da2899SCharles.Forsyth			(n, toks) := sys->tokenize(sspec, "=");
579*37da2899SCharles.Forsyth			if (n == 0) continue;
580*37da2899SCharles.Forsyth			if (n > 2) {
581*37da2899SCharles.Forsyth				sys->fprint(stderr, "Error in config file %s\n", fspec);
582*37da2899SCharles.Forsyth				continue;
583*37da2899SCharles.Forsyth			}
584*37da2899SCharles.Forsyth			if (n == 2) {
585*37da2899SCharles.Forsyth				asection := hd toks;
586*37da2899SCharles.Forsyth				toks = tl toks;
587*37da2899SCharles.Forsyth				alias := hd toks;
588*37da2899SCharles.Forsyth				aliases = (asection, alias) :: aliases;
589*37da2899SCharles.Forsyth				continue;
590*37da2899SCharles.Forsyth			}
591*37da2899SCharles.Forsyth			section = hd toks;
592*37da2899SCharles.Forsyth		} else {
593*37da2899SCharles.Forsyth			(n, toks) := sys->tokenize(line, "=");
594*37da2899SCharles.Forsyth			if (n == 2) {
595*37da2899SCharles.Forsyth				name := strip(hd toks);
596*37da2899SCharles.Forsyth				toks = tl toks;
597*37da2899SCharles.Forsyth				value := strip(hd toks);
598*37da2899SCharles.Forsyth				plist = (name, value) :: plist;
599*37da2899SCharles.Forsyth			}
600*37da2899SCharles.Forsyth		}
601*37da2899SCharles.Forsyth	}
602*37da2899SCharles.Forsyth	if (section != "") clist = Cfg (section, plist) :: clist;
603*37da2899SCharles.Forsyth	return (clist, aliases);
604*37da2899SCharles.Forsyth}
605*37da2899SCharles.Forsyth
606*37da2899SCharles.Forsyth
607*37da2899SCharles.Forsyth# Load printer driver if necessary
608*37da2899SCharles.Forsythload_driver(p: ref Printer)
609*37da2899SCharles.Forsyth{
610*37da2899SCharles.Forsyth	if (p.pdriver != nil) return;
611*37da2899SCharles.Forsyth	modpath := Pdriver->PATHPREFIX + p.ptype.driver;
612*37da2899SCharles.Forsyth	p.pdriver = load Pdriver modpath;
613*37da2899SCharles.Forsyth	if (p.pdriver == nil) sys->fprint(stderr, "Failed to load driver %s: %r\n", modpath);
614*37da2899SCharles.Forsyth	p.pdriver->init(DEBUG);
615*37da2899SCharles.Forsyth}
616*37da2899SCharles.Forsyth
617*37da2899SCharles.Forsyth
618*37da2899SCharles.Forsyth# Strip leading/trailing spaces
619*37da2899SCharles.Forsyth
620*37da2899SCharles.Forsythstrip(s: string): string
621*37da2899SCharles.Forsyth{
622*37da2899SCharles.Forsyth	(dummy1, s1) := str->splitl(s, "^ \t");
623*37da2899SCharles.Forsyth	(s2, dummy2) := str->splitr(s1, "^ \t");
624*37da2899SCharles.Forsyth	return s2;
625*37da2899SCharles.Forsyth}
626