1749 lines
46 KiB
C
1749 lines
46 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
|
|
*/
|
|
/* @(#)$TOG: win.c /main/9 1997/06/18 17:33:01 samborn $ */
|
|
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Protocols.h>
|
|
#include <Xm/MwmUtil.h>
|
|
|
|
#include <Xm/Form.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/LabelG.h>
|
|
#include <Xm/SeparatoG.h>
|
|
#include <Xm/DialogS.h>
|
|
#include <Xm/MessageB.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/Text.h>
|
|
|
|
#include "xims.h"
|
|
#include <limits.h>
|
|
|
|
|
|
Display *Dpy = (Display *) 0;
|
|
Widget TopW = (Widget) 0;
|
|
XtAppContext appC = (XtAppContext) 0;
|
|
|
|
static Widget SelW = (Widget) 0;
|
|
static Widget ModeW = (Widget) 0;
|
|
static Widget MsgW = (Widget) 0;
|
|
static Widget HelpW = (Widget) 0;
|
|
static Widget HostW = (Widget) 0;
|
|
static Widget HostText = (Widget) 0;
|
|
|
|
static Widget SelRC = (Widget) 0;
|
|
static Widget HostRC = (Widget) 0;
|
|
|
|
static Widget FocusW = (Widget) 0;
|
|
|
|
static int (*defaultErrorHandler)() = 0;
|
|
|
|
|
|
/* application resource */
|
|
typedef struct {
|
|
String selectionHelpMsg;
|
|
String modeHelpMsg;
|
|
String windowLocation;
|
|
} AppResRec, *AppResP;
|
|
|
|
static AppResRec appres;
|
|
|
|
static XtResource app_resources[] = {
|
|
{ "selectionHelpMsg", "SelectionHelpMsg", XtRString, sizeof(String),
|
|
XtOffset(AppResP, selectionHelpMsg), XtRString, (XtPointer)NULL },
|
|
{ "modeHelpMsg", "ModeHelpMsg", XtRString, sizeof(String),
|
|
XtOffset(AppResP, modeHelpMsg), XtRString, (XtPointer)NULL },
|
|
{ "windowLocation", "WindowLocation", XtRString, sizeof(String),
|
|
XtOffset(AppResP, windowLocation), XtRString, (XtPointer)NULL },
|
|
};
|
|
|
|
static XrmOptionDescRec options[] = {
|
|
{ "-geometry", "*XmDialogShell.geometry", XrmoptionSepArg, (XPointer) NULL },
|
|
{ "-fn", "*fontList", XrmoptionSepArg, (XPointer) NULL },
|
|
{ "-font", "*fontList", XrmoptionSepArg, (XPointer) NULL },
|
|
|
|
};
|
|
|
|
static char *fallbacks[] = {
|
|
NULL
|
|
};
|
|
|
|
|
|
#define OK_BTN 0
|
|
#define CANCEL_BTN 1
|
|
#define CLEAR_BTN 2
|
|
#define HOST_BTN 3
|
|
#define HELP_BTN 4
|
|
|
|
#ifdef DEBUG2
|
|
#define WIN_FUNC (MWM_FUNC_RESIZE | MWM_FUNC_MOVE)
|
|
#define WIN_DECR (MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_RESIZEH)
|
|
#else
|
|
#define WIN_FUNC (MWM_FUNC_MOVE)
|
|
#define WIN_DECR (MWM_DECOR_BORDER)
|
|
#endif
|
|
|
|
#define MSGWIN_FUNC 0
|
|
#define MSGWIN_DECR (MWM_DECOR_BORDER)
|
|
/* #define DIALOG_STYLE XmDIALOG_MODELESS */
|
|
#define DIALOG_STYLE XmDIALOG_PRIMARY_APPLICATION_MODAL
|
|
|
|
#define MAX_HOSTNAME_LEN 63 /* limitation of ARPA host name */
|
|
#define TEXT_COLUMNS (MAX_HOSTNAME_LEN / 4)
|
|
|
|
/* beep */
|
|
#ifdef DEBUG
|
|
#define Beep() XBell(Dpy, 0); DPR(("Beep!\n"))
|
|
#else
|
|
#define Beep() XBell(Dpy, 0)
|
|
#endif /* DEBUG */
|
|
|
|
|
|
/* local functions */
|
|
/* window env */
|
|
static int ignoreBadWindow(/* dpy, error */);
|
|
static void finish_window(/* w, end_window */);
|
|
static int own_main_atom(/* win */);
|
|
static int disown_main_atom(/* win */);
|
|
/* selection window */
|
|
static void free_ims_list(/* list */);
|
|
static void clear_selection_var(/* */);
|
|
static void finish_selection_window(/* end_window */);
|
|
static void done_cb(/* w, client_data, call_data */);
|
|
static void select_cb(/* w, client_data, call_data */);
|
|
static void host_btn_cb(/* w, client_data, call_data */);
|
|
static void help_cb(/* w, client_data, call_data */);
|
|
static int create_selection_window(/* */);
|
|
static int change_host(/* new_host, host_type */);
|
|
static void add_btn_trans(/* btn */);
|
|
static void change_ims_list(/* last_ims_name, init_idx */);
|
|
static void set_host_label(/* host_type, hostname */);
|
|
static void add_cmd_btn(/* parent_rc, cb_ok, cb_clear, cb_cancel, cb_host, cb_help */);
|
|
/* host window */
|
|
static void start_host_window(/* cur_host */);
|
|
static void finish_host_window(/* */);
|
|
static void host_done_cb(/* w, client_data, call_data */);
|
|
static void host_clear_cb(/* w, client_data, call_data */);
|
|
static void host_done_action(/* w, ev, args, num_args */);
|
|
static void create_host_window(/* cur_host */);
|
|
/* mode window */
|
|
static void finish_mode_window(/* end_window */);
|
|
static void mode_done_cb(/* w, client_data, call_data */);
|
|
static void mode_cb(/* w, client_data, call_data */);
|
|
static void mode_help_cb(/* w, client_data, call_data */);
|
|
static int create_mode_window(/* cur_mode */);
|
|
/* help window */
|
|
static void help_ok(/* w, client_data, call_data */);
|
|
static void create_help(/* */);
|
|
/* msg window */
|
|
static void dialog_resp_cb(/* w, client_data, call_data */);
|
|
static int wait_confirmation(/* w */);
|
|
/* locate window */
|
|
static int window_location(/* loc_str */);
|
|
static void locate_window(/* w */);
|
|
/* cursor */
|
|
static void set_cursor(/* w, is_wait */);
|
|
/* timer */
|
|
static void xt_timer_cb(/* client_data, timer_id */);
|
|
|
|
|
|
/* ******** window env ******** */
|
|
|
|
int open_display(void)
|
|
{
|
|
if (Dpy) return NoError; /* already done */
|
|
|
|
Dpy = XOpenDisplay(Opt.DisplayName);
|
|
if (!Dpy) {
|
|
DPR(("%s: cannot open display \"%s\"\n",
|
|
ProgramName, XDisplayName(Opt.DisplayName)));
|
|
return ErrOpenDpy;
|
|
}
|
|
return NoError;
|
|
}
|
|
|
|
void close_display(void)
|
|
{
|
|
if (TopW) return; /* Xt not finished */
|
|
|
|
if (Dpy) {
|
|
XCloseDisplay(Dpy);
|
|
Dpy = (Display *) 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
int window_env_ok(void)
|
|
{
|
|
return winEnv.status != WIN_ST_NONE ? True : False;
|
|
}
|
|
|
|
int init_window_env(void)
|
|
{
|
|
enum { XA_DTIMS_ATOM_MAIN, XA_DTIMS_ATOM_STATUS, XA_DTIMS_ATOM_DATA,
|
|
NUM_ATOMS };
|
|
static char *atom_names[] = {
|
|
DTIMS_ATOM_MAIN, DTIMS_ATOM_STATUS, DTIMS_ATOM_DATA };
|
|
|
|
Display *dpy = (Display *) 0;
|
|
Widget topW = (Widget) 0;
|
|
XtAppContext app = (XtAppContext) 0;
|
|
int ret = NoError;
|
|
Atom atoms[XtNumber(atom_names)];
|
|
|
|
if (winEnv.status != WIN_ST_NONE) return NoError;
|
|
|
|
/* disable XIM on my own XmText* */
|
|
putenv("XMODIFIERS=@im=_XIMP_None"); /* putenv("XMODIFIERS=@im=none"); */
|
|
XtSetLanguageProc(NULL, NULL, NULL);
|
|
|
|
if (!Dpy) {
|
|
ret = open_display();
|
|
if (ret != NoError)
|
|
return ret;
|
|
}
|
|
|
|
if (!(OpFlag & FLAG_NORESOURCE) && isXsession()) {
|
|
if (open_display() == NoError) { /* set RESOURCE_MANAGER */
|
|
load_resources();
|
|
}
|
|
}
|
|
if (Dpy) close_display();
|
|
|
|
topW = XtAppInitialize(&app, DTIMS_CLASS,
|
|
options, XtNumber(options),
|
|
&Wargc, Wargv, fallbacks, (ArgList) NULL, (Cardinal) 0);
|
|
|
|
dpy = XtDisplay(topW);
|
|
XtSetMappedWhenManaged(topW, False);
|
|
XtRealizeWidget(topW);
|
|
|
|
/* set my error handler */
|
|
defaultErrorHandler = XSetErrorHandler(ignoreBadWindow);
|
|
|
|
XtGetApplicationResources(topW, &appres,
|
|
app_resources, XtNumber(app_resources),
|
|
NULL, 0);
|
|
|
|
#if 0
|
|
/* handle system Menu's "close" */
|
|
XmAddWMProtocolCallback(topW,
|
|
XmInternAtom(dpy, "WM_DELETE_WINDOW", True),
|
|
(XtCallbackProc)end_window_env, (XtPointer)0);
|
|
#endif
|
|
|
|
Dpy = dpy; TopW = topW; appC = app; /* @@@ */
|
|
|
|
XInternAtoms(dpy, atom_names, XtNumber(atom_names), False, atoms);
|
|
|
|
winEnv.Dpy = dpy;
|
|
winEnv.TopW = topW;
|
|
winEnv.appC = app;
|
|
winEnv.atom_main = atoms[XA_DTIMS_ATOM_MAIN];
|
|
winEnv.atom_status = atoms[XA_DTIMS_ATOM_STATUS];
|
|
winEnv.atom_data = atoms[XA_DTIMS_ATOM_DATA];
|
|
winEnv.atom_owner = XGetSelectionOwner(dpy, winEnv.atom_main);
|
|
winEnv.status = WIN_ST_INIT;
|
|
|
|
clear_cmd_property(XtWindow(topW));
|
|
|
|
if (winEnv.atom_main == None)
|
|
return ErrOpenDpy;
|
|
|
|
if ((OpMode == MODE_START || OpMode == MODE_LISTNAME)
|
|
&& !(OpFlag & FLAG_REMOTERUN)) {
|
|
if (own_main_atom(XtWindow(TopW)) != True) {
|
|
DPR(("another program is running on the display '%s'\n",
|
|
XDisplayString(Dpy)));
|
|
return ErrAnotherProg;
|
|
}
|
|
}
|
|
|
|
return NoError;
|
|
}
|
|
|
|
void end_window_env(void)
|
|
{
|
|
if (TopW) {
|
|
disown_main_atom(XtWindow(TopW));
|
|
XSetErrorHandler(defaultErrorHandler);
|
|
|
|
/* XtUnmapWidget(TopW); */
|
|
XtDestroyWidget(TopW);
|
|
XtDestroyApplicationContext(appC);
|
|
} else if (Dpy)
|
|
close_display();
|
|
|
|
TopW = (Widget) 0;
|
|
appC = (XtAppContext) 0;
|
|
Dpy = (Display *) 0;
|
|
|
|
ximsMain();
|
|
|
|
/* return; */
|
|
}
|
|
|
|
/* clear WM_COMMAND property */
|
|
int clear_cmd_property(Window win)
|
|
{
|
|
int ret, ac = 0;
|
|
int clear_ok = False;
|
|
char **av = NULL;
|
|
|
|
/* if (!Dpy || !win) return False; */
|
|
|
|
ret = XGetCommand(Dpy, win, &av, &ac);
|
|
if (ret && ac > 0) {
|
|
XFreeStringList(av);
|
|
XSetCommand(Dpy, win, 0, 0);
|
|
XSync(Dpy, False);
|
|
clear_ok = True;
|
|
DPR2(("\tWM_COMMAND cleared on %#x\n", win));
|
|
}
|
|
|
|
return clear_ok;
|
|
}
|
|
|
|
static int ignoreBadWindow(Display *dpy, XErrorEvent *error)
|
|
{
|
|
if (error->error_code == BadWindow || error->error_code == BadDrawable) {
|
|
return 0;
|
|
} else { /* invoke default error handler */
|
|
return (*defaultErrorHandler)(dpy, error);
|
|
}
|
|
}
|
|
|
|
#ifdef unused
|
|
static void finish_window(Widget *w, int end_window)
|
|
{
|
|
if (*w) {
|
|
XtUnmapWidget(*w);
|
|
XtDestroyWidget(*w);
|
|
*w = (Widget) 0;
|
|
}
|
|
|
|
if (end_window)
|
|
end_window_env();
|
|
|
|
return;
|
|
}
|
|
#endif /* unused */
|
|
|
|
|
|
/* own DTIMS_ATOM_MAIN */
|
|
static int own_main_atom(Window win)
|
|
{
|
|
Window owner = None;
|
|
|
|
if (winEnv.atom_main == None) return False;
|
|
/* if (winEnv.atom_owner != None) return False; */
|
|
|
|
owner = XGetSelectionOwner(winEnv.Dpy, winEnv.atom_main);
|
|
if (owner != None && owner != win) {
|
|
winEnv.atom_owner = owner;
|
|
return False;
|
|
}
|
|
|
|
XSetSelectionOwner(winEnv.Dpy, winEnv.atom_main, win, CurrentTime);
|
|
DPR2(("own_main_atom(%#x): atom=%s[%d]\n",
|
|
win, DTIMS_ATOM_MAIN, winEnv.atom_main));
|
|
winEnv.atom_owner = XGetSelectionOwner(winEnv.Dpy, winEnv.atom_main);
|
|
|
|
return winEnv.atom_owner == win ? True : False;
|
|
}
|
|
|
|
/* disown DTIMS_ATOM_MAIN */
|
|
static int disown_main_atom(Window win)
|
|
{
|
|
if (winEnv.atom_main == None) return False;
|
|
/* if (winEnv.atom_owner == None) return False; */
|
|
|
|
/* give up ownership of DTIMS_ATOM_MAIN */
|
|
if (XGetSelectionOwner(winEnv.Dpy, winEnv.atom_main) == winEnv.atom_owner)
|
|
XSetSelectionOwner(winEnv.Dpy, winEnv.atom_main, None, CurrentTime);
|
|
winEnv.atom_owner = XGetSelectionOwner(winEnv.Dpy, winEnv.atom_main);
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
/* ******** resource_manager ******** */
|
|
|
|
static char *saved_xdefs = NULL; /* should not be freed */
|
|
|
|
int save_RM(void)
|
|
{
|
|
if (!Dpy) return False;
|
|
saved_xdefs = XResourceManagerString(Dpy);
|
|
return saved_xdefs ? True : False;
|
|
}
|
|
|
|
int merge_RM(char *res1, char *res2)
|
|
{
|
|
char cmdbuf[BUFSIZ*2];
|
|
int ret;
|
|
|
|
if (!Dpy) return False;
|
|
|
|
cmdbuf[0] = 0;
|
|
if (isDT()) {
|
|
char *dtres_cmd = DTSESSION_RES_PATH;
|
|
if (is_executable(dtres_cmd)) {
|
|
sprintf(cmdbuf, "%s -merge -system -xdefaults ", dtres_cmd);
|
|
if (res1) { strcat(cmdbuf, " -file "); strcat(cmdbuf, res1); }
|
|
if (res2) { strcat(cmdbuf, " -file "); strcat(cmdbuf, res2); }
|
|
strcat(cmdbuf, " >/dev/null 2>&1");
|
|
}
|
|
}
|
|
if (!cmdbuf[0]) {
|
|
sprintf(cmdbuf, "%s %s %s 2>/dev/null | %s -merge -quiet - 2>/dev/null",
|
|
CAT_PATH, res1, res2, XRDB_PATH);
|
|
}
|
|
|
|
ret = system(cmdbuf);
|
|
|
|
DPR2(("merge_RM(): '%s' & '%s' merged to RESOURCE_MANAGER\n", res1, res2));
|
|
return ret == 0 ? True : False;
|
|
}
|
|
|
|
int restore_RM(void)
|
|
{
|
|
int len = saved_xdefs ? strlen(saved_xdefs) : 0;
|
|
int max = (XMaxRequestSize(Dpy) << 2) - 28;
|
|
int mode = PropModeReplace;
|
|
unsigned char *bp = (unsigned char *) saved_xdefs;
|
|
Window root = RootWindow(Dpy, 0);
|
|
|
|
if (!Dpy /* || len < 0 */) return False;
|
|
|
|
DPR2(("restore_RM(): saved RESOURCE_MANAGER = %d (bytes)\n", len));
|
|
|
|
if (saved_xdefs == NULL) { /* len == 0 */
|
|
XDeleteProperty(Dpy, root, XA_RESOURCE_MANAGER);
|
|
#if 0
|
|
XSync(Dpy, False);
|
|
{ char buf[BUFSIZ];
|
|
sprintf(buf, "%s -quiet -remove 2>/dev/null", XRDB_PATH);
|
|
DPR(("restore_RM(): '%s'\n", buf));
|
|
system(buf);
|
|
}
|
|
#endif
|
|
return True;
|
|
}
|
|
|
|
if (len > max) {
|
|
XGrabServer(Dpy);
|
|
do {
|
|
XChangeProperty(Dpy, root,
|
|
XA_RESOURCE_MANAGER, XA_STRING, 8, mode, bp, len);
|
|
bp += max; len -= max;
|
|
mode = PropModeAppend;
|
|
} while (len > max);
|
|
}
|
|
XChangeProperty(Dpy, root,
|
|
XA_RESOURCE_MANAGER, XA_STRING, 8, mode, bp, len);
|
|
if (mode != PropModeReplace)
|
|
XUngrabServer(Dpy);
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
/* ******** selection window ******** */
|
|
|
|
static int CurIdx = -1;
|
|
static char *CurHost = NULL;
|
|
static int CurHostType = HOST_UNKNOWN;
|
|
static ImsList *curList = 0;
|
|
static bool selection_changed = False;
|
|
|
|
|
|
static void free_ims_list(ImsList *list)
|
|
{
|
|
/* DPR(("free_ims_list(list=%p)\n", list)); */
|
|
if (list && list != localList && list != userSel.list) {
|
|
clear_ImsList(list);
|
|
FREE(list);
|
|
}
|
|
}
|
|
|
|
static void clear_selection_var(void)
|
|
{
|
|
free_ims_list(curList);
|
|
curList = (ImsList *) 0;
|
|
|
|
if (CurHost) FREE(CurHost);
|
|
CurHost = NULL;
|
|
CurHostType = HOST_UNKNOWN;
|
|
CurIdx = -1;
|
|
selection_changed = False;
|
|
}
|
|
|
|
int start_selection_window(void)
|
|
{
|
|
int ret = NoError;
|
|
|
|
if ((ret = init_window_env()) != NoError)
|
|
return ret;
|
|
|
|
clear_selection_var();
|
|
curList = userSel.list;
|
|
/* curHost = NEWSTR(userSel.hostname); */
|
|
|
|
if ((ret = create_selection_window()) != NoError)
|
|
return ret;
|
|
|
|
/* handle system Menu's "close" */
|
|
XmAddWMProtocolCallback(XtParent(SelW),
|
|
XmInternAtom(Dpy, "WM_DELETE_WINDOW", True),
|
|
(XtCallbackProc)done_cb, (XtPointer)CANCEL_BTN);
|
|
|
|
if (isXsession()) {
|
|
clear_cmd_property(XtWindow(TopW));
|
|
}
|
|
|
|
locate_window(SelW);
|
|
XtManageChild(SelW);
|
|
XtPopup(XtParent(SelW), XtGrabNone);
|
|
|
|
if (FocusW)
|
|
XmProcessTraversal(FocusW, XmTRAVERSE_CURRENT);
|
|
|
|
XtRealizeWidget(TopW);
|
|
XtAppMainLoop(appC);
|
|
/* not reached */
|
|
return NoError;
|
|
}
|
|
|
|
static void finish_selection_window(int end_window)
|
|
{
|
|
DPR(("finish_selection_window(end=%s)\n", end_window ? "True" : "False"));
|
|
|
|
clear_selection_var();
|
|
|
|
stop_help();
|
|
|
|
if (SelW) {
|
|
#if 0
|
|
if (TopW)
|
|
disown_main_atom(XtWindow(TopW));
|
|
#endif
|
|
|
|
XtUnmanageChild(SelW);
|
|
XtPopdown(XtParent(SelW));
|
|
XtDestroyWidget(XtParent(SelW));
|
|
SelW = (Widget) 0;
|
|
|
|
if (HostW) {
|
|
XtUnmanageChild(HostW);
|
|
XtPopdown(XtParent(HostW));
|
|
XtDestroyWidget(XtParent(HostW));
|
|
HostW = (Widget) 0;
|
|
}
|
|
}
|
|
|
|
if (end_window)
|
|
end_window_env();
|
|
|
|
return;
|
|
}
|
|
|
|
static void done_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
int canceled = (int)(intptr_t) client_data == CANCEL_BTN;
|
|
int idx;
|
|
UserSelection *sel = &userSel;
|
|
|
|
if (!canceled) { /* update userSel */
|
|
idx = CurIdx;
|
|
DPR2(("done_cb(): selected IMS: [%d]%s\n",
|
|
idx, curList->elist[idx]->name));
|
|
|
|
if (curList->elist[idx]->status != NoError) {
|
|
Beep();
|
|
return;
|
|
}
|
|
|
|
if ((CurHost != sel->hostname)
|
|
|| (CurHost && sel->hostname && strcmp(sel->hostname, CurHost))
|
|
|| sel->list != curList || sel->ims_idx != idx)
|
|
selection_changed = True;
|
|
|
|
if (selection_changed == True) {
|
|
update_user_selection(sel, curList, idx, CurHost, CurHostType);
|
|
curList = (ImsList *) 0;
|
|
}
|
|
}
|
|
|
|
finish_selection_window(False);
|
|
|
|
OpErrCode = NoError;
|
|
OpState = canceled ? State_Select_Canceled : State_Select_Done;
|
|
ximsMain();
|
|
}
|
|
|
|
static void select_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
int new_idx = (int)(intptr_t) client_data;
|
|
|
|
if (new_idx < 0 || new_idx >= curList->num_ent) {
|
|
DPR(("select_cb():\tinvalid index (%d)\n", new_idx));
|
|
return;
|
|
}
|
|
|
|
DPR3(("select_cb(): '%s' selected (%d <- %d)\n",
|
|
curList->elist[new_idx]->name, new_idx, CurIdx));
|
|
|
|
CurIdx = new_idx;
|
|
}
|
|
|
|
static void host_btn_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
start_host_window(CurHost);
|
|
}
|
|
|
|
static void help_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
ximsHelp(HELP_SELECTION);
|
|
}
|
|
|
|
|
|
static int create_selection_window(void)
|
|
{
|
|
Widget form, sel_rc, host_rc, cmd_rc, lb, sep;
|
|
Widget w_tbl[8];
|
|
Arg args[16];
|
|
int i, j, n;
|
|
int ret;
|
|
bool use_local = False;
|
|
|
|
/* selection top window */
|
|
|
|
i = 0;
|
|
XtSetArg(args[i], XmNmwmFunctions, WIN_FUNC); i++;
|
|
XtSetArg(args[i], XmNmwmDecorations, WIN_DECR); i++;
|
|
XtSetArg(args[i], XmNdefaultPosition, False); i++;
|
|
XtSetArg(args[i], XmNnoResize, True); i++;
|
|
XtSetArg(args[i], XmNallowShellResize, True); i++;
|
|
/* XtSetArg(args[i], XmNresizable, True); i++; */
|
|
XtSetArg(args[i], XmNmappedWhenManaged, False); i++;
|
|
SelW =
|
|
form = XmCreateFormDialog(TopW, "Selection", args, i);
|
|
|
|
/* for child of form */
|
|
i = 0;
|
|
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
|
|
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
|
|
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
|
|
n = 0;
|
|
w_tbl[n] = 0;
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[n] = lb = XmCreateLabelGadget(form, "title", args, i + 1);
|
|
|
|
if (RemoteOn()) {
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
j = i + 1;
|
|
XtSetArg(args[j], XmNorientation, XmHORIZONTAL); j++;
|
|
XtSetArg(args[j], XmNpacking, XmPACK_TIGHT); j++;
|
|
XtSetArg(args[j], XmNisAligned, TRUE); j++;
|
|
XtSetArg(args[j], XmNentryAlignment, XmALIGNMENT_BEGINNING); j++;
|
|
XtSetArg(args[j], XmNentryBorder, 0); j++;
|
|
XtSetArg(args[j], XmNmarginHeight, 1); j++;
|
|
XtSetArg(args[j], XmNmarginWidth, 20); j++;
|
|
HostRC =
|
|
w_tbl[++n] = host_rc = XmCreateRowColumn(form, "host_rc", args, j);
|
|
}
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
j = i + 1;
|
|
XtSetArg(args[j], XmNorientation, XmHORIZONTAL); j++;
|
|
XtSetArg(args[j], XmNpacking, XmPACK_COLUMN); j++;
|
|
XtSetArg(args[j], XmNnumColumns, curList->num_ent); j++;
|
|
XtSetArg(args[j], XmNisAligned, TRUE); j++;
|
|
XtSetArg(args[j], XmNentryAlignment, XmALIGNMENT_BEGINNING); j++;
|
|
XtSetArg(args[j], XmNentryBorder, 0); j++;
|
|
XtSetArg(args[j], XmNmarginHeight, 10); j++;
|
|
/* XtSetArg(args[j], XmNmarginWidth, 40); j++; */
|
|
SelRC =
|
|
w_tbl[++n] = sel_rc = XmCreateRadioBox(form, "select_rc", args, j);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[++n] = sep = XmCreateSeparatorGadget(form, "sep", args, i + 1);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
XtSetArg(args[i+1], XmNbottomAttachment, XmATTACH_FORM);
|
|
w_tbl[++n] = cmd_rc = XmCreateRowColumn(form,"cmd_rc", args, i + 2);
|
|
|
|
use_local = True;
|
|
if (RemoteOn()) {
|
|
switch (userSel.host_type) {
|
|
case HOST_UNKNOWN:
|
|
put_xims_errmsg(ErrUnknownHost, userSel.hostname, 0, 0);
|
|
ret = change_host(NULL, HOST_LOCAL);
|
|
break;
|
|
case HOST_REMOTE:
|
|
ret = change_host(userSel.hostname, userSel.host_type);
|
|
if (ret == NoError) {
|
|
change_ims_list(userSel.name, -1);
|
|
use_local = False;
|
|
} else {
|
|
if (ret != ErrRemoteAction) {
|
|
put_xims_errmsg(ret, 0 /* userSel.hostname */, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (use_local)
|
|
change_ims_list(NULL, userSel.ims_idx);
|
|
|
|
add_cmd_btn(cmd_rc, done_cb, 0, done_cb,
|
|
RemoteOn() ? host_btn_cb : 0, help_cb);
|
|
|
|
XtManageChildren(w_tbl, ++n);
|
|
|
|
XtManageChild(SelW); locate_window(SelW); XtUnmanageChild(SelW);
|
|
XtVaSetValues(SelW, XmNmappedWhenManaged, True, NULL);
|
|
XtVaSetValues(XtParent(SelW), XmNmappedWhenManaged, True, NULL);
|
|
set_cursor(SelW, False);
|
|
|
|
return NoError;
|
|
}
|
|
|
|
|
|
static int change_host(char *new_host, int host_type)
|
|
{
|
|
int ret = NoError;
|
|
ImsList *new_list = (ImsList *) 0;
|
|
|
|
if (new_host && host_type == HOST_REMOTE) {
|
|
set_cursor(HostW, True);
|
|
ret = get_remote_conf(&new_list, new_host, NULL, NULL);
|
|
set_cursor(HostW, False);
|
|
} else {
|
|
if (!localList)
|
|
ret = get_ims_list(&localList, NULL, True);
|
|
new_host = NULL;
|
|
new_list = localList;
|
|
}
|
|
|
|
if (ret == NoError) {
|
|
if (CurHost) FREE(CurHost);
|
|
CurHost = new_host ? NEWSTR(new_host) : NULL;
|
|
CurHostType = host_type;
|
|
|
|
DPR(("change_host(%s): curList=(%p) <- (%p)\n",
|
|
new_host, new_list, curList));
|
|
free_ims_list(curList);
|
|
curList = new_list;
|
|
} else if (new_list) {
|
|
free_ims_list(new_list);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
# define SelectByReturn 1
|
|
|
|
#ifdef SelectByReturn
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/PushB.h>
|
|
#define createPB XmCreatePushButton
|
|
#define createTB XmCreateToggleButton
|
|
|
|
static void add_btn_trans(Widget btn)
|
|
{
|
|
char btn_trans_str[] = "<Key>Return: ArmAndActivate()";
|
|
static XtTranslations btn_trans = 0;
|
|
|
|
if (!btn_trans)
|
|
btn_trans = XtParseTranslationTable(btn_trans_str);
|
|
XtOverrideTranslations(btn, btn_trans);
|
|
}
|
|
|
|
#else
|
|
#include <Xm/ToggleBG.h>
|
|
#include <Xm/PushBG.h>
|
|
#define createPB XmCreatePushButtonGadget
|
|
#define createTB XmCreateToggleButtonGadget
|
|
#define add_btn_trans(btn)
|
|
# endif /* SelectByReturn */
|
|
|
|
|
|
static void change_ims_list(char *last_ims_name, int init_idx)
|
|
{
|
|
int idx;
|
|
int i, j;
|
|
Arg args[8];
|
|
XmString str;
|
|
static int num_chld = 0;
|
|
static Widget tb[MAXIMSENT];
|
|
|
|
#define IMS_OK(i) (curList->elist[i]->status == NoError)
|
|
|
|
/* deternime initial selection */
|
|
idx = -1;
|
|
if (last_ims_name) {
|
|
i = get_ims_idx(curList, last_ims_name);
|
|
if (i >= 0 && IMS_OK(i))
|
|
idx = i;
|
|
}
|
|
if (idx < 0) {
|
|
if (init_idx >= 0 && init_idx < curList->num_ent && IMS_OK(init_idx)) {
|
|
idx = init_idx;
|
|
} else {
|
|
idx = curList->default_idx;
|
|
if (!(idx >= 0 && idx < curList->num_ent && IMS_OK(idx))) {
|
|
for (idx = 0; idx < curList->num_ent; idx++)
|
|
if (IMS_OK(idx)) break;
|
|
if (idx >= curList->num_ent)
|
|
idx = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < curList->num_ent; j++) {
|
|
str = XmStringCreateLocalized(curList->elist[j]->label);
|
|
i = 0;
|
|
XtSetArg(args[i], XmNset, j == idx ? True : False); i++;
|
|
XtSetArg(args[i], XmNsensitive, IMS_OK(j)); i++;
|
|
XtSetArg(args[i], XmNlabelString, str); i++;
|
|
XtSetArg(args[i], XmNspacing, 10); i++;
|
|
if (j < num_chld) {
|
|
XtSetValues(tb[j], args, i);
|
|
} else {
|
|
tb[j] = createTB(SelRC, "ims", args, i);
|
|
XtAddCallback(tb[j], XmNvalueChangedCallback, select_cb, (XtPointer)(intptr_t) j);
|
|
add_btn_trans(tb[j]);
|
|
}
|
|
XmStringFree(str);
|
|
}
|
|
if (j > num_chld)
|
|
num_chld = j;
|
|
else if (j < num_chld)
|
|
XtUnmanageChildren(tb + j, num_chld - j);
|
|
XtManageChildren(tb, j);
|
|
|
|
CurIdx = idx;
|
|
if (RemoteOn()) {
|
|
if (CurHostType == HOST_UNKNOWN)
|
|
CurHostType = check_hostname(CurHost);
|
|
set_host_label(CurHostType, CurHost);
|
|
}
|
|
|
|
#undef IMS_OK
|
|
}
|
|
|
|
static void set_host_label(int host_type, char *hostname)
|
|
{
|
|
static Widget lb_host = 0;
|
|
|
|
/* if (!HostRC) return; */
|
|
|
|
if (host_type == HOST_REMOTE) { /* change HostLabel & manage HostRC */
|
|
XmString str;
|
|
|
|
if (!lb_host) {
|
|
Widget lb;
|
|
Arg args[4];
|
|
int n = 0;
|
|
|
|
XtSetArg(args[n], XmNmarginLeft, 100); n++;
|
|
lb = XmCreateLabelGadget(HostRC, "host_label", args, n);
|
|
lb_host = XmCreateLabelGadget(HostRC, "hostname", NULL, 0);
|
|
XtManageChild(lb);
|
|
XtManageChild(lb_host);
|
|
}
|
|
str = XmStringCreateLocalized(hostname);
|
|
XtVaSetValues(lb_host, XmNlabelString, str, NULL);
|
|
XmStringFree(str);
|
|
|
|
XtManageChild(HostRC);
|
|
} else {
|
|
/* unmanage HostRC */
|
|
XtUnmanageChild(HostRC);
|
|
}
|
|
}
|
|
|
|
|
|
static void add_cmd_btn(Widget parent_rc, void (*cb_ok)(),
|
|
void (*cb_clear)(), void (*cb_cancel)(),
|
|
void (*cb_host)(), void (*cb_help)())
|
|
{
|
|
Widget pb[4];
|
|
Arg args[12];
|
|
int n, nbtn;
|
|
|
|
nbtn = 0;
|
|
if (cb_ok) nbtn++;
|
|
if (cb_clear) nbtn++;
|
|
if (cb_cancel) nbtn++;
|
|
if (cb_host) nbtn++;
|
|
if (cb_help) nbtn++;
|
|
if (nbtn == 0) return;
|
|
|
|
/* command buttons on "cmd_rc" */
|
|
n = 0;
|
|
if (nbtn > 3) {
|
|
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); n++;
|
|
} else {
|
|
XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
|
|
XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
|
|
}
|
|
XtSetArg(args[n], XmNnumColumns, nbtn); n++;
|
|
XtSetArg(args[n], XmNisAligned, TRUE); n++;
|
|
XtSetArg(args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
|
|
XtSetArg(args[n], XmNentryBorder, 0); n++;
|
|
XtSetArg(args[n], XmNmarginHeight, 1); n++;
|
|
XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
|
|
/* XtSetArg(args[n], XmNmarginWidth, 20); n++; */
|
|
/* XtSetArg(args[n], XmNspacing, 20); n++; */
|
|
XtSetValues(parent_rc, args, n);
|
|
|
|
/* for child of parent_rc */
|
|
|
|
nbtn = 0;
|
|
n = 0;
|
|
if (cb_ok) {
|
|
pb[nbtn] = createPB(parent_rc, "OK", args, n);
|
|
XtAddCallback(pb[nbtn], XmNactivateCallback,
|
|
cb_ok, (XtPointer)OK_BTN);
|
|
FocusW = pb[nbtn];
|
|
/* XtVaSetValues(parent_rc, XmNinitialFocus, pb, NULL); */
|
|
nbtn++;
|
|
}
|
|
if (cb_clear) {
|
|
pb[nbtn] = createPB(parent_rc, "Clear", args, n);
|
|
XtAddCallback(pb[nbtn], XmNactivateCallback,
|
|
cb_clear, (XtPointer)CLEAR_BTN);
|
|
nbtn++;
|
|
}
|
|
if (cb_cancel) {
|
|
pb[nbtn] = createPB(parent_rc, "Cancel", args, n);
|
|
XtAddCallback(pb[nbtn], XmNactivateCallback,
|
|
cb_cancel, (XtPointer)CANCEL_BTN);
|
|
nbtn++;
|
|
}
|
|
if (cb_host) {
|
|
pb[nbtn] = createPB(parent_rc, "ChangeHost", args, n);
|
|
XtAddCallback(pb[nbtn], XmNactivateCallback,
|
|
cb_host, (XtPointer)HOST_BTN);
|
|
nbtn++;
|
|
}
|
|
if (cb_help) {
|
|
pb[nbtn] = createPB(parent_rc, "Help", args, n);
|
|
XtAddCallback(pb[nbtn], XmNactivateCallback,
|
|
cb_help, (XtPointer)HELP_BTN);
|
|
nbtn++;
|
|
}
|
|
#ifdef SelectByReturn
|
|
for (n = 0; n < nbtn; n++)
|
|
add_btn_trans(pb[n]);
|
|
#endif /* SelectByReturn */
|
|
|
|
XtManageChildren(pb, nbtn);
|
|
}
|
|
|
|
/* ***** host window ***** */
|
|
|
|
static void start_host_window(char *cur_host)
|
|
{
|
|
int ret;
|
|
|
|
if (!HostW) {
|
|
create_host_window(cur_host);
|
|
|
|
/* handle system Menu's "close" */
|
|
XmAddWMProtocolCallback(XtParent(HostW),
|
|
XmInternAtom(Dpy, "WM_DELETE_WINDOW", True),
|
|
(XtCallbackProc)host_done_cb, (XtPointer)CANCEL_BTN);
|
|
}
|
|
|
|
XtVaSetValues(HostText, XmNvalue, CurHost, NULL);
|
|
|
|
if (HostText)
|
|
XmProcessTraversal(HostText, XmTRAVERSE_CURRENT);
|
|
|
|
locate_window(HostW);
|
|
XtManageChild(HostW);
|
|
XtPopup(XtParent(HostW), XtGrabNone);
|
|
|
|
#ifdef DEBUG
|
|
pr_brk("start_host_window");
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
static void finish_host_window(void)
|
|
{
|
|
DPR(("finish_host_window()\n"));
|
|
|
|
if (HostW) {
|
|
XtUnmanageChild(HostW);
|
|
XtPopdown(XtParent(HostW));
|
|
/* not destroy */
|
|
}
|
|
}
|
|
|
|
static void host_done_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
int cancel = (int)(intptr_t) client_data == CANCEL_BTN;
|
|
int ret = NoError;
|
|
char *new_host, *txt, *p;
|
|
bool host_changed = False;
|
|
int host_type;
|
|
|
|
if (cancel) {
|
|
finish_host_window();
|
|
return;
|
|
}
|
|
|
|
/* if (!HostText) return; */
|
|
new_host = NULL;
|
|
txt = XmTextFieldGetString(HostText);
|
|
if (txt) {
|
|
p = trim_line(txt);
|
|
new_host = (*p) ? p : NULL;
|
|
}
|
|
if (new_host) {
|
|
if (!(CurHost) || strcmp(CurHost, new_host)) {
|
|
host_type = check_hostname(new_host);
|
|
|
|
switch (host_type) {
|
|
case HOST_LOCAL:
|
|
new_host = NULL;
|
|
if (CurHost)
|
|
host_changed = True;
|
|
break;
|
|
case HOST_REMOTE:
|
|
host_changed = True;
|
|
break;
|
|
case HOST_UNKNOWN:
|
|
host_changed = False;
|
|
put_xims_errmsg(ErrUnknownHost, new_host, 0, 0);
|
|
|
|
/* don't finish window */
|
|
XtFree(txt);
|
|
return;
|
|
}
|
|
}
|
|
} else if (CurHost) { /* 'new_host == NULL' ==> local host */
|
|
host_type = HOST_LOCAL;
|
|
host_changed = True;
|
|
}
|
|
|
|
DPR(("host_cb(): hostname %s changed '%s' (<- %s)\n",
|
|
host_changed ? NULL : "NOT", new_host, CurHost));
|
|
|
|
if (host_changed) {
|
|
char *last_ims = NULL;
|
|
|
|
/* save the name of selected ims */
|
|
if (CurIdx >= 0 && CurIdx < curList->num_ent)
|
|
last_ims = NEWSTR(curList->elist[CurIdx]->name);
|
|
|
|
ret = change_host(new_host, host_type);
|
|
if (ret == NoError) {
|
|
finish_host_window();
|
|
change_ims_list(last_ims, -1);
|
|
selection_changed = True;
|
|
} else {
|
|
if (ret != ErrRemoteAction) {
|
|
put_xims_errmsg(ret, new_host, 0, 0);
|
|
}
|
|
/* don't finish window */
|
|
}
|
|
|
|
FREE(last_ims);
|
|
} else {
|
|
finish_host_window();
|
|
}
|
|
|
|
XtFree(txt);
|
|
|
|
#ifdef DEBUG
|
|
pr_brk("host_done_window");
|
|
#endif
|
|
}
|
|
|
|
static void host_clear_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
/* if (!HostText) return; */
|
|
XtVaSetValues(HostText, XmNvalue, "", NULL);
|
|
}
|
|
|
|
static void host_done_action(Widget w, XEvent *ev, String *args, Cardinal *num_args)
|
|
{
|
|
host_done_cb(w, (XtPointer) OK_BTN, 0);
|
|
}
|
|
|
|
static void create_host_window(char *cur_host)
|
|
{
|
|
Widget form, cmd_rc, lb1, sep, w_tbl[5];
|
|
Widget host_desc, host_rc, host_lb, host_txt;
|
|
Arg args[16], hargs[8];
|
|
int i, j, n;
|
|
Widget hw[4];
|
|
int nhw = 0;
|
|
XtTranslations trans;
|
|
static char host_trans[] = "<Key>Return: host-done()";
|
|
static XtActionsRec host_actions[] = {
|
|
{ "host-done", (XtActionProc) host_done_action }
|
|
};
|
|
|
|
i = 0;
|
|
XtSetArg(args[i], XmNmwmFunctions, WIN_FUNC); i++;
|
|
XtSetArg(args[i], XmNmwmDecorations, WIN_DECR); i++;
|
|
XtSetArg(args[i], XmNdefaultPosition, False); i++;
|
|
XtSetArg(args[i], XmNnoResize, True); i++;
|
|
XtSetArg(args[i], XmNallowShellResize, True); i++;
|
|
XtSetArg(args[i], XmNmappedWhenManaged, False); i++;
|
|
XtSetArg(args[i], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); i++;
|
|
HostW =
|
|
form = XmCreateFormDialog(TopW, "Host", args, i);
|
|
|
|
/* for child of form */
|
|
i = 0;
|
|
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
|
|
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
|
|
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
|
|
n = 0;
|
|
w_tbl[n] = 0;
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[n] = lb1 = XmCreateLabelGadget(form, "title", args, i + 1);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
j = i + 1;
|
|
XtSetArg(args[j], XmNmarginHeight, 8); j++;
|
|
XtSetArg(args[j], XmNmarginWidth, 8); j++;
|
|
w_tbl[++n] = host_desc = XmCreateLabelGadget(form, "host_desc", args, j);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
j = i + 1;
|
|
XtSetArg(args[j], XmNorientation, XmHORIZONTAL); j++;
|
|
XtSetArg(args[j], XmNpacking, XmPACK_TIGHT); j++;
|
|
XtSetArg(args[j], XmNisAligned, TRUE); j++;
|
|
XtSetArg(args[j], XmNentryAlignment, XmALIGNMENT_BEGINNING); j++;
|
|
XtSetArg(args[j], XmNentryBorder, 0); j++;
|
|
XtSetArg(args[j], XmNmarginHeight, 1); j++;
|
|
/* XtSetArg(args[j], XmNmarginWidth, 20); j++; */
|
|
w_tbl[++n] = host_rc = XmCreateRowColumn(form, "host_rc", args, j);
|
|
|
|
nhw = 0;
|
|
j = 0;
|
|
XtSetArg(hargs[j], XmNalignment, XmALIGNMENT_BEGINNING); j++;
|
|
hw[nhw++] = host_lb = XmCreateLabelGadget(host_rc, "host_label", hargs, j);
|
|
j = 0;
|
|
/* XtSetArg(hargs[j], XmNcolumns, TEXT_COLUMNS); j++; */
|
|
/* XtSetArg(hargs[j], XmNmaxLength, MAX_HOSTNAME_LEN); j++; */
|
|
XtSetArg(hargs[j], XmNeditable, True); j++;
|
|
XtSetArg(hargs[j], XmNvalue, cur_host); j++;
|
|
XtSetArg(hargs[j], XmNmarginHeight, 1); j++;
|
|
XtSetArg(hargs[j], XmNmarginWidth, 1); j++;
|
|
HostText =
|
|
hw[nhw++] = host_txt = XmCreateTextField(host_rc, "host_text", hargs, j);
|
|
XtManageChildren(hw, nhw);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[++n] = sep = XmCreateSeparatorGadget(form, "sep", args, i + 1);
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
XtSetArg(args[i+1], XmNbottomAttachment, XmATTACH_FORM);
|
|
w_tbl[++n] = cmd_rc = XmCreateRowColumn(form, "cmd_rc", args, i + 2);
|
|
XtManageChildren(w_tbl, ++n);
|
|
|
|
add_cmd_btn(cmd_rc, host_done_cb, host_clear_cb, host_done_cb, 0, 0);
|
|
|
|
/* set 'host-done' action for 'Return' key */
|
|
XtAppAddActions(appC, host_actions, XtNumber(host_actions));
|
|
trans = XtParseTranslationTable(host_trans);
|
|
XtOverrideTranslations(HostText, trans);
|
|
|
|
XtManageChild(HostW); locate_window(HostW); XtUnmanageChild(HostW);
|
|
XtVaSetValues(XtParent(HostW), XmNmappedWhenManaged, True, NULL);
|
|
XtVaSetValues(HostW, XmNmappedWhenManaged, True, NULL);
|
|
set_cursor(HostW, False);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* ******** mode window ******** */
|
|
|
|
static int OrgMode = SEL_MODE_NONE;
|
|
static int CurMode = SEL_MODE_NONE;
|
|
|
|
int start_mode_window(int cur_mode)
|
|
{
|
|
int ret;
|
|
|
|
OrgMode = CurMode = cur_mode;
|
|
|
|
if ((ret = init_window_env()) != NoError)
|
|
return ret;
|
|
|
|
if ((ret = create_mode_window(cur_mode)) != NoError)
|
|
return ret;
|
|
|
|
/* handle system Menu's "close" */
|
|
XmAddWMProtocolCallback(XtParent(ModeW),
|
|
XmInternAtom(Dpy, "WM_DELETE_WINDOW", True),
|
|
(XtCallbackProc)mode_done_cb, (XtPointer)CANCEL_BTN);
|
|
|
|
locate_window(ModeW);
|
|
XtManageChild(ModeW);
|
|
XtPopup(XtParent(ModeW), XtGrabNone);
|
|
|
|
if (FocusW)
|
|
XmProcessTraversal(FocusW, XmTRAVERSE_CURRENT);
|
|
|
|
XtAppMainLoop(appC);
|
|
/* not rearched */
|
|
return NoError;
|
|
}
|
|
|
|
static void finish_mode_window(int end_window)
|
|
{
|
|
if (ModeW) {
|
|
XtUnmanageChild(ModeW);
|
|
XtPopdown(XtParent(ModeW));
|
|
XtDestroyWidget(XtParent(ModeW));
|
|
ModeW = (Widget) 0;
|
|
}
|
|
stop_help();
|
|
|
|
if (end_window)
|
|
end_window_env();
|
|
|
|
return;
|
|
}
|
|
|
|
static void mode_done_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
int ret = NoError;
|
|
int canceled = (int)(intptr_t) client_data == CANCEL_BTN;
|
|
|
|
DPR(("mode_done(%s):\torg=%d cur=%d\n",
|
|
canceled ? "Cancel" : "OK", OrgMode, CurMode));
|
|
if (canceled) {
|
|
OpErrCode = NoError;
|
|
OpState = State_Mode_Canceled;
|
|
} else {
|
|
ret = set_select_mode(OrgMode, CurMode);
|
|
|
|
OpErrCode = ret;
|
|
OpState = State_Mode_Done;
|
|
|
|
if (OpErrCode != NoError) {
|
|
finish_mode_window(False);
|
|
LastErrMsg = OpErrCode;
|
|
put_xims_errmsg(OpErrCode, 0, 0, 0);
|
|
if (WaitingDialogReply) {
|
|
DPR(("mode_done_cb(): enter xevent_loop()\n"));
|
|
xevent_loop(); /* never returns */
|
|
}
|
|
}
|
|
}
|
|
finish_mode_window(True);
|
|
/* never returns */
|
|
}
|
|
|
|
static void mode_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
int is_set = (int)((XmToggleButtonCallbackStruct *)call_data)->set;
|
|
int is_auto = (int)(intptr_t) client_data;
|
|
|
|
CurMode = (is_auto && is_set) ? SEL_MODE_AUTO : SEL_MODE_NOAUTO;
|
|
}
|
|
|
|
static void mode_help_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
ximsHelp(HELP_MODE);
|
|
}
|
|
|
|
static int create_mode_window(int cur_mode)
|
|
{
|
|
Widget form, mode_rc, cmd_rc, lb1, sep, w_tbl[8];
|
|
Arg args[16];
|
|
int i, j, n;
|
|
|
|
i = 0;
|
|
XtSetArg(args[i], XmNmwmFunctions, WIN_FUNC); i++;
|
|
XtSetArg(args[i], XmNmwmDecorations, WIN_DECR); i++;
|
|
XtSetArg(args[i], XmNdefaultPosition, False); i++;
|
|
XtSetArg(args[i], XmNnoResize, True); i++;
|
|
XtSetArg(args[i], XmNallowShellResize, True); i++;
|
|
XtSetArg(args[i], XmNmappedWhenManaged, False); i++;
|
|
ModeW =
|
|
form = XmCreateFormDialog(TopW, "Mode", args, i);
|
|
|
|
/* for child of form */
|
|
i = 0;
|
|
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
|
|
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
|
|
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
|
|
n = 0;
|
|
w_tbl[n] = 0;
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[n] = lb1 = XmCreateLabelGadget(form, "title", args, i + 1);
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
j = i + 1;
|
|
XtSetArg(args[j], XmNisAligned, TRUE); j++;
|
|
XtSetArg(args[j], XmNentryAlignment, XmALIGNMENT_BEGINNING); j++;
|
|
XtSetArg(args[j], XmNentryBorder, 0); j++;
|
|
XtSetArg(args[j], XmNmarginHeight, 10); j++;
|
|
XtSetArg(args[j], XmNmarginWidth, 30); j++;
|
|
|
|
#ifdef SelectByReturn
|
|
/* use TB */
|
|
XtSetArg(args[j], XmNorientation, XmHORIZONTAL); j++;
|
|
XtSetArg(args[j], XmNpacking, XmPACK_COLUMN); j++;
|
|
XtSetArg(args[j], XmNnumColumns, NUM_SEL_MODE); j++;
|
|
w_tbl[++n] = mode_rc = XmCreateRadioBox(form, "mode_rc", args, j);
|
|
{
|
|
Arg bargs[8];
|
|
Widget tb[NUM_SEL_MODE];
|
|
int k = 0;
|
|
int set_idx = cur_mode == SEL_MODE_AUTO ? 1 : 0;
|
|
|
|
k = 0;
|
|
XtSetArg(bargs[k], XmNspacing, 10); k++;
|
|
tb[0] = createTB(mode_rc, "button_0", bargs, k);
|
|
tb[1] = createTB(mode_rc, "button_1", bargs, k);
|
|
for (k = 0; k < NUM_SEL_MODE; k++) {
|
|
XtVaSetValues(tb[k], XmNset, k == set_idx ? True : False, NULL);
|
|
XtAddCallback(tb[k], XmNvalueChangedCallback, mode_cb, (XtPointer)(intptr_t) k);
|
|
add_btn_trans(tb[k]);
|
|
}
|
|
XtManageChildren(tb, NUM_SEL_MODE);
|
|
}
|
|
#else
|
|
/* use TBGadget */
|
|
XtSetArg(args[j], XmNbuttonCount, NUM_SEL_MODE); j++;
|
|
XtSetArg(args[j], XmNbuttonSet, cur_mode == SEL_MODE_AUTO ? 1 : 0); j++;
|
|
XtSetArg(args[j], XmNsimpleCallback, mode_cb); j++;
|
|
w_tbl[++n] = mode_rc = XmCreateSimpleRadioBox(form, "mode_rc", args, j);
|
|
#endif /* SelectByReturn */
|
|
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
w_tbl[++n] = sep = XmCreateSeparatorGadget(form, "sep", args, i + 1);
|
|
XtSetArg(args[i], XmNtopWidget, w_tbl[n]);
|
|
XtSetArg(args[i+1], XmNbottomAttachment, XmATTACH_FORM);
|
|
w_tbl[++n] = cmd_rc = XmCreateRowColumn(form, "cmd_rc", args, i + 2);
|
|
XtManageChildren(w_tbl, ++n);
|
|
|
|
add_cmd_btn(cmd_rc, mode_done_cb, 0, mode_done_cb, 0, mode_help_cb);
|
|
|
|
XtManageChild(ModeW); locate_window(ModeW); XtUnmanageChild(ModeW);
|
|
XtVaSetValues(XtParent(ModeW), XmNmappedWhenManaged, True, NULL);
|
|
XtVaSetValues(ModeW, XmNmappedWhenManaged, True, NULL);
|
|
set_cursor(ModeW, False);
|
|
|
|
return NoError;
|
|
}
|
|
|
|
|
|
/* ******** ximsHelp ******** */
|
|
|
|
static void help_ok(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
stop_help();
|
|
}
|
|
|
|
void stop_help(void)
|
|
{
|
|
if (HelpW) {
|
|
XtUnmanageChild(HelpW);
|
|
XtPopdown(XtParent(HelpW));
|
|
}
|
|
}
|
|
|
|
static void create_help(void)
|
|
{
|
|
int i;
|
|
Arg args[10];
|
|
|
|
i = 0;
|
|
XtSetArg(args[i], XmNmwmFunctions, WIN_FUNC); i++;
|
|
XtSetArg(args[i], XmNmwmDecorations, WIN_DECR); i++;
|
|
XtSetArg(args[i], XmNautoUnmanage, True); i++;
|
|
XtSetArg(args[i], XmNdefaultPosition, False); i++;
|
|
XtSetArg(args[i], XmNnoResize, True); i++;
|
|
XtSetArg(args[i], XmNallowShellResize, True); i++;
|
|
XtSetArg(args[i], XmNmappedWhenManaged, False); i++;
|
|
HelpW = XmCreateInformationDialog(TopW, "Help", args, i);
|
|
|
|
XtUnmanageChild(XmMessageBoxGetChild(HelpW, XmDIALOG_CANCEL_BUTTON));
|
|
XtUnmanageChild(XmMessageBoxGetChild(HelpW, XmDIALOG_HELP_BUTTON));
|
|
XtAddCallback(HelpW, XmNokCallback, help_ok, (XtPointer)0);
|
|
|
|
/* help_dialog is not located correctly unless once managed */
|
|
/* XtSetMappedWhenManaged(XtParent(HelpW), False); */
|
|
XtManageChild(HelpW);
|
|
XtUnmanageChild(HelpW);
|
|
XtSetMappedWhenManaged(XtParent(HelpW), True);
|
|
XtSetMappedWhenManaged(HelpW, True);
|
|
set_cursor(HelpW, False);
|
|
|
|
return;
|
|
}
|
|
|
|
void ximsHelp(int help_type)
|
|
{
|
|
char *msg = NULL;
|
|
XmString str;
|
|
static int last_help_type = -1;
|
|
|
|
if (!HelpW)
|
|
create_help();
|
|
|
|
if (help_type != last_help_type) {
|
|
|
|
switch (help_type) {
|
|
case HELP_MODE: msg = appres.modeHelpMsg; break;
|
|
default:
|
|
case HELP_SELECTION: msg = appres.selectionHelpMsg; break;
|
|
}
|
|
|
|
if (!msg || !*msg) {
|
|
Beep();
|
|
#ifdef DEBUG
|
|
if (DebugLvl > 0)
|
|
msg = "help message not defined in resource file\n";
|
|
else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (XtIsManaged(HelpW))
|
|
XtUnmanageChild(HelpW);
|
|
|
|
str = XmStringCreateLocalized(msg);
|
|
XtVaSetValues(HelpW, XmNmessageString, str, NULL);
|
|
XmStringFree(str);
|
|
|
|
last_help_type = help_type;
|
|
}
|
|
|
|
locate_window(HelpW);
|
|
XtManageChild(HelpW);
|
|
XtPopup(XtParent(HelpW), XtGrabNone);
|
|
}
|
|
|
|
|
|
/* ******** message dialog ******** */
|
|
|
|
static int dialog_resp = XmCR_NONE;
|
|
static bool in_confirmation = False;
|
|
|
|
static void dialog_resp_cb(Widget w, XtPointer client_data, XtPointer call_data)
|
|
{
|
|
Widget msg_box = (Widget) client_data;
|
|
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
|
|
|
|
dialog_resp = cbs->reason;
|
|
XtUnmanageChild(msg_box);
|
|
|
|
if (!in_confirmation) {
|
|
WaitingDialogReply = False;
|
|
DPR3(("dialog_resp_cb(): WaitingDialogReply ==> False\n"));
|
|
|
|
if (InWaitingState())
|
|
ximsMain();
|
|
}
|
|
}
|
|
|
|
#ifdef unused
|
|
static int wait_confirmation(Widget w)
|
|
{
|
|
XtAppContext context;
|
|
|
|
dialog_resp = XmCR_NONE;
|
|
|
|
/* XtManageChild(w); */
|
|
/* context = XtWidgetToApplicationContext(w); */
|
|
context = appC;
|
|
in_confirmation = True;
|
|
while (dialog_resp == XmCR_NONE || XtAppPending(context)) {
|
|
XtAppProcessEvent(context, XtIMAll);
|
|
}
|
|
XtUnmanageChild(w);
|
|
in_confirmation = False;
|
|
|
|
return dialog_resp;
|
|
}
|
|
#endif /* unused */
|
|
|
|
int put_msg_win(int type, char *msg)
|
|
{
|
|
int reply;
|
|
Widget btn;
|
|
int wait_resp = FALSE;
|
|
XmString str;
|
|
int ret;
|
|
|
|
DPR3(("put_msg_win(type=%d):\tmsg=%s", type, msg));
|
|
|
|
if (!msg || !*msg) {
|
|
DPR(("put_msg_win(): msg is empty\n"));
|
|
return -1;
|
|
} else if (msg[strlen(msg) - 1] != '\n') {
|
|
DPR(("put_msg_win(): msg isn't terminated by '\\n'\n"));
|
|
return -1;
|
|
}
|
|
|
|
switch (type) {
|
|
case MSGTYP_FATAL: type = XmDIALOG_ERROR; break;
|
|
case MSGTYP_WARN: type = XmDIALOG_WARNING; break;
|
|
case MSGTYP_CONFIRM: type = XmDIALOG_QUESTION;
|
|
wait_resp = TRUE; break;
|
|
default:
|
|
case MSGTYP_INFO: type = XmDIALOG_INFORMATION; break;
|
|
}
|
|
|
|
if ((ret = init_window_env()) != NoError)
|
|
return -1;
|
|
|
|
if (!MsgW) { /* create message dialog */
|
|
Arg args[10];
|
|
int i = 0;
|
|
|
|
XtSetArg(args[i], XmNautoUnmanage, True); i++;
|
|
XtSetArg(args[i], XmNmwmFunctions, WIN_FUNC); i++;
|
|
XtSetArg(args[i], XmNmwmDecorations, WIN_DECR); i++;
|
|
XtSetArg(args[i], XmNdefaultButtonType, XmDIALOG_OK_BUTTON); i++;
|
|
XtSetArg(args[i], XmNdefaultPosition, False); i++;
|
|
XtSetArg(args[i], XmNnoResize, True); i++;
|
|
XtSetArg(args[i], XmNallowShellResize, True); i++;
|
|
XtSetArg(args[i], XmNmappedWhenManaged, False); i++;
|
|
MsgW = XmCreateMessageDialog(TopW, "Message", args, i);
|
|
XtUnmanageChild(XmMessageBoxGetChild(MsgW, XmDIALOG_HELP_BUTTON));
|
|
XtAddCallback(MsgW, XmNokCallback, dialog_resp_cb, (XtPointer)MsgW);
|
|
XtAddCallback(MsgW, XmNcancelCallback, dialog_resp_cb, (XtPointer)MsgW);
|
|
|
|
/* dialog is not located correctly unless once managed */
|
|
XtManageChild(MsgW); XtUnmanageChild(MsgW);
|
|
XtSetMappedWhenManaged(XtParent(MsgW), True);
|
|
XtSetMappedWhenManaged(MsgW, True);
|
|
set_cursor(MsgW, False);
|
|
}
|
|
btn = XmMessageBoxGetChild(MsgW, XmDIALOG_CANCEL_BUTTON);
|
|
|
|
if (wait_resp) XtManageChild(btn);
|
|
else XtUnmanageChild(btn);
|
|
|
|
str = XmStringCreateLocalized(msg);
|
|
XtVaSetValues(MsgW, XmNdialogType, type,
|
|
XmNmessageString, str,
|
|
XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
|
|
/*
|
|
XmNdialogStyle, wait_resp ? XmDIALOG_FULL_APPLICATION_MODAL
|
|
: XmDIALOG_MODELESS,
|
|
*/
|
|
NULL);
|
|
XmStringFree(str);
|
|
|
|
locate_window(MsgW);
|
|
XtManageChild(MsgW);
|
|
if (type == MSGTYP_FATAL || type == MSGTYP_WARN) {
|
|
Beep();
|
|
}
|
|
|
|
reply = XmCR_OK;
|
|
if (wait_resp) {
|
|
#ifdef unused
|
|
DPR3(("wait_dialog_resp(START): WaitingDialogReply ==> True\n"));
|
|
WaitingDialogReply = True;
|
|
|
|
reply = wait_confirmation(MsgW);
|
|
|
|
WaitingDialogReply = False;
|
|
DPR3(("wait_dialog_resp(DONE): WaitingDialogReply ==> False\n"));
|
|
#endif /* unused */
|
|
} else {
|
|
DPR3(("put_msg_win(): WaitingDialogReply ==> True\n"));
|
|
WaitingDialogReply = True;
|
|
}
|
|
|
|
return (reply == XmCR_OK) ? True : False;
|
|
}
|
|
|
|
|
|
/* ******** locate_window ******** */
|
|
|
|
#define LOC_NONE -1
|
|
#define LOC_CENTER 0
|
|
#define LOC_TOP (1<<0)
|
|
#define LOC_BOTTOM (1<<1)
|
|
#define LOC_LEFT (1<<2)
|
|
#define LOC_RIGHT (1<<3)
|
|
#define LOC_MARGIN 5
|
|
|
|
static int window_location(char *loc_str)
|
|
{
|
|
int locate_type = LOC_CENTER;
|
|
char *lower_str, *p;
|
|
|
|
lower_str = NEWSTR(loc_str);
|
|
if (p = lower_str) {
|
|
to_lower_str(p);
|
|
if (strstr(lower_str, "center")) locate_type |= LOC_CENTER;
|
|
if (strstr(lower_str, "top")) locate_type |= LOC_TOP;
|
|
if (strstr(lower_str, "bottom")) locate_type |= LOC_BOTTOM;
|
|
if (strstr(lower_str, "left")) locate_type |= LOC_LEFT;
|
|
if (strstr(lower_str, "right")) locate_type |= LOC_RIGHT;
|
|
FREE(lower_str);
|
|
}
|
|
return locate_type;
|
|
}
|
|
|
|
static void locate_window(Widget w)
|
|
{
|
|
int scr;
|
|
int x, y;
|
|
int dpy_w, dpy_h;
|
|
Dimension width, height;
|
|
static int locate_type = LOC_NONE;
|
|
|
|
/* if (!isXsession()) return; */
|
|
|
|
if (locate_type == LOC_NONE) {
|
|
locate_type = window_location(appres.windowLocation);
|
|
DPR3(("locate_window(): locate_type=%d (%s)\n",
|
|
locate_type, appres.windowLocation));
|
|
}
|
|
|
|
width = height = (Dimension) 0;
|
|
scr = XDefaultScreen(Dpy);
|
|
dpy_w = DisplayWidth(Dpy, scr);
|
|
dpy_h = DisplayHeight(Dpy, scr);
|
|
|
|
XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, NULL);
|
|
|
|
x = y = 0;
|
|
if (locate_type) {
|
|
if (locate_type & LOC_TOP) y = LOC_MARGIN;
|
|
if (locate_type & LOC_BOTTOM) y = dpy_h - height - LOC_MARGIN * 2;
|
|
if (locate_type & LOC_LEFT) x = LOC_MARGIN;
|
|
if (locate_type & LOC_RIGHT) x = dpy_w - width - LOC_MARGIN * 2;
|
|
}
|
|
if (!x) x = (int) (dpy_w - width - LOC_MARGIN * 2) / 2;
|
|
if (!y) y = (int) (dpy_h - height - LOC_MARGIN * 2) / 2;
|
|
|
|
DPR3(("locate_window(): w=%d h=%d ==> x=%d y=%d\n", width, height, x, y));
|
|
|
|
XtVaSetValues(w, XmNx, x, XmNy, y, NULL);
|
|
}
|
|
|
|
|
|
/* ******** cursor (normal / wait) ******** */
|
|
|
|
static void set_cursor(Widget w, int is_wait)
|
|
{
|
|
static Cursor cursors[2] = { None, None };
|
|
int idx;
|
|
|
|
idx = is_wait ? 1 : 0;
|
|
|
|
/* if (!Dpy || !TopW || !w) return; */
|
|
if (cursors[idx] == None) {
|
|
cursors[idx] = XCreateFontCursor(Dpy, idx ? XC_watch : XC_left_ptr);
|
|
}
|
|
|
|
XDefineCursor(Dpy, XtWindow(w), cursors[idx]);
|
|
XFlush(Dpy);
|
|
}
|
|
|
|
|
|
/* ***** waiting functions ***** */
|
|
void xevent_loop(void)
|
|
{
|
|
if (appC)
|
|
XtAppMainLoop(appC);
|
|
}
|
|
|
|
static time_t xt_start_tm = 0L; /* in sec */
|
|
static XtIntervalId xt_last_timer = (XtIntervalId)0;
|
|
static bool xt_waiting = False;
|
|
|
|
void xt_start_waiting(void)
|
|
{
|
|
if (!appC) return;
|
|
|
|
xt_start_tm = time((time_t) 0);
|
|
xt_last_timer = XtAppAddTimeOut(appC, (unsigned long) Opt.Interval,
|
|
xt_timer_cb, (XtPointer)0);
|
|
/* if (!xt_last_timer) return; */
|
|
|
|
DPR(("xt_start_waiting(): EventLoop (interval=%d)\n", Opt.Interval));
|
|
|
|
xt_waiting = True;
|
|
XtAppMainLoop(appC);
|
|
}
|
|
|
|
void xt_stop_waiting(void)
|
|
{
|
|
if (xt_last_timer) {
|
|
XtRemoveTimeOut(xt_last_timer);
|
|
xt_last_timer = (XtIntervalId) 0;
|
|
}
|
|
|
|
xt_waiting = False;
|
|
ximsWaitDone();
|
|
}
|
|
|
|
static void xt_timer_cb(XtPointer client_data, XtIntervalId *timer_id)
|
|
{
|
|
int lapse;
|
|
|
|
/* DPR3(("xt_timer_cb(timer_id=%d): last_timer=%d\n",
|
|
*timer_id, xt_last_timer)); */
|
|
|
|
if (*timer_id != xt_last_timer) return;
|
|
xt_last_timer = (XtIntervalId) 0;
|
|
lapse = (int) time((time_t) 0) - xt_start_tm;
|
|
|
|
#ifdef DEBUG
|
|
if (DebugLvl >= 1) putc('.', LogFp), fflush(LogFp);
|
|
#endif
|
|
|
|
if (im_mod_available((RunEnv *) 0) != 0 || lapse >= Opt.Timeout) {
|
|
DPR(("xt_timer_cb(tmout=%d): wait done (%d sec.)\n",
|
|
Opt.Timeout, lapse));
|
|
xt_stop_waiting(); /* never returns */
|
|
}
|
|
|
|
xt_last_timer = XtAppAddTimeOut(appC, (unsigned long) Opt.Interval,
|
|
xt_timer_cb, (XtPointer)0);
|
|
return;
|
|
}
|
|
|