dtpdm: XtVaGetValues, XtPointer, XtArgVal, ...
[oweals/cde.git] / cde / programs / dtpdm / Main.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 /* $TOG: Main.c /main/11 1998/04/20 12:58:06 mgreess $ */
24 /*
25  * dtpdm/Main.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 <stdlib.h>
37 #include <Xm/XmAll.h>
38 #include <Xm/ColorObjP.h>       /* for Xme Color Obj access API */
39 #include <Dt/dtpdmd.h>
40 #include <Dt/EnvControlP.h>
41
42 #include "MainWindow.h"
43 #include "PrinterBox.h"
44 #include "JobBox.h"
45 #include "PdmMsgs.h"
46
47 /*
48  * PDM Shell
49  */
50 typedef struct _PdmShell
51 {
52     /*
53      * application shell widget data
54      */
55     XtAppContext app_context;
56     Display* display;
57     Window parent_window;
58     XWindowAttributes parent_attr;
59     Widget widget;
60     /*
61      * command line parameters
62      */
63     String print_display_spec;
64     String print_context_str;
65     
66 } PdmShell;
67
68 /*
69  * application resources
70  */
71 static XrmOptionDescRec PdmOptions[] =
72 {
73    { "-window", "parentWindowStr", XrmoptionSepArg, (caddr_t)0    },
74    { "-pdisplay", "printDisplaySpec", XrmoptionSepArg, (caddr_t)NULL },
75    { "-pcontext", "printContextStr", XrmoptionSepArg, (caddr_t)0 }
76 };
77
78 static XtResource PdmResources[] =
79 {
80     { "printDisplaySpec", "PrintDisplaySpec", XmRString, sizeof(String),
81       XtOffsetOf(PdmShell, print_display_spec), XmRImmediate, (XtPointer)NULL,
82     },
83     { "printContextStr", "PrintContextStr", XmRString, sizeof(String),
84       XtOffsetOf(PdmShell, print_context_str), XmRImmediate, (XtPointer)NULL,
85     }
86 };
87
88 /*
89  * fallback resources
90  */
91 static String PdmShellFallbackResources[] =
92 {
93     "Dtpdm.title: Print Setup"
94 };
95
96 /*
97  * static function declarations
98  */
99 static PdmShell* PdmShellNew();
100 static int PdmShellCreate(PdmShell*, const String*, int*, String*);
101 static void PdmShellPresent(PdmShell* me);
102 static Boolean PdmStartOkWorkProc(XtPointer client_data);
103
104 /*
105  * ------------------------------------------------------------------------
106  * Name: PdmShellNew
107  *
108  * Description:
109  *
110  *     Allocates a new PdmShell data structure.
111  *
112  * Return value:
113  *
114  *     A pointer to the new PdmShell structure.
115  *
116  */
117 static PdmShell*
118 PdmShellNew()
119 {
120     return (PdmShell*)XtCalloc(1, sizeof(PdmShell));
121 }
122
123 /*
124  * ------------------------------------------------------------------------
125  * Name: PdmShellCreate
126  *
127  * Description:
128  *
129  *     This function creates a top level application shell.
130  *
131  * Return value:
132  *
133  *     0 if successful; a PDM_EXIT code if not.
134  *
135  */
136 static int
137 PdmShellCreate(PdmShell* me,
138                const String* fallback_resources,
139                int* argc_in_out, String* argv_in_out)
140 {
141     String app_class;
142     String app_name;
143     XmPixelSet pixelSets[XmCO_NUM_COLORS];
144     XrmClass class_list[3];
145     XrmDatabase db;
146     XrmName name_list[3];
147     XrmRepresentation rep_type;
148     XrmValue value;
149     int decor;
150     int funcs;
151     short secondary_id;
152     /*
153      * create the application context and open the video display
154      */
155     XtToolkitInitialize();
156     XtSetLanguageProc((XtAppContext)NULL, (XtLanguageProc)NULL,
157                       (XtPointer)NULL);
158     me->app_context = XtCreateApplicationContext();
159
160     XtAppSetFallbackResources(me->app_context, (String*)fallback_resources);
161
162     me->display =
163         XtOpenDisplay(me->app_context, (String)NULL,
164                       (String)NULL, "Dtpdm",
165                       PdmOptions, XtNumber(PdmOptions),
166                       argc_in_out, argv_in_out);
167     if((Display*)NULL == me->display)
168         return PDM_EXIT_VXAUTH;
169     XtGetApplicationNameAndClass(me->display, &app_name, &app_class);
170     /*
171      * the fallback resources are only intended for the video display, so
172      * remove them from the application context
173      */
174     XtAppSetFallbackResources(me->app_context, (String*)NULL);
175     /*
176      * get the parent video window id from the display's resource database
177      */
178     db = XtDatabase(me->display);
179     name_list[0] = XrmStringToQuark(app_name);
180     name_list[1] = XrmStringToQuark("parentWindowStr");
181     name_list[2] = NULLQUARK;
182     class_list[0] = XrmStringToQuark(app_class);
183     class_list[1] = XrmStringToQuark("ParentWindowStr");
184     class_list[2] = NULLQUARK;
185     XrmQGetResource(db, name_list, class_list, &rep_type, &value);
186     if(!value.addr) return PDM_EXIT_ERROR;
187     me->parent_window = (Window)strtoul((char*)value.addr, (char**)NULL, 0);
188     /*
189      * obtain the parent video window's attributes
190      */
191     if(!XGetWindowAttributes(me->display, me->parent_window, &me->parent_attr))
192         return PDM_EXIT_ERROR;
193     /*
194      * register interest in the DestroyNotify event for the parent window
195      */
196     XSelectInput(me->display, me->parent_window, StructureNotifyMask);
197     /*
198      * create the application shell
199      */
200     decor = MWM_DECOR_ALL | MWM_DECOR_RESIZEH | MWM_DECOR_MINIMIZE
201         | MWM_DECOR_MAXIMIZE;
202     funcs = MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MINIMIZE
203         | MWM_FUNC_MAXIMIZE;
204     me->widget = 
205         XtVaAppCreateShell(app_name, app_class,
206                            applicationShellWidgetClass,
207                            me->display,
208                            XmNdeleteResponse, XmDESTROY,
209                            XmNmappedWhenManaged, False,
210                            XmNmwmDecorations, decor,
211                            XmNmwmFunctions, funcs,
212                            XmNmwmInputMode,MWM_INPUT_PRIMARY_APPLICATION_MODAL,
213                            XmNscreen, me->parent_attr.screen,
214                            XmNtransient, True,
215                            NULL);
216     /*
217      * pick up the secondary color set, so that the PDM presents the same
218      * colors as a secondary window. (the XmColorObj is created by the
219      * the XmDisplay object, which is created when the app shell is
220      * created)
221      */
222     if(XmeGetColorObjData(XtScreen(me->widget), (int*)NULL,
223                           pixelSets, XmCO_NUM_COLORS,
224                           (short*)NULL, (short*)NULL, (short*)NULL,
225                           &secondary_id, (short*)NULL))
226     {
227         /*
228          * In the Xrm database, reassign primary color resource values
229          * with the corresponding secondary color values. This will cause
230          * subsequently created widgets that utilize colors from the
231          * primary set to actually present secondary colors.
232          */
233         db = XtScreenDatabase(XtScreen(me->widget));
234         value.size = sizeof(Pixel);
235         value.addr = (char*)&pixelSets[secondary_id].bg;
236         XrmPutResource (&db, "*background", "Pixel", &value);
237         XrmPutResource (&db, "*frameBackground", "Pixel", &value);
238         value.addr = (char*)&pixelSets[secondary_id].fg;
239         XrmPutResource (&db, "*foreground", "Pixel", &value);
240         XrmPutResource (&db, "*backPageForeground", "Pixel", &value);
241         value.addr = (char*)&pixelSets[secondary_id].bs;
242         XrmPutResource (&db, "*bottomShadowColor", "Pixel", &value);
243         value.addr = (char*)&pixelSets[secondary_id].ts;
244         XrmPutResource (&db, "*topShadowColor", "Pixel", &value);
245     }
246     /*
247      * get the application resources
248      */
249     XtGetApplicationResources(me->widget, me,
250                               PdmResources, XtNumber(PdmResources),
251                               NULL, 0);
252     /*
253      * return
254      */
255     return 0;
256 }
257
258 /*
259  * ------------------------------------------------------------------------
260  * Name: PdmShellPresent
261  *
262  * Description:
263  *
264  *     Displays the application shell as a transient for the window
265  *     passed via the -window command line parameter.
266  *
267  *
268  * Return value:
269  *
270  *     True if successful.
271  *
272  */
273 static void
274 PdmShellPresent(PdmShell* me)
275 {
276     int parent_abs_x, parent_abs_y;
277     Position x, y;
278     XtArgVal  width0, height0;
279     Dimension width, height;
280     Window dummy_child;
281     /*
282      * get the absolute screen coordinates of the parent window
283      */
284     XTranslateCoordinates(me->display, me->parent_window,
285                           me->parent_attr.root, 
286                           0, 0,
287                           &parent_abs_x,
288                           &parent_abs_y,
289                           &dummy_child);
290     /*
291      * get the dimensions of the PDM window
292      */
293     XtRealizeWidget(me->widget);
294     XtVaGetValues(me->widget, XmNwidth, &width0, XmNheight, &height0, NULL);
295     width = (Dimension)width0;
296     height = (Dimension)height0;
297     /*
298      * determine the origin of the PDM popup such that it is
299      * centered w.r.t. the parent window
300      */
301     x = parent_abs_x + me->parent_attr.width/2 - width/2;
302     y = parent_abs_y + me->parent_attr.height/2 - height/2;
303     /*
304      * update the app shell position
305      */
306     XtVaSetValues(me->widget, XmNx, x, XmNy, y, NULL);
307     /*
308      * present the PDM as transient for the passed video window
309      *
310      * Note: this only works if the passed video window is a
311      *       top-level window; i.e. one that the window manager
312      *       manages.
313      */
314     XSetTransientForHint(me->display, XtWindow(me->widget),
315                          me->parent_window);
316     /*
317      * map the PDM popup
318      */
319     XtMapWidget(me->widget);
320 }
321
322 /*
323  * ------------------------------------------------------------------------
324  * Name: PdmStartOkWorkProc
325  *
326  * Description:
327  *
328  *     Send the PDM_START_OK message to the dtpdmd on stderr. This
329  *     routine is an Xt work proc that is intended to be invoked by Xt
330  *     following the dispatch of all events generated during
331  *     startup. This function is only called once during the life of the
332  *     app.
333  *
334  * Return value:
335  *
336  *     True, which causes Xt to remove this work proc.
337  *
338  */
339 static Boolean
340 PdmStartOkWorkProc(XtPointer client_data)
341 {
342     fprintf(stderr, "PDM_START_OK");
343     fflush(stderr);
344     return True;
345 }
346
347 /*
348  * ------------------------------------------------------------------------
349  * Name: main
350  *
351  * Description:
352  *
353  *     main function for the DtPrint Dialog Manager.
354  *
355  * Return value:
356  *
357  *     This function never returns.
358  *
359  */
360 int main(int argc, char* argv[])
361 {
362     PdmShell* pdm_shell;
363     PdmMainWin* pdm_main_window;
364     String* fallback_resources;
365     int status;
366     XEvent event;
367
368     /*
369      * Initialize environment so we can find message catalog.
370      */
371     _DtEnvControl(DT_ENV_SET);
372
373     /*
374      * ensure we can convert Xp attributes for this locale
375      */
376     if(!XSupportsLocale())
377     {
378         fprintf(stderr, "%s\n", PDM_MSG_ERR_X_LOCALE);
379         exit(PDM_EXIT_ERROR);
380     }
381     /*
382      * create the PDM objects for the app shell, the main window, and the
383      * setup boxes
384      */
385     pdm_shell = PdmShellNew();
386     pdm_main_window = PdmMainWinNew();
387     PdmMainWinAddSetupBox(pdm_main_window, PdmPrinterBoxNew());
388     PdmMainWinAddSetupBox(pdm_main_window, PdmJobBoxNew());
389     /*
390      * create the application shell widget
391      */
392     fallback_resources =
393         PdmMainWinMergeFallbacks(pdm_main_window,
394                                  PdmShellFallbackResources,
395                                  XtNumber(PdmShellFallbackResources));
396     status = PdmShellCreate(pdm_shell, fallback_resources, &argc, argv);
397     if(0 != status)
398     {
399         PdmMainWinDelete(pdm_main_window);
400         exit(status);
401     }
402     XtFree((char*)fallback_resources);
403     /*
404      * create the main PDM window widget hierarchy
405      */
406     PdmMainWinCreate(pdm_main_window,
407                      pdm_shell->widget,
408                      pdm_shell->print_display_spec,
409                      pdm_shell->print_context_str);
410     /*
411      * display the PDM
412      */
413     PdmShellPresent(pdm_shell);
414     /*
415      * signal the PDM is up following startup event processing
416      */
417     XtAppAddWorkProc(pdm_shell->app_context,
418                      PdmStartOkWorkProc, (XtPointer)NULL);
419     /*
420      * main loop
421      */
422     for(;;)
423     {
424         /*
425          * get the next event
426          */
427         XtAppNextEvent(pdm_shell->app_context, &event);
428         /*
429          * check to see if the parent video window has been destroyed
430          */
431         if(event.xany.display == pdm_shell->display
432            &&
433            event.xany.window == pdm_shell->parent_window
434            &&
435            event.xany.type == DestroyNotify)
436         {
437             PdmMainWinDelete(pdm_main_window);
438             exit(PDM_EXIT_CANCEL);
439         }
440         else
441             XtDispatchEvent(&event);
442     }
443     /*
444      * not reached
445      */
446     return 0;
447 }