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