Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtpdm / PdmXp.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: PdmXp.c /main/4 1996/08/12 18:43:03 cde-hp $ */
24 /*
25  * dtpdm/PdmXp.c
26  */
27 /*
28  * (c) Copyright 1996 Digital Equipment Corporation.
29  * (c) Copyright 1996 Hewlett-Packard Company.
30  * (c) Copyright 1996 International Business Machines Corp.
31  * (c) Copyright 1996 Sun Microsystems, Inc.
32  * (c) Copyright 1996 Novell, Inc. 
33  * (c) Copyright 1996 FUJITSU LIMITED.
34  * (c) Copyright 1996 Hitachi.
35  */
36 #include <stdio.h>
37 #include <sys/stat.h>
38 #include "PdmXp.h"
39
40 #include <X11/Intrinsic.h>
41
42 typedef enum {
43     PDMXP_JOB, PDMXP_DOC, PDMXP_PRINTER, PDMXP_SERVER,
44     PDMXP_BAD_POOL /* should always be last in list */
45 } PdmXpPoolIndex;
46
47
48 /*
49  * static function declarations
50  */
51 static const char* PdmXpGetQualifier(PdmXp* me);
52 static char* PdmXpBuildResourceName(PdmXp* me, PdmOid id_att);
53 static XrmDatabase PdmXpLoadPool(PdmXp* me, XPAttributes type);
54
55
56 /*
57  * ------------------------------------------------------------------------
58  * Name: PdmXpNew
59  *
60  * Description:
61  *
62  *     Creates a new PdmXp instance structure.
63  *
64  * Return value:
65  *
66  *     The new PdmXp instance structure.
67  *
68  */
69 PdmXp*
70 PdmXpNew()
71 {
72     return (PdmXp*)XtCalloc(1, sizeof(PdmXp));
73 }
74
75 /*
76  * ------------------------------------------------------------------------
77  * Name: PdmXpDelete
78  *
79  * Description:
80  *
81  *     Closes an existing Xp connection, and frees the passed
82  *     PdmXp instance structure.
83  *
84  * Return value:
85  *
86  *     None.
87  *
88  */
89 void
90 PdmXpDelete(PdmXp* me)
91 {
92     PdmXpClose(me);
93     XtFree((char*)me);
94 }
95
96 /*
97  * ------------------------------------------------------------------------
98  * Name: PdmXpOpen
99  *
100  * Description:
101  *
102  *     This function opens the passed print display specifier and sets
103  *     the passed print context on the newly opened print display.
104  *
105  * Return value:
106  *
107  *     If successful, the print display pointer is returned. If unable to
108  *     open the display, or if the display does not support the Xp
109  *     extension, NULL is returned.
110  *
111  */
112 Display*
113 PdmXpOpen(PdmXp* me,
114           char* display_spec,
115           char* context_str)
116 {
117     /*
118      * only maintain one connection
119      */
120     PdmXpClose(me);
121     /*
122      * open the passed display spec
123      */
124     me->display = XOpenDisplay(display_spec);
125     if(me->display)
126     {
127         int error_base;
128         int event_base;
129         /*
130          * check to see if the display is a print server
131          */
132         if(XpQueryExtension(me->display, &event_base, &error_base))
133         {
134             /*
135              * set the passed print context on the print display
136              */
137             me->context = strtoul(context_str, (char**)NULL, 0);
138             /*
139              * load the resource DB qualifier
140              */
141             PdmXpGetQualifier(me);
142         }
143         else
144         {
145             XCloseDisplay(me->display);
146             me->display = (Display*)NULL;
147         }
148     }
149
150     return me->display;
151 }
152
153 /*
154  * ------------------------------------------------------------------------
155  * Name: PdmXpClose
156  *
157  * Description:
158  *
159  *     Closes the print display.
160  *
161  * Return value:
162  *
163  *     None.
164  *
165  */
166 void
167 PdmXpClose(PdmXp* me)
168 {
169     if(me->display)
170     {
171         int i;
172         
173         for(i = 0; i < PDMXP_POOL_COUNT; i++)
174         {
175             if(me->pool[i] != (XrmDatabase)NULL)
176             {
177                 XrmDestroyDatabase(me->pool[i]);
178                 me->pool[i] == (XrmDatabase)NULL;
179             }
180         }
181         XCloseDisplay(me->display);
182         me->display = NULL;
183         me->context = (XPContext)NULL;
184     }
185 }
186
187 /*
188  * ------------------------------------------------------------------------
189  * Name: PdmXpLoadPool
190  *
191  * Description:
192  *
193  *     
194  *
195  * Return value:
196  *
197  *     
198  *
199  */
200 static XrmDatabase
201 PdmXpLoadPool(PdmXp* me, XPAttributes type)
202 {
203     PdmXpPoolIndex i;
204     /*
205      * determine the index into the pool array based on the Xp pool type
206      */
207     switch(type)
208     {
209     case XPJobAttr:
210         i = PDMXP_JOB;
211         break;
212     case XPDocAttr:
213         i = PDMXP_DOC;
214         break;
215     case XPPrinterAttr:
216         i = PDMXP_PRINTER;
217         break;
218     case XPServerAttr:
219         i = PDMXP_SERVER;
220         break;
221     default:
222         return (XrmDatabase)NULL;
223         break;
224     }
225     /*
226      * get the attributes from the X print server
227      */
228     if(me->pool[i] == (XrmDatabase)NULL)
229     {
230         XTextProperty text_prop;
231         char** list;
232         int count;
233         
234         text_prop.value = (unsigned char*)
235             XpGetAttributes(me->display, me->context, type);
236         text_prop.encoding = XInternAtom(me->display, "COMPOUND_TEXT", False);
237         text_prop.format = 8;
238         text_prop.nitems = strlen((char*)text_prop.value);
239         if(Success ==
240            XmbTextPropertyToTextList(me->display, &text_prop, &list, &count))
241         {
242             if(count > 0)
243                 me->pool[i] = XrmGetStringDatabase(list[0]);
244
245             XFreeStringList(list);          
246         }
247     }
248
249     return me->pool[i];
250 }
251
252 /*
253  * ------------------------------------------------------------------------
254  * Name: PdmXpGetQualifier
255  *
256  * Description:
257  *
258  *     
259  *
260  * Return value:
261  *
262  *
263  */
264 static const char*
265 PdmXpGetQualifier(PdmXp* me)
266 {
267     if(me->qualifier == (char*)NULL)
268     {
269         if(PdmXpLoadPool(me, XPPrinterAttr) != (XrmDatabase)NULL)
270         {
271             char* str_type;
272             XrmValue value;
273             
274             if(XrmGetResource(me->pool[PDMXP_PRINTER],
275                               "qualifier", "qualifier", &str_type, &value))
276             {
277                 me->qualifier = XtNewString((char*)value.addr);
278                 me->qualifier_len = strlen(me->qualifier);
279             }
280         }
281     }
282     return me->qualifier;
283 }
284
285
286
287 /*
288  * ------------------------------------------------------------------------
289  * Name: PdmXpBuildResourceName
290  *
291  * Description:
292  *
293  *     
294  *
295  * Return value:
296  *
297  *     A new fully-qualified resource name. It is the caller's
298  *     responsibility to free the returned string by calling XtFree.
299  *
300  */
301 static char*
302 PdmXpBuildResourceName(PdmXp* me, PdmOid id_att)
303 {
304     char* ptr;
305     char* res_name;
306     int oid_str_len;
307     /*
308      * allocate memory for the resource name
309      */
310     oid_str_len = PdmOidStringLength(id_att);
311     ptr = res_name =
312         XtMalloc(me->qualifier_len + 1 + oid_str_len + 1);
313     /*
314      * build the resource name from the printer name and the string value
315      * for the passed attribute id
316      */
317     strncpy(ptr, me->qualifier, me->qualifier_len);
318     ptr += me->qualifier_len;
319     *ptr = '.';
320     ptr += 1;
321     strncpy(ptr, PdmOidString(id_att), oid_str_len);
322     ptr += oid_str_len;
323     *ptr = '\0';
324     /*
325      * return
326      */
327     return res_name;
328 }
329
330
331 /*
332  * ------------------------------------------------------------------------
333  * Name: PdmXpGetValue
334  *
335  * Description:
336  *
337  *     
338  *
339  * Return value:
340  *
341  *     pdmoid_none if the attribute value is not found.
342  *
343  */
344 PdmOid
345 PdmXpGetValue(PdmXp* me,
346               XPAttributes type,
347               PdmOid id_att)
348 {
349     const char* value;
350     
351     value = PdmXpGetStringValue(me, type, id_att);
352
353     return PdmOidFromString(value);
354 }
355
356 /*
357  * ------------------------------------------------------------------------
358  * Name: PdmXpGetStringValue
359  *
360  * Description:
361  *
362  *     
363  *
364  * Return value:
365  *
366  *     NULL if the attribute value is not found, or if the resource
367  *     representation type is not a string.
368  *
369  */
370 const char*
371 PdmXpGetStringValue(PdmXp* me,
372                     XPAttributes type,
373                     PdmOid id_att)
374 {
375     char* res_name;
376     char* str_type;
377     XrmValue value;
378     Bool found;
379     
380     XrmDatabase pool;
381     
382     pool = PdmXpLoadPool(me, type);
383     if(pool == (XrmDatabase)NULL)
384         return (const char*)NULL;
385
386     res_name = PdmXpBuildResourceName(me, id_att);
387     found = XrmGetResource(pool, res_name, res_name, &str_type, &value);
388     XtFree(res_name);
389     
390     /*
391      * return
392      */
393     if(found)
394         return (const char*)value.addr;
395     else
396         return (const char*)NULL;
397 }
398
399 /*
400  * ------------------------------------------------------------------------
401  * Name: PdmXpSetValue
402  *
403  * Description:
404  *
405  *     
406  *
407  * Return value:
408  *
409  *     
410  *
411  */
412 void
413 PdmXpSetValue(PdmXp* me,
414               XPAttributes type,
415               PdmOid id_att,
416               PdmOid id_val)
417 {
418     PdmXpSetStringValue(me, type, id_att, PdmOidString(id_val));
419 }
420
421 /*
422  * ------------------------------------------------------------------------
423  * Name: PdmXpSetStringValue
424  *
425  * Description:
426  *
427  *     
428  *
429  * Return value:
430  *
431  *     
432  *
433  */
434 void
435 PdmXpSetStringValue(PdmXp* me,
436                     XPAttributes type,
437                     PdmOid id_att,
438                     const char* str_val)
439 {
440     char* res_name;
441    
442     XrmDatabase pool;
443     
444     pool = PdmXpLoadPool(me, type);
445     if(pool == (XrmDatabase)NULL)
446         return;
447
448     res_name = PdmXpBuildResourceName(me, id_att);
449     XrmPutStringResource(&pool, res_name, (char*)str_val);
450     XtFree(res_name);
451 }
452
453 /*
454  * ------------------------------------------------------------------------
455  * Name: PdmXpUpdateAttributes
456  *
457  * Description:
458  *
459  *     
460  *
461  * Return value:
462  *
463  *     
464  *
465  */
466 void
467 PdmXpUpdateAttributes(PdmXp* me)
468 {
469     char fname[L_tmpnam];
470     
471     if(tmpnam(fname))
472     {
473         int i;
474         XrmDatabase pool;
475         XPAttributes type;
476         FILE* fp;
477         struct stat stbuf;
478         int retlen;
479         char* data = NULL;
480         int data_size = 0;
481         XTextProperty text_prop;
482
483         for(i = 0; i < PDMXP_POOL_COUNT; i++)
484         {
485             if(me->pool[i] != (XrmDatabase)NULL)
486             {
487                 switch(i)
488                 {
489                 case PDMXP_JOB:
490                     type = XPJobAttr;
491                     break;
492                 case PDMXP_DOC:
493                     type = XPDocAttr;
494                     break;
495                 default:
496                     continue;
497                 }
498                 /*
499                  * write out the attribute pool to a file Xrm DB
500                  */
501                 XrmPutFileDatabase(me->pool[i], fname);
502                 /*
503                  * open the new file Xrm DB
504                  */
505                 if(fp = fopen(fname, "r"))
506                 {
507                     /*
508                      * read the file to create a string Xrm DB
509                      */
510                     fstat(fileno(fp), &stbuf);
511                     if(stbuf.st_size + 1 > data_size)
512                     {
513                         data_size = stbuf.st_size + 1;
514                         data = XtRealloc(data, data_size);
515                     }
516                     retlen = read(fileno(fp), data, stbuf.st_size);
517                     fclose(fp);
518                     unlink(fname);
519                     data[retlen] = '\0';
520                     /*
521                      * convert to compund text
522                      */
523                     if(Success == 
524                        XmbTextListToTextProperty(me->display,
525                                                  &data, 1,
526                                                  XCompoundTextStyle,
527                                                  &text_prop))
528                     {
529                         /*
530                          * use the string Xrm DB to update the Xp server
531                          */
532                         XpSetAttributes(me->display, me->context,
533                                         type, (char*)text_prop.value,
534                                         XPAttrMerge);
535                         if(text_prop.value)
536                             XFree(text_prop.value);
537                     }
538                 }
539             }
540
541         }
542         XtFree(data);
543     }
544 }