1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/dtterm/DtTermMain.c
2018-07-03 17:58:52 +01:00

2126 lines
62 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-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 libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
#ifndef lint
#ifdef VERBOSE_REV_INFO
static char rcs_id[] = "$TOG: DtTermMain.c /main/19 1999/09/17 13:26:34 mgreess $";
#endif /* VERBOSE_REV_INFO */
#endif /* lint */
/* *
* (c) Copyright 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. *
*/
#ifdef sun
#include <dlfcn.h>
#endif /* sun */
#include "TermHeader.h"
#include "TermPrim.h"
#include "TermPrimDebug.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <signal.h>
#include <Xm/Form.h>
#include <Xm/TextF.h>
#include <Xm/PushBG.h>
#include <Xm/LabelG.h>
#include <Xm/Protocols.h>
#include <Xm/Display.h>
/*
* This for the sleazy hack to get the window manager frame width/height
*/
#include <Xm/VendorSEP.h>
#define DEBUG_INCLUDES /*DKS*/
#ifdef DEBUG_INCLUDES
#include "TermPrimBufferP.h"
#include "TermPrimParserP.h"
#include "TermPrimPendingTextP.h"
#include "TermPrimSelectP.h"
#include "TermPrimP.h"
#include "TermPrimRenderP.h"
#include "TermPrimLineDrawP.h"
#include "TermPrimLineFontP.h"
#include "TermBufferP.h"
#include "TermP.h"
#include "TermParseTableP.h"
#include "TermFunction.h"
/* #include "TermFunctionKeyP.h" */
#include "TermViewP.h"
#endif /* DEBUG_INCLUDES */
#include "TermPrim.h"
#include "TermView.h"
#include "TermViewMenu.h"
#include "DtTermMain.h"
#include "DtTermSyntax.h"
#ifdef TERMINAL_SERVER
#include "DtTermServer.h"
#endif /* TERMINAL_SERVER */
#include "TermPrimWMProtocols.h"
#include "TermPrimMessageCatI.h"
#ifdef LOG_USAGE
#include "DtTermLogit.h"
#endif /* LOG_USAGE */
#ifdef HPVUE
#include <Xv/Session.h>
#include <Xv/EnvControl.h>
#define DtSessionSavePath XvSessionSavePath
#define DtSessionRestorePath XvSessionRestorePath
#define DtWsmGetWorkspacesOccupied XvGetWorkspacePresence
#define DtWsmSetWorkspacesOccupied XvSetWorkspaceHints
#else /* HPVUE */
#include <Dt/Dt.h>
#include <Dt/Wsm.h>
#include <Dt/EnvControlP.h>
#endif /* HPVUE */
/* From Xm/BaseClassI.h */
extern XmWidgetExtData _XmGetWidgetExtData(
Widget widget,
#if NeedWidePrototypes
unsigned int extType) ;
#else
unsigned char extType) ;
#endif /* NeedWidePrototypes */
/* forward declarations... */
static void activateCallback(
Widget w,
XtPointer client_data,
XtPointer call_data
);
static void ToggleMenuBar(
Widget w,
XtPointer client_data,
XtPointer call_data
);
static void SaveSessionCB(
Widget w,
caddr_t client_data,
caddr_t call_data );
static Boolean RestoreSession(
Widget topDog,
Arg *arglist,
int i);
static void SaveTerm(
DtTermViewWidget dtvw,
int cloneNum,
int fd);
static void RestoreTerm(
Widget shellWidget,
DtTermViewWidget dtvw,
int termNum,
XrmDatabase db);
static void SetWorkSpaceHints(
Widget shell,
char *workspaces );
static void TestProbeHandler(
Widget w,
XtPointer client_data,
XEvent *event,
Boolean *ctd);
static void RegisterTestProbe(
Widget topLevel,
DtTermViewWidget tw);
static char defaultIgnoredKeysyms[] = "\
<Key>F1\n\
<Key>F2\n\
<Key>F3\n\
<Key>F4\n\
<Key>F5\n\
<Key>F6\n\
<Key>F7\n\
<Key>F8\n\
<Key>F9\n\
<Key>F10\n\
<Key>F11\n\
<Key>F12\
";
typedef struct _termattrs {
char *debugString;
char *ignoredKeysyms;
char *session;
Boolean loginShell;
#ifdef TERMINAL_SERVER
Boolean block;
Boolean exitOnLastClose;
Boolean server;
char *serverId;
Boolean standAlone;
int PingInterval;
#endif
#ifdef SUN_TERMINAL_SERVER
Boolean server;
#endif
char *title;
char *icon_name;
char *dtterm_name;
} TERMATTRS;
#ifdef TERMINAL_SERVER
static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False,
TRUE, False, False, NULL, False, 5, NULL, NULL, NULL};
#elif SUN_TERMINAL_SERVER
static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False, False, NULL, NULL, NULL};
#else
static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False, NULL, NULL, NULL };
#endif
static Atom xa_MOTIF_WM_MESSAGES = None;
static Atom xa_DTTERM_TOGGLE_MENUBAR = None;
static Atom xa_DTTERM_TEST_PROBE_IDS = None;
static Atom xa_DTTERM_REMOTE_PROBE_REQUEST = None;
static Atom xa_WM_SAVE_YOURSELF;
static XtAppContext appContext;
static Widget topLevel;
static Widget topShell;
static char *title = NULL;
static DtTermViewWidget *instance_list = NULL;
static Boolean RestoringTerms = False;
static int savedArgc = 0;
static char **savedArgv = NULL;
#ifdef SUN_TERMINAL_SERVER
int InstanceCount = 0;
#else
#ifndef TERMINAL_SERVER
static int InstanceCount = 0;
#endif /* TERMINAL_SERVER */
#endif /* SUN_TERMINAL_SERVER */
static const char _true[] = "true";
static const char _false[] = "false";
/* command line options...
*/
static XrmOptionDescRec optionDescList[] = {
/* special (not end user) options...
*/
{"-~", "*debugLevel", XrmoptionSepArg, (XtPointer) NULL},
{"-debugLevel", "*debugLevel", XrmoptionSepArg, (XtPointer) NULL},
{"-session", "*session", XrmoptionSepArg, (XtPointer) NULL},
#ifdef TERMINAL_SERVER
/* server options...
*/
{"-noBlocking", "*blocking", XrmoptionNoArg, (XtPointer) _false},
{"-server", "*server", XrmoptionNoArg, (XtPointer) _true},
{"-serverId", "*serverId", XrmoptionSepArg, (XtPointer) NULL},
#endif /* TERMINAL_SERVER */
#ifdef SUN_TERMINAL_SERVER
{"-dtserver", "*server", XrmoptionNoArg, (XtPointer) _true},
{"-sdtserver", "*server", XrmoptionNoArg, (XtPointer) _true},
#endif /* SUN_TERMINAL_SERVER */
/* terminal emulation options...
*/
{"-132", "*c132", XrmoptionNoArg, (XtPointer) _true},
{"+132", "*c132", XrmoptionNoArg, (XtPointer) _false},
{"-aw", "*autoWrap", XrmoptionNoArg, (XtPointer) _true},
{"+aw", "*autoWrap", XrmoptionNoArg, (XtPointer) _false},
{"-bs", "*backgroundIsSelect",
XrmoptionNoArg, (XtPointer) _true},
{"+bs", "*backgroundIsSelect",
XrmoptionNoArg, (XtPointer) _false},
{"-C", "*consoleMode", XrmoptionNoArg, (XtPointer) _true},
{"-cc", "*charClass", XrmoptionSepArg, (XtPointer) NULL},
{"-cu", "*curses", XrmoptionNoArg, (XtPointer) _true},
{"+cu", "*curses", XrmoptionNoArg, (XtPointer) _false},
{"-e", NULL, XrmoptionSkipLine,
(XtPointer) NULL},
{"-fb", "*userBoldFont", XrmoptionSepArg, (XtPointer) NULL},
{"-fn", "*userFont", XrmoptionSepArg, (XtPointer) NULL},
{"+iconic", ".iconic", XrmoptionNoArg, (XtPointer) _false},
{"-j", "*jumpScroll", XrmoptionNoArg, (XtPointer) _true},
{"+j", "*jumpScroll", XrmoptionNoArg, (XtPointer) _false},
{"-kshMode", "*kshMode", XrmoptionNoArg, (XtPointer) _true},
{"+kshMode", "*kshMode", XrmoptionNoArg, (XtPointer) _false},
{"-l", "*logging", XrmoptionNoArg, (XtPointer) _true},
{"+l", "*logging", XrmoptionNoArg, (XtPointer) _false},
{"-lf", "*logFile", XrmoptionSepArg, (XtPointer) NULL},
{"-ls", "*loginShell", XrmoptionNoArg, (XtPointer) _true},
{"+ls", "*loginShell", XrmoptionNoArg, (XtPointer) _false},
{"-map", "*mapOnOutput", XrmoptionNoArg, (XtPointer) _true},
{"+map", "*mapOnOutput", XrmoptionNoArg, (XtPointer) _false},
{"-mb", "*marginBell", XrmoptionNoArg, (XtPointer) _true},
{"+mb", "*marginBell", XrmoptionNoArg, (XtPointer) _false},
{"-ms", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
{"-n", "*iconName", XrmoptionSepArg, (XtPointer) NULL},
{"-nb", "*nMarginBell", XrmoptionSepArg, (XtPointer) NULL},
{"-rw", "*reverseWrap", XrmoptionNoArg, (XtPointer) _true},
{"+rw", "*reverseWrap", XrmoptionNoArg, (XtPointer) _false},
{"-sb", "*scrollBar", XrmoptionNoArg, (XtPointer) _true},
{"+sb", "*scrollBar", XrmoptionNoArg, (XtPointer) _false},
{"-sf", "*sunFunctionKeys", XrmoptionNoArg, (XtPointer) _true},
{"+sf", "*sunFunctionKeys", XrmoptionNoArg, (XtPointer) _false},
{"-si", "*scrollTtyOutput", XrmoptionNoArg, (XtPointer) _true},
{"+si", "*scrollTtyOutput", XrmoptionNoArg, (XtPointer) _false},
{"-sk", "*scrollKey", XrmoptionNoArg, (XtPointer) _true},
{"+sk", "*scrollKey", XrmoptionNoArg, (XtPointer) _false},
{"-sl", "*saveLines", XrmoptionSepArg, (XtPointer) NULL},
{"-ti", "*termId", XrmoptionSepArg, (XtPointer) NULL},
{"-tm", "*ttyModes", XrmoptionSepArg, (XtPointer) NULL},
{"-tn", "*termName", XrmoptionSepArg, (XtPointer) NULL},
{"-standAlone", "*standAlone", XrmoptionNoArg, (XtPointer) _true},
{"-vb", "*visualBell", XrmoptionNoArg, (XtPointer) _true},
{"+vb", "*visualBell", XrmoptionNoArg, (XtPointer) _false},
/* legacy options that are ignored...
*/
{"-ah", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+ah", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-b", NULL, XrmoptionSepArg, (XtPointer) NULL},
{"-cb", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+cb", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-cn", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+cn", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-cr", NULL, XrmoptionSepArg, (XtPointer) NULL},
{"-s", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+s", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-t", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+t", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-ut", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+ut", NULL, XrmoptionNoArg, (XtPointer) _false},
{"-wf", NULL, XrmoptionNoArg, (XtPointer) _true},
{"+wf", NULL, XrmoptionNoArg, (XtPointer) _false},
};
/* application specific resources...
*/
static XtResource applicationResources[] = {
{"debugLevel", "DebugLevel", XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, debugString), XtRImmediate, NULL},
{"ignoredKeysyms", "IgnoredKeysyms", XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, ignoredKeysyms), XtRImmediate, NULL},
{"loginShell", "LoginShell", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, loginShell), XtRString, "false"},
{"session", "Session", XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, session), XtRString, NULL},
#ifdef TERMINAL_SERVER
{"blocking", "Blocking", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, block), XtRString, "true"},
{"exitOnLastClose", "ExitOnLastClose", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, exitOnLastClose), XtRString, "false"},
{"server", "Server", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, server), XtRString, "false"},
{"serverId", "ServerId", XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, serverId), XtRImmediate, NULL},
{"standAlone", "StandAlone", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, standAlone), XtRString, "false"},
{"pingInterval", "PingInterval", XtRInt, sizeof(int),
XtOffsetOf(TERMATTRS, PingInterval), XtRString, "5"},
#endif /* TERMINAL_SERVER */
#ifdef SUN_TERMINAL_SERVER
{"server", "Server", XtRBoolean, sizeof(Boolean),
XtOffsetOf(TERMATTRS, server), XtRString, "false"},
#endif /* SUN_TERMINAL_SERVER */
{XtNtitle, XtCTitle, XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, title), XtRString, (caddr_t) NULL},
{XtNiconName, XtCIconName, XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, icon_name), XtRString, (caddr_t) NULL},
{"name", "Name", XtRString, sizeof(char *),
XtOffsetOf(TERMATTRS, dtterm_name), XtRString, (caddr_t) NULL},
};
extern String fallbackResources[];
#ifdef sun
void
sunSetupIA(Widget w)
{
int i, major_op, first_event, first_err;
int *pids;
void (*IAptr)()=(void (*)())NULL;
DtTermPrimitiveWidget tw;
if ((IAptr = (void (*)())dlsym(RTLD_NEXT, "XSolarisIASetProcessInfo"))!=NULL) {
pids = (int *)malloc(sizeof(int) * (InstanceCount + 1));
pids[0] = getpid();
for (i = 0; i < InstanceCount; i++) {
tw = (DtTermPrimitiveWidget)instance_list[i]->termview.term;
pids[i + 1] = tw->term.subprocessPid;
}
if (XQueryExtension(XtDisplay(w), "SolarisIA",
&major_op, &first_event, &first_err))
(*IAptr)(XtDisplay(w),pids,
0x1,InstanceCount + 1);
free(pids);
}
}
#endif /* sun */
#ifdef DELAY_DESTROY
static void
DestroyTree(XtPointer client_data, XtIntervalId *id)
{
(void) XtDestroyWidget((Widget) client_data);
}
#endif /* DELAY_DESTROY */
/*ARGSUSED*/
static void
DestroyDtTerm(Widget w, XtPointer client_data, XtPointer call_data)
{
/* destroy the whole interface... */
(void) XtDestroyWidget((Widget) client_data);
}
/*ARGSUSED*/
static void
ExitTimeout(XtPointer client_data, XtIntervalId *id)
{
if (title) {
XtFree(title);
}
(void) exit(0);
}
/*ARGSUSED*/
static void
DecrementInstanceCountAndExit(Widget w, XtPointer client_data,
XtPointer call_data)
{
DtTermViewWidget *new_instance_list;
int i,j;
/****************
*
* First, update the instance list cache by "deleting" the current instance
*
****************/
InstanceCount--;
if (InstanceCount > 0)
{
new_instance_list = (DtTermViewWidget *)XtMalloc(sizeof(DtTermViewWidget) * InstanceCount);
for (j = 0,i = 0; i < (InstanceCount+1); i++)
if (instance_list[i] != (DtTermViewWidget )w)
{
new_instance_list[j] = instance_list[i];
j++;
}
XtFree((char *)instance_list);
instance_list = new_instance_list;
}
else
XtFree((char *)instance_list);
/* check off this instance... */
#ifdef TERMINAL_SERVER
if (attrs.standAlone || !attrs.serverId) {
#endif /* TERMINAL_SERVER */
#ifdef notdef
if (!attrs.server) {
#endif /* notdef */
if (InstanceCount <= 0) {
/* use a timeout so that the toolkit can finish killing off
* this widget...
*/
(void) XtAppAddTimeOut(XtWidgetToApplicationContext(w), 0,
ExitTimeout, (XtPointer) 0);
}
#ifdef TERMINAL_SERVER
} else {
ServerInstanceTerminated((Widget) client_data);
}
#endif /* TERMINAL_SERVER */
#ifdef notdef
} else {
/* Here is where one would add the call into sunDtTermServer.c
* implement a "lurking" dtterm server. */
}
#endif /* notdef */
}
/***************************************************************************
* *
* RegisterTestProbe - shoves a property on the root window that says *
* we're ready to be tested, and sets up the event handler for the client *
* messages. *
* *
***************************************************************************/
static void RegisterTestProbe(
Widget topLevel,
DtTermViewWidget tw
)
{
Window win = XtWindow(topLevel);
if (xa_DTTERM_TEST_PROBE_IDS == None)
{
xa_DTTERM_TEST_PROBE_IDS = XInternAtom(XtDisplay(topLevel),
"_DTTERM_TEST_PROBE_IDS", False);
}
if (xa_DTTERM_REMOTE_PROBE_REQUEST == None)
{
xa_DTTERM_REMOTE_PROBE_REQUEST = XInternAtom(XtDisplay(topLevel),
"_DTTERM_REMOTE_PROBE_REQUEST", False);
}
XChangeProperty(XtDisplay(topLevel), RootWindowOfScreen(XtScreen(topLevel)),
xa_DTTERM_TEST_PROBE_IDS, xa_DTTERM_TEST_PROBE_IDS,
32, PropModeReplace, (unsigned char *)&win, 1);
XtAddEventHandler(topLevel, NoEventMask , True, (XtEventHandler )TestProbeHandler,
(XtPointer )tw);
}
#define ONE_BYTE 0
#define TWO_BYTE 1
#define FOUR_BYTE 2
#define FOUR_BYTE_PTR 3
#define GET_USER_KEY_LOCK 4
#define GET_AUTO_LINE_FEED 5
#define GET_CURSOR_VISIBLE 6
#define GET_SCROLLBAR_WINDOW 7
/***************************************************************************
* *
* TestProbeHandler - handle the client message for test probes *
* *
***************************************************************************/
static void TestProbeHandler(
Widget w,
XtPointer client_data,
XEvent *event,
Boolean *ctd)
{
XClientMessageEvent *cm = (XClientMessageEvent *)event;
DtTermViewWidget tw = (DtTermViewWidget )client_data;
Window win;
Atom prop_name, actual_type;
int prop_type; /* THIS WILL BREAK ON A 16-BIT INT SYSTEM */
int actual_format;
long offset, length;
unsigned long nitems, bytes_left;
unsigned char *data;
typedef union {
char c;
unsigned char uc;
int i;
short s;
char *cp;
} alltype;
alltype fourbyte;
alltype twobyte;
alltype onebyte;
unsigned char *reply;
Arg al[5];
*ctd = True;
if (cm->send_event == False) return;
if (cm->message_type != xa_DTTERM_REMOTE_PROBE_REQUEST) return;
reply = (unsigned char*) malloc(sizeof(unsigned char) * 1024);
/****************
*
* If it's a xa_DTTERM_REMOTE_PROBE_REQUEST, then the data is three 32-bit
* quantities: 0 is the window ID, 1 is the property atom to get off the
* window, and 2 is the number of bytes required to getvalues the requested
* data.
*
****************/
*ctd = False;
win = cm->data.l[0];
prop_name = cm->data.l[1];
prop_type = cm->data.l[2];
offset = 0;
length = 1000L;
if (XGetWindowProperty(XtDisplay(w), win, prop_name, offset, length,
False, AnyPropertyType, &actual_type,&actual_format,
&nitems, &bytes_left, &data) == Success)
{
switch(prop_type)
{
case GET_CURSOR_VISIBLE:
sprintf((char *)reply,"%d", (int )_DtTermPrimGetCursorVisible(tw->termview.term));
break;
case GET_USER_KEY_LOCK:
sprintf((char *)reply,"%d", (int )_DtTermGetUserKeyLock(tw->termview.term));
break;
case GET_AUTO_LINE_FEED:
sprintf((char *)reply,"%d", (int )_DtTermGetAutoLineFeed(tw->termview.term));
break;
case GET_SCROLLBAR_WINDOW:
sprintf((char *)reply, "0x%lx", tw->termview.scrollBar.widget ?
XtWindow(tw->termview.scrollBar.widget) : 0);
break;
case ONE_BYTE:
XtSetArg(al[0], (XtPointer ) data,&onebyte);
if (!strcmp((char *)data, XmNmenuBar) ||
!strcmp((char *)data, DtNscrollBar))
XtGetValues((Widget)tw, al, 1);
else
XtGetValues(tw->termview.term, al, 1);
sprintf((char *)reply,"%d", onebyte.uc);
break;
case TWO_BYTE:
XtSetArg(al[0], (XtPointer ) data,&twobyte);
XtGetValues(tw->termview.term, al, 1);
sprintf((char *)reply,"%d", twobyte.s);
break;
case FOUR_BYTE:
case FOUR_BYTE_PTR:
XtSetArg(al[0], (XtPointer ) data,&fourbyte);
XtGetValues(tw->termview.term, al, 1);
if (prop_type == FOUR_BYTE_PTR)
if (fourbyte.cp) {
sprintf((char *)reply,"%s", fourbyte.cp);
} else {
sprintf((char *)reply,"%s", "<NULL>");
}
else
sprintf((char *)reply,"%d", fourbyte.i);
break;
default:
sprintf((char *)reply,"%s","ERROR");
}
XChangeProperty(XtDisplay(w), win, prop_name, prop_name, 8,
PropModeReplace, reply, strlen((char *)reply));
XSync(XtDisplay(w),False);
}
free(reply);
}
static void
AddMenubarToggle
(
Widget topLevel,
Widget termViewWidget
)
{
Arg al[20];
int ac;
char *menu;
char buffer[BUFSIZ];
/* intern the necessary atoms... */
if (xa_MOTIF_WM_MESSAGES == None) {
/* get the atom value... */
xa_MOTIF_WM_MESSAGES = XInternAtom(XtDisplay(topLevel),
"_MOTIF_WM_MESSAGES", False);
}
if (xa_DTTERM_TOGGLE_MENUBAR == None) {
/* get the atom value... */
xa_DTTERM_TOGGLE_MENUBAR = XInternAtom(XtDisplay(topLevel),
"_DTTERM_TOGGLE_MENUBAR", False);
}
/* add a menubar toggle to the mwm pulldown... */
ac = 0;
menu = GETMESSAGE(NL_SETN_Main,1,"\
Sep f.separator\n\
Toggle\\ Menu\\ Bar f.send_msg %d\
");
(void) sprintf(buffer, menu, xa_DTTERM_TOGGLE_MENUBAR);
(void) XtSetArg(al[ac], XmNmwmMenu, buffer); ac++;
(void) XtSetValues(topLevel, al, ac);
/* add a protocoll handler for MOTIF_WM_MESSAGES... */
if (xa_MOTIF_WM_MESSAGES != None) {
(void) XmAddProtocols(topLevel, xa_MOTIF_WM_MESSAGES,
&xa_DTTERM_TOGGLE_MENUBAR, 1);
(void) XmAddProtocolCallback(topLevel, xa_MOTIF_WM_MESSAGES,
xa_DTTERM_TOGGLE_MENUBAR,
ToggleMenuBar, (XtPointer) termViewWidget);
}
}
static void
CloneCallback(Widget wid, XtPointer client_data, XtPointer call_data)
{
DtTermViewWidget w = (DtTermViewWidget) wid;
DtTermViewCallbackStruct *termCB = (DtTermViewCallbackStruct *) call_data;
Widget parent = XtParent((Widget) w);
Widget shellWidget;
Widget termWidget;
Arg arglist[10];
int i;
/* duplicate the dtterm widget's parent widget...
*/
if (XtIsShell(parent)) {
int argc;
String *argv;
Boolean allowShellResize;
#ifdef COPY_WHEN_CLONING
String geometry;
Dimension width;
Dimension height;
#endif /* COPY_WHEN_CLONING */
char *topShellIconName;
i = 0;
if (XtIsApplicationShell(parent)) {
(void) XtSetArg(arglist[i], XmNargc, &argc); i++;
(void) XtSetArg(arglist[i], XmNargv, &argv); i++;
}
#ifdef COPY_WHEN_CLONING
(void) XtSetArg(arglist[i], XmNgeometry, &geometry); i++;
(void) XtSetArg(arglist[i], XmNwidth, &width); i++;
(void) XtSetArg(arglist[i], XmNheight, &height); i++;
#endif /* COPY_WHEN_CLONING */
(void) XtSetArg(arglist[i], XmNallowShellResize, &allowShellResize);
i++;
(void) XtGetValues(parent, arglist, i);
i = 0;
if (XtIsApplicationShell(parent)) {
(void) XtSetArg(arglist[i], XmNargc, argc); i++;
(void) XtSetArg(arglist[i], XmNargv, argv); i++;
}
#ifdef COPY_WHEN_CLONING
(void) XtSetArg(arglist[i], XmNgeometry, geometry); i++;
(void) XtSetArg(arglist[i], XmNwidth, width); i++;
(void) XtSetArg(arglist[i], XmNheight, height); i++;
#endif /* COPY_WHEN_CLONING */
(void) XtSetArg(arglist[i], XmNallowShellResize, allowShellResize); i++;
/* Set the title (and icon name) for the clone (new) dtterm window
the same as the initial title (and icon name) of the top level
shell dtterm window
*/
(void) XtSetArg(arglist[i], XmNtitle, attrs.title); i++;
if (attrs.icon_name)
topShellIconName = attrs.icon_name;
else if (attrs.dtterm_name)
topShellIconName = attrs.dtterm_name;
else topShellIconName = attrs.title;
(void) XtSetArg(arglist[i], XmNiconName, topShellIconName); i++;
shellWidget = XtAppCreateShell((char *) 0, "Dtterm",
XtClass(parent), XtDisplay((Widget) w), arglist, i);
} else {
i = 0;
(void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
shellWidget = XtAppCreateShell((char *) 0, "Dtterm",
applicationShellWidgetClass, XtDisplay((Widget) w), arglist, i);
}
#ifdef COPY_WHEN_CLONING
termWidget = DtCreateTermView(shellWidget, "dtTermView", termCB->arglist,
termCB->argcount);
#else /* COPY_WHEN_CLONING */
termWidget = DtCreateTermView(shellWidget, "dtTermView", termCB->arglist,
0);
#endif /* COPY_WHEN_CLONING */
/* add a menubar toggle to the mwm pulldown... */
(void) AddMenubarToggle(shellWidget, termWidget);
(void) InstanceCount++;
(void) XtManageChild(termWidget);
/* destroy the widget on child termination... */
(void) XtAddCallback(termWidget, DtNsubprocessTerminationCallback,
DestroyDtTerm, (XtPointer) shellWidget);
(void) XtAddCallback(termWidget, XmNdestroyCallback,
DecrementInstanceCountAndExit, (XtPointer) topLevel);
(void) _DtTermPrimAddDeleteWindowCallback(shellWidget, DestroyDtTerm,
(XtPointer) shellWidget);
(void) XtAddCallback(termWidget, DtNnewCallback,
CloneCallback, (XtPointer) 0);
instance_list = (DtTermViewWidget *)XtRealloc((char *)instance_list,
(sizeof(DtTermViewWidget) * InstanceCount));
instance_list[InstanceCount - 1] = (DtTermViewWidget )termWidget;
(void) XtRealizeWidget(shellWidget);
return;
}
static void
ToggleMenuBar
(
Widget w,
XtPointer client_data,
XtPointer call_data
)
{
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
if (cb->event->xclient.message_type == xa_MOTIF_WM_MESSAGES) {
/* can't use case here, since we are not switching on a pre-defined
* value...
*/
if (cb->event->xclient.data.l[0] == xa_DTTERM_TOGGLE_MENUBAR) {
(void) _DtTermViewMenuToggleMenuBar((Widget) client_data);
}
}
}
#ifdef SUN_TERMINAL_SERVER
Boolean
#else
static void
#endif /* SUN_TERMINAL_SERVER */
CreateInstance
(
Widget topLevelWidget,
char *name,
Arg *arglist,
int argcnt,
Boolean enableCloneCallback
)
{
Widget termViewWidget;
/* bump our session count... */
#ifdef LOG_USAGE
(void) LogBumpSessionCount(1);
#endif /* LOG_USAGE */
termViewWidget = DtCreateTermView(topLevelWidget, name, arglist, argcnt);
/* add a menubar toggle to the mwm pulldown... */
(void) AddMenubarToggle(topLevelWidget, termViewWidget);
#ifdef TERMINAL_SERVER
if (attrs.standAlone || !attrs.serverId) {
#endif /* TERMINAL_SERVER */
(void) InstanceCount++;
#ifdef TERMINAL_SERVER
}
#endif /* TERMINAL_SERVER */
(void) XtManageChild(termViewWidget);
/* destroy the widget on termination... */
(void) XtAddCallback(termViewWidget, DtNsubprocessTerminationCallback,
DestroyDtTerm, (XtPointer) topLevelWidget);
(void) XtAddCallback(termViewWidget, XmNdestroyCallback,
DecrementInstanceCountAndExit, (XtPointer) topLevelWidget);
(void) _DtTermPrimAddDeleteWindowCallback(topLevelWidget, DestroyDtTerm,
(XtPointer) topLevelWidget);
instance_list = (DtTermViewWidget * ) XtRealloc((char *)instance_list, (sizeof(DtTermViewWidget) * InstanceCount));
instance_list[InstanceCount - 1] = (DtTermViewWidget )termViewWidget;
if (enableCloneCallback)
(void) XtAddCallback(termViewWidget, DtNnewCallback,
CloneCallback, (XtPointer) 0);
#ifdef SUN_TERMINAL_SERVER
return(True);
#endif
}
void
AtExitProc(void)
{
static int i = 0;
i++;
#ifdef BBA
_bA_dump();
#endif /* BBA */
}
void
SignalHandler
(
int sig
)
{
DebugF('s', 10, fprintf(stderr, ">>SignalHandler() starting\n"));
_DtTermPrimPtyCleanup();
_DtTermPrimUtmpCleanup();
_DtTermPrimLogFileCleanup();
DebugF('s', 10, fprintf(stderr, ">>SignalHandler() finished\n"));
(void) exit(0);
}
static int signalList[] = {
SIGHUP,
SIGINT,
SIGQUIT,
/* SIGILL, */
/* SIGTRAP, */
/* SIGABRT, */
/* SIGIOT, */
/* SIGEMT, */
/* SIGFPE, */
SIGKILL,
/* SIGBUS, */
/* SIGSEGV, */
/* SIGSYS, */
SIGPIPE,
SIGALRM,
SIGTERM,
SIGUSR1,
SIGUSR2,
/* SIGVTALRM, */
/* SIGPROF, */
/* SIGLOST, */
};
static Boolean
GetBindingsProperty
(
Display *display,
String property,
String *binding
)
{
char *prop = (char *) 0;
Atom actualType;
int actualFormat;
unsigned long numItems;
unsigned long bytesAfter;
(void) XGetWindowProperty(display,
RootWindow(display, 0),
XmInternAtom(display, property, FALSE),
0,
(long) 1000000,
FALSE,
XA_STRING,
&actualType,
&actualFormat,
&numItems,
&bytesAfter,
(unsigned char **) &prop);
if ((actualType != XA_STRING) ||
(actualFormat != 8) ||
(numItems == 0)) {
if (prop) {
XFree(prop);
}
return(False);
} else {
*binding = prop;
return(True);
}
}
#ifndef XmNdefaultVirtualBindings
#define XmNdefaultVirtualBindings "defaultVirtualBindings"
#endif /* XmNdefaultVirtualBindings */
static void
FixOSFBindings
(
Display *display
)
{
Widget w;
Arg al[10];
int ac;
char *origDisplayBindings,*freeOrigBindings=NULL;
char *newDisplayBindings;
char *c1;
char *c2;
char *cHold;
int i1;
char **ignoredKeysymList;
int numIgnoredKeysyms;
/* malloc a copy of the ignoredKeysym string... */
if (attrs.ignoredKeysyms && *attrs.ignoredKeysyms) {
c1 = XtMalloc(strlen(attrs.ignoredKeysyms) + 1);
(void) strcpy(c1, attrs.ignoredKeysyms);
attrs.ignoredKeysyms = c1;
}
/* count the number of keysyms in the list... */
for (c1 = attrs.ignoredKeysyms, numIgnoredKeysyms = 0; c1 && *c1; ) {
numIgnoredKeysyms++;
c1 = strchr(c1, '\n');
if (c1) {
(void) c1++;
}
}
/* malloc space for the array... */
ignoredKeysymList = (char **) XtMalloc((numIgnoredKeysyms + 1) *
sizeof(char *));
/* build the list... */
for (c1 = attrs.ignoredKeysyms, i1 = 0; i1 < numIgnoredKeysyms; i1++) {
ignoredKeysymList[i1] = c1;
c1 = strchr(c1, '\n');
if (c1 && *c1) {
*c1++ = '\0';
}
}
/* null terminate the list... */
ignoredKeysymList[i1] = (char *) 0;
w = XmGetXmDisplay(display);
ac = 0;
(void) XtSetArg(al[ac], XmNdefaultVirtualBindings, &origDisplayBindings);
ac++;
(void) XtGetValues(w, al, ac);
if (!origDisplayBindings) {
GetBindingsProperty(display, "_MOTIF_BINDINGS", &origDisplayBindings);
freeOrigBindings = origDisplayBindings ;
}
if (!origDisplayBindings) {
GetBindingsProperty(display, "_MOTIF_DEFAULT_BINDINGS",
&origDisplayBindings);
freeOrigBindings = origDisplayBindings ;
}
if (!origDisplayBindings) {
XtFree((char *)ignoredKeysymList);
return;
}
DebugF('b', 10, fprintf(stderr,
"FixOSFBindings(): bindings: %s\n", origDisplayBindings));
newDisplayBindings = XtMalloc(strlen(origDisplayBindings) + 1);
c1 = origDisplayBindings;
c2 = newDisplayBindings;
while (*c1) {
/* remember the current position in the new string... */
cHold = c2;
/* copy over everything up to the '\n' or null... */
while (*c1 && (*c1 != '\n')) {
*c2++ = *c1++;
}
/* null terminate the string... */
*c2 = '\0';
/* run through the exclusion list and look for a match... */
for (i1 = 0; i1 < numIgnoredKeysyms; i1++) {
DebugF('b', 10, fprintf(stderr, "!strcmp(\"%s\", \"%s\") = %d\n",
c2 - strlen(ignoredKeysymList[i1]),
ignoredKeysymList[i1],
!strcmp(c2 - strlen(ignoredKeysymList[i1]),
ignoredKeysymList[i1])));
if ((strlen(ignoredKeysymList[i1]) <= (size_t)(c2 - cHold)) &&
!strcmp(c2 - strlen(ignoredKeysymList[i1]),
ignoredKeysymList[i1])) {
/* we hit a match... */
DebugF('b', 10, fprintf(stderr, "match!\n"));
break;
}
}
/* if we hit a match, back up the string... */
if (i1 < numIgnoredKeysyms) {
DebugF('b', 10, fprintf(stderr, "dropping %s\n", cHold));
c2 = cHold;
/* skip over whitespace in the source... */
while (isspace(*c1)) {
c1++;
}
} else {
/* copy over whitespace in the source... */
DebugF('b', 10, fprintf(stderr, "keeping %s\n", cHold));
while (isspace(*c1)) {
*c2++ = *c1++;
}
cHold = c2;
}
}
/* null terminate the string... */
*c2 = '\0';
/* and set this new bindings string... */
ac = 0;
(void) XtSetArg(al[ac], XmNdefaultVirtualBindings, newDisplayBindings);
ac++;
(void) XtSetValues(w, al, ac);
/* changed from XtFree to free as it was allocated with malloc to avoid FMM */
if (freeOrigBindings) free(origDisplayBindings);
XtFree((char *)ignoredKeysymList);
/* and finally, reparse the string... */
_XmVirtKeysInitialize(w);
}
static void
removeWmCommandCallback
(
Widget w,
XtPointer clientData,
XEvent *event,
Boolean *cont
)
{
static Atom xa_WM_STATE = None;
Boolean firstTime = True;
if (firstTime) {
xa_WM_STATE = XInternAtom(XtDisplay(w), "WM_STATE", True);
firstTime = False;
}
if (((XPropertyEvent *) event)->atom == xa_WM_STATE) {
/* blow away the atom... */
(void) XDeleteProperty(XtDisplay(w), XtWindow(w),
XA_WM_COMMAND);
/* we have done our job and don't need to be called again... */
(void) XtRemoveEventHandler(w, (EventMask) XtAllEvents,
True, removeWmCommandCallback, clientData);
}
}
static char *
base_name(
char *name
)
{
char *cp;
cp = strrchr(name, '/');
return(cp ? cp + 1 : name);
}
int
main(int argc, char **argv)
{
Arg arglist[20];
int i;
char *c;
char *c2;
char *saved_arg0;
char **commandToExecute = (char **) 0;
int ptyMasterFd = -1;
struct sigaction sa;
#ifdef SUN_TERMINAL_SERVER
Boolean iAmTheServer = False;
#endif /* SUN_TERMINAL_SERVER */
(void) atexit(AtExitProc);
if (c = getenv("dttermDebugFlags")) {
(void) setDebugFlags(c);
}
if (isDebugSet('T')) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) timeStamp("starting");
}
if (c = getenv("dttermDelayFlags"))
{
if (NULL != c)
{
int delay = atoi(c);
pid_t pid = getpid();
printf("dtterm (%d) sleeping for %d seconds\n", pid, delay);
sleep(delay);
}
}
/* before we do anything, let's set up signal handlers to clean up
* after ourself...
*/
(void) sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = SignalHandler;
/* trap all signals that we want to clean up after... */
for (i = 0; i < (sizeof(signalList) / sizeof(signalList[0])); i++) {
(void) sigaction(signalList[i], &sa, (struct sigaction *) 0);
}
/* ignore SIGHUP... */
sa.sa_handler = SIG_IGN;
(void) sigaction(SIGHUP, &sa, (struct sigaction *) 0);
/*
** set up the environment variables for this client...
*/
#if defined(HPVUE)
#if (OSMINORVERSION > 01)
VuEnvControl(VUE_ENV_SET);
#endif /* (OSMINORVERSION > 01) */
#else
_DtEnvControl(DT_ENV_SET);
#endif /* HPVUE */
/* set up the I18N world... */
(void) XtSetLanguageProc(NULL, NULL, NULL);
if (isDebugSet('T')) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) timeStamp("XtSetLangProc() finished");
}
/* before we initialize Xt, let's save argv and argc... */
savedArgc = argc;
savedArgv = (char **) XtMalloc((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++) {
savedArgv[i] = XtMalloc(strlen(argv[i]) + 1);
(void) strcpy(savedArgv[i], argv[i]);
#ifdef SUN_TERMINAL_SERVER
if ((!strcmp(argv[i], "-sdtserver")) || (!strcmp(argv[i], "-dtserver")))
iAmTheServer = TRUE;
#endif /* SUN_TERMINAL_SERVER */
}
savedArgv[i] = (char *) 0;
#ifdef sun
(void) setsid();
#endif /* sun */
/* before we do anything with the toolkit, let's usurp the constraint
* initialize proc for the XmManager widget class. This will allow us
* to prevent it from performing that awful
* DoMagicBBCompatibilityStuff() on us that steals (among other things)
* our return key. Note that currently, this is all that the
* XmManager widget does for widgets, but if it did more than we
* would loose out on that.
*/
/* initialize Xt and the X world... */
(void) DtTermInitialize();
i = 0;
(void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
topLevel = XtAppInitialize(&appContext,
"Dtterm",
optionDescList,
XtNumber(optionDescList),
&argc,
argv,
fallbackResources,
arglist,
i);
#ifdef SUN_TERMINAL_SERVER
if (iAmTheServer) {
(void) ServerStartSession(topLevel, savedArgc, savedArgv,
attrs.loginShell,
commandToExecute);
}
#endif /* SUN_TERMINAL_SERVER */
/* get application specific resources... */
i = 0;
/* Need to specify base address of the resources. In our case, attrs */
(void) XtGetApplicationResources(topLevel, (XtPointer)&attrs,
applicationResources,
XtNumber(applicationResources),
arglist, i);
/* set all the debug flags... */
(void) setDebugFlags(attrs.debugString);
(void) FixOSFBindings(XtDisplay(topLevel));
/* Add the Save_yourself callback... */
xa_WM_SAVE_YOURSELF = XInternAtom(XtDisplay(topLevel),
"WM_SAVE_YOURSELF", False);
XmAddWMProtocolCallback(topLevel, xa_WM_SAVE_YOURSELF,
(XtCallbackProc)SaveSessionCB, (XtPointer)NULL);
i = 0;
(void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
(void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
topShell = XtAppCreateShell((char *) 0, "Dtterm",
applicationShellWidgetClass, XtDisplay(topLevel), arglist, i);
if (attrs.session != NULL)
RestoringTerms = TRUE;
if (isDebugSet('T')) {
#ifdef BBA
#pragma BBA_IGNORE
#endif /*BBA*/
(void) timeStamp("XtAppInitialize() finished");
}
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
(void) Syntax(argv[0], argv[i]);
exit(1);
}
switch(argv[i][1]) {
case 'S' :
/* slave mode...
*/
/* skip past the '-S'... */
c = argv[i] + 2;
if (c2 = strchr(c, '.')) {
/* skip past the '.'... */
(void) c2++;
} else {
/* skip past the first 2 characters since they are the
* name of the pty...
*/
c2 = c + 2;
}
/* use scanf instead of atoi since it won't change the value
* of ptyMasterFd if the string does not contain a valid
* number...
*/
(void) sscanf(c2, "%d", &ptyMasterFd);
break;
case 'e' :
/* command to exec...
*/
(void) i++;
if (i < argc) {
commandToExecute = &argv[i];
i = argc;
}
break;
case 'h' :
case 'u' :
/* help/usage...
*/
(void) Help(argv[0]);
exit(0);
break;
default :
(void) Syntax(argv[0], argv[i]);
(void) exit(1);
break;
}
}
#ifdef TERMINAL_SERVER
if (attrs.standAlone || !attrs.serverId) {
#endif /* TERMINAL_SERVER */
/* log our startup... */
#ifdef LOG_USAGE
(void) LogStart(0, argc, argv);
#endif /* LOG_USAGE */
i = 0;
if (commandToExecute) {
(void) XtSetArg(arglist[i], DtNsubprocessArgv, commandToExecute);
i++;
}
if (!RestoringTerms || !RestoreSession(topShell, arglist, i)) {
RestoringTerms = False;
if (ptyMasterFd >= 0) {
/* set the workspace for the initial dtterm instance... */
(void) XtSetArg(arglist[i], DtNtermDevice, ptyMasterFd); i++;
(void) XtSetArg(arglist[i], DtNtermDeviceAllocate, False); i++;
(void) XtSetArg(arglist[i], DtNsubprocessExec, False); i++;
(void) CreateInstance(topShell, "dtTermView", arglist, i, False);
}
else {
(void) CreateInstance(topShell, "dtTermView", arglist, i, True);
}
}
/* realize the interface... */
i = 0;
(void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
(void) XtSetValues(topLevel, arglist, i);
(void) XtRealizeWidget(topLevel);
#ifdef SUN_TERMINAL_SERVER
if (iAmTheServer)
FinishToolTalkInit(topLevel);
#endif /* SUN_TERMINAL_SERVER */
/* Set title to the command to execute (if any)
*/
if (commandToExecute && !attrs.title) {
attrs.title = base_name (commandToExecute[0]);
}
/* Else set title to default ("Terminal")
*/
if (!attrs.title) {
title = XtMalloc(strlen(GETMESSAGE(NL_SETN_Main, 3, "Terminal")) + 1);
(void) strcpy(title, GETMESSAGE(NL_SETN_Main, 3, "Terminal"));
attrs.title = title;
}
/* realize the interface... */
i = 0;
(void) XtSetArg(arglist[i], XmNtitle, attrs.title); i++;
if ((!attrs.icon_name) && (!attrs.dtterm_name)) {
(void) XtSetArg(arglist[i], XmNiconName, attrs.title); i++;
}
(void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
(void) XtSetArg(arglist[i], XmNgeometry, NULL); i++;
(void) XtSetValues(topShell, arglist, i);
(void) XtRealizeWidget(topShell);
if (RestoringTerms != True) {
/* use the wm command to pass the -xrm resource to the wm... */
(void) XSetCommand(XtDisplay(topShell), XtWindow(topShell),
savedArgv, savedArgc);
/* add a callback to remove it after it has been seen... */
(void) XtAddEventHandler(topShell, (EventMask) PropertyChangeMask,
False, removeWmCommandCallback, (XtPointer) 0);
}
(void) XtSetArg(arglist[0], XmNmappedWhenManaged, True);
(void) XtSetValues(topShell, arglist, 1);
XtMapWidget(topShell);
RegisterTestProbe(topShell,instance_list[0]);
if (ptyMasterFd >= 0) {
/* write out the window id... */
char buffer[BUFSIZ];
(void) sprintf(buffer, "%lx\n", XtWindow(topLevel));
(void) write(ptyMasterFd, buffer, strlen(buffer));
}
#ifdef sun
sunSetupIA(topLevel);
#endif /* sun */
#ifdef TERMINAL_SERVER
} else {
if (ptyMasterFd >= 0) {
(void) fprintf(stderr,
GETMESSAGE(NL_SETN_Main,2, "%s: the -S option cannot be used with the -server or -serverid options\n"),
argv[0]);
(void) exit(1);
}
i = 0;
(void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
(void) XtSetValues(topLevel, arglist, i);
(void) XtRealizeWidget(topLevel);
(void) ServerStartSession(topLevel, savedArgc, savedArgv,
attrs.server, attrs.serverId, attrs.exitOnLastClose,
attrs.block, attrs.loginShell,
commandToExecute);
}
#endif /* TERMINAL_SERVER */
/* and hand off to Xt... */
(void) XtAppMainLoop(appContext);
}
/************************************************************************
*
* SaveSessionCB
*
************************************************************************/
/* ARGSUSED */
static void
SaveSessionCB(
Widget w, /* widget id */
caddr_t client_data, /* data from application */
caddr_t call_data ) /* data from widget class */
{
char *longpath, *fileName;
char bufr[1024];
int fd;
char *xa_CommandStr[1024];
int i,j;
if(!XtIsShell(w))
w = XtParent(w);
DtSessionSavePath(w, &longpath, &fileName);
/* Create the session file */
if ((fd = creat (longpath, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP)) == -1)
{
return;
}
sprintf(bufr, "*dtterm.numClonedTerms: %d\n", InstanceCount);
write (fd, bufr, strlen(bufr));
for(i = 0; i < InstanceCount; i++)
SaveTerm(instance_list[i], i, fd);
sprintf(bufr,
"*dtterm.sessionFileVersionId: dttermSessionFileVersion.1.0.0\n");
write (fd, bufr, strlen(bufr));
close(fd);
i = 0;
xa_CommandStr[i] = savedArgv[0]; i++;
xa_CommandStr[i] = "-session"; i++;
xa_CommandStr[i] = fileName; i++;
/****************
*
* Now restore the command line minus the old session parameter
*
****************/
for (j = 1; j < savedArgc; j++)
{
if (strcmp(savedArgv[j], "-session") == 0)
{
j++;
continue;
}
else
{
xa_CommandStr[i] = savedArgv[j];
i++;
}
}
XSetCommand(XtDisplay(topLevel),
XtWindow(topLevel), xa_CommandStr, i);
XtFree ((char *)fileName);
}
static void
SaveTerm(
DtTermViewWidget dtvw,
int cloneNum,
int fd)
{
char *bufr = malloc(1024);
Position x,y;
Dimension width, height;
Atom *pWsPresence;
unsigned long numInfo;
unsigned char charCursorStyle;
int blinkRate;
Boolean jumpScroll;
Boolean marginBell;
int nMarginBell;
Boolean visualBell;
Boolean reverseVideo;
Boolean cursorMode;
Boolean keypadMode;
Boolean autoWrap;
Boolean reverseWrap;
Boolean c132;
Boolean lockState;
Boolean autoLineFeed;
Boolean menuBar;
Boolean scrollBar;
short rows;
short columns;
char *cwd;
static char *defaultCwd = (char *) 0;
Arg al[30];
int ac;
char buffer[BUFSIZ];
DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
static Boolean firstTime = True;
static Atom xa_WM_STATE = None;
struct _wmStateStruct {
CARD32 state;
Window icon;
} *prop;
Atom actualType;
int actualFormat;
unsigned long nItems;
unsigned long bytesAfter;
XmVendorShellExtObject vendorExt;
XmWidgetExtData extData;
x = XtX(XtParent(dtvw));
y = XtY(XtParent(dtvw));
/*
* Modify x & y to take into account window mgr frames
* This is pretty bogus, but I don't know a better way to do it.
*/
extData = _XmGetWidgetExtData(XtParent(dtvw), XmSHELL_EXTENSION);
vendorExt = (XmVendorShellExtObject)extData->widget;
x -= vendorExt->vendor.xOffset;
y -= vendorExt->vendor.yOffset;
width = XtWidth(XtParent(dtvw));
height = XtHeight(XtParent(dtvw));
sprintf(bufr, "*dtterm_%d.x: %d\n", cloneNum, x);
sprintf(bufr, "%s*dtterm_%d.y: %d\n", bufr, cloneNum, y);
sprintf(bufr, "%s*dtterm_%d.width: %d\n", bufr, cloneNum, width);
sprintf(bufr, "%s*dtterm_%d.height: %d\n", bufr, cloneNum, height);
/* Write out iconic state...
*/
if (firstTime) {
xa_WM_STATE = XInternAtom(XtDisplay(dtvw), "WM_STATE", True);
firstTime = False;
}
if (xa_WM_STATE && (Success == XGetWindowProperty(
XtDisplay(dtvw),
XtWindow(XtParent(dtvw)),
xa_WM_STATE,
0L,
(sizeof(struct _wmStateStruct) + 3) / 4,
False,
AnyPropertyType,
&actualType,
&actualFormat,
&nItems,
&bytesAfter,
(unsigned char **) &prop))) {
if (prop->state == IconicState) {
sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
"True");
} else {
sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
"False");
}
}
if(DtWsmGetWorkspacesOccupied(XtDisplay(dtvw),
XtWindow(XtParent(dtvw)), &pWsPresence,
&numInfo) == Success)
{
int i;
sprintf(bufr, "%s*dtterm_%d.workspaceList: ", bufr, cloneNum);
for(i = 0; i < numInfo; i++)
{
char *name = XGetAtomName(XtDisplay(dtvw),
pWsPresence[i]);
sprintf(bufr, "%s %s", bufr, name);
XtFree(name);
}
sprintf(bufr, "%s\n", bufr);
XtFree((char *)pWsPresence);
}
write (fd, bufr, strlen(bufr));
sprintf(bufr, "*dtterm_%d.userFontListIndex: %d\n", cloneNum,
_DtTermViewGetUserFontListIndex((Widget )dtvw));
write (fd, bufr, strlen(bufr));
/* get the current widget values... */
ac = 0;
(void) XtSetArg(al[ac], DtNmenuBar, &menuBar); ac++;
(void) XtSetArg(al[ac], DtNscrollBar, &scrollBar); ac++;
(void) XtGetValues((Widget)dtvw, al, ac);
ac = 0;
(void) XtSetArg(al[ac], DtNrows, &rows); ac++;
(void) XtSetArg(al[ac], DtNcolumns, &columns); ac++;
(void) XtSetArg(al[ac], DtNblinkRate, &blinkRate); ac++;
(void) XtSetArg(al[ac], DtNcharCursorStyle, &charCursorStyle); ac++;
(void) XtSetArg(al[ac], DtNblinkRate, &blinkRate); ac++;
(void) XtSetArg(al[ac], DtNjumpScroll, &jumpScroll); ac++;
(void) XtSetArg(al[ac], DtNmarginBell, &marginBell); ac++;
(void) XtSetArg(al[ac], DtNnMarginBell, &nMarginBell); ac++;
(void) XtSetArg(al[ac], DtNvisualBell, &visualBell); ac++;
(void) XtSetArg(al[ac], DtNreverseVideo, &reverseVideo); ac++;
(void) XtSetArg(al[ac], DtNappCursorDefault, &cursorMode); ac++;
(void) XtSetArg(al[ac], DtNappKeypadDefault, &keypadMode); ac++;
(void) XtSetArg(al[ac], DtNautoWrap, &autoWrap); ac++;
(void) XtSetArg(al[ac], DtNreverseWrap, &reverseWrap); ac++;
(void) XtSetArg(al[ac], DtNc132, &c132); ac++;
(void) XtGetValues((Widget)dtw, al, ac);
lockState = _DtTermGetUserKeyLock((Widget) dtw);
autoLineFeed = _DtTermGetAutoLineFeed((Widget) dtw);
/* get the current working directory if it was saved... */
cwd = _DtTermGetCurrentWorkingDirectory((Widget) dtw);
if (!cwd || !*cwd) {
/* no saved cwd, use the one we were started from... */
if (!defaultCwd) {
/* first time through, use getcwd() to get it... */
if (getcwd(buffer, sizeof(buffer))) {
defaultCwd = XtMalloc(strlen(buffer) + 1);
(void) strcpy(defaultCwd, buffer);
}
}
cwd = defaultCwd;
}
(void) sprintf(bufr, "*dtterm_%d*rows: %d\n", cloneNum, rows);
(void) write(fd, bufr, strlen(bufr));
(void) sprintf(bufr, "*dtterm_%d*columns: %d\n", cloneNum, columns);
(void) write(fd, bufr, strlen(bufr));
if(menuBar == False)
{
sprintf(bufr, "*dtterm_%d*menuBar: False\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(scrollBar == False)
{
sprintf(bufr, "*dtterm_%d*scrollBar: False\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if (_DtTermPrimGetCursorVisible((Widget )dtw))
{
if (charCursorStyle == DtTERM_CHAR_CURSOR_BAR)
sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BAR\n", cloneNum);
else
sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BOX\n", cloneNum);
}
else
sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_INVISIBLE\n", cloneNum);
write (fd, bufr, strlen(bufr));
sprintf(bufr, "*dtterm_%d*blinkRate: %d\n", cloneNum,blinkRate);
write (fd, bufr, strlen(bufr));
if(jumpScroll == False)
{
sprintf(bufr, "*dtterm_%d*jumpScroll: False\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(marginBell == True)
{
sprintf(bufr, "*dtterm_%d*marginBell: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
sprintf(bufr, "*dtterm_%d*nMarginBell: %d\n", cloneNum,nMarginBell);
write (fd, bufr, strlen(bufr));
}
if(visualBell == True)
{
sprintf(bufr, "*dtterm_%d*visualBell: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(reverseVideo == True)
{
sprintf(bufr, "*dtterm_%d*reverseVideo: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(cursorMode == True)
{
sprintf(bufr, "*dtterm_%d*appCursorDefault: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(keypadMode == True)
{
sprintf(bufr, "*dtterm_%d*appKeypadDefault: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(autoWrap == False)
{
sprintf(bufr, "*dtterm_%d*autoWrap: False\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(reverseWrap == True)
{
sprintf(bufr, "*dtterm_%d*reverseWrap: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(c132 == True)
{
sprintf(bufr, "*dtterm_%d*c132: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
}
if(lockState == False)
sprintf(bufr, "*dtterm_%d*userKeyLock: False\n", cloneNum);
else
sprintf(bufr, "*dtterm_%d*userKeyLock: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
if(autoLineFeed == False)
sprintf(bufr, "*dtterm_%d*autoLineFeed: False\n", cloneNum);
else
sprintf(bufr, "*dtterm_%d*autoLineFeed: True\n", cloneNum);
write (fd, bufr, strlen(bufr));
if (cwd && *cwd) {
(void) sprintf(bufr, "*dtterm_%d*currentWorkingDirectory: %s\n",
cloneNum, cwd);
(void) write(fd, bufr, strlen(bufr));
}
free(bufr);
}
/***********************************************************************
*
* RestoreSession - returns True for success, False for failure...
*
***********************************************************************/
static Boolean
RestoreSession(
Widget topDog,
Arg *passedAl,
int passedAc)
{
char *fileName = attrs.session;
char *path;
XrmDatabase db;
char *tmpStr;
XrmName xrm_name[5];
XrmRepresentation rep_type;
XrmValue value;
Widget ShellWidget;
int numToRestore, i, j;
Arg al[30];
int ac;
if(DtSessionRestorePath(topLevel, &path, fileName) == False)
path = fileName;
/* Open the file as a resource database */
if ((db = XrmGetFileDatabase (path)) == NULL)
{
/* if we got a bogus filename, bail out... */
return(False);
}
xrm_name[0] = XrmStringToQuark ("dtterm");
xrm_name[1] = XrmStringToQuark ("numClonedTerms");
xrm_name[2] = 0;
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
/* if we got nothing back, bail out... */
if (!value.addr || !*((char *) value.addr)) {
return(False);
}
numToRestore = atoi((char *)value.addr);
/* if we don't have at least one to restore, bail out... */
if (numToRestore < 1) {
return(False);
}
ShellWidget = topDog;
for (j = 0; j < numToRestore; j++)
{
/* use the passed arglist as a starting point... */
for (ac = 0; ac < passedAc; ac++) {
al[ac].value = passedAl[ac].value;
al[ac].name = passedAl[ac].name;
}
(void) CreateInstance(ShellWidget, "dtTermView", al, ac, True);
RestoreTerm(ShellWidget, instance_list[j], j, db);
(void) XtSetArg(al[0], XmNmappedWhenManaged, True);
(void) XtSetValues(ShellWidget, al, 1);
/* mapping the shell widget here is redundant, and it turns out
* was responsible for CMVC7216: broken restoring of
* iconified instances in multiple workspaces...
*/
ac = 0;
(void) XtSetArg(al[ac], XmNallowShellResize, True); ac++;
(void) XtSetArg(al[ac], XmNmappedWhenManaged, True); ac++;
ShellWidget = XtAppCreateShell((char *) 0, "Dtterm",
applicationShellWidgetClass, XtDisplay(topDog), al, ac);
}
/* success, return True... */
return(True);
}
static void
RestoreTerm(
Widget shellWidget,
DtTermViewWidget dtvw,
int termNum,
XrmDatabase db)
{
char buf[1024];
XrmName xrm_name[5];
XrmRepresentation rep_type;
XrmValue value;
DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
Position x,y;
Dimension width, height;
char *ws_list;
unsigned char charCursorStyle;
int blinkRate;
Boolean jumpScroll;
Boolean marginBell;
int nMarginBell;
Boolean visualBell;
Boolean reverseVideo;
Boolean cursorMode;
Boolean keypadMode;
Boolean autoWrap;
Boolean reverseWrap;
Boolean c132;
Boolean lockState;
Boolean autoLineFeed;
Boolean menuBar;
Boolean scrollBar;
char *cwd;
Arg al[30];
int ac;
int rows = 0;
int columns = 0;
sprintf(buf, "dtterm_%d", termNum);
xrm_name[0] = XrmStringToQuark(buf);
xrm_name[2] = 0;
/* Pass 1, before widget realization...
*/
/* get x position */
xrm_name[1] = XrmStringToQuark ("x");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
x = atoi((char *)value.addr);
/* get y position */
xrm_name [1] = XrmStringToQuark ("y");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
y = atoi((char *)value.addr);
/* get width */
xrm_name [1] = XrmStringToQuark ("width");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
width = atoi((char *)value.addr);
/* get height */
xrm_name [1] = XrmStringToQuark ("height");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
height = atoi((char *)value.addr);
/****************
*
* First the shell resources...
*
****************/
ac = 0;
(void) XtSetArg(al[ac], XmNx, x); ac++;
(void) XtSetArg(al[ac], XmNy, y); ac++;
(void) XtSetArg(al[ac], XmNwidth, width); ac++;
(void) XtSetArg(al[ac], XmNheight, height); ac++;
/* get iconify... */
xrm_name[1] = XrmStringToQuark("iconify");
if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
if (!strcmp((char *)value.addr, "True")) {
(void) XtSetArg(al[ac], XmNinitialState, IconicState); ac++;
} else {
(void) XtSetArg(al[ac], XmNinitialState, NormalState); ac++;
}
} else {
(void) XtSetArg(al[ac], XmNinitialState, NormalState);
}
(void) XtSetValues(XtParent((Widget)dtvw), al, ac);
/****************
*
* Now the TermView resources...
*
****************/
ac = 0;
xrm_name[1] = XrmStringToQuark ("rows");
if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
rows = atoi((char *)value.addr);
(void) XtSetArg(al[ac], DtNrows, rows); ac++;
}
xrm_name[1] = XrmStringToQuark ("columns");
if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
columns = atoi((char *)value.addr);
(void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
}
xrm_name[1] = XrmStringToQuark ("menuBar");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], XmNmenuBar, False); ac++;}
xrm_name[1] = XrmStringToQuark ("scrollBar");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNscrollBar, False); ac++;}
xrm_name[1] = XrmStringToQuark ("userFontListIndex");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True) {
_DtTermViewSetUserFontListIndex((Widget )dtvw, atol(value.addr));
}
(void) XtSetValues((Widget)dtvw, al, ac);
/****************
*
* And finally the termprim stuff...
*
****************/
ac = 0;
if(rows > 0) {
(void) XtSetArg(al[ac], DtNrows, rows); ac++;
}
if(columns > 0) {
(void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
}
xrm_name[1] = XrmStringToQuark ("charCursorStyle");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
if (!strcmp(value.addr, "CHARCURSOR_INVISIBLE"))
_DtTermPrimSetCursorVisible((Widget )dtw, False);
else
{
if (!strcmp(value.addr, "CHARCURSOR_BAR"))
(void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BAR);
else
(void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BOX);
ac++;
}
xrm_name [1] = XrmStringToQuark ("blinkRate");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
blinkRate = atoi((char *)value.addr);
(void) XtSetArg(al[ac], DtNblinkRate, blinkRate); ac++;
xrm_name[1] = XrmStringToQuark ("jumpScroll");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNjumpScroll, False); ac++;}
xrm_name[1] = XrmStringToQuark ("marginBell");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{
(void) XtSetArg(al[ac], DtNmarginBell, True); ac++;
xrm_name [1] = XrmStringToQuark ("nMarginBell");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
nMarginBell = atoi((char *)value.addr);
(void) XtSetArg(al[ac], DtNnMarginBell, nMarginBell);ac++;
}
xrm_name[1] = XrmStringToQuark ("visualBell");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNvisualBell, True); ac++;}
xrm_name[1] = XrmStringToQuark ("reverseVideo");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNreverseVideo, True); ac++;}
xrm_name[1] = XrmStringToQuark ("appCursorDefault");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNappCursorDefault, True); ac++;}
xrm_name[1] = XrmStringToQuark ("appKeypadDefault");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNappKeypadDefault, True); ac++;}
xrm_name[1] = XrmStringToQuark ("autoWrap");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNautoWrap, False); ac++;}
xrm_name[1] = XrmStringToQuark ("reverseWrap");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNreverseWrap, True); ac++;}
xrm_name[1] = XrmStringToQuark ("c132");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNc132, True); ac++;}
xrm_name[1] = XrmStringToQuark ("reverseVideo");
if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
{(void) XtSetArg(al[ac], DtNreverseVideo, True); ac++;}
xrm_name[1] = XrmStringToQuark ("userKeyLock");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
if (!strcmp(value.addr, "True"))
_DtTermSetUserKeyLock((Widget) dtw, True);
else
_DtTermSetUserKeyLock((Widget) dtw, False);
xrm_name[1] = XrmStringToQuark ("autoLineFeed");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
if (!strcmp(value.addr, "True"))
_DtTermSetAutoLineFeed((Widget) dtw, True);
else
_DtTermSetAutoLineFeed((Widget) dtw, False);
(void) XtSetValues((Widget)dtw, al, ac);
xrm_name[1] = XrmStringToQuark ("currentWorkingDirectory");
XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
if (value.addr && *value.addr) {
_DtTermSetCurrentWorkingDirectory((Widget) dtw, value.addr);
}
/* realize the interface...
*/
(void) XtRealizeWidget(shellWidget);
/* Pass 2, after widget realization...
*/
/* get workspace list */
xrm_name[1] = XrmStringToQuark("workspaceList");
XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value);
SetWorkSpaceHints( XtParent((Widget)dtvw),(char *) value.addr);
}
static void
SetWorkSpaceHints
(
Widget shell,
char *workspaces
)
{
char * ptr;
Atom * workspace_atoms = NULL;
int num_workspaces=0;
Atom thisWsAtom;
if (workspaces) {
do {
ptr = strchr (workspaces, ' ');
if (ptr != NULL)
*ptr = 0;
thisWsAtom = None;
/* if we haven't hit a match, try interning the atom... */
if (thisWsAtom == None) {
thisWsAtom = XmInternAtom (XtDisplay(shell), workspaces, True);
}
if (thisWsAtom != None) {
workspace_atoms = (Atom *) XtRealloc ((char *)workspace_atoms,
sizeof (Atom) * (num_workspaces + 1));
workspace_atoms[num_workspaces] = thisWsAtom;
num_workspaces++;
}
if (ptr != NULL) {
*ptr = ' ';
workspaces = ptr + 1;
}
} while (ptr != NULL);
if (num_workspaces > 0) {
DtWsmSetWorkspacesOccupied(XtDisplay(shell), XtWindow (shell),
workspace_atoms, num_workspaces);
}
XtFree ((char *) workspace_atoms);
workspace_atoms = NULL;
}
}