/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* Motif Release 1.2.4
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$TOG: WmInitWs.c /main/18 1999/09/20 15:18:22 mgreess $"
#endif
#endif
/*
* (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994 Novell, Inc.
*/
/*
* Included Files:
*/
#include "WmGlobal.h"
#include "WmResNames.h"
#ifdef WSM
#include "WmHelp.h"
#endif /* WSM */
#include "WmICCC.h"
#ifdef PANELIST
#define DTWM_NEED_FNTPL
#include "WmIBitmap.h"
#endif /* PANELIST */
#ifndef NO_OL_COMPAT
#include "WmOL.h"
#endif /* NO_OL_COMPAT */
#include <X11/Xos.h>
#include <X11/cursorfont.h>
#include <Xm/Xm.h>
#include <X11/Shell.h>
#include <X11/Core.h>
#include <X11/keysym.h>
#include <Xm/AtomMgr.h>
#ifndef NO_HP_KEY_REMAP
#include <Xm/VirtKeysP.h>
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
# include <Xm/DrawingA.h>
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
typedef struct
{
String default_name ;
String new_name ;
} str_xref_rec, *str_xref ;
#endif /* NO_HP_KEY_REMAP */
#ifdef WSM
#include <Dt/GetDispRes.h>
#include <Dt/SessionP.h>
#include <Dt/DtP.h>
#include <Dt/Message.h>
#include <Dt/WsmM.h>
#endif /* WSM */
/* Busy is also defined in the BMS -> bms.h. This conflicts with
* /usr/include/X11/Xasync.h on ibm.
*/
#ifdef _AIX
#ifdef Busy
#undef Busy
#endif
#endif
#include <X11/Xlibint.h>
/*
* include extern functions
*/
#ifdef WSM
#include "WmBackdrop.h"
#endif /* WSM */
#include "WmCDInfo.h"
#include "WmColormap.h"
#include "WmError.h"
#include "WmEvent.h"
#include "WmFeedback.h"
#include "WmFunction.h"
#include "WmIDecor.h"
#ifdef WSM
#include "WmIPC.h"
#endif /* WSM */
#include "WmIPlace.h"
#include "WmIconBox.h"
#include "WmKeyFocus.h"
#ifdef PANELIST
#include "WmPanelP.h" /* for typedef in WmManage.h */
#endif /* PANELIST */
#include "WmManage.h"
#include "WmMenu.h"
#ifdef WSM
#include "WmPresence.h"
#endif /* WSM */
#include "WmProperty.h"
#include "WmResCvt.h"
#include "WmResource.h"
#include "WmSignal.h"
#include "WmProtocol.h"
#include "WmCDecor.h"
#include "stdio.h"
#include "WmResParse.h"
#ifdef WSM
#include <stdlib.h>
#endif /* WSM */
#include "WmXSMP.h"
/*
* Function Declarations:
*/
#include "WmInitWs.h"
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
# include "WmWsmLib/wsm_proto.h"
# include "WmWsmLib/utm_send.h"
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
#ifdef WSM
static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
#endif /* WSM */
void InitWmDisplayEnv (void);
#ifndef NO_MESSAGE_CATALOG
void InitNlsStrings (void);
#endif
#ifndef NO_HP_KEY_REMAP
Boolean VirtKeys4DIN(Display *dpy);
#endif /* NO_HP_KEY_REMAP */
#ifdef WSM
/* limited to 3 chars max */
#define UNSPECIFIED_SCREEN_NAME "fbk"
char **dpy2Argv; /* copy for second display */
int dpy2Argc;
#ifndef PANELIST
WmScreenData *dtSD; /* for the "DT screen" of the display */
#endif /* PANELIST */
#endif /* WSM */
/*
* Global Variables:
*/
extern int firstTime;
#ifndef NO_MESSAGE_CATALOG
extern char * pWarningStringFile;
extern char * pWarningStringLine;
#endif
/*
* InitMouseBinding
*
* Special case for a two button mouse; move the BMENU binding
* from Button3 to Button2. Fails for one-button mice.
*/
static void
InitMouseBinding(void)
{
wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
if (wmGD.numMouseButtons < 3) {
wmGD.bMenuButton = Button2;
} else {
wmGD.bMenuButton = Button3;
}
}
/******************************<->*************************************
*
* BuildLockMaskSequence ()
*
* Set up the sequence of modifier masks to use to when grabbing
* key- and button-bindings. This sequence of masks is NULL
* terminated.
*
* Input:
* wmGD.lockingModMask
*
* Output:
* wmGD.pLockMaskSequence
*
*
*************************************<->***********************************/
static void
BuildLockMaskSequence(void)
{
int i, j, k;
unsigned int mask;
unsigned int thisbit;
Boolean bit_on;
int num_masks;
int num_bits;
int bit;
int run;
/*
* Count the bits to determine the number of elements in
* the mask sequence. The actual number of masks is
* 2^<bitcount> - 1. We're not interested in the case
* where there none of the mask bits are set.
*/
mask = wmGD.lockingModMask;
num_bits=0;
while (mask)
{
if (mask & 0x1)
{
num_bits++;
}
mask = mask >> 1;
}
num_masks = (0x1 << num_bits) - 1;
/*
* Allocate the space for the mask sequence + terminator.
*/
wmGD.pLockMaskSequence = (unsigned int *)
XtCalloc (num_masks+1, sizeof (unsigned int));
/*
* Fill in the mask sequence
*/
mask = wmGD.lockingModMask;
thisbit = 0x1;
bit = 0;
while (mask && thisbit)
{
/* find next bit */
while (!(thisbit & mask))
{
thisbit = thisbit << 1;
}
/* clear it from mask */
mask &= ~thisbit;
bit++;
/*
* Set it in the appropriate slots in the
* mask sequence. The start of the loop is
* funny because we skip the case of all the
* bits cleared.
*/
run = (0x1 << bit-1); /* number of consecutive masks to set
bits in */
bit_on = False; /* are we setting bits or not? */
for (j=0, k=run-1; j<num_masks; j++, k--)
{
if (k < 1)
{
if (bit_on)
bit_on = False;
else
bit_on = True;
k = run;
}
if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
}
}
}
/******************************<->*************************************
*
* SetupLockingModifierMask ()
*
* Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
* when processing key- and button-bindings.
*
* We want to try to ignore the set of locking modifers
* such as Shift Lock, Num Lock, Kana Lock, etc. This involves
* some amount of guessing since these things can be mapped
* onto any of the Mod1-Mod5 modifiers. The approach taken is to
* identify the mapping of the locking modifier keysyms to
* Mod1-Mod5 and build the set of masks needed to ignore them.
*
*************************************<->***********************************/
/*
* This is the set of locking modifiers keysyms that might be
* bound to Mod1-Mod5. (Caps Lock is handled independently of
* this set.)
*/
static KeySym pksLockingMods[] = {
XK_Scroll_Lock,
XK_Kana_Lock,
XK_Num_Lock,
XK_Mode_switch
};
#define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
static void
SetupLockingModifierMask(void)
{
int i, j, start_index;
XModifierKeymap *modifier_map = NULL;
static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
Mod3Mask, Mod4Mask, Mod5Mask };
Display *dpy = wmGD.display;
int pkcLockingMods[NUM_LOCKING_MODS];
int kcq, kc;
for (i=0; i<NUM_LOCKING_MODS; i++)
{
pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
}
/*
* Start out with Caps lock and add others we discover.
*/
wmGD.lockingModMask = LockMask;
modifier_map = XGetModifierMapping(dpy);
/* just check Mod1 through Mod5 */
start_index = modifier_map->max_keypermod * Mod1MapIndex;
for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
kc = modifier_map->modifiermap[i];
if (kc)
{
for (j=0; j<NUM_LOCKING_MODS; j++)
{
if (pkcLockingMods[j] == kc)
{
wmGD.lockingModMask |= mod_masks[this_mod];
break;
}
}
}
}
BuildLockMaskSequence();
if(modifier_map != NULL)
XFreeModifiermap(modifier_map);
}
/******************************<->*************************************
*
* MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
*
* Catch and handle changes to the mapping of the modifier keys.
*
*************************************<->***********************************/
static void
MappingEventHandler(
Widget w,
XtPointer client_data,
XEvent *event,
Boolean *cont_to_dispatch)
{
if(event->xany.type != MappingNotify ||
event->xmapping.request == MappingPointer)
return;
if(event->xmapping.request == MappingModifier)
SetupLockingModifierMask();
}
/******************************<->*************************************
*
* InitWmGlobal (argc, argv, environ)
*
*
* Description:
* -----------
* This function initializes the workspace manager.
*
*
* Inputs:
* ------
* argc = number of command line arguments (+1)
*
* argv = window manager command line arguments
*
* environ = window manager environment
*
*
* Outputs:
* -------
* wmGD = (initialize the global data structure)
*
*************************************<->***********************************/
void InitWmGlobal (int argc, char *argv [], char *environ [])
{
XSetWindowAttributes sAttributes;
int scr;
int managed = 0;
char pch[80];
Boolean activeSet = False;
Boolean processedGlobalResources = False;
WmScreenData *pSD;
Arg args[20];
int argnum;
char *res_class;
int savedArgc;
wmGD.errorFlag = False;
#ifdef WSM
#ifndef PANELIST
dtSD = NULL;
#else /* PANELIST */
wmGD.dtSD = NULL;
wmGD.iSlideUpsInProgress = 0;
#endif /*PANELIST */
#endif /* WSM */
SetupWmSignalHandlers (0); /* dummy paramater */
/*
* Do (pre-toolkit) initialization:
*/
wmGD.windowContextType = XUniqueContext ();
wmGD.screenContextType = XUniqueContext ();
#ifndef IBM_169380
wmGD.cmapWindowContextType = XUniqueContext ();
#endif
#ifdef WSM
wmGD.mwmWindowContextType = XUniqueContext ();
#endif /* WSM */
/* copy argv (the XtInititalize changes the original) for use in restart */
savedArgc = argc;
CopyArgv (argc, argv);
wmGD.environ = environ;
#ifdef WSM
wmGD.pWmPB = _DtWmParseNewBuf();
#endif /* WSM */
/* set our name */
if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
{
wmGD.mwmName++;
}
else
{
wmGD.mwmName = wmGD.argv[0];
}
#ifdef WSM
if (MwmBehavior)
{
res_class = WM_RESOURCE_CLASS;
}
else
{
res_class = DT_WM_RESOURCE_CLASS;
}
wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
#else /* WSM */
res_class = WM_RESOURCE_CLASS;
#endif /* WSM */
wmGD.display = (Display *)NULL;
wmGD.topLevelW = (Widget)NULL;
/*
* Do X Tookit initialization:
*/
XtToolkitInitialize();
wmGD.mwmAppContext = XtCreateApplicationContext();
AddWmResourceConverters ();
wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
NULL,
wmGD.mwmName,
res_class,
NULL,
0,
&argc, /* R5 changed from Cardinal to int*/
argv);
if (!wmGD.display)
{
Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
#if defined(sun) && defined(ALLPLANES)
{
int dummy;
wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display,
&dummy, &dummy);
}
#endif /* defined(sun) && defined(ALLPLANES) */
/*
* Setup error handling:
*/
WmInitErrorHandler(wmGD.display);
/*
* Initialize cursor size info and
* display the startup cursor.
*/
InitCursorInfo ();
#ifdef WSM
InitWmDisplayEnv ();
#endif
ShowWaitState (TRUE);
/*
* Initialize support for BMenu virtual mouse binding
*/
InitMouseBinding();
/*
* Set up the _MOTIF_BINDINGS property on the root window
* of screen 0. Must do this before we create shells.
*/
ProcessMotifBindings ();
#ifndef NO_HP_KEY_REMAP
/* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
* mechanism for selecting a virtual key binding table.
* When a client connects to a display, code inside of libXm
* gets the vendor identifier from the server and uses this
* identifier to select a default virtual key binding table
* from an internal list of possible tables (provided to
* OSF by vendors). A virtual key binding table maps OSF
* virtual keysyms to an "appropriate" set of X keysyms for
* a particular server vendor. The problem with this
* mechanism is that it only allows for a _single_ default
* virtual key binding table per server vendor. If a
* hardware vendor ships more than one distinct keyboard,
* then the single virtual key binding table selected for
* that server might not be appropriate for all keyboards.
* The HP migration from the "ITF" keyboard to the "PC-style"
* keyboard causes this problem to be exposed for Motif
* clients. The default HP virtual key binding table maps
* osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
* respectively. But since hpInsertChar and hpDeleteChar
* are absent from the PC-style keyboard, HP servers with
* this keyboard do not generate key events that map to the
* important osfInsert and osfDelete virtual keys.
* The Motif 1.2 version of libXm installs (one or two)
* properties on the root window, these properties exporting
* the virtual key binding table to be used by all (subsequently
* connected) Motif clients. The VirtKeys4DIN routine attempts
* to ensure that the virtual key binding table exported by
* those properties does not include dependencies on keysyms
* that are not available in the server's current modmap.
* The routine accomplishes this by searching the keyboard
* mapping of the display for the absence of known problematic
* keysyms. For those keysyms that are missing from the
* keyboard map, the corresponding dependencies in the
* virtual key binding table are altered to use pre-determined
* substitutes (which are generic X keysyms that are present
* on the PC-style keyboard mapping).
* The side-effects of this routine are that if there are no
* key binding properties on the root window when this routine
* is called, there will be a property installed (this occurs
* with all Motif 1.2 clients anyway). Since the virtual key
* binding table is only altered if it contains a keysym that
* is missing from the server's keyboard mapping, there is
* little chance of deleterious effects.
*/
VirtKeys4DIN(DISPLAY);
#endif /* NO_HP_KEY_REMAP */
argnum = 0;
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
XtSetArg (args[argnum], XtNx, 10000); argnum++;
XtSetArg (args[argnum], XtNy, 0); argnum++;
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
XtSetArg (args[argnum], XtNheight, 10); argnum++;
XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
XtSetArg (args[argnum], XtNjoinSession, True); argnum++;
#ifdef WSM
XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever); argnum++;
#else
XtSetArg (args[argnum], XtNrestartStyle, SmRestartIfRunning); argnum++;
#endif
XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
/* create topmost shell (application shell) */
wmGD.topLevelW = XtAppCreateShell (NULL,
res_class,
sessionShellWidgetClass,
DISPLAY,
args,
argnum);
#ifdef __osf__
_XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
_XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
#endif
XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
MappingEventHandler, NULL);
/* Add callbacks used for communication with Session Manager. */
AddSMCallbacks ();
/* allocate namespace for screens */
InitScreenNames();
/*
* Determine the screen management policy (all or none)
* Process command line arguments that we handle
* This could change the number of screens we manage
*/
ProcessGlobalScreenResources ();
ProcessCommandLine (argc, argv);
#ifdef WSM
/*
* Make sure backdrops are in our icon search path.
* This call MUST occur before ANY icons are looked up either
* explicitly or through resource processing!!!
* Uses variables set by ProcessGlobalScreenResources and
* ProcessCommandLine.
*/
{
int sNum;
Boolean useMaskRtn;
Boolean useMultiColorIcons;
Boolean useIconFileCacheRtn;
String sBdPath;
sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
&useMultiColorIcons, &useIconFileCacheRtn);
sBdPath = wmGD.backdropDirs;
InsureDefaultBackdropDir ((char **) &sBdPath);
_DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum),
sBdPath, useMultiColorIcons);
XtFree(sBdPath);
}
#endif /* WSM */
/*
* Allocate data and initialize for screens we manage:
*/
if (!(wmGD.Screens = (WmScreenData *)
XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
{
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
else
{
sAttributes.event_mask = SubstructureRedirectMask;
for (scr=0; scr<wmGD.numScreens; scr++)
{
int sNum;
/*
* Gain control of the root windows of each screen:
*/
sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
wmGD.errorFlag = False;
XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum),
CWEventMask, &sAttributes);
/*
* Do XSync to force server action and catch errors
* immediately.
*/
XSync (DISPLAY, False /* do not discard events */);
if ((wmGD.errorFlag) &&
(RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
(wmGD.errorRequestCode == X_ChangeWindowAttributes))
{
sprintf(pch,
((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
Warning ((char *) &pch[0]);
wmGD.Screens[scr].managed = False;
}
else
{
if (!processedGlobalResources)
{
#ifdef WSM
enum {
XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
static char *atom_names[] = {
_XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
_XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
_XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
_XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
Atom atoms[XtNumber(atom_names)];
XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names),
False, atoms);
wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
wmGD.xa_DT_SM_START_ACK_WINDOWS =
atoms[XA_DT_SM_START_ACK_WINDOWS];
wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
atoms[XA_DT_SM_STOP_ACK_WINDOWS];
wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
#endif /* WSM */
#ifndef NO_OL_COMPAT
InitOLCompat();
#endif /* NO_OL_COMPAT */
#ifndef NO_SHAPE
wmGD.hasShape = XShapeQueryExtension (DISPLAY,
&wmGD.shapeEventBase,
&wmGD.shapeErrorBase);
#endif /* NO_SHAPE */
wmGD.replayEnterEvent = False;
wmGD.menuActive = NULL;
wmGD.menuUnpostKeySpec = NULL;
wmGD.F_NextKeySpec = NULL;
wmGD.F_PrevKeySpec = NULL;
wmGD.passKeysActive = False;
wmGD.passKeysKeySpec = NULL;
wmGD.checkHotspot = False;
wmGD.configAction = NO_ACTION;
wmGD.configPart = FRAME_NONE;
wmGD.configSet = False;
wmGD.preMove = False;
wmGD.gadgetClient = NULL;
wmGD.wmTimers = NULL;
wmGD.clientDefaultTitle =
XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
wmGD.iconDefaultTitle =
XmStringCreateLocalized(DEFAULT_ICON_TITLE);
wmGD.attributesWindow = (Window)NULL;
wmGD.clickData.pCD = NULL;
wmGD.clickData.clickPending = False;
wmGD.clickData.doubleClickPending = False;
wmGD.systemModalActive = False;
wmGD.activeIconTextDisplayed = False;
wmGD.movingIcon = False;
wmGD.queryScreen = True;
wmGD.dataType = GLOBAL_DATA_TYPE;
wmGD.pLockMaskSequence = NULL;
SetupLockingModifierMask ();
#ifdef WSM
wmGD.requestContextWin = (Window) 0L;
wmGD.cppCommand = NULL;
wmGD.evLastButton.button = 0;
wmGD.bReplayedButton = False;
wmGD.bSuspendSecondaryRestack = False;
/*
* Get a second display connection for
* internal WM windows.
*/
wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
NULL,
wmGD.mwmName,
res_class,
NULL,
0,
&dpy2Argc,
dpy2Argv);
if (!wmGD.display1)
{
ShowWaitState (FALSE);
Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
_DtGetSmWindow(DISPLAY,
RootWindow(DISPLAY, 0),
&wmGD.dtSmWindow) ;
#ifdef PANACOMM
/*
* If this is the first screen we've managed,
* tell the session manager we're ready
*/
if (!processedGlobalResources)
{
SendClientMsg( wmGD.dtSmWindow,
(long) wmGD.xa_DT_SM_WM_PROTOCOL,
(long) wmGD.xa_DT_WM_READY,
CurrentTime, NULL, 0);
}
#endif /* PANACOMM */
/* create topmost shell (application shell) */
argnum = 0;
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
XtSetArg (args[argnum], XtNx, 10000); argnum++;
XtSetArg (args[argnum], XtNy, 0); argnum++;
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
XtSetArg (args[argnum], XtNheight, 10); argnum++;
XtSetArg (args[argnum],
XtNmappedWhenManaged, False); argnum++;
wmGD.topLevelW1 =
XtAppCreateShell (NULL,
res_class,
applicationShellWidgetClass,
DISPLAY1,
args,
argnum);
#endif /* WSM */
/*
* if this is the first screen we can manage,
* process global.
*/
processedGlobalResources = True;
/*
* Get the _MOTIF_WM_INFO property and determine
* the startup / restart state.
*/
ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
/*
* Process global window manager resources:
*/
#ifndef NO_MESSAGE_CATALOG
InitBuiltinSystemMenu();
#endif
ProcessWmResources ();
}
InitWmScreen (&(wmGD.Screens[scr]), sNum);
wmGD.Screens[scr].managed = True;
managed++;
#ifdef WSM
GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
#endif /* WSM */
if (!activeSet)
{
activeSet = True;
ACTIVE_PSD = &wmGD.Screens[scr];
}
}
}
if (managed == 0)
{
/*
* No screens for me to manage, give up.
*/
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
}
#ifdef WSM
/*
* Initialize the IPC mechanism
*/
dtInitialize(argv[0], wmGD.mwmAppContext);
#ifndef NO_MESSAGE_CATALOG
/*
* Set up NLS error messages.
* Must be done after DtInitialize.
*/
InitNlsStrings ();
#endif
/*
* For multiple connections to the server, turn off
* the geometry manager's insistence on synchronous
* management.
*/
argnum = 0;
XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
XtSetValues (wmGD.topLevelW, args, argnum);
XtSetValues (wmGD.topLevelW1, args, argnum);
#endif /* WSM */
/*
* Prepare to have child processes (e.g., exec'ed commands).
* The X connection should not be passed on to child processes
* (it should be automatically closed when a fork is done).
*/
if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
{
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
#ifdef WSM
{
enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
XA_DT_WORKSPACE_INFO, XA_WmNall,
XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
static char *atom_names[] = {
_XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
_XA_DT_WORKSPACE_INFO, WmNall,
_XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
_XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
Atom atoms[XtNumber(atom_names)];
XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
}
#endif /* WSM */
/* Initialize properties used in session management. */
wmGD.xa_SM_CLIENT_ID =
XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
wmGD.xa_WMSAVE_HINT =
XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
/* Load client resource database. */
wmGD.clientResourceDB = LoadClientResourceDB();
/*
* Make the window manager workspace window.
* Setup the _MOTIF_WM_INFO property on the root window.
*/
SetupWmWorkspaceWindows ();
/* make the cursors that the window manager uses */
MakeWorkspaceCursors ();
/* Sync the table used by Mwm's modifier parser to actual modMasks used */
SyncModifierStrings();
/*
* Setup screen data and resources (after processing Wm resources.
*/
for (scr = 0; scr < wmGD.numScreens; scr++)
{
pSD = &(wmGD.Screens[scr]);
if (pSD->managed)
{
#ifdef WSM
if (XDefaultScreen (wmGD.display) == pSD->screen)
{
wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
}
#endif /* WSM */
/*
* Initialize workspace colormap data.
*/
InitWorkspaceColormap (pSD);
/*
* Process the window manager resource description file (.mwmrc):
*/
#ifdef PANELIST
ProcessWmFile (pSD, False /* not nested */);
#else /* PANELIST */
ProcessWmFile (pSD);
#endif /* PANELIST */
/*
* Setup default resources for the system menu and key bindings:
*/
SetupDefaultResources (pSD);
/*
* Make global window manager facilities:
*/
if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
{
/* create active icon window */
CreateActiveIconTextWindow(pSD);
}
/*
* Make menus and other resources that are used by window manager
* functions that are activated by menus, buttons and keys.
*/
MakeWmFunctionResources (pSD);
}
#ifdef WSM
/*
*
* Set root cursor to be a pointer for dtwm
*
*/
# ifdef __osf__
/* Fixes problem on multiscreen where cursor is only
* set on primary screen.
*/
if (DtwmBehavior)
{
XDefineCursor (DISPLAY,
RootWindow (DISPLAY, scr),
wmGD.workspaceCursor);
}
# endif
#endif /* WSM */
}
#ifdef PANELIST
/*
* Remove any temp config file we created if we needed to
* convert DT 2.0 syntax to DT 3.0
*/
DeleteTempConfigFileIfAny();
#endif /* PANELIST */
#ifdef WSM
/*
* Point second display's resource data base
* to the first display's resource data base
* so dtwm "clients" change colors dynamically.
*
* NEW LOCATION
*/
wmGD.display1->db = wmGD.display->db;
#endif /* WSM */
/*
* Realize the top level widget, make the window override
* redirect so we don't manage it, and then move it out of the way
*/
XtRealizeWidget (wmGD.topLevelW);
#ifdef WSM
XtRealizeWidget (wmGD.topLevelW1);
/*
* Initialize the message handling.
* (This must be done after the realize because a window
* is required for ICCCM-style messaging).
*/
dtInitializeMessaging (wmGD.topLevelW);
#endif /* WSM */
sAttributes.override_redirect = True;
XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
CWOverrideRedirect, &sAttributes);
/* setup window manager inter-client communications conventions handling */
SetupWmICCC ();
/*
* Use the WM_SAVE_YOURSELF protocol
* for notification of when to save ourself
*/
#ifdef WSM
SetMwmSaveSessionInfo(wmGD.commandWindow);
#endif
/*
* Initialize window manager event handling:
*/
InitEventHandling ();
/*
* Initialize frame component graphics
*/
{
for (scr = 0; scr < wmGD.numScreens; scr++)
{
pSD = &(wmGD.Screens[scr]);
if (pSD->managed)
{
InitClientDecoration (pSD);
/*
* Make an icon box if specificed:
*/
if (pSD->useIconBox)
{
InitIconBox (pSD);
}
/*
* Adopt client windows that exist before wm startup:
*/
AdoptInitialClients (pSD);
/*
* Setup initial keyboard focus and colormap focus:
*/
InitColormapFocus (pSD);
}
}
for (scr = 0; scr < wmGD.numScreens; scr++)
{
#ifdef WSM
int iws;
#endif /* WSM */
pSD = &(wmGD.Screens[scr]);
if (pSD->managed)
{
ACTIVE_PSD = &wmGD.Screens[scr];
#ifdef WSM
MapIconBoxes (pSD->pActiveWS);
ChangeBackdrop (pSD->pActiveWS);
#ifdef HP_VUE
UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
#endif /* HP_VUE */
SetCurrentWorkspaceProperty (pSD);
SetWorkspaceListProperty (pSD);
for (iws=0; iws < pSD->numWorkspaces; iws++)
{
SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
}
XFlush (DISPLAY);
/* MapWorkspaceBox (); */
#ifdef PANELIST
/*
* Allocate front panel widgets
*/
if (wmGD.useFrontPanel && (pSD == wmGD.dtSD))
{
Pixmap iconBitmap;
Arg al[5];
int ac;
Widget wFpShell;
WmPanelistObject pPanelist;
wmGD.dtSD->wPanelist =
WmPanelistAllocate(pSD->screenTopLevelW1,
(XtPointer) &wmGD, (XtPointer) pSD);
pPanelist = (WmPanelistObject) pSD->wPanelist;
if (pPanelist != NULL && O_Shell(pPanelist))
{
/*
* Make a default front panel icon image.
*/
iconBitmap = XCreateBitmapFromData (DISPLAY,
pSD->rootWindow,
(char *) fntpl_i_bm_bits,
fntpl_i_bm_width,
fntpl_i_bm_height);
ac = 0;
XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++;
XtSetValues (O_Shell(pPanelist), al, ac);
}
}
if (wmGD.useFrontPanel && pSD->wPanelist &&
(pSD == wmGD.dtSD))
{
/*
* Make the front panel visible
*/
WmPanelistShow (pSD->wPanelist);
/*
* Find special clients associated with the
* front panel. This needs to be done after
* WmPanelistShow where the data is set up.
*/
ScanForPushRecallClients (pSD);
ScanForEmbeddedClients (pSD);
}
#endif /* PANELIST */
RestoreHelpDialogs(pSD);
#else /* WSM */
MapIconBoxes (pSD->pActiveWS);
#endif /* WSM */
}
}
firstTime = 0;
}
InitKeyboardFocus ();
#ifndef WSM
InitWmDisplayEnv ();
#endif
ShowWaitState (FALSE);
#ifdef WSM
/*
* Tell the rest of DT that we're up
*/
dtReadyNotification();
#endif /* WSM */
#ifdef DEBUG_RESOURCE_DATABASE
XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
#endif /* DEBUG_RESOURCE_DATABASE */
} /* END OF FUNCTION InitWmGlobal */
/******************************<->*************************************
*
* InitWmScreen
*
*
* Description:
* -----------
* This function initializes a screen data block.
*
* Inputs:
* -------
* pSD = pointer to preallocated screen data block
* sNum = screen number for this screen
*
* Outputs:
* -------
*************************************<->***********************************/
void
InitWmScreen (WmScreenData *pSD, int sNum)
{
Arg args[12];
int argnum;
#ifdef WSM
int wsnum;
WmWorkspaceData *pwsI;
int buf_size;
int i;
static int dupnum = 0;
int iwsx;
#endif /* WSM */
char *pDisplayName;
#define LENCBUFFER 256
char buffer[LENCBUFFER]; /* screen name & display name! */
char displayName[LENCBUFFER];
char *token1, *token2;
/*
* Set screen data values
*/
pSD->rootWindow = RootWindow (DISPLAY, sNum);
pSD->clientCounter = 0;
pSD->defaultSystemMenuUseBuiltin = TRUE;
pSD->displayString = NULL;
pSD->acceleratorMenuCount = 0;
pSD->activeIconTextWin = (Window)NULL;
pSD->focusPriority = 0;
pSD->inputScreenWindow = (Window)NULL;
pSD->colormapFocus = NULL;
pSD->keySpecs = NULL;
pSD->screen = sNum;
pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
pSD->confirmboxW[RESTART_ACTION] = NULL;
pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
pSD->feedbackWin = (Window)NULL;
pSD->fbStyle = FB_OFF;
pSD->fbWinWidth = 0;
pSD->fbWinHeight = 0;
pSD->fbLocation[0] = '\0';
pSD->fbSize[0] = '\0';
pSD->fbLocX = 0;
pSD->fbLocY = 0;
pSD->fbSizeX = 0;
pSD->fbSizeY = 0;
pSD->fbLastX = -1;
pSD->fbLastY = -1;
pSD->fbLastWidth = -1;
pSD->fbLastHeight = -1;
pSD->fbTop = NULL;
pSD->fbBottom = NULL;
pSD->actionNbr = -1;
pSD->clientList = NULL;
pSD->lastClient = NULL;
pSD->lastInstalledColormap = (Colormap)NULL;
pSD->shrinkWrapGC = NULL;
pSD->bitmapCache = NULL;
pSD->bitmapCacheSize = 0;
pSD->bitmapCacheCount = 0;
pSD->dataType = SCREEN_DATA_TYPE;
pSD->managed = False;
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
pSD->cciTree = NULL;
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
#ifdef WSM
pSD->initialWorkspace=NULL;
pSD->presence.shellW = NULL;
pSD->presence.onScreen = False;
pSD->presence.userDismissed = True;
pSD->workspaceList = NULL;
pSD->numWorkspaces = 0;
pSD->numWsDataAllocated = 0;
pSD->lastBackdropWin = NULL;
pSD->pDtSessionItems = NULL;
pSD->totalSessionItems = 0;
pSD->remainingSessionItems = 0;
pSD->cachedHelp = NULL;
pSD->dtHelp.shell = (Widget)NULL;
pSD->dtHelp.dialog = (Widget)NULL;
pSD->dtHelp.errorDialog = (Widget)NULL;
pSD->dtHelp.xPos = 0;
pSD->dtHelp.yPos = 0;
pSD->dtHelp.restored = False;
pSD->dtHelp.onScreen = False;
pSD->dtHelp.userDismissed = False;
pSD->dtHelp.pCDforClient= NULL;
pSD->helpResources=NULL;
pSD->bMarqueeSelectionInitialized = False;
pSD->woN = (Window) 0L;
pSD->woS = (Window) 0L;
pSD->woE = (Window) 0L;
pSD->woW = (Window) 0L;
#endif /* WSM */
#ifdef PANELIST
pSD->wPanelist = NULL;
pSD->pECD = NULL;
pSD->numPushRecallClients = 0;
pSD->numEmbeddedClients = 0;
pSD->pPRCD = NULL;
pSD->iconBoxControl = False;
#endif /* PANELIST */
#ifdef WSM
pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
/*
* We've got display resolution type--now, let's get color
* characteristics.
*/
ProcessWmColors (pSD);
if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
{
sprintf (buffer, "%d", sNum);
buf_size = strlen(buffer) + 1;
if ((wmGD.screenNames[sNum] =
(unsigned char *)XtRealloc (wmGD.screenNames[sNum], buf_size)) == NULL)
{
Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
else
{
strcpy((char *)wmGD.screenNames[sNum], buffer);
}
} /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
#endif /* WSM */
/*
* Save screen context
*/
XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
(caddr_t)pSD);
/*
* Create shell widget for screen resource hierarchy
*/
argnum = 0;
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
XtSetArg (args[argnum], XtNx, 10000); argnum++;
XtSetArg (args[argnum], XtNy, 10000); argnum++;
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
XtSetArg (args[argnum], XtNheight, 10); argnum++;
XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
XtSetArg (args[argnum], XtNdepth,
DefaultDepth(DISPLAY, sNum)); argnum++;
XtSetArg (args[argnum], XtNscreen,
ScreenOfDisplay(DISPLAY, sNum)); argnum++;
XtSetArg (args[argnum], XtNcolormap,
DefaultColormap(DISPLAY, sNum)); argnum++;
XtSetArg (args[argnum], XtNvisual,
DefaultVisual(DISPLAY, sNum)); argnum++;
pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
vendorShellWidgetClass,
wmGD.topLevelW,
args,
argnum);
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
/* Create a DrawingArea as a child of the popupShell. This will be used
* to handle UTM traffic relating to cci. We need this
* particular widget to get the callbacks from conversion requests made
* against Mwm and the requests Mwm makes against other clients.
*/
pSD->utmShell = XmCreateDrawingArea(pSD->screenTopLevelW, "UTM_Shell",
NULL, 0);
XtManageChild(pSD->utmShell);
/*
* Setup the destinationCallback handler to handle conversion
* requests made by Mwm against other clients.
*/
XtAddCallback(pSD->utmShell, XmNdestinationCallback, UTMDestinationProc,
NULL);
/* Must realize to own WM_i if unmapped, causes mwm to
freeze when menu is displayed. */
XtPopup(pSD->screenTopLevelW, XtGrabNone);
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
#ifdef WSM
argnum = 0;
XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
XtSetArg (args[argnum], XtNx, 10000); argnum++;
XtSetArg (args[argnum], XtNy, 10000); argnum++;
XtSetArg (args[argnum], XtNwidth, 10); argnum++;
XtSetArg (args[argnum], XtNheight, 10); argnum++;
XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
XtSetArg (args[argnum], XtNmappedWhenManaged, False); argnum++;
XtSetArg (args[argnum], XtNdepth,
DefaultDepth(DISPLAY1, sNum)); argnum++;
XtSetArg (args[argnum], XtNscreen,
ScreenOfDisplay(DISPLAY1, sNum)); argnum++;
XtSetArg (args[argnum], XtNcolormap,
DefaultColormap(DISPLAY1, sNum)); argnum++;
pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
vendorShellWidgetClass,
wmGD.topLevelW1,
args,
argnum);
XtRealizeWidget (pSD->screenTopLevelW1);
#endif /* WSM */
/*
* Fetch screen based resources
*/
ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
/*
* Initialize other screen resources and parameters
*/
MakeXorGC (pSD);
InitIconSize(pSD);
#ifdef WSM
/*
* Complete initialization of workspace structures
*/
for (wsnum = 0,
pwsI = pSD->pWS; wsnum < pSD->numWorkspaces;
wsnum++, pwsI++)
{
/*
* Set up workspace for this screen
*/
InitWmWorkspace (pwsI, pSD);
}
if (pSD->initialWorkspace)
{
/*
* restore to the last initialWorkspace saved from
* Quit, Restart, OR save session
*/
/*
* Compare initialWorkspace against workspace name,
* NOT workspace title.
*/
for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
{
if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
{
break;
}
}
/* check bounds */
if (iwsx >= pSD->numWorkspaces)
{
/* make first workspace in list the active one to start with */
pSD->pActiveWS = pSD->pWS;
}
else
{
pSD->pActiveWS = &pSD->pWS[iwsx];
}
}
else
{
/* make first workspace in list the active one to start with */
pSD->pActiveWS = pSD->pWS;
}
#else /* WSM */
/*
* Allocate and initialize a workspace structure
*/
if (!(pSD->pWS = (WmWorkspaceData *) XtMalloc (sizeof(WmWorkspaceData))))
{
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 8, "Insufficient memory for Workspace data")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
/*
* Set up workspace for this screen
*/
InitWmWorkspace (pSD->pWS, pSD);
pSD->pActiveWS = pSD->pWS;
#endif /* WSM */
pDisplayName = DisplayString (DISPLAY);
/*
* Construct displayString for this string.
*
* NOTE: The variable buffer is reused here. It was
* used earlier to generate a screen name.
*/
strcpy(displayName, pDisplayName);
token1 = (char*)strtok(displayName, ":"); /* parse of hostname */
if((token2 = (char*)strtok(NULL, ".")) || /* parse off dpy & scr # */
(token2 = (char*)strtok(NULL, "")) ||
(displayName[0] == ':'))
{
if (displayName[0] == ':') /* local dpy (special case) */
{
if ((token2 = (char*)strtok(token1, ".")) != NULL) /* parse dpy# */
sprintf(buffer, "DISPLAY=:%s.%d",
token2, sNum);
} else { /* otherwise process normally */
sprintf(buffer, "DISPLAY=%s:%s.%d",
token1, token2, sNum);
}
/*
* Allocate space for the display string
*/
if ((pSD->displayString =
(String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 9,
"Insufficient memory for displayString")));
}
else
{
strcpy(pSD->displayString, buffer);
}
}
} /* END OF FUNCTION InitWmScreen */
/*************************************<->*************************************
*
* InitWmWorkspace
*
*
* Description:
* -----------
* This function initializes a workspace data block.
*
* Inputs:
* -------
* pWS = pointer to preallocated workspace data block
* pSD = ptr to parent screen data block
*
* Outputs:
* -------
*************************************<->***********************************/
void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
{
Arg args[10];
int argnum;
#ifndef WSM
#define DEFAULT_WS_NAME "workspace"
#endif /* not WSM */
pWS->pSD = pSD;
pWS->pIconBox = NULL;
pWS->dataType = WORKSPACE_DATA_TYPE;
#ifdef WSM
pWS->backdrop.window = 0;
pWS->backdrop.nameAtom = 0;
pWS->backdrop.image = NULL;
pWS->numClients = 0;
pWS->sizeClientList = 0;
pWS->ppClients = 0;
pWS->buttonW = NULL;
#else /* WSM */
if ((pWS->name = (char *)
XtMalloc ((1+strlen(DEFAULT_WS_NAME)) * sizeof (char))) == NULL)
{
ShowWaitState (FALSE);
ExitWM (WM_ERROR_EXIT_VALUE);
}
strcpy (pWS->name, DEFAULT_WS_NAME);
#endif /* WSM */
/*
* Create widget for workspace resource hierarchy
*/
argnum = 0;
XtSetArg (args[argnum], XtNdepth,
DefaultDepth(DISPLAY, pSD->screen)); argnum++;
XtSetArg (args[argnum], XtNscreen,
ScreenOfDisplay(DISPLAY, pSD->screen)); argnum++;
XtSetArg (args[argnum], XtNcolormap,
DefaultColormap(DISPLAY, pSD->screen)); argnum++;
XtSetArg (args[argnum], XtNwidth, 5); argnum++;
XtSetArg (args[argnum], XtNheight, 5); argnum++;
pWS->workspaceTopLevelW = XtCreateWidget ( pWS->name,
xmPrimitiveWidgetClass,
pSD->screenTopLevelW,
args,
argnum);
#ifdef WSM
/* internalize the workspace name */
pWS->id = XInternAtom (DISPLAY, pWS->name, False);
#endif /* WSM */
/*
* Process workspace based resources
*/
ProcessWorkspaceResources (pWS);
/* setup icon placement */
if (wmGD.iconAutoPlace)
{
InitIconPlacement (pWS);
}
} /* END OF FUNCTION InitWmWorkspace */
#ifdef WSM
/******************************<->*************************************
*
* InsureDefaultBackdropDir(char **ppchBackdropDirs)
*
*
* Description:
* -----------
* This function checks and edits a directory path to insure
* that the system backdrop directroy (/usr/dt/backdrops) is in the
* path. If not it adds it to the end. Further, it always adds the user's
* backdrop directory ($HOME/.dt/backdrops) to the beginning of the path
* and the system admin directory (/etc/dt/backdrops) before the system
* directory.
*
* Inputs:
* -------
* ppchBackdropDirs - Pointer to a pointer to a directory path
* (must be allocated memory)
*
* Outputs:
* -------
* *ppchBackdropDirs - Directory path may be modified, path
* pointer may be realloc'ed.
*
* Comments:
* --------
* Assumes that the default directory does not start with a
* multi-byte character.
*
******************************<->***********************************/
static void
InsureDefaultBackdropDir(char **ppchBackdropDirs)
{
int len;
Boolean bFound = False;
char *pch, *pchEnd, *pch2, *tmpptr;
char *pchD = DEFAULT_BACKDROP_DIR;
unsigned int chlen;
char * homeDir;
/*
* Set up initial stuff
*/
pch = *ppchBackdropDirs;
len = strlen (pchD);
pchEnd = pch + strlen(pch);
while (!bFound && (pch != NULL) && (*pch != NULL))
{
if (strncmp (pch, pchD, len) == 0)
{
/* found partial match, confirm complete match ...
* complete match if char off end of partial match
* is a NULL or a colon
*/
pch2 = pch + len;
if ((pch2 <= pchEnd) &&
((*pch2 == NULL) ||
(((mblen (pch2, MB_CUR_MAX) == 1) &&
(*pch2 == ':')))))
{
bFound = True;
}
}
else
{
/* find next path component */
pch = strchr (pch, (int) ':');
if ((pch != NULL) && (*pch != NULL))
{
/* skip path separator */
chlen = mblen (pch, MB_CUR_MAX);
pch += chlen;
}
}
}
/*
* Always add the user's home directory to the beginning of the string
*/
homeDir = (char *) XmeGetHomeDirName();
/*
* If found add the user's home directory ($HOME/.dt/backdrops) and the
* admin directory /etc/dt/backdrops to the beginning of the string
*/
if (bFound)
{
len = strlen (homeDir) + strlen("/.dt/backdrops") +
strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
tmpptr = XtMalloc (len * sizeof (char *));
strcpy (tmpptr, homeDir);
strcat (tmpptr, "/.dt/backdrops");
strcat (tmpptr, ":");
strcat (tmpptr, "/etc/dt/backdrops");
strcat (tmpptr, ":");
strcat (tmpptr, *ppchBackdropDirs);
*ppchBackdropDirs = tmpptr;
}
else
/*
* If string not found, then add home directory to the beginning of
* string and the admin directory and system directory to the end.
*/
{
len = strlen (homeDir) + strlen("/.dt/backdrops") +
strlen (*ppchBackdropDirs) + strlen(pchD) +
strlen("/etc/dt/backdrops") + 4;
tmpptr = XtMalloc (len * sizeof (char *));
strcpy (tmpptr, homeDir);
strcat (tmpptr, "/.dt/backdrops");
strcat (tmpptr, ":");
strcat (tmpptr, *ppchBackdropDirs);
strcat (tmpptr, ":");
strcat (tmpptr, "/etc/dt/backdrops");
strcat (tmpptr, ":");
strcat (tmpptr, pchD);
*ppchBackdropDirs = tmpptr;
}
} /* END OF FUNCTION InsureDefaultBackdropDirs */
#endif /* WSM */
/*************************************<->*************************************
*
* ProcessMotifWmInfo (rootWindowOfScreen)
*
*
* Description:
* -----------
* This function is used retrieve and save the information in the
* _MOTIF_WM_INFO property. If the property does not exist then
* the start / restart state is set to initial startup with the
* user specified (not standard) configuration.
*
*
* Outputs:
* -------
* wmGD.useStandardBehavior = True if set indicated in property
*
* wmGD.wmRestarted = True if the window manager was restarted
*
*************************************<->***********************************/
void ProcessMotifWmInfo (Window rootWindowOfScreen)
{
MwmInfo *pMwmInfo;
wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
{
wmGD.useStandardBehavior =
(pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
wmGD.wmRestarted = True;
XFree ((char *)pMwmInfo);
}
else
{
wmGD.useStandardBehavior = False;
wmGD.wmRestarted = False;
}
} /* END OF FUNCTION ProcessMotifWmInfo */
/*************************************<->*************************************
*
* SetupWmWorkspaceWindows ()
*
*
* Description:
* -----------
* This function is used to setup a window that can be used in doing window
* management functions. This window is not visible on the screen.
*
*
* Outputs:
* -------
* pSD->wmWorkspaceWin = window that is used to hold wm properties
*
*************************************<->***********************************/
void SetupWmWorkspaceWindows (void)
{
int scr;
WmScreenData *pSD;
XSetWindowAttributes sAttributes;
for (scr = 0; scr < wmGD.numScreens; scr++)
{
pSD = &(wmGD.Screens[scr]);
if (pSD->managed)
{
sAttributes.override_redirect = True;
sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow,
-100, -100, 10, 10, 0, 0,
InputOnly, CopyFromParent,
(CWOverrideRedirect |CWEventMask),
&sAttributes);
XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
SetMwmInfo (pSD->rootWindow,
(long) ((wmGD.useStandardBehavior) ?
MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM),
pSD->wmWorkspaceWin);
#ifdef WSM
XSaveContext (DISPLAY, pSD->wmWorkspaceWin,
wmGD.mwmWindowContextType, (caddr_t)pSD);
#endif /* WSM */
}
}
} /* END OF FUNCTION SetupWmWorkspaceWindow */
/*************************************<->*************************************
*
* MakeWorkspaceCursors ()
*
*
* Description:
* -----------
* This function makes the cursors that the window manager uses.
*
*
* Inputs:
* ------
* XXinput = ...
*
* XXinput = ...
*
*
* Outputs:
* -------
* wmGD = (stretchCursors ...)
*
*************************************<->***********************************/
void MakeWorkspaceCursors (void)
{
wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
wmGD.stretchCursors[STRETCH_NORTH_WEST] =
XCreateFontCursor (DISPLAY, XC_top_left_corner);
wmGD.stretchCursors[STRETCH_NORTH] =
XCreateFontCursor (DISPLAY, XC_top_side);
wmGD.stretchCursors[STRETCH_NORTH_EAST] =
XCreateFontCursor (DISPLAY, XC_top_right_corner);
wmGD.stretchCursors[STRETCH_EAST] =
XCreateFontCursor (DISPLAY, XC_right_side);
wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
wmGD.stretchCursors[STRETCH_SOUTH] =
XCreateFontCursor (DISPLAY, XC_bottom_side);
wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
wmGD.stretchCursors[STRETCH_WEST] =
XCreateFontCursor (DISPLAY, XC_left_side);
wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
} /* END OF FUNCTION MakeWorkspaceCursors */
/*************************************<->*************************************
*
* MakeWmFunctionResources (pSD)
*
*
* Description:
* -----------
* This function makes menus and other resources that are used by window
* manager functions.
*
*
* Inputs:
* ------
* wmGD = (menuSpecs, keySpecs, buttonSpecs)
*
*
* Outputs:
* -------
* wmGD (menuSpecs) = new menu panes, protocol atoms
*
*************************************<->***********************************/
void MakeWmFunctionResources (WmScreenData *pSD)
{
ButtonSpec *buttonSpec;
KeySpec *keySpec;
MenuSpec *menuSpec;
Context menuContext;
/*
* Scan through the menu specifications and make wm protocol atoms.
*/
/*
* Scan through the button binding specifications making menus if the
* f.menu function is invoked.
*/
buttonSpec = pSD->buttonSpecs;
while (buttonSpec)
{
if (buttonSpec->wmFunction == F_Menu)
{
if (buttonSpec->context & F_CONTEXT_WINDOW)
{
menuContext = F_CONTEXT_WINDOW;
}
else if (buttonSpec->context & F_CONTEXT_ICON)
{
menuContext = F_CONTEXT_ICON;
}
else
{
menuContext = F_CONTEXT_ROOT;
}
menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
menuContext,
buttonSpec->context,
(MenuItem *) NULL, FALSE);
if (menuSpec)
/*
* If successful, save in pSD->acceleratorMenuSpecs
* Note: these accelerators have nonzero contexts.
*/
{
SaveMenuAccelerators (pSD, menuSpec);
}
else
{
buttonSpec->wmFunction = F_Nop;
}
}
buttonSpec = buttonSpec->nextButtonSpec;
}
/*
* Scan through the key binding specifications making menus if the
* f.menu function is invoked.
*/
keySpec = pSD->keySpecs;
while (keySpec)
{
if (keySpec->wmFunction == F_Menu)
{
if (keySpec->context & F_CONTEXT_WINDOW)
{
menuContext = F_CONTEXT_WINDOW;
}
else if (keySpec->context & F_CONTEXT_ICON)
{
menuContext = F_CONTEXT_ICON;
}
else
{
menuContext = F_CONTEXT_ROOT;
}
menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
keySpec->context,
(MenuItem *) NULL, FALSE);
if (menuSpec)
/*
* If successful, save in pSD->acceleratorMenuSpecs
* Note: these accelerators have nonzero contexts.
*/
{
SaveMenuAccelerators (pSD, menuSpec);
}
else
{
keySpec->wmFunction = F_Nop;
}
}
keySpec = keySpec->nextKeySpec;
}
} /* END OF FUNCTION MakeWmFunctionResources */
/*************************************<->*************************************
*
* MakeXorGC (pSD)
*
*
* Description:
* -----------
* Make an XOR graphic context for resizing and moving
*
*
* Inputs:
* ------
* pSD = pointer to screen data
*
* Outputs:
* -------
* Modifies global data
*
* Comments:
* --------
*
*
*************************************<->***********************************/
void MakeXorGC (WmScreenData *pSD)
{
XGCValues gcv;
XtGCMask mask;
mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
gcv.function = GXinvert;
gcv.line_width = 0;
gcv.cap_style = CapNotLast;
gcv.subwindow_mode = IncludeInferiors;
/* Fix so that the rubberbanding for resize and move will
* have more contrasting colors.
*/
gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^
WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
mask = mask | GCPlaneMask;
pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
} /* END OF FUNCTION MakeXorGC */
/*************************************<->*************************************
*
* CopyArgv (argc, argv)
*
*
* Description:
* -----------
* This function makes a copy of the window manager's argv for use by
* the f.restart function. A copy must be kept because XtInitialize
* changes argv.
*
*
* Inputs:
* ------
* argc = the number of strings in argv
*
* argv = window manager parameters
*
*
* Outputs:
* -------
* Return = a copy of argv
*
*************************************<->***********************************/
void CopyArgv (int argc, char *argv [])
{
int i;
if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
wmGD.argv = argv;
#ifdef WSM
dpy2Argv = argv;
#endif /* WSM */
}
else
{
for (i = 0; i < argc; i++)
{
wmGD.argv[i] = argv[i];
}
wmGD.argv[i] = NULL;
#ifdef WSM
if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
dpy2Argv = argv;
}
else
{
for (i = 0; i < argc; i++)
{
dpy2Argv[i] = argv[i];
}
dpy2Argc = argc;
dpy2Argv[i] = NULL;
}
#endif /* WSM */
}
} /* END OF FUNCTION CopyArgv */
/*************************************<->*************************************
*
* InitScreenNames ()
*
*
* Description:
* -----------
* Initializes the name space for screen names
*
* Outputs:
* -------
* Modifies global data
* + screenNames
*
* Comments:
* --------
* Initializes screenNames to contain a numeric name for each screen
*
*************************************<->***********************************/
void InitScreenNames (void)
{
int num, numScreens;
numScreens = ScreenCount (wmGD.display);
if (!(wmGD.screenNames =
(unsigned char **) XtMalloc (numScreens * sizeof(char *))))
{
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
for (num=0; num<numScreens; num++)
{
if (!(wmGD.screenNames[num] =
(unsigned char *) XtMalloc (4*sizeof(char))))
{
ShowWaitState (FALSE);
Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
/* default name is left justified, 3-chars max, zero terminated */
#ifdef WSM
sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
#else /* WSM */
sprintf((char *)wmGD.screenNames[num],"%d",num%1000);
#endif /* WSM */
}
}
#ifndef NO_MESSAGE_CATALOG
void InitNlsStrings (void)
{
char * tmpString;
#ifdef WSM
/*
* Initialize messages
*/
wmGD.okLabel=XmStringCreateLocalized(_DtOkString);
wmGD.cancelLabel=XmStringCreateLocalized(_DtCancelString);
wmGD.helpLabel=XmStringCreateLocalized(_DtHelpString);
#endif /* WSM */
/*
* catgets returns a pointer to an area that is over written
* on each call to catgets.
*/
tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
if ((wmNLS.default_icon_box_title =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
wmNLS.default_icon_box_title = "Icons";
}
else
{
strcpy(wmNLS.default_icon_box_title, tmpString);
}
#ifdef WSM
tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
if ((pWarningStringFile =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
}
else
{
strcpy(pWarningStringFile, tmpString);
}
tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
if ((pWarningStringLine =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
pWarningStringLine = "%s: %s on line %d of specification string\n";
}
else
{
strcpy(pWarningStringLine, tmpString);
}
tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
if ((wmNLS.defaultVersionTitle =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
wmNLS.defaultVersionTitle = "About Workspace Manager";
}
else
{
strcpy(wmNLS.defaultVersionTitle, tmpString);
}
tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
if ((wmNLS.defaultDtwmHelpTitle =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
}
else
{
strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
}
tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
if ((wmNLS.defaultHelpTitle =
(char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
{
Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
wmNLS.defaultHelpTitle = "Workspace Manager - Help";
}
else
{
strcpy(wmNLS.defaultHelpTitle, tmpString);
}
#endif /* WSM */
} /* InitNlsStrings */
#endif
/******************************<->*************************************
*
* InitWmDisplayEnv
*
*
* Description:
* -----------
* This function saves the display string for putenv in F_Exec.
*
* Inputs:
* -------
*
* Outputs:
* -------
*************************************<->***********************************/
void
InitWmDisplayEnv (void)
{
char *pDisplayName;
char buffer[256];
char displayName[256];
pDisplayName = DisplayString (DISPLAY);
/*
* Construct displayString for this string.
*/
strcpy(displayName, pDisplayName);
sprintf(buffer, "DISPLAY=%s",displayName);
/*
* Allocate space for the display string
*/
if ((wmGD.displayString =
(String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
{
wmGD.displayString = NULL;
Warning (((char *)GETMESSAGE(40, 9,
"Insufficient memory for displayString")));
}
else
{
strcpy(wmGD.displayString, buffer);
#ifdef WSM
putenv(wmGD.displayString);
#endif /* WSM */
}
} /* END OF FUNCTION InitWmDisplayEnv */
#ifndef NO_HP_KEY_REMAP
static str_xref
GetReplacementList(
Display *dsp,
str_xref std_xref,
int count)
{
int min_kc ;
int max_kc ;
int ks_per_kc ;
int kc_count ;
KeySym *key_map ;
unsigned i ;
str_xref xref_rtn = NULL ;
unsigned num_xref = 0 ;
XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
kc_count = max_kc + 1 - min_kc ;
key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
if( key_map == NULL )
{
return NULL ;
}
kc_count *= ks_per_kc ;
i = 0 ;
while( i < count )
{
KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
unsigned j = 0 ;
while( j < kc_count )
{
if( key_map[j] == ks )
{
/* Found keysym used in virtkey table in keymap,
* so break -> j != kc_count
*/
break ;
}
++j ;
}
if( j == kc_count )
{
/* Didn't find keysym of virtkey table, so add record to
* returned list which will later cause replacement in
* virtkeys table.
*/
xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
sizeof( str_xref_rec) * (num_xref + 2)) ;
xref_rtn[num_xref++] = std_xref[i] ;
xref_rtn[num_xref].default_name = NULL ;
}
++i ;
}
XFree( (char *) key_map) ;
return xref_rtn ;
}
static Boolean
GetBindingsProperty(
Display *dsp,
Atom property,
String *binding)
{
Atom actual_type ;
int actual_format ;
unsigned long num_items ;
unsigned long bytes_after ;
unsigned char *prop = NULL ;
XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
&prop) ;
if( (actual_type != XA_STRING)
|| (actual_format != 8)
|| (num_items == 0) )
{
if( prop != NULL )
{
XFree( prop) ;
}
return FALSE ;
}
*binding = (String) prop ;
return TRUE ;
}
static void
SetBindingsProperty(
Display *dsp,
Atom property,
String binding)
{
XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
}
static String
FixupBindingsString(
String bindingsString,
str_xref repl_xref)
{
String fixed_str = XtNewString( bindingsString) ;
String ptr_next = fixed_str ;
while( repl_xref->default_name != NULL )
{
String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
unsigned orig_len = strlen( repl_xref->default_name) ;
if( ks_ptr == NULL )
{
/* Only increment to next replacement when no other instances
* are found in fixed_str.
*/
++repl_xref ;
ptr_next = fixed_str ;
continue ;
}
if( (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
&& (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len)) )
{
unsigned new_len = strlen( repl_xref->new_name) ;
unsigned suffix_len = strlen( ks_ptr + orig_len) ;
if( new_len > orig_len )
{
unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
unsigned prefix_len ;
*ks_ptr = '\0' ;
prefix_len = strlen( fixed_str) ;
fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
ks_ptr = fixed_str + prefix_len ;
}
memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
memcpy( ks_ptr, repl_xref->new_name, new_len) ;
ptr_next = ks_ptr + new_len ;
}
else
{
ptr_next = ks_ptr + 1 ;
}
}
return fixed_str ;
}
Boolean
VirtKeys4DIN(
Display *dsp)
{
/* This routine examines the X server's key map table to determine
* if certain HP-specific keysyms are missing. If they are, then
* the Motif virtual binding table properties are updated to utilize
* generic X keysyms instead of the missing HP vendor keysyms.
* In particular, this fixes the Motif virtual key binding table for
* correct operation on HP systems using the AT2/DIN style keyboard.
*/
static char *prop_names[] = { "_MOTIF_BINDINGS",
"_MOTIF_DEFAULT_BINDINGS" } ;
static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
{ "hpDeleteChar", "Delete" },
{ "End", "F7" },
} ;
Boolean PropChanged4DIN = FALSE ;
unsigned i ;
char *bindingsString ;
unsigned prop_existed ;
Atom *prop_atoms ;
str_xref vkeysym_xref ;
unsigned num_props = XtNumber( prop_names) ;
vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
if( vkeysym_xref == NULL )
{
return PropChanged4DIN ;
}
prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
prop_existed = FALSE ;
i = 0 ;
while( i < num_props )
{
if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
{
String new_bstring = FixupBindingsString( bindingsString,
vkeysym_xref) ;
prop_existed = TRUE ;
XFree( bindingsString) ;
if( new_bstring != NULL )
{
SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
XtFree( new_bstring) ;
}
}
++i ;
}
if( !prop_existed )
{
bindingsString = NULL ;
_XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
XtFree( bindingsString) ;
i = 0 ;
while( i < num_props )
{
if( GetBindingsProperty( dsp, prop_atoms[i], &bindingsString) )
{
String new_bstring = FixupBindingsString( bindingsString,
vkeysym_xref) ;
XtFree( bindingsString) ;
if( new_bstring != NULL )
{
PropChanged4DIN = TRUE ;
SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
XtFree( new_bstring) ;
}
XFree( bindingsString) ;
}
++i ;
}
}
XtFree( (char *) vkeysym_xref) ;
XtFree( (char *) prop_atoms) ;
return PropChanged4DIN ;
}
#endif /* NO_HP_KEY_REMAP */
#ifdef WSM
/**************************** eof ***************************/
#endif /* WSM */