Commit | Line | Data |
---|---|---|
0efb8845 WJ |
1 | /* Copyright (C) 1991, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* zprops.c */ | |
21 | /* Device property operators */ | |
22 | #include "memory_.h" | |
23 | #include "ghost.h" | |
24 | #include "alloc.h" | |
25 | #include "dict.h" | |
26 | #include "errors.h" | |
27 | #include "oper.h" | |
28 | #include "name.h" | |
29 | #include "store.h" | |
30 | #include "gsprops.h" | |
31 | #include "gsmatrix.h" /* for gxdevice.h */ | |
32 | #include "gxdevice.h" | |
33 | ||
34 | /* Imported procedures */ | |
35 | extern int array_get(P3(ref *, long, ref *)); | |
36 | ||
37 | /* Forward references */ | |
38 | private int props_to_stack(P3(gs_prop_item *, os_ptr, int)); | |
39 | private int props_from_stack(P3(gs_prop_item *, os_ptr, int)); | |
40 | ||
41 | /* getdeviceprops */ | |
42 | int | |
43 | zgetdeviceprops(os_ptr op) | |
44 | { gx_device *dev; | |
45 | gs_prop_item *plist; | |
46 | int count; | |
47 | int code; | |
48 | check_type(*op, t_device); | |
49 | dev = op->value.pdevice; | |
50 | count = (*dev->procs->get_props)(dev, NULL); | |
51 | plist = (gs_prop_item *)alloc(count, sizeof(gs_prop_item), "getdeviceprops"); | |
52 | if ( plist == 0 ) return_error(e_VMerror); | |
53 | (*dev->procs->get_props)(dev, plist); | |
54 | code = props_to_stack(plist, op + 1, count); | |
55 | alloc_free((char *)plist, count, sizeof(gs_prop_item), "getdeviceprops"); | |
56 | if ( code >= 0 ) | |
57 | { make_mark(op); | |
58 | push(code); | |
59 | code = 0; | |
60 | } | |
61 | return code; | |
62 | } | |
63 | ||
64 | /* putdeviceprops */ | |
65 | int | |
66 | zputdeviceprops(os_ptr op) | |
67 | { gx_device *dev; | |
68 | gs_prop_item *plist; | |
69 | os_ptr mp; | |
70 | int count, acount = 0; | |
71 | int code; | |
72 | check_type(*op, t_device); | |
73 | dev = op->value.pdevice; | |
74 | for ( mp = op - 1; !r_has_type(mp, t_mark); mp-- ) | |
75 | { if ( mp <= osbot ) return e_unmatchedmark; | |
76 | switch ( r_type(mp) ) | |
77 | { | |
78 | case t_array: | |
79 | case t_mixedarray: | |
80 | case t_shortarray: | |
81 | acount += r_size(mp); | |
82 | } | |
83 | } | |
84 | count = op - mp - 1; | |
85 | if ( count & 1 ) return e_rangecheck; | |
86 | count >>= 1; | |
87 | plist = (gs_prop_item *)alloc(count + acount, sizeof(gs_prop_item), "putdeviceprops"); | |
88 | if ( plist == 0 ) return_error(e_VMerror); | |
89 | code = props_from_stack(plist, mp + 1, count); | |
90 | if ( code >= 0 ) | |
91 | code = (*dev->procs->put_props)(dev, plist, count + acount); | |
92 | alloc_free((char *)plist, count + acount, sizeof(gs_prop_item), "putdeviceprops"); | |
93 | if ( code >= 0 ) | |
94 | { *mp = *op; | |
95 | osp = op = mp; | |
96 | } | |
97 | return code; | |
98 | } | |
99 | ||
100 | /* ------ Initialization procedure ------ */ | |
101 | ||
102 | op_def zprops_op_defs[] = { | |
103 | {"1getdeviceprops", zgetdeviceprops}, | |
104 | {"2putdeviceprops", zputdeviceprops}, | |
105 | op_def_end(0) | |
106 | }; | |
107 | ||
108 | /* ------ Internal routines ------ */ | |
109 | ||
110 | /* Get properties from a property list to the stack. */ | |
111 | private int | |
112 | props_to_stack(gs_prop_item *plist, os_ptr op0, int count) | |
113 | { gs_prop_item *pi; | |
114 | os_ptr op; | |
115 | int i; | |
116 | int code; | |
117 | for ( op = op0, pi = plist, i = count; i != 0; pi++, i-- ) | |
118 | { ref value; | |
119 | const char *nstr = pi->pname; | |
120 | int nlen = pi->name_size; | |
121 | if ( nstr == 0 ) continue; /* no name, skip */ | |
122 | if ( ostop - op < 2 ) return e_stackoverflow; | |
123 | if ( nlen < 0 ) nlen = strlen(nstr); | |
124 | code = name_ref((const byte *)nstr, nlen, op, 0); | |
125 | if ( code < 0 ) return code; | |
126 | switch ( pi->type ) | |
127 | { | |
128 | case (int)prt_int: | |
129 | make_int(&value, pi->value.i); | |
130 | break; | |
131 | case (int)prt_float: | |
132 | make_real(&value, pi->value.f); | |
133 | break; | |
134 | case (int)prt_bool: | |
135 | make_bool(&value, pi->value.b); | |
136 | break; | |
137 | case (int)prt_string: | |
138 | { ushort size = pi->value.a.size; | |
139 | char *str; | |
140 | if ( size == (ushort)(-1) ) | |
141 | size = strlen(pi->value.a.p.s); | |
142 | str = alloc(size, 1, "props_to_stack(string)"); | |
143 | if ( str == 0 ) return e_VMerror; | |
144 | memcpy(str, pi->value.a.p.s, size); | |
145 | make_tasv(&value, t_string, a_all, size, bytes, (byte *)str); | |
146 | } break; | |
147 | case (int)prt_int_array: | |
148 | case (int)prt_float_array: | |
149 | { uint size = pi->value.a.size; | |
150 | ref *arefs = alloc_refs(size, "props_to_stack(array)"); | |
151 | uint j; | |
152 | gs_prop_item *pv = pi->value.a.p.v; | |
153 | if ( arefs == 0 ) return e_VMerror; | |
154 | make_tasv_new(&value, t_array, a_all, size, refs, arefs); | |
155 | for ( j = 0; j < size; j++, arefs++, pv++ ) | |
156 | if ( pi->type == prt_int_array ) | |
157 | make_int_new(arefs, pv->value.i); | |
158 | else | |
159 | make_real_new(arefs, pv->value.f); | |
160 | } break; | |
161 | default: | |
162 | return e_typecheck; | |
163 | } | |
164 | ref_assign(op + 1, &value); | |
165 | op += 2; | |
166 | } | |
167 | return op - op0; | |
168 | } | |
169 | ||
170 | /* Set properties from the stack. */ | |
171 | /* Returns the number of elements copied. */ | |
172 | /* Entries with non-name keys are not copied; */ | |
173 | /* entries with invalid values are copied with status = pv_typecheck. */ | |
174 | private int | |
175 | props_from_stack(gs_prop_item *plist /* [count + acount] */, os_ptr op0, | |
176 | int count) | |
177 | { gs_prop_item *pi = plist; | |
178 | gs_prop_item *pai = plist + count; | |
179 | os_ptr op = op0 + 1; | |
180 | for ( ; count; op += 2, count-- ) | |
181 | { ref sref; | |
182 | if ( !r_has_type(op - 1, t_name) ) return e_typecheck; | |
183 | name_string_ref(op - 1, &sref); | |
184 | pi->pname = (char *)sref.value.bytes; | |
185 | pi->name_size = r_size(&sref); | |
186 | pi->status = pv_set; | |
187 | switch ( r_type(op) ) | |
188 | { | |
189 | case t_null: | |
190 | pi->type = prt_null; | |
191 | break; | |
192 | case t_integer: | |
193 | pi->type = prt_int; | |
194 | pi->value.i = op->value.intval; | |
195 | break; | |
196 | case t_real: | |
197 | pi->type = prt_float; | |
198 | pi->value.f = op->value.realval; | |
199 | break; | |
200 | case t_boolean: | |
201 | pi->type = prt_bool; | |
202 | pi->value.b = op->value.index; | |
203 | break; | |
204 | case t_name: | |
205 | name_string_ref(op, &sref); | |
206 | goto nst; | |
207 | case t_string: | |
208 | ref_assign(&sref, op); | |
209 | pi->type = prt_string; | |
210 | pi->value.a.p.s = (char *)op->value.bytes; | |
211 | nst: pi->value.a.size = r_size(&sref); | |
212 | break; | |
213 | case t_array: | |
214 | case t_mixedarray: | |
215 | case t_shortarray: | |
216 | { uint size = r_size(op); | |
217 | uint i; | |
218 | gs_prop_item *pv; | |
219 | gs_prop_type tv = prt_int; | |
220 | pi->type = prt_int_array; | |
221 | pi->value.a.p.v = pai; | |
222 | pi->value.a.size = size; | |
223 | top: pv = pai; | |
224 | for ( i = 0; i < size; i++ ) | |
225 | { ref rnum; | |
226 | array_get(op, (long)i, &rnum); | |
227 | pv->pname = 0; | |
228 | pv->type = tv; | |
229 | switch ( r_type(&rnum) ) | |
230 | { | |
231 | case t_real: | |
232 | if ( tv == prt_int ) | |
233 | { tv = prt_float; | |
234 | pi->type = prt_float_array; | |
235 | goto top; | |
236 | } | |
237 | pv++->value.f = rnum.value.realval; | |
238 | break; | |
239 | case t_integer: | |
240 | if ( tv == prt_int ) | |
241 | pv++->value.i = rnum.value.intval; | |
242 | else | |
243 | pv++->value.f = rnum.value.intval; | |
244 | break; | |
245 | default: | |
246 | pi->status = pv_typecheck; | |
247 | } | |
248 | } | |
249 | ||
250 | pai = pv; | |
251 | } break; | |
252 | default: | |
253 | pi->status = pv_typecheck; | |
254 | } | |
255 | pi++; | |
256 | } | |
257 | return 0; | |
258 | } |