Application.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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 libraries 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: Application.C /main/15 1998/10/01 12:10:26 mgreess $ */
  24. /*
  25. *+SNOTICE
  26. *
  27. * RESTRICTED CONFIDENTIAL INFORMATION:
  28. *
  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
  35. * Sun's request.
  36. *
  37. * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
  38. *
  39. *+ENOTICE
  40. */
  41. ///////////////////////////////////////////////////////////////////////////////
  42. //////////////////////////////////////////////////////////////////////////////
  43. // This example code is from the book:
  44. //
  45. // Object-Oriented Programming with C++ and OSF/Motif
  46. // by
  47. // Douglas Young
  48. // Prentice Hall, 1992
  49. // ISBN 0-13-630252-1
  50. //
  51. // Copyright 1991 by Prentice Hall
  52. // All Rights Reserved
  53. //
  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. //////////////////////////////////////////////////////////////////////////////
  59. ////////////////////////////////////////////////////////////
  60. // Application.C:
  61. ////////////////////////////////////////////////////////////
  62. #include "Application.h"
  63. #include "MainWindow.h"
  64. #include <X11/StringDefs.h>
  65. #include <X11/Shell.h>
  66. #include <assert.h>
  67. #include <stdlib.h>
  68. #include <sys/types.h>
  69. #include <time.h>
  70. #include <unistd.h>
  71. #include <nl_types.h>
  72. #include <string.h>
  73. #include "EUSDebug.hh"
  74. XtResource
  75. Application::_appResources[] = {
  76. {
  77. "workspaceList", "WorkspaceList", XtRString, sizeof(XtRString),
  78. XtOffset(Application *, _appWorkspaceList), XtRString, (XtPointer) NULL
  79. }
  80. };
  81. // XPG3 compatible. NL_CAT_LOCALE is set to 1 (non-zero) in XPG4. Use NL_CAT_LOCALE
  82. // for all catopen() calls. This is also defined in include/DtMail/Common.h for dtmail
  83. // and libDtMail catopen calls, if later on we have a common include file for
  84. // dtmail, libDtMail and MotifApp, we can move this define over there.
  85. #if defined(sun) && (_XOPEN_VERSION == 3)
  86. #undef NL_CAT_LOCALE
  87. #define NL_CAT_LOCALE 0
  88. // If NL_CAT_LOCALE is not defined in other platforms, set it to 0
  89. #elif !defined(NL_CAT_LOCALE)
  90. #define NL_CAT_LOCALE 0
  91. #endif
  92. #ifdef hpV4
  93. /*
  94. * Wrapper around catgets -- this makes sure the message string is saved
  95. * in a safe location; so repeated calls to catgets() do not overwrite
  96. * the catgets() internal buffer. This has been a problem on HP systems.
  97. */
  98. char *catgets_cache2(nl_catd catd, int set, int num, char *dflt)
  99. {
  100. #define MSGS_PER_SET_MAX 12
  101. #define NUM_SETS_MAX 2
  102. /* array to hold messages from catalog */
  103. static char *MsgCat[NUM_SETS_MAX][MSGS_PER_SET_MAX];
  104. /* convert to a zero based index */
  105. int setIdx = set - 1;
  106. int numIdx = num - 1;
  107. if ( ! MsgCat[setIdx][numIdx] ) {
  108. MsgCat[setIdx][numIdx] = strdup( catgets(catd, set, num, dflt));
  109. }
  110. return MsgCat[setIdx][numIdx];
  111. }
  112. #endif
  113. Application *theApplication = NULL;
  114. nl_catd catd = (nl_catd) -1; // catgets file descriptor
  115. extern String ApplicationFallbacks[];
  116. Application::Application ( char *appClassName ) :
  117. UIComponent ( appClassName )
  118. {
  119. // Set the global Application pointer
  120. DebugPrintf(2, "Application::Application(%p \"%s\")\n", appClassName, appClassName);
  121. theApplication = this;
  122. // Initialize data members
  123. _display = NULL;
  124. _appContext = NULL;
  125. _bMenuButton = 0;
  126. _windows = NULL;
  127. _numWindows = 0;
  128. _shutdownEnabled = 1;
  129. _applicationClass = strdup ( appClassName );
  130. _appWorkspaceList = NULL;
  131. _lastInteractiveEventTime = 0;
  132. _originalEgid = 0;
  133. _originalRgid = 0;
  134. }
  135. void Application::initialize ( int *argcp, char **argv )
  136. {
  137. DebugPrintf(2, "Application::initialize(%p %d, %p)\n", argcp, *argcp, argv);
  138. DebugPrintf(3, "Application::initialize - Initializing privileges.\n");
  139. // The Solaris sendmail operates differently than the HP/IBM sendmail.
  140. // sendmail on Solaris runs as 'root' and so has access permissions
  141. // to any file on the system. sendmail on HP/IBM runs as set-group-id
  142. // 'mail' and so requires that all mailboxes that it may deliver e-mail
  143. // to be writable either by being group mail group writable, or by being
  144. // writable by the world. On those platforms, then, dtmail is required
  145. // to always run with set-group-id mail otherwise, when mailboxes are
  146. // saved, they will loose their group ownership and sendmail will no
  147. // onger be able to deliver to those mailboxes.
  148. // we have to be set-gid to group "mail" when opening and storing
  149. // folders. But we don't want to do everything as group mail.
  150. // here we record our original gid, and set the effective gid
  151. // back the the real gid. We'll set it back when we're dealing
  152. // with folders...
  153. //
  154. _originalEgid = getegid(); // remember effective group ID
  155. _originalRgid = getgid(); // remember real group ID
  156. disableGroupPrivileges(); // disable group privileges from here on
  157. DebugPrintf(3, "Application::initialize - Initializing Xt.\n");
  158. _w = XtOpenApplication (
  159. &_appContext,
  160. _applicationClass,
  161. (XrmOptionDescList) NULL, 0,
  162. argcp, argv, ApplicationFallbacks,
  163. sessionShellWidgetClass, (ArgList) NULL, 0 );
  164. // Extract and save a pointer to the X display structure
  165. DebugPrintf(3, "Application::initialize - Extracting display.\n");
  166. _display = XtDisplay ( _w );
  167. // Set virtual BMenu mouse binding
  168. int numButtons = XGetPointerMapping(_display, (unsigned char *)NULL, 0);
  169. _bMenuButton = (numButtons < 3) ? Button2 : Button3;
  170. // The Application class is less likely to need to handle
  171. // "surprise" widget destruction than other classes, but
  172. // we might as well install a callback to be safe and consistent
  173. DebugPrintf(3, "Application::initialize - Installing destroy handler.\n");
  174. installDestroyHandler();
  175. // Center the shell, and make sure it isn't visible
  176. DebugPrintf(3, "Application::initialize - Setting window size.\n");
  177. XtVaSetValues ( _w,
  178. XmNmappedWhenManaged, FALSE,
  179. XmNx, DisplayWidth ( _display, 0 ) / 2,
  180. XmNy, DisplayHeight ( _display, 0 ) / 2,
  181. XmNwidth, 1,
  182. XmNheight, 1,
  183. NULL );
  184. // The instance name of this object was set in the UIComponent
  185. // constructor, before the name of the program was available
  186. // Free the old name and reset it to argv[0]
  187. DebugPrintf(3, "Application::initialize - Deleting name %p\n", _name);
  188. free(_name);
  189. _name = strdup ( argv[0] );
  190. // Force the shell window to exist so dialogs popped up from
  191. // this shell behave correctly
  192. DebugPrintf(3, "Application::initialize - Realizing shell window.\n");
  193. XtRealizeWidget ( _w );
  194. getResources(_appResources, XtNumber(_appResources));
  195. // Initialize and manage any windows registered
  196. // with this application.
  197. for ( int i = 0; i < _numWindows; i++ )
  198. {
  199. DebugPrintf(3, "Application::initialize - Initializing windows[%d]\n", i);
  200. _windows[i]->initialize();
  201. DebugPrintf(3, "Application::initialize - Managing windows[%d]\n", i);
  202. _windows[i]->manage();
  203. }
  204. }
  205. // Calling _exit() now to work around a problem with threads
  206. // deadlocking if exit() is called.
  207. // Need to fix the threads deadlocking bug and then replace
  208. // _exit() with exit().
  209. Application::~Application()
  210. {
  211. //
  212. // Allocated using strdup, so free using free.
  213. //
  214. free((void*) _applicationClass);
  215. delete []_windows;
  216. #ifdef CDExc21492
  217. #if defined(__hpux)
  218. this->BasicComponent::~BasicComponent();
  219. #else
  220. BasicComponent::~BasicComponent();
  221. #endif
  222. #endif
  223. catclose(catd);
  224. // In an MT environment, calling exit() causes threads to
  225. // hang and a deadlock results.
  226. // Call _exit() instead
  227. _exit(0);
  228. }
  229. // ApplicationExtractEventTime - extract the time the
  230. // current event happened if it is one we are interested
  231. // in - this is used to delay actions that can lock the application
  232. // while the user is being interactive with the application
  233. //
  234. inline void Application::extractAndRememberEventTime(XEvent *event)
  235. {
  236. switch (((XAnyEvent *)event)->type)
  237. {
  238. case KeyPress: // press any key on the keyboard
  239. case ButtonPress: // press any botton on the screen
  240. case MotionNotify: // motion events
  241. _lastInteractiveEventTime = time((time_t *)0);
  242. break;
  243. }
  244. }
  245. void Application::handleEvents()
  246. {
  247. // Just loop forever
  248. #if 0
  249. XtAppMainLoop ( _appContext );
  250. #else
  251. XEvent event;
  252. _lastInteractiveEventTime = time((time_t *)0);
  253. for (;;) {
  254. XtAppNextEvent( _appContext, &event );
  255. extractAndRememberEventTime( &event );
  256. XtDispatchEvent( &event );
  257. }
  258. #endif
  259. }
  260. void Application::registerWindow ( MainWindow *window )
  261. {
  262. int i;
  263. MainWindow **newList;
  264. // Allocate a new list large enough to hold the new
  265. // object, and copy the contents of the current list
  266. // to the new list
  267. newList = new MainWindow*[_numWindows + 1];
  268. for ( i = 0; i < _numWindows; i++ )
  269. newList[i] = _windows[i];
  270. // Install the new list and add the window to the list
  271. if (_numWindows > 0) delete []_windows;
  272. _windows = newList;
  273. _windows[_numWindows] = window;
  274. _numWindows++;
  275. }
  276. void Application::unregisterWindow ( MainWindow *window )
  277. {
  278. int i, index;
  279. // If this is the last window bye bye.
  280. if (isEnabledShutdown() && _numWindows == 1)
  281. {
  282. _numWindows--;
  283. // Call derived class's shutdown method.
  284. shutdown();
  285. return;
  286. }
  287. // Copy all objects, except the one to be removed, to a new list
  288. MainWindow **newList = new MainWindow*[_numWindows - 1];
  289. for (i=0, index=0; i<_numWindows; i++)
  290. if (_windows[i] != window)
  291. newList[index++] = _windows[i];
  292. delete []_windows;
  293. _windows = newList;
  294. _numWindows--;
  295. }
  296. void Application::manage()
  297. {
  298. // Manage all application windows. This will pop up
  299. // iconified windows as well.
  300. for ( int i = 0; i < _numWindows; i++ )
  301. _windows[i]->manage();
  302. }
  303. void Application::unmanage()
  304. {
  305. // Unmanage all application windows
  306. for ( int i = 0; i < _numWindows; i++ )
  307. _windows[i]->unmanage();
  308. }
  309. void Application::iconify()
  310. {
  311. // Iconify all top-level windows.
  312. for ( int i = 0; i < _numWindows; i++ )
  313. _windows[i]->iconify();
  314. }
  315. void
  316. Application::open_catalog()
  317. {
  318. // open message catalog file
  319. catd = catopen("MotifApp", NL_CAT_LOCALE);
  320. }
  321. void
  322. Application::setAppWorkspaceList(char *workspaceList)
  323. {
  324. // open message catalog file
  325. if (NULL != _appWorkspaceList)
  326. free(_appWorkspaceList);
  327. _appWorkspaceList = strdup(workspaceList);
  328. }