2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: Application.C /main/15 1998/10/01 12:10:26 mgreess $ */
27 * RESTRICTED CONFIDENTIAL INFORMATION:
29 * The information in this document is subject to special
30 * restrictions in a confidential disclosure agreement bertween
31 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
32 * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
33 * Sun's specific written approval. This documment and all copies
34 * and derivative works thereof must be returned or destroyed at
37 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
41 ///////////////////////////////////////////////////////////////////////////////
42 //////////////////////////////////////////////////////////////////////////////
43 // This example code is from the book:
45 // Object-Oriented Programming with C++ and OSF/Motif
48 // Prentice Hall, 1992
51 // Copyright 1991 by Prentice Hall
52 // All Rights Reserved
54 // Permission to use, copy, modify, and distribute this software for
55 // any purpose except publication and without fee is hereby granted, provided
56 // that the above copyright notice appear in all copies of the software.
57 ///////////////////////////////////////////////////////////////////////////////
58 //////////////////////////////////////////////////////////////////////////////
61 ////////////////////////////////////////////////////////////
63 ////////////////////////////////////////////////////////////
64 #include "Application.h"
65 #include "MainWindow.h"
66 #include <X11/StringDefs.h>
67 #include <X11/Shell.h>
70 #include <sys/types.h>
76 #include "EUSDebug.hh"
80 Application::_appResources[] = {
82 "workspaceList", "WorkspaceList", XtRString, sizeof(XtRString),
83 XtOffset(Application *, _appWorkspaceList), XtRString, (XtPointer) NULL
87 // XPG3 compatible. NL_CAT_LOCALE is set to 1 (non-zero) in XPG4. Use NL_CAT_LOCALE
88 // for all catopen() calls. This is also defined in include/DtMail/Common.h for dtmail
89 // and libDtMail catopen calls, if later on we have a common include file for
90 // dtmail, libDtMail and MotifApp, we can move this define over there.
92 #if defined(sun) && (_XOPEN_VERSION == 3)
94 #define NL_CAT_LOCALE 0
96 // If NL_CAT_LOCALE is not defined in other platforms, set it to 0
97 #elif !defined(NL_CAT_LOCALE)
98 #define NL_CAT_LOCALE 0
103 * Wrapper around catgets -- this makes sure the message string is saved
104 * in a safe location; so repeated calls to catgets() do not overwrite
105 * the catgets() internal buffer. This has been a problem on HP systems.
107 char *catgets_cache2(nl_catd catd, int set, int num, char *dflt)
110 #define MSGS_PER_SET_MAX 12
111 #define NUM_SETS_MAX 2
113 /* array to hold messages from catalog */
114 static char *MsgCat[NUM_SETS_MAX][MSGS_PER_SET_MAX];
116 /* convert to a zero based index */
117 int setIdx = set - 1;
118 int numIdx = num - 1;
120 if ( ! MsgCat[setIdx][numIdx] ) {
121 MsgCat[setIdx][numIdx] = strdup( catgets(catd, set, num, dflt));
124 return MsgCat[setIdx][numIdx];
129 Application *theApplication = NULL;
131 nl_catd catd = (nl_catd) -1; // catgets file descriptor
133 extern String ApplicationFallbacks[];
135 Application::Application ( char *appClassName ) :
136 UIComponent ( appClassName )
138 // Set the global Application pointer
139 DebugPrintf(2, "Application::Application(%p \"%s\")\n", appClassName, appClassName);
141 theApplication = this;
143 // Initialize data members
150 _shutdownEnabled = 1;
151 _applicationClass = strdup ( appClassName );
152 _appWorkspaceList = NULL;
153 _lastInteractiveEventTime = 0;
158 void Application::initialize ( int *argcp, char **argv )
160 DebugPrintf(2, "Application::initialize(%p %d, %p)\n", argcp, *argcp, argv);
162 DebugPrintf(3, "Application::initialize - Initializing privileges.\n");
164 // The Solaris sendmail operates differently than the HP/IBM sendmail.
165 // sendmail on Solaris runs as 'root' and so has access permissions
166 // to any file on the system. sendmail on HP/IBM runs as set-group-id
167 // 'mail' and so requires that all mailboxes that it may deliver e-mail
168 // to be writable either by being group mail group writable, or by being
169 // writable by the world. On those platforms, then, dtmail is required
170 // to always run with set-group-id mail otherwise, when mailboxes are
171 // saved, they will loose their group ownership and sendmail will no
172 // onger be able to deliver to those mailboxes.
174 // we have to be set-gid to group "mail" when opening and storing
175 // folders. But we don't want to do everything as group mail.
176 // here we record our original gid, and set the effective gid
177 // back the the real gid. We'll set it back when we're dealing
180 _originalEgid = getegid(); // remember effective group ID
181 _originalRgid = getgid(); // remember real group ID
182 disableGroupPrivileges(); // disable group privileges from here on
184 DebugPrintf(3, "Application::initialize - Initializing Xt.\n");
186 _w = XtOpenApplication (
189 (XrmOptionDescList) NULL, 0,
190 argcp, argv, ApplicationFallbacks,
191 sessionShellWidgetClass, (ArgList) NULL, 0 );
193 // Extract and save a pointer to the X display structure
194 DebugPrintf(3, "Application::initialize - Extracting display.\n");
195 _display = XtDisplay ( _w );
197 // Set virtual BMenu mouse binding
198 int numButtons = XGetPointerMapping(_display, (unsigned char *)NULL, 0);
199 _bMenuButton = (numButtons < 3) ? Button2 : Button3;
201 // The Application class is less likely to need to handle
202 // "surprise" widget destruction than other classes, but
203 // we might as well install a callback to be safe and consistent
204 DebugPrintf(3, "Application::initialize - Installing destroy handler.\n");
205 installDestroyHandler();
207 // Center the shell, and make sure it isn't visible
208 DebugPrintf(3, "Application::initialize - Setting window size.\n");
210 XmNmappedWhenManaged, FALSE,
211 XmNx, DisplayWidth ( _display, 0 ) / 2,
212 XmNy, DisplayHeight ( _display, 0 ) / 2,
217 // The instance name of this object was set in the UIComponent
218 // constructor, before the name of the program was available
219 // Free the old name and reset it to argv[0]
220 DebugPrintf(3, "Application::initialize - Deleting name %p\n", _name);
222 _name = strdup ( argv[0] );
224 // Force the shell window to exist so dialogs popped up from
225 // this shell behave correctly
226 DebugPrintf(3, "Application::initialize - Realizing shell window.\n");
227 XtRealizeWidget ( _w );
229 getResources(_appResources, XtNumber(_appResources));
231 // Initialize and manage any windows registered
232 // with this application.
234 for ( int i = 0; i < _numWindows; i++ )
236 DebugPrintf(3, "Application::initialize - Initializing windows[%d]\n", i);
237 _windows[i]->initialize();
238 DebugPrintf(3, "Application::initialize - Managing windows[%d]\n", i);
239 _windows[i]->manage();
243 // Calling _exit() now to work around a problem with threads
244 // deadlocking if exit() is called.
245 // Need to fix the threads deadlocking bug and then replace
246 // _exit() with exit().
248 Application::~Application()
251 // Allocated using strdup, so free using free.
253 free((void*) _applicationClass);
257 #if defined(__hpux) || defined(USL) || defined(__uxp__)
258 this->BasicComponent::~BasicComponent();
260 BasicComponent * The_End = this;
261 The_End->BasicComponent::~BasicComponent();
263 BasicComponent::~BasicComponent();
269 // In an MT environment, calling exit() causes threads to
270 // hang and a deadlock results.
271 // Call _exit() instead
276 // ApplicationExtractEventTime - extract the time the
277 // current event happened if it is one we are interested
278 // in - this is used to delay actions that can lock the application
279 // while the user is being interactive with the application
282 inline void Application::extractAndRememberEventTime(XEvent *event)
284 switch (((XAnyEvent *)event)->type)
286 case KeyPress: // press any key on the keyboard
287 case ButtonPress: // press any botton on the screen
288 case MotionNotify: // motion events
289 _lastInteractiveEventTime = time((time_t *)0);
294 void Application::handleEvents()
298 XtAppMainLoop ( _appContext );
302 _lastInteractiveEventTime = time((time_t *)0);
305 XtAppNextEvent( _appContext, &event );
306 extractAndRememberEventTime( &event );
307 XtDispatchEvent( &event );
312 void Application::registerWindow ( MainWindow *window )
315 MainWindow **newList;
317 // Allocate a new list large enough to hold the new
318 // object, and copy the contents of the current list
321 newList = new MainWindow*[_numWindows + 1];
323 for ( i = 0; i < _numWindows; i++ )
324 newList[i] = _windows[i];
326 // Install the new list and add the window to the list
328 if (_numWindows > 0) delete []_windows;
330 _windows[_numWindows] = window;
335 void Application::unregisterWindow ( MainWindow *window )
339 // If this is the last window bye bye.
341 if (isEnabledShutdown() && _numWindows == 1)
345 // Call derived class's shutdown method.
350 // Copy all objects, except the one to be removed, to a new list
352 MainWindow **newList = new MainWindow*[_numWindows - 1];
354 for (i=0, index=0; i<_numWindows; i++)
355 if (_windows[i] != window)
356 newList[index++] = _windows[i];
363 void Application::manage()
365 // Manage all application windows. This will pop up
366 // iconified windows as well.
368 for ( int i = 0; i < _numWindows; i++ )
369 _windows[i]->manage();
372 void Application::unmanage()
374 // Unmanage all application windows
376 for ( int i = 0; i < _numWindows; i++ )
377 _windows[i]->unmanage();
380 void Application::iconify()
382 // Iconify all top-level windows.
384 for ( int i = 0; i < _numWindows; i++ )
385 _windows[i]->iconify();
390 Application::open_catalog()
392 // open message catalog file
393 catd = catopen("MotifApp", NL_CAT_LOCALE);
397 Application::setAppWorkspaceList(char *workspaceList)
399 // open message catalog file
400 if (NULL != _appWorkspaceList)
401 free(_appWorkspaceList);
403 _appWorkspaceList = strdup(workspaceList);