#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "DialogF.h"
#include "misc.h"
#include "nedit_malloc.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <Xm/Xm.h>
#include <Xm/MessageB.h>
#include <Xm/DialogS.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/SelectioB.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/keysym.h>
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
#define NUM_DIALOGS_SUPPORTED 6
#define NUM_BUTTONS_SUPPORTED 3
#define NUM_BUTTONS_MAXPROMPT 4
#define MAX_TITLE_LEN 256
enum dialogBtnIndecies {
OK_BTN,
APPLY_BTN,
CANCEL_BTN,
HELP_BTN};
struct dfcallbackstruct {
unsigned button;
Boolean done_with_dialog;
unsigned apply_up;
Boolean destroyed;
};
static char **PromptHistory =
NULL;
static int NPromptHistoryItems = -
1;
static void apply_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data);
static void help_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data);
static void cancel_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data);
static void ok_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data);
static void destroy_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data);
static void focusCB(Widget w, Widget dialog,
caddr_t call_data);
static void addEscapeHandler(Widget dialog,
struct dfcallbackstruct *df,
int whichBtn);
static void escapeHelpCB(Widget w, XtPointer callData, XEvent *event,
Boolean *cont);
static void escapeApplyCB(Widget w, XtPointer callData, XEvent *event,
Boolean *cont);
static void createMnemonics(Widget w);
unsigned DialogF(
int dialog_type, Widget parent,
unsigned n,
const char* title,
const char* msgstr, ...)
{
va_list var;
Widget dialog, dialog_shell;
unsigned dialog_num, prompt;
XmString but_lbl_xms[
NUM_BUTTONS_MAXPROMPT];
XmString msgstr_xms, input_string_xms, titstr_xms;
char msgstr_vsp[
DF_MAX_MSG_LENGTH+
1];
char *but_lbl, *input_string =
NULL, *input_string_ptr;
int argcount, num_but_lbls =
0, i, but_index, cancel_index = -
1;
Arg args[
256];
char titleCopy[
MAX_TITLE_LEN];
struct dfcallbackstruct df;
static int dialog_types[] = {
XmDIALOG_ERROR,
XmDIALOG_INFORMATION,
XmDIALOG_MESSAGE,
XmDIALOG_QUESTION,
XmDIALOG_WARNING,
XmDIALOG_PROMPT
};
static char *dialog_name[] = {
"Error",
"Information",
"Message",
"Question",
"Warning",
"Prompt"
};
static unsigned char selectionButton_id[] =
{
XmDIALOG_OK_BUTTON,
XmDIALOG_APPLY_BUTTON,
XmDIALOG_CANCEL_BUTTON,
XmDIALOG_HELP_BUTTON
};
Cardinal
N_SELECTION_BUTTONS = XtNumber(selectionButton_id);
static unsigned char messageButton_id[] =
{
XmDIALOG_OK_BUTTON,
XmDIALOG_CANCEL_BUTTON,
XmDIALOG_HELP_BUTTON
};
Cardinal
N_MESSAGE_BUTTONS = XtNumber(messageButton_id);
static char *button_name[] = {
XmNokLabelString,
XmNapplyLabelString,
XmNcancelLabelString,
XmNhelpLabelString
};
if ((dialog_type >
NUM_DIALOGS_SUPPORTED) || (dialog_type <=
0)) {
printf (
"\nError calling DialogF - Unsupported dialog type\n");
return (
0);
}
dialog_num = dialog_type -
1;
prompt = (dialog_type ==
DF_PROMPT);
if ((!prompt && (n >
NUM_BUTTONS_SUPPORTED)) ||
(prompt && (n >
NUM_BUTTONS_MAXPROMPT))) {
printf (
"\nError calling DialogF - Too many buttons specified\n");
return (
0);
}
df.done_with_dialog = False;
df.destroyed = False;
va_start (var, msgstr);
if (prompt) {
input_string = va_arg(var,
char*);
}
if (n ==
NUM_BUTTONS_MAXPROMPT)
df.apply_up =
1;
else
df.apply_up =
0;
for (argcount =
0; argcount < (
int)n; ++argcount) {
but_lbl = va_arg(var,
char *);
but_lbl_xms[num_but_lbls] = XmStringCreateLtoR (but_lbl,
XmSTRING_DEFAULT_CHARSET);
but_index = df.apply_up ? argcount :
((argcount ==
0) ? argcount : argcount+
1);
XtSetArg (args[argcount], button_name[but_index],
but_lbl_xms[num_but_lbls++]);
if (!strcmp(but_lbl,
"Cancel") || !strcmp(but_lbl,
"Dismiss"))
cancel_index = but_index;
}
if (n ==
1)
cancel_index =
0;
vsprintf (msgstr_vsp, msgstr, var);
va_end(var);
strncpy(&titleCopy[
0], title,
MAX_TITLE_LEN);
titleCopy[
MAX_TITLE_LEN-
1] =
'\0';
msgstr_xms = XmStringCreateLtoR(msgstr_vsp, XmSTRING_DEFAULT_CHARSET);
titstr_xms = XmStringCreateLtoR(titleCopy, XmSTRING_DEFAULT_CHARSET);
if (prompt) {
XtSetArg (args[argcount], XmNselectionLabelString, msgstr_xms);
argcount++;
XtSetArg (args[argcount], XmNdialogTitle, titstr_xms);
argcount++;
XtSetArg (args[argcount], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
argcount ++;
dialog = CreatePromptDialog(parent, dialog_name[dialog_num], args,
argcount);
XtAddCallback (dialog, XmNokCallback, (XtCallbackProc)ok_callback,
(
char *)&df);
XtAddCallback (dialog, XmNcancelCallback,
(XtCallbackProc)cancel_callback, (
char *)&df);
XtAddCallback (dialog, XmNhelpCallback, (XtCallbackProc)help_callback,
(
char *)&df);
XtAddCallback (dialog, XmNapplyCallback, (XtCallbackProc)apply_callback,
(
char *)&df);
RemapDeleteKey(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
XtVaSetValues(dialog, XmNdefaultButton,
NULL,
NULL);
XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
XmNfocusCallback, (XtCallbackProc)focusCB, (
char *)dialog);
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
XmNmaxLength,
DF_MAX_PROMPT_LENGTH-
1,
NULL);
switch (n) {
case 0:
case 3:
break;
case 1:
XtUnmanageChild (XmSelectionBoxGetChild (dialog,
XmDIALOG_CANCEL_BUTTON) );
case 2:
XtUnmanageChild (XmSelectionBoxGetChild (dialog,
XmDIALOG_HELP_BUTTON) );
break;
case 4:
XtManageChild (XmSelectionBoxGetChild (dialog,
XmDIALOG_APPLY_BUTTON) );
df.apply_up =
1;
default:
break;
}
for (i =
0; (
unsigned) i <
N_SELECTION_BUTTONS; i++)
{
Widget button = XmSelectionBoxGetChild(dialog, selectionButton_id[i]);
if (XtIsManaged(button))
{
XtVaSetValues(button, XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
}
}
if (cancel_index == -
1)
addEscapeHandler(dialog,
NULL,
0);
else if (cancel_index !=
CANCEL_BTN)
addEscapeHandler(dialog, &df, cancel_index);
AddMotifCloseCallback(XtParent(dialog),
(XtCallbackProc)(cancel_index ==
APPLY_BTN ? apply_callback :
(cancel_index ==
CANCEL_BTN ? cancel_callback :
(cancel_index ==
HELP_BTN ? help_callback : ok_callback))), &df);
XtAddCallback(dialog, XmNdestroyCallback,
(XtCallbackProc)destroy_callback, &df);
if (NPromptHistoryItems != -
1)
AddHistoryToTextWidget(XmSelectionBoxGetChild(dialog,XmDIALOG_TEXT),
&PromptHistory, &NPromptHistoryItems);
ManageDialogCenteredOnPointer(dialog);
for (i=
0; i<
20; i++)
XmProcessTraversal(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
XmTRAVERSE_CURRENT);
while (!df.done_with_dialog && !df.destroyed)
XtAppProcessEvent (XtWidgetToApplicationContext(dialog), XtIMAll);
if (!df.destroyed) {
argcount =
0;
XtSetArg (args[argcount], XmNtextString, &input_string_xms); argcount++;
XtGetValues (dialog, args, argcount);
XmStringGetLtoR (input_string_xms, XmSTRING_DEFAULT_CHARSET,
&input_string_ptr);
strcpy (input_string, input_string_ptr);
XmStringFree(input_string_xms );
NEditFree(input_string_ptr);
XtRemoveCallback(dialog, XmNdestroyCallback,
(XtCallbackProc)destroy_callback, &df);
XtDestroyWidget(dialog);
}
PromptHistory =
NULL;
NPromptHistoryItems = -
1;
}
else {
XtSetArg (args[argcount], XmNmessageString, msgstr_xms); argcount++;
XtSetArg (args[argcount], XmNdialogType, dialog_types[dialog_num]);
argcount ++;
XtSetArg (args[argcount], XmNdialogTitle, titstr_xms);
argcount++;
XtSetArg (args[argcount], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
argcount ++;
dialog_shell = CreateDialogShell (parent, dialog_name[dialog_num],
0,
0);
dialog = XmCreateMessageBox (dialog_shell,
"msg box", args, argcount);
XtAddCallback (dialog, XmNokCallback, (XtCallbackProc)ok_callback,
(
char *)&df);
XtAddCallback (dialog, XmNcancelCallback,
(XtCallbackProc)cancel_callback, (
char *)&df);
XtAddCallback (dialog, XmNhelpCallback, (XtCallbackProc)help_callback,
(
char *)&df);
switch (n) {
case 0:
case 3:
break;
case 1:
XtUnmanageChild (XmMessageBoxGetChild (dialog,
XmDIALOG_CANCEL_BUTTON) );
case 2:
XtUnmanageChild (XmMessageBoxGetChild (dialog,
XmDIALOG_HELP_BUTTON) );
break;
default:
break;
}
for (i =
0; (
unsigned) i <
N_MESSAGE_BUTTONS; i++)
{
Widget button = XmMessageBoxGetChild(dialog, messageButton_id[i]);
if (XtIsManaged(button))
{
XtVaSetValues(button, XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
}
}
createMnemonics(dialog_shell);
AddDialogMnemonicHandler(dialog_shell,
TRUE);
if (cancel_index == -
1)
addEscapeHandler(dialog,
NULL,
0);
else if (cancel_index !=
CANCEL_BTN)
addEscapeHandler(dialog, &df, cancel_index);
AddMotifCloseCallback(XtParent(dialog),
(XtCallbackProc)(cancel_index ==
APPLY_BTN ? apply_callback :
(cancel_index ==
CANCEL_BTN ? cancel_callback :
(cancel_index ==
HELP_BTN ? help_callback : ok_callback))),&df);
XtAddCallback(dialog_shell, XmNdestroyCallback,
(XtCallbackProc)destroy_callback, &df);
ManageDialogCenteredOnPointer(dialog);
while (!df.done_with_dialog && !df.destroyed)
XtAppProcessEvent (XtWidgetToApplicationContext(dialog), XtIMAll);
if (!df.destroyed) {
XtRemoveCallback(dialog_shell, XmNdestroyCallback,
(XtCallbackProc)destroy_callback, &df);
XtDestroyWidget(dialog_shell);
}
}
XmStringFree(msgstr_xms);
XmStringFree(titstr_xms);
for (i =
0; i < num_but_lbls; ++i)
XmStringFree(but_lbl_xms[i]);
if (df.destroyed) {
df.button = cancel_index ==
APPLY_BTN ?
2 :
(cancel_index ==
CANCEL_BTN ?
2 + df.apply_up :
(cancel_index ==
HELP_BTN ?
3 + df.apply_up :
1));
}
df.apply_up =
0;
return (df.button);
}
void SetDialogFPromptHistory(
char **historyList,
int nItems)
{
PromptHistory = historyList;
NPromptHistoryItems = nItems;
}
static void ok_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data)
{
client_data->done_with_dialog = True;
client_data->button =
1;
}
static void cancel_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data)
{
client_data->done_with_dialog = True;
client_data->button =
2 + client_data->apply_up;
}
static void help_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data)
{
client_data->done_with_dialog = True;
client_data->button =
3 + client_data->apply_up;
}
static void apply_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data)
{
client_data->done_with_dialog = True;
client_data->button =
2;
}
static void destroy_callback (Widget w,
struct dfcallbackstruct *client_data,
caddr_t call_data)
{
client_data->destroyed = True;
}
static void focusCB(Widget w, Widget dialog,
caddr_t call_data)
{
XtVaSetValues(dialog, XmNdefaultButton,
XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
NULL);
}
static void addEscapeHandler(Widget dialog,
struct dfcallbackstruct *df,
int whichBtn)
{
XtAddEventHandler(dialog, KeyPressMask, False, whichBtn ==
APPLY_BTN ?
escapeApplyCB : escapeHelpCB, (XtPointer)df);
XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
True, GrabModeAsync, GrabModeAsync);
}
static void escapeHelpCB(Widget w, XtPointer callData, XEvent *event,
Boolean *cont)
{
if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
return;
if (callData !=
NULL)
help_callback(w, (
struct dfcallbackstruct *)callData,
NULL);
*cont = False;
}
static void escapeApplyCB(Widget w, XtPointer callData, XEvent *event,
Boolean *cont)
{
if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
return;
if (callData !=
NULL)
apply_callback(w, (
struct dfcallbackstruct *)callData,
NULL);
*cont = False;
}
static void recurseCreateMnemonics(Widget w, Boolean *mnemonicUsed)
{
WidgetList children;
Cardinal numChildren, i;
XtVaGetValues(w,
XmNchildren, &children,
XmNnumChildren, &numChildren,
NULL);
for (i =
0; i < numChildren; i++)
{
Widget child = children[i];
if (XtIsComposite(child))
{
recurseCreateMnemonics(child, mnemonicUsed);
}
else if (XtIsSubclass(child, xmPushButtonWidgetClass) ||
XtIsSubclass(child, xmPushButtonGadgetClass))
{
XmString xmslabel;
char *label;
int c;
XtVaGetValues(child, XmNlabelString, &xmslabel,
NULL);
if (XmStringGetLtoR(xmslabel, XmSTRING_DEFAULT_CHARSET, &label))
{
int labelLen = strlen(label);
for (c =
0; c < labelLen; c++)
{
unsigned char lc = tolower((
unsigned char)label[c]);
if (!mnemonicUsed[lc] && isalnum(lc))
{
mnemonicUsed[lc] =
TRUE;
XtVaSetValues(child, XmNmnemonic, label[c],
NULL);
break;
}
}
NEditFree(label);
}
XmStringFree(xmslabel);
}
}
}
static void createMnemonics(Widget w)
{
Boolean mnemonicUsed[
UCHAR_MAX +
1];
memset(mnemonicUsed,
FALSE,
sizeof(mnemonicUsed));
recurseCreateMnemonics(w, mnemonicUsed);
}