зеркало из https://github.com/mozilla/gecko-dev.git
6322 строки
181 KiB
C
6322 строки
181 KiB
C
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public License
|
||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
* http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
* for the specific language governing rights and limitations under the
|
||
* NPL.
|
||
*
|
||
* The Initial Developer of this code under the NPL is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
/*
|
||
dialogs.c --- General UI functions used elsewhere.
|
||
Created: Jamie Zawinski <jwz@netscape.com>, 23-Jun-94.
|
||
*/
|
||
|
||
|
||
/* #define DOCINFO_SOURCE_TEXT */
|
||
#define DOCINFO_VISUAL_TEXT
|
||
|
||
#include "mozilla.h"
|
||
#include "net.h" /* for fe_makeSecureTitle */
|
||
#include "xlate.h"
|
||
#include "xfe.h"
|
||
#include "felocale.h"
|
||
#include "outline.h"
|
||
#include "mailnews.h"
|
||
|
||
#include <Xm/FileSBP.h> /* for hacking FS lossage */
|
||
|
||
#include <Xm/XmAll.h>
|
||
#include <Xm/CascadeB.h>
|
||
|
||
#include <Xfe/XfeP.h> /* for xfe widgets and utilities */
|
||
|
||
#include "libi18n.h"
|
||
#include "intl_csi.h"
|
||
|
||
#include "np.h"
|
||
#include "xp_trace.h"
|
||
#include <layers.h>
|
||
#include "xeditor.h"
|
||
#include "xp_qsort.h"
|
||
|
||
/* for XP_GetString() */
|
||
#include <xpgetstr.h>
|
||
extern int XFE_OPEN_FILE;
|
||
extern int XFE_ERROR_OPENING_FILE;
|
||
extern int XFE_CANNOT_READ_FILE;
|
||
extern int XFE_ERROR_OPENING_PIPE;
|
||
extern int XFE_NO_SUBJECT;
|
||
extern int XFE_UNKNOWN_ERROR_CODE;
|
||
extern int XFE_INVALID_FILE_ATTACHMENT_DOESNT_EXIST;
|
||
extern int XFE_INVALID_FILE_ATTACHMENT_NOT_READABLE;
|
||
extern int XFE_INVALID_FILE_ATTACHMENT_IS_A_DIRECTORY;
|
||
extern int XFE_ERROR_SAVING_OPTIONS;
|
||
extern int XFE_X_RESOURCES_NOT_INSTALLED_CORRECTLY;
|
||
extern int XFE_OUTBOX_CONTAINS_MSG;
|
||
extern int XFE_OUTBOX_CONTAINS_MSGS;
|
||
extern int XFE_CONTINUE_MOVEMAIL;
|
||
extern int XFE_CANCEL_MOVEMAIL;
|
||
extern int XFE_MOVEMAIL_EXPLANATION;
|
||
extern int XFE_SHOW_NEXT_TIME;
|
||
extern int XFE_MAIL_SPOOL_UNKNOWN;
|
||
extern int XFE_CANT_SAVE_PREFS;
|
||
extern int XFE_JAVASCRIPT_APP;
|
||
extern int XFE_DIALOGS_PRINTING;
|
||
extern int XFE_DIALOGS_DEFAULT_VISUAL_AND_COLORMAP;
|
||
extern int XFE_DIALOGS_DEFAULT_VISUAL_AND_PRIVATE_COLORMAP;
|
||
extern int XFE_DIALOGS_NON_DEFAULT_VISUAL;
|
||
extern int XFE_DIALOGS_FROM_NETWORK;
|
||
extern int XFE_DIALOGS_FROM_DISK_CACHE;
|
||
extern int XFE_DIALOGS_FROM_MEMORY_CACHE;
|
||
extern int XFE_DIALOGS_DEFAULT;
|
||
|
||
#if XmVersion >= 2000
|
||
extern void _XmOSBuildFileList(String,String,unsigned char,String * *,
|
||
unsigned int *,unsigned int *);
|
||
|
||
extern char * _XmStringGetTextConcat(XmString);
|
||
|
||
extern int _XmOSFileCompare(XmConst void *,XmConst void *);
|
||
|
||
extern String _XmOSFindPatternPart(String);
|
||
|
||
extern void _XmOSQualifyFileSpec(String,String,String *,String *);
|
||
|
||
extern XmGeoMatrix _XmGeoMatrixAlloc(unsigned int,unsigned int,unsigned int);
|
||
|
||
extern Boolean _XmGeoSetupKid(XmKidGeometry,Widget);
|
||
|
||
extern void _XmMenuBarFix(XmGeoMatrix,int,XmGeoMajorLayout,XmKidGeometry);
|
||
|
||
extern void _XmSeparatorFix(XmGeoMatrix,int,XmGeoMajorLayout,XmKidGeometry);
|
||
|
||
extern void _XmDestroyParentCallback(Widget,XtPointer,XtPointer);
|
||
|
||
#endif /* XmVersion >= 2000 */
|
||
|
||
|
||
#define DOCINFO_CHARSET_TEXT
|
||
|
||
/* Kludge around conflicts between Motif and xp_core.h... */
|
||
#undef Bool
|
||
#define Bool char
|
||
|
||
typedef enum {
|
||
Answer_Invalid = -1,
|
||
Answer_Cancel = 0,
|
||
Answer_OK,
|
||
Answer_Apply,
|
||
Answer_Destroy } Answers;
|
||
|
||
struct fe_confirm_data {
|
||
MWContext *context;
|
||
Answers answer;
|
||
void *return_value;
|
||
void *return_value_2;
|
||
Widget widget;
|
||
Widget text, text2;
|
||
Boolean must_match;
|
||
};
|
||
|
||
#ifdef MOZ_MAIL_NEWS
|
||
extern void fe_getMessageBody(MWContext *context, char **pBody, uint32 *body_size, MSG_FontCode **font_changes);
|
||
extern void fe_doneWithMessageBody(MWContext *context, char *pBody, uint32 body_size);
|
||
#endif
|
||
|
||
extern const char* FE_GetFolderDirectory(MWContext* context);
|
||
|
||
/*static void fe_confirm_cb (Widget, XtPointer, XtPointer);*/
|
||
static void fe_clear_text_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_ok_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_apply_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_cancel_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_finish_cb (Widget, XtPointer, XtPointer);
|
||
|
||
static void fe_destroy_snarf_text_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_snarf_pw_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_destroy_snarf_pw2_cb (Widget, XtPointer, XtPointer);
|
||
|
||
void fe_browse_file_of_text (MWContext *context, Widget text_field, Boolean dirp);
|
||
|
||
/*
|
||
* A real Info dialog - with ! instead of error icon.
|
||
* Now we don't have to have "error: no new messages on server"
|
||
*/
|
||
void
|
||
FE_Message(MWContext * context, const char* message)
|
||
{
|
||
if (context && context->type != MWContextBiff)
|
||
fe_Message(context, message);
|
||
}
|
||
|
||
/* FE_Alert is no longer defined in fe_proto.h */
|
||
void
|
||
FE_Alert (MWContext *context, const char *message)
|
||
{
|
||
if (context && context->type == MWContextBiff)
|
||
return;
|
||
|
||
if (context)
|
||
XFE_Alert (context, message);
|
||
else
|
||
{
|
||
Widget toplevel = FE_GetToplevelWidget();
|
||
if ( toplevel ) {
|
||
fe_Alert_2(toplevel, message);
|
||
} else {
|
||
/* So that didn't even work. Write to stdout and
|
||
* exit.
|
||
*/
|
||
XP_ABORT((message));
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Hack for 109371 */
|
||
void
|
||
FE_Alert_modal (MWContext *context, const char *message)
|
||
{
|
||
if (context && context->type == MWContextBiff)
|
||
return;
|
||
|
||
if (context)
|
||
fe_Alert_modal(CONTEXT_WIDGET (context), message);
|
||
else
|
||
{
|
||
Widget toplevel = FE_GetToplevelWidget();
|
||
if ( toplevel ) {
|
||
fe_Alert_2(toplevel, message);
|
||
} else {
|
||
/* So that didn't even work. Write to stdout and
|
||
* exit.
|
||
*/
|
||
XP_ABORT((message));
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Lame hack to get the right title for javascript dialogs.
|
||
* This should be instead added to the call arguments.
|
||
*/
|
||
static MWContext *javaScriptCallingContextHack = 0;
|
||
|
||
/* Display a message, and wait for the user to click "Ok".
|
||
A pointer to the string is not retained.
|
||
The call to FE_Alert() returns immediately - it does not
|
||
wait for the user to click OK.
|
||
*/
|
||
void
|
||
XFE_Alert (MWContext *context, const char *message)
|
||
{
|
||
/* Keep the context around, so we can pull the domain name
|
||
* full the dialog title.
|
||
*/
|
||
if (context->bJavaScriptCalling)
|
||
javaScriptCallingContextHack = context;
|
||
|
||
fe_Alert_2(CONTEXT_WIDGET (context), message);
|
||
}
|
||
|
||
/* Just like XFE_Alert, but with a different dialog title. */
|
||
void
|
||
fe_stderr (MWContext *context, const char *message)
|
||
{
|
||
(void) fe_dialog (CONTEXT_WIDGET (context),
|
||
(fe_globalData.stderr_dialog_p &&
|
||
fe_globalData.stdout_dialog_p
|
||
? "stdout_stderr"
|
||
: fe_globalData.stderr_dialog_p ? "stderr"
|
||
: fe_globalData.stdout_dialog_p ? "stdout" : "???" ),
|
||
message, FALSE, 0, FALSE, FALSE, 0);
|
||
}
|
||
|
||
|
||
/* Let the user confirm or deny assertion `message' (returns True or False.)
|
||
A pointer to the prompt-string is not retained.
|
||
*/
|
||
XP_Bool
|
||
XFE_Confirm (MWContext *context, const char *message)
|
||
{
|
||
return fe_Confirm_2 (CONTEXT_WIDGET (context), message);
|
||
}
|
||
|
||
/*
|
||
* Yet Another front end function that
|
||
* noone told us we were supposed to implement.
|
||
*/
|
||
PRBool
|
||
XP_Confirm(MWContext *c, const char *msg)
|
||
{
|
||
return XFE_Confirm(c,msg);
|
||
}
|
||
|
||
Boolean
|
||
fe_Confirm_2 (Widget parent, const char *message)
|
||
{
|
||
return (Bool) ((int) fe_dialog (parent, "question", message,
|
||
TRUE, 0, TRUE, FALSE, 0));
|
||
}
|
||
|
||
void
|
||
fe_Alert_modal (Widget parent, const char *message)
|
||
{
|
||
(void) fe_dialog (parent, "error", message, FALSE, 0, TRUE, FALSE, 0);
|
||
}
|
||
|
||
void
|
||
fe_Alert_2 (Widget parent, const char *message)
|
||
{
|
||
(void) fe_dialog (parent, "error", message, FALSE, 0, FALSE, FALSE, 0);
|
||
}
|
||
|
||
#if !defined(HAVE_SYSERRLIST)
|
||
#include <sys/errno.h>
|
||
extern char *sys_errlist[];
|
||
extern int sys_nerr;
|
||
#endif
|
||
|
||
/* Like perror, but with a dialog.
|
||
*/
|
||
void
|
||
fe_perror (MWContext *context, const char *message)
|
||
{
|
||
fe_perror_2 (CONTEXT_WIDGET (context), message);
|
||
}
|
||
|
||
void
|
||
fe_perror_2 (Widget parent, const char *message)
|
||
{
|
||
int e = errno;
|
||
char *es = 0;
|
||
char buf1 [2048];
|
||
char buf2 [512];
|
||
char *b = buf1;
|
||
if (e >= 0 && e < sys_nerr)
|
||
{
|
||
es = sys_errlist [e];
|
||
}
|
||
else
|
||
{
|
||
PR_snprintf (buf2, sizeof (buf2), XP_GetString( XFE_UNKNOWN_ERROR_CODE ),
|
||
errno);
|
||
es = buf2;
|
||
}
|
||
if (message)
|
||
PR_snprintf (buf1, sizeof (buf1), "%.900s\n%.900s", message, es);
|
||
else
|
||
b = buf2;
|
||
fe_Alert_2 (parent, b);
|
||
}
|
||
|
||
void
|
||
fe_UnmanageChild_safe (Widget w)
|
||
{
|
||
if (w) XtUnmanageChild (w);
|
||
}
|
||
|
||
|
||
void
|
||
fe_NukeBackingStore (Widget widget)
|
||
{
|
||
XSetWindowAttributes attrs;
|
||
unsigned long attrmask;
|
||
|
||
if (!XtIsTopLevelShell (widget))
|
||
widget = XtParent (widget);
|
||
XtRealizeWidget (widget);
|
||
|
||
attrmask = CWBackingStore | CWSaveUnder;
|
||
attrs.backing_store = NotUseful;
|
||
attrs.save_under = False;
|
||
XChangeWindowAttributes (XtDisplay (widget), XtWindow (widget),
|
||
attrmask, &attrs);
|
||
}
|
||
|
||
|
||
Widget
|
||
|
||
#ifdef OSF1
|
||
fe_CreateTextField (Widget parent, char *name, Arg *av, int ac)
|
||
#else
|
||
fe_CreateTextField (Widget parent, const char *name, Arg *av, int ac)
|
||
#endif
|
||
{
|
||
Widget w;
|
||
|
||
#if 1
|
||
w = XmCreateTextField (parent, (char *) name, av, ac);
|
||
#else
|
||
XtSetArg (av[ac], XmNeditMode, XmSINGLE_LINE_EDIT); ac++;
|
||
w = XmCreateTextField (parent, (char *) name, av, ac);
|
||
#endif
|
||
|
||
fe_HackTextTranslations (w);
|
||
return w;
|
||
}
|
||
|
||
Widget
|
||
fe_CreateText (Widget parent, const char *name, Arg *av, int ac)
|
||
{
|
||
Widget w = XmCreateText (parent, (char *) name, av, ac);
|
||
fe_HackTextTranslations (w);
|
||
return w;
|
||
}
|
||
|
||
|
||
static void
|
||
fe_select_text(Widget text)
|
||
{
|
||
XmTextPosition first = 0;
|
||
XmTextPosition last = XmTextGetLastPosition (text);
|
||
XP_ASSERT (XtIsRealized(text));
|
||
XmTextSetSelection (text, first, last,
|
||
XtLastTimestampProcessed (XtDisplay (text)));
|
||
}
|
||
|
||
|
||
/* The purpose of this function is try disable all grabs and settle
|
||
* focus issues. This will be called before we popup a dialog
|
||
* (modal or non-modal). This needs to do all these:
|
||
* - if a menu was posted, unpost it.
|
||
* - if a popup menu was up, pop it down.
|
||
* - if an option menu, pop it down.
|
||
*/
|
||
void fe_fixFocusAndGrab(MWContext *context)
|
||
{
|
||
Widget focus_w;
|
||
Widget mainw;
|
||
XEvent event;
|
||
int i;
|
||
|
||
mainw = CONTEXT_WIDGET(context);
|
||
focus_w = XmGetFocusWidget(mainw);
|
||
|
||
/* Unpost Menubar */
|
||
if (focus_w && XmIsCascadeButton(focus_w) &&
|
||
XmIsRowColumn(XtParent(focus_w))) {
|
||
/* 1. Found the menubar. Unpost it.
|
||
* To do that, we makeup a dummy event and use it with the
|
||
* CleanupMenuBar() action.
|
||
* WARNING: if focus_w was a XmCascadeButtonGadget we wont be able to
|
||
* do this.
|
||
*/
|
||
event.xany.type = 0;
|
||
event.xany.serial = 0;
|
||
event.xany.send_event = 0;
|
||
event.xany.display = fe_display;
|
||
event.xany.window = XtWindow(focus_w);
|
||
XtCallActionProc(focus_w, "CleanupMenuBar", &event, NULL, 0);
|
||
}
|
||
|
||
/* Identify and Popdown any OptionMenu that was active */
|
||
if (focus_w && XmIsRowColumn(XtParent(focus_w))) {
|
||
unsigned char type;
|
||
Widget w;
|
||
XtVaGetValues(XtParent(focus_w), XmNrowColumnType, &type, 0);
|
||
if (type == XmMENU_OPTION) {
|
||
XtVaGetValues(focus_w, XmNsubMenuId, &w, 0);
|
||
if (w) XtUnmanageChild(w);
|
||
}
|
||
}
|
||
|
||
/* Identify and Popdown any popup menus that were active */
|
||
for (i=0; i < XfeNumPopups(mainw); i++) {
|
||
Widget popup = XfePopupListIndex(mainw,i);
|
||
if (XtIsShell(popup) && XmIsMenuShell(popup))
|
||
if (XfeShellIsPoppedUp(popup)) {
|
||
#ifdef DEBUG_dora
|
||
printf("popdown... name %s shell is popped up\n", XtName(popup));
|
||
#endif
|
||
XtPopdown(popup);
|
||
}
|
||
}
|
||
}
|
||
|
||
static char *fe_makeSecureTitle( MWContext *context )
|
||
{
|
||
History_entry *h;
|
||
char *domain = 0;
|
||
char *title = 0;
|
||
|
||
if( !context )
|
||
{
|
||
return title;
|
||
}
|
||
|
||
h = SHIST_GetCurrent (&context->hist);
|
||
|
||
if (!h || !h->address) return title;
|
||
|
||
domain = NET_ParseURL(h->address, GET_HOST_PART);
|
||
|
||
if (domain) {
|
||
title = PR_smprintf("%s - %s", domain, XP_GetString(XFE_JAVASCRIPT_APP));
|
||
XP_FREE(domain);
|
||
} else {
|
||
title = PR_smprintf("%s", XP_GetString(XFE_JAVASCRIPT_APP));
|
||
}
|
||
|
||
return title;
|
||
}
|
||
|
||
void *
|
||
fe_prompt (MWContext *context, Widget mainw,
|
||
const char *title, const char *message,
|
||
XP_Bool question_p, const char *default_text,
|
||
XP_Bool wait_p, XP_Bool select_p,
|
||
char **passwd)
|
||
{
|
||
/* Keep the context around, so we can pull the domain name
|
||
* full the dialog title.
|
||
*/
|
||
if (context->bJavaScriptCalling)
|
||
javaScriptCallingContextHack = context;
|
||
|
||
return fe_dialog(mainw, title, message, question_p,
|
||
default_text, wait_p, select_p, passwd);
|
||
}
|
||
|
||
/* This function is complete madness - it takes a billion flags
|
||
and does everything in the world because somehow I thought it would save
|
||
me a bunch of lines of code but it's just a MESS!
|
||
*/
|
||
void *
|
||
fe_dialog (Widget mainw,
|
||
const char *title, const char *message,
|
||
XP_Bool question_p, const char *default_text,
|
||
XP_Bool wait_p, XP_Bool select_p,
|
||
char **passwd)
|
||
{
|
||
Widget shell, dialog;
|
||
Widget text = 0, pwtext = 0;
|
||
XmString xm_message = 0;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
char title2 [255];
|
||
struct fe_MWContext_cons *cons;
|
||
int i;
|
||
char *javaScriptTitle = 0; /* dialog title when javascript calls */
|
||
XP_Bool javaScriptCalling = FALSE;
|
||
|
||
strcpy (title2, title);
|
||
strcat (title2, "_popup");
|
||
|
||
/* Use this global variable hackery to get the context */
|
||
if (javaScriptCallingContextHack) {
|
||
javaScriptTitle = fe_makeSecureTitle(javaScriptCallingContextHack);
|
||
javaScriptCallingContextHack = NULL;
|
||
javaScriptCalling = TRUE;
|
||
}
|
||
|
||
if (!mainw) {
|
||
/* Yikes. Well, this can happen if someone calls FE_Alert() on a biff
|
||
context or some other context without a window. We could ignore it,
|
||
but I think it better to try and put the dialog up *someplace*. So,
|
||
look for some context with a reasonable window. */
|
||
for (cons = fe_all_MWContexts ; cons && !mainw; cons = cons->next) {
|
||
mainw = CONTEXT_WIDGET(cons->context);
|
||
}
|
||
if (!mainw) return NULL;
|
||
}
|
||
|
||
while(!XtIsWMShell(mainw) && (XtParent(mainw)!=0))
|
||
mainw = XtParent(mainw);
|
||
|
||
/* so, if the context that is popping up the dialog is hidden, we need
|
||
to pop it up _somewhere_, so we run down the list of contexts *again*,
|
||
and pop it up over one of them. This should work. I think. */
|
||
if (!XfeIsViewable(mainw))
|
||
{
|
||
Widget attempt = mainw;
|
||
/* instead of popping up the dialog at (0,0) pop it up over
|
||
the active context */
|
||
for (cons = fe_all_MWContexts ;
|
||
cons && !XfeIsViewable(attempt);
|
||
cons = cons->next)
|
||
{
|
||
attempt = CONTEXT_WIDGET(cons->context);
|
||
|
||
while(!XtIsWMShell(attempt) && (XtParent(attempt)!=0))
|
||
attempt = XtParent(attempt);
|
||
}
|
||
|
||
/* oh well, we tried. */
|
||
if (attempt)
|
||
mainw = attempt;
|
||
}
|
||
|
||
/* If any dialog is already up we will cascade these dialogs. Thus this
|
||
* dialog will be the child of the last popped up dialog.
|
||
*/
|
||
i = XfeNumPopups(mainw);
|
||
while (i>0)
|
||
if (XmIsDialogShell(XfePopupListIndex(mainw,i-1)) &&
|
||
(XfeIsViewable(XfePopupListIndex(mainw,i-1)))) {
|
||
/* Got a new mainw */
|
||
Widget newmainw = XfePopupListIndex(mainw,i-1);
|
||
#ifdef DEBUG_dp
|
||
fprintf(stderr, "Using mainw: %s[%x] (%s[%x] num_popup=%d)\n",
|
||
XtName(newmainw), newmainw,
|
||
XtName(mainw), mainw, i);
|
||
#endif /* DEBUG_dp */
|
||
mainw = newmainw;
|
||
i = XfeNumPopups(mainw);
|
||
}
|
||
else i--;
|
||
|
||
/* Popdown any popup menu that was active. If not, this could get motif
|
||
* motif really confused as to who has focus as the new dialog that we
|
||
* are going to popup will undo a grab that the popup did without the
|
||
* popup's knowledge.
|
||
*/
|
||
for (cons = fe_all_MWContexts ; cons; cons = cons->next)
|
||
fe_fixFocusAndGrab(cons->context);
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
shell = XmCreateDialogShell (mainw, title2, av, ac);
|
||
|
||
/* If it is java script that is posting this, use this special title */
|
||
if (javaScriptTitle) {
|
||
XtVaSetValues (shell, XmNtitle, javaScriptTitle, 0);
|
||
free(javaScriptTitle);
|
||
}
|
||
|
||
ac = 0;
|
||
if (message)
|
||
xm_message = XmStringCreateLtoR ((char *) message,
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
XtSetArg (av[ac], XmNdialogStyle, (wait_p
|
||
? XmDIALOG_FULL_APPLICATION_MODAL
|
||
: XmDIALOG_MODELESS)); ac++;
|
||
XtSetArg (av[ac], XmNdialogType,
|
||
(default_text
|
||
? XmDIALOG_MESSAGE
|
||
: (question_p
|
||
? XmDIALOG_QUESTION
|
||
: (javaScriptCalling
|
||
? XmDIALOG_WARNING
|
||
: XmDIALOG_ERROR)))); ac++;
|
||
if (xm_message) XtSetArg (av[ac], XmNmessageString, xm_message), ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
dialog = XmCreateMessageBox (shell, "dialog", av, ac);
|
||
if (xm_message) XmStringFree (xm_message);
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XtNameToWidget (dialog, "*Help"));
|
||
#endif
|
||
|
||
|
||
if (! question_p )
|
||
{
|
||
Widget cancel = 0;
|
||
XtVaGetValues (dialog, XmNcancelButton, &cancel, 0);
|
||
if (! cancel) abort ();
|
||
XtUnmanageChild (cancel);
|
||
}
|
||
|
||
if (default_text)
|
||
{
|
||
Widget clear;
|
||
Widget text_parent = dialog;
|
||
Widget ulabel = 0, plabel = 0;
|
||
|
||
text = 0;
|
||
pwtext = 0;
|
||
|
||
if (passwd && passwd != (char **) 1)
|
||
{
|
||
ac = 0;
|
||
text_parent = XmCreateForm (dialog, "dialogform", av, ac);
|
||
ulabel = XmCreateLabelGadget (text_parent, "userLabel", av, ac);
|
||
plabel = XmCreateLabelGadget (text_parent, "passwdLabel", av, ac);
|
||
XtVaSetValues (ulabel,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||
XmNbottomWidget, plabel,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNrightWidget, plabel,
|
||
0);
|
||
XtVaSetValues (plabel,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
}
|
||
|
||
if (passwd != (char **) 1)
|
||
{
|
||
ac = 0;
|
||
text = fe_CreateTextField (text_parent, "text", av, ac);
|
||
fe_SetTextField(text, default_text);
|
||
XtVaSetValues (text, XmNcursorPosition, 0, 0);
|
||
}
|
||
|
||
if (passwd)
|
||
{
|
||
ac = 0;
|
||
pwtext = fe_CreateTextField (text_parent, "pwtext", av, ac);
|
||
}
|
||
|
||
if (text && pwtext)
|
||
{
|
||
if (fe_globalData.nonterminal_text_translations)
|
||
XtOverrideTranslations (text, fe_globalData.
|
||
nonterminal_text_translations);
|
||
|
||
XtVaSetValues (text,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||
XmNbottomWidget, pwtext,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, ulabel,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (pwtext,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, plabel,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtManageChild (ulabel);
|
||
XtManageChild (plabel);
|
||
}
|
||
|
||
if (text)
|
||
XtManageChild (text);
|
||
if (pwtext)
|
||
XtManageChild (pwtext);
|
||
|
||
if (text && pwtext)
|
||
XtManageChild (text_parent);
|
||
|
||
XtVaSetValues (text_parent, XmNinitialFocus, (text ? text : pwtext), 0);
|
||
XtVaSetValues (dialog, XmNinitialFocus, (text ? text : pwtext), 0);
|
||
|
||
ac = 0;
|
||
clear = XmCreatePushButtonGadget (dialog, "clear", av, ac);
|
||
if (pwtext)
|
||
XtAddCallback (clear, XmNactivateCallback, fe_clear_text_cb, pwtext);
|
||
if (text)
|
||
XtAddCallback (clear, XmNactivateCallback, fe_clear_text_cb, text);
|
||
XtManageChild (clear);
|
||
}
|
||
|
||
if (! wait_p)
|
||
{
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_cb, shell);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cb, shell);
|
||
XtManageChild (dialog);
|
||
if (text && select_p)
|
||
fe_select_text (text);
|
||
return False;
|
||
}
|
||
else
|
||
{
|
||
struct fe_confirm_data data;
|
||
void *ret_val = 0;
|
||
|
||
/* data.context = context; */
|
||
data.answer = Answer_Invalid;
|
||
data.widget = shell;
|
||
data.text = (text ? text : pwtext);
|
||
data.text2 = ((text && pwtext) ? pwtext : 0);
|
||
data.return_value = 0;
|
||
data.return_value_2 = 0;
|
||
|
||
XtVaSetValues (shell, XmNdeleteResponse, XmDESTROY, 0);
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_ok_cb, &data);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
if (text)
|
||
XtAddCallback (text, XmNdestroyCallback, fe_destroy_snarf_text_cb,
|
||
&data);
|
||
|
||
if (text && pwtext)
|
||
XtAddCallback (pwtext, XmNdestroyCallback, fe_destroy_snarf_pw2_cb,
|
||
&data);
|
||
else if (pwtext)
|
||
XtAddCallback (pwtext, XmNdestroyCallback, fe_destroy_snarf_pw_cb,
|
||
&data);
|
||
|
||
if (pwtext)
|
||
fe_SetupPasswdText (pwtext, 1024);
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
|
||
if (text)
|
||
{
|
||
XtVaSetValues (text, XmNcursorPosition, 0, 0);
|
||
XtVaSetValues (text, XmNcursorPositionVisible, True, 0);
|
||
if (select_p)
|
||
fe_select_text (text);
|
||
}
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (default_text)
|
||
{
|
||
if (data.answer == Answer_OK) /* user clicked OK at the text */
|
||
{
|
||
if (text && pwtext)
|
||
{
|
||
if (!data.return_value || !data.return_value_2) abort ();
|
||
*passwd = data.return_value_2;
|
||
ret_val = data.return_value;
|
||
}
|
||
else if (text || pwtext)
|
||
{
|
||
if (! data.return_value) abort ();
|
||
ret_val = data.return_value;
|
||
}
|
||
else
|
||
abort ();
|
||
}
|
||
else /* user clicked cancel */
|
||
{
|
||
if (data.return_value)
|
||
free (data.return_value);
|
||
if (data.return_value_2)
|
||
free (data.return_value_2);
|
||
ret_val = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret_val = (data.answer == Answer_OK
|
||
? (void *) True
|
||
: (void *) False);
|
||
}
|
||
|
||
/* We need to suck the values out of the widgets before destroying them.
|
||
*/
|
||
/* Ok, with the new way, it got destroyed by the callbacks on the
|
||
OK and Cancel buttons. */
|
||
/* XtDestroyWidget (shell); */
|
||
return ret_val;
|
||
}
|
||
}
|
||
|
||
|
||
void
|
||
fe_Message (MWContext *context, const char *message)
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget shell, dialog;
|
||
XmString xm_message;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
shell = XmCreateDialogShell (mainw, "message_popup", av, ac);
|
||
ac = 0;
|
||
xm_message = XmStringCreateLtoR ((char *) message, XmFONTLIST_DEFAULT_TAG);
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_MESSAGE); ac++;
|
||
XtSetArg (av[ac], XmNmessageString, xm_message); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
dialog = XmCreateMessageBox (shell, "message", av, ac);
|
||
XmStringFree (xm_message);
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XtNameToWidget (dialog, "*Help"));
|
||
#endif
|
||
|
||
{
|
||
Widget cancel = 0;
|
||
XtVaGetValues (dialog, XmNcancelButton, &cancel, 0);
|
||
if (! cancel) abort ();
|
||
XtUnmanageChild (cancel);
|
||
}
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_cb, shell);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cb, shell);
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
}
|
||
|
||
static void
|
||
fe_destroy_ok_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
data->answer = Answer_OK;
|
||
XtDestroyWidget(data->widget);
|
||
}
|
||
|
||
static void
|
||
fe_destroy_cancel_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
data->answer = Answer_Cancel;
|
||
XtDestroyWidget(data->widget);
|
||
}
|
||
|
||
static void
|
||
fe_destroy_apply_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
data->answer = Answer_Apply;
|
||
XtDestroyWidget(data->widget);
|
||
}
|
||
|
||
static void
|
||
fe_destroy_finish_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
if (data->answer == Answer_Invalid)
|
||
data->answer = Answer_Destroy;
|
||
}
|
||
|
||
static void
|
||
fe_destroy_snarf_text_cb (Widget widget, XtPointer closure,XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
Widget text = data->text;
|
||
if (text)
|
||
{
|
||
char *plaintext = 0;
|
||
data->return_value = 0;
|
||
plaintext = fe_GetTextField(text);
|
||
data->return_value = XP_STRDUP(plaintext ? plaintext : "");
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_destroy_snarf_pw_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
Widget text = data->text;
|
||
if (text)
|
||
data->return_value = fe_GetPasswdText (text);
|
||
}
|
||
|
||
static void
|
||
fe_destroy_snarf_pw2_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
Widget text = data->text2;
|
||
if (text)
|
||
data->return_value_2 = fe_GetPasswdText (text);
|
||
}
|
||
|
||
|
||
/* Callback used by the clear button to nuke the contents of the text field. */
|
||
static void
|
||
fe_clear_text_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
Widget text = (Widget) closure;
|
||
fe_SetTextField (text, "");
|
||
/* Focus on the text widget after this, since otherwise you have to
|
||
click again. */
|
||
XmProcessTraversal (text, XmTRAVERSE_CURRENT);
|
||
}
|
||
|
||
/* When we are not blocking waiting for a response to a dialog, this is used
|
||
by the buttons to make it get lost when no longer needed (the default would
|
||
otherwise be to merely unmanage it instead of destroying it.) */
|
||
static void
|
||
fe_destroy_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
Widget shell = XtParent (widget);
|
||
while (!XmIsDialogShell (shell))
|
||
shell = XtParent (shell);
|
||
XtDestroyWidget (shell);
|
||
}
|
||
|
||
|
||
|
||
/* Create a XmString that will render in the given width or less. If
|
||
the given string is too big, then chop out stuff by clipping out the
|
||
center and replacing it with "...". */
|
||
XmString
|
||
fe_StringChopCreate(char* message, char* tag, XmFontList font_list,
|
||
int maxwidth)
|
||
{
|
||
XmString label = XmStringCreate ((char *) message, tag);
|
||
int string_width;
|
||
uint16 csid;
|
||
|
||
if (!font_list) return label;
|
||
|
||
string_width = XmStringWidth(font_list, label);
|
||
if (string_width >= maxwidth) {
|
||
/* The string is bigger than the label. Mid-truncate it. */
|
||
|
||
XmString try;
|
||
int length = 0;
|
||
int maxlength = XP_STRLEN(message);
|
||
char* text = XP_ALLOC(maxlength + 10);
|
||
if (!text) return label;
|
||
|
||
csid = INTL_CharSetNameToID(tag);
|
||
if (csid==CS_UNKNOWN) {
|
||
csid = INTL_CharSetNameToID(INTL_ResourceCharSet());
|
||
}
|
||
string_width = 0;
|
||
while (string_width < maxwidth && length < maxlength) {
|
||
length++;
|
||
INTL_MidTruncateString(csid, message, text, length);
|
||
try = XmStringCreate(text, tag);
|
||
if (!try) break;
|
||
string_width = XmStringWidth(font_list, try);
|
||
if (string_width >= maxwidth) {
|
||
XmStringFree(try);
|
||
} else {
|
||
XmStringFree(label);
|
||
label = try;
|
||
}
|
||
try = 0;
|
||
}
|
||
|
||
free (text);
|
||
}
|
||
|
||
return label;
|
||
}
|
||
|
||
/* Dealing with field/value pairs.
|
||
|
||
This takes a "value" widget and an arbitrary number of "label" widgets.
|
||
It finds the widest label, and attaches the "value" widget to the left
|
||
edge of its parent with an offset such that it falls just beyond the
|
||
right edge of the widest label widget.
|
||
|
||
The argument list is expected to be NULL-terminated.
|
||
*/
|
||
|
||
/* #ifdef AIXV3 */
|
||
/* I don't understand - this seems not to be broken any more, and now
|
||
the "hack" way doesn't compile either. Did someone upgrade me?? */
|
||
/* # define BROKEN_VARARGS */
|
||
/* #endif */
|
||
|
||
#ifdef BROKEN_VARARGS
|
||
/* Sorry, we can't be bothered to implement varargs correctly. */
|
||
# undef va_list
|
||
# undef va_start
|
||
# undef va_arg
|
||
# undef va_end
|
||
# define va_list int
|
||
# define va_start(list,first_arg) list = 0
|
||
# define va_arg(list, type) (++list, (type) (list == 1 ? varg0 : \
|
||
list == 2 ? varg1 : \
|
||
list == 3 ? varg2 : \
|
||
list == 4 ? varg3 : \
|
||
list == 5 ? varg4 : \
|
||
list == 6 ? varg5 : \
|
||
list == 7 ? varg6 : \
|
||
list == 8 ? varg7 : \
|
||
list == 9 ? varg8 : 0))
|
||
# define va_end(list)
|
||
#endif
|
||
|
||
|
||
void
|
||
#ifdef BROKEN_VARARGS
|
||
fe_attach_field_to_labels (Widget value_field,
|
||
void *varg0, void *varg1, void *varg2, void *varg3,
|
||
void *varg4, void *varg5, void *varg6, void *varg7,
|
||
void *varg8)
|
||
#else
|
||
fe_attach_field_to_labels (Widget value_field, ...)
|
||
#endif
|
||
{
|
||
va_list vargs;
|
||
Widget current;
|
||
Widget widest = 0;
|
||
Position left = 0;
|
||
long max_width = -1;
|
||
|
||
va_start (vargs, value_field);
|
||
while ((current = va_arg (vargs, Widget)))
|
||
{
|
||
Dimension width = 0;
|
||
Position left = 0;
|
||
Position right = 10;
|
||
|
||
#ifdef Motif_doesnt_suck
|
||
/* Getting the leftOffset of a Gadget may randomly dump core */
|
||
if (XmIsGadget (current))
|
||
abort ();
|
||
XtVaGetValues (current,
|
||
XmNwidth, &width,
|
||
XmNleftOffset, &left,
|
||
/* XmNrightOffset, &right,*/
|
||
0);
|
||
|
||
#else
|
||
width = XfeWidth(current);
|
||
#endif
|
||
|
||
width += (left + right);
|
||
if (((long) width) > max_width)
|
||
{
|
||
widest = current;
|
||
max_width = (long) width;
|
||
}
|
||
}
|
||
va_end (vargs);
|
||
|
||
if (! widest)
|
||
abort ();
|
||
#ifdef Motif_doesnt_suck
|
||
XtVaGetValues (value_field, XmNleftOffset, &left, 0);
|
||
#endif
|
||
XtVaSetValues (value_field,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNleftOffset, max_width + left,
|
||
0);
|
||
}
|
||
|
||
|
||
/* Files
|
||
*/
|
||
static XmString fe_file_selection_directory;
|
||
|
||
/*
|
||
* This code tried to make some minor improvements to the standard
|
||
* Motif 1.2* File Selection Box dialog. The code here attempts
|
||
* to use the existing Motif code for the bulk of the work, and to
|
||
* replace some parts of Motif's behavior with something simpler.
|
||
* I've also added some nice things conceptually lifted from the Mac
|
||
* file picker, and at the request of users. In hindsight it might
|
||
* have been easier to just write a new file picker widget, preferably
|
||
* one that is semantically compatible with the Motif widget. Next time.
|
||
*
|
||
* Anyway, this stuff is conditionally compiled. Most of this is
|
||
* controlled by the USE_WINNING_FILE_SELECTION define. When
|
||
* you turn this guy on, it enables a bunch of hacks to the standard
|
||
* Motif behavior. Best to take a look, but below is a snippet from
|
||
* the resource file. Note that some of the hacks (the simple layout
|
||
* hacks) require Motif source knowledge because they must attack the
|
||
* FSB class record directly. We've moved that code out (see the
|
||
* define FEATURE_MOTIF_FSB_CLASS_HACKING) because we can't make the
|
||
* Motif code public.
|
||
*
|
||
* Related to these hacks, but somewhat orthogonal to them, we try to
|
||
* save the last accessed directory. This makes life a little easier
|
||
* than always going back to (say) HOME.
|
||
*
|
||
* From the resource file:
|
||
*
|
||
* This resource enables some hacks to the File Selection Box
|
||
* which use a simpler layout algorithm than the standard Motif
|
||
* code. The directory and file listings are always maintained
|
||
* as equal size. We don't do this for SGI, as they have solved
|
||
* the problem. See *useEnhancedFSB above.
|
||
* @NOTSGI@*nsMotifFSBHacks: True
|
||
*
|
||
* This resource enables the CDE mode of the File Selection Box.
|
||
* You must be running a CDE enhanced Motif library for this
|
||
* option to work. This resource will apply pathMode=1 to the
|
||
* File Selection Box. If you specify nsMotifFSBHacks and
|
||
* nsMotifFSBCdeMode, some of the keyboard and filter enhancements
|
||
* of nsMotifFSBHacks will also be applied, the layout hacks will not.
|
||
* *nsMotifFSBCdeMode: False
|
||
*
|
||
* ...djw
|
||
*/
|
||
#ifdef USE_WINNING_FILE_SELECTION
|
||
|
||
#include <Xm/XmP.h>
|
||
#include <Xm/XmosP.h>
|
||
|
||
static void
|
||
fe_force_configure(Widget widget)
|
||
{
|
||
Dimension width = _XfeWidth(widget);
|
||
Dimension height = _XfeHeight(widget);
|
||
Dimension border_width = _XfeBorderWidth(widget);
|
||
|
||
_XfeHeight(widget) += 1;
|
||
XtResizeWidget(widget, width, height, border_width);
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_get_dir_entries(String directory, String pattern,
|
||
unsigned type,
|
||
String** file_list_r, unsigned int* nfiles_r)
|
||
{
|
||
unsigned int n;
|
||
unsigned len = strlen(directory);
|
||
|
||
*file_list_r = NULL;
|
||
#ifdef XM_GET_DIR_ENTRIES_OK
|
||
_XmOSGetDirEntries(directory, pattern, type, FALSE, FALSE,
|
||
file_list_r, nfiles_r, &n);
|
||
#else
|
||
_XmOSBuildFileList(directory, pattern, type,
|
||
file_list_r, nfiles_r, &n);
|
||
|
||
for (n = 0; n < *nfiles_r; n++) {
|
||
String old_s = (*file_list_r)[n];
|
||
String new_s;
|
||
|
||
if (strncmp(directory, old_s, len) == 0) {
|
||
new_s = (String)XtNewString(&old_s[len]);
|
||
XtFree(old_s);
|
||
(*file_list_r)[n] = new_s;
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_file_search_proc(Widget widget, XtPointer call_data)
|
||
{
|
||
XmFileSelectionBoxCallbackStruct* search_data
|
||
= (XmFileSelectionBoxCallbackStruct *)call_data;
|
||
String directory;
|
||
String pattern;
|
||
String* file_list;
|
||
unsigned int nfiles;
|
||
Arg args[10];
|
||
Cardinal n;
|
||
Cardinal nn;
|
||
XmString* xm_string_file_list;
|
||
XmString xm_directory;
|
||
|
||
if (!(directory = _XmStringGetTextConcat(search_data->dir))) {
|
||
return;
|
||
}
|
||
|
||
if (!(pattern = _XmStringGetTextConcat(search_data->pattern))) {
|
||
XtFree(directory);
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* _XmOSGetDirEntries() is being really wierd! Use this guy
|
||
* instead..djw
|
||
*/
|
||
file_list = NULL;
|
||
fe_file_selection_get_dir_entries(directory, pattern, XmFILE_REGULAR,
|
||
&file_list, &nfiles);
|
||
|
||
for (n = 0, nn = 0; n < nfiles; n++) {
|
||
if (file_list[n][0] == '.') /* no more dot files ! */
|
||
continue;
|
||
|
||
file_list[nn++] = file_list[n];
|
||
}
|
||
nfiles = nn;
|
||
|
||
if (nfiles != 0) {
|
||
if (nfiles > 1)
|
||
XP_QSORT((void *)file_list, nfiles, sizeof(char *), _XmOSFileCompare);
|
||
|
||
xm_string_file_list = (XmString*)XtMalloc(nfiles * sizeof(XmString));
|
||
|
||
for (n = 0; n < nfiles; n++) {
|
||
xm_string_file_list[n] = XmStringLtoRCreate(file_list[n],
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
} else {
|
||
xm_string_file_list = NULL;
|
||
}
|
||
|
||
/* The Motif book says update the XmNdirectory */
|
||
xm_directory = XmStringLtoRCreate(directory, XmFONTLIST_DEFAULT_TAG);
|
||
|
||
/* Update the list widget */
|
||
n = 0;
|
||
XtSetArg(args[n], XmNfileListItems, xm_string_file_list); n++;
|
||
XtSetArg(args[n], XmNfileListItemCount, nfiles); n++;
|
||
XtSetArg(args[n], XmNlistUpdated, TRUE); n++;
|
||
XtSetArg(args[n], XmNdirectory, xm_directory); n++;
|
||
#if 0
|
||
XtSetArg(args[n], XmNdirectoryValid, TRUE); n++;
|
||
#endif
|
||
XtSetValues(widget, args, n);
|
||
|
||
#if 1
|
||
fe_force_configure(widget);
|
||
#endif
|
||
|
||
/* And save directory default for next time */
|
||
if (fe_file_selection_directory)
|
||
XmStringFree(fe_file_selection_directory);
|
||
fe_file_selection_directory = xm_directory;
|
||
|
||
if (nfiles != 0) {
|
||
/*
|
||
* Cleanup.
|
||
*/
|
||
for (n = 0; n < nfiles; n++) {
|
||
XmStringFree(xm_string_file_list[n]);
|
||
XtFree(file_list[n]);
|
||
}
|
||
XtFree((char *)xm_string_file_list);
|
||
}
|
||
|
||
XtFree((char *)directory);
|
||
XtFree((char *)pattern);
|
||
|
||
if (file_list)
|
||
XtFree((char *)file_list);
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_dir_search_proc(Widget widget, XtPointer call_data)
|
||
{
|
||
XmFileSelectionBoxCallbackStruct* search_data
|
||
= (XmFileSelectionBoxCallbackStruct *)call_data;
|
||
String directory;
|
||
Arg args[10];
|
||
Cardinal n;
|
||
Cardinal m;
|
||
String * dir_list;
|
||
unsigned int ndirs;
|
||
unsigned int mdirs;
|
||
XmString * xm_string_dir_list;
|
||
XmString xm_directory;
|
||
int attempts;
|
||
char* p;
|
||
|
||
XtVaGetValues(widget, XmNdirectory, &xm_directory, 0);
|
||
|
||
if (XmStringByteCompare(xm_directory, search_data->dir) == True) {
|
||
/* Update the list widget */
|
||
n = 0;
|
||
XtSetArg(args[n], XmNlistUpdated, FALSE); n++;
|
||
XtSetArg(args[n], XmNdirectoryValid, TRUE); n++;
|
||
XtSetValues(widget, args, n);
|
||
return;
|
||
}
|
||
|
||
directory = _XmStringGetTextConcat(search_data->dir);
|
||
|
||
ndirs = 0;
|
||
for (attempts = 0; ndirs == 0; attempts++) {
|
||
dir_list = NULL;
|
||
fe_file_selection_get_dir_entries(directory, "*", XmFILE_DIRECTORY,
|
||
&dir_list, &ndirs);
|
||
if (ndirs) {
|
||
if (attempts != 0) {
|
||
XmFileSelectionBoxCallbackStruct new_data;
|
||
XmQualifyProc q_proc;
|
||
|
||
/*
|
||
* Cleanup old stuff that won't be re-used.
|
||
*/
|
||
XmStringFree(search_data->dir);
|
||
if (search_data->mask)
|
||
XmStringFree(search_data->mask);
|
||
|
||
memset(&new_data, 0, sizeof(XmFileSelectionBoxCallbackStruct));
|
||
new_data.reason = search_data->reason;
|
||
new_data.event = search_data->event;
|
||
new_data.dir = XmStringLtoRCreate(directory,
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
new_data.dir_length = XmStringLength(new_data.dir);
|
||
new_data.pattern = search_data->pattern;
|
||
new_data.pattern_length = search_data->pattern_length;
|
||
|
||
/*
|
||
* Reset the spec, because we may get called 50M
|
||
* times if this broken state.
|
||
*/
|
||
XtVaSetValues(widget,
|
||
XmNdirectory, new_data.dir,
|
||
XmNdirSpec, new_data.dir,
|
||
0);
|
||
|
||
/*
|
||
* Call qualify proc to install new directory
|
||
* into widget.
|
||
*/
|
||
XtVaGetValues(widget, XmNqualifySearchDataProc, &q_proc, 0);
|
||
(*q_proc)(widget, (XtPointer)&new_data,
|
||
(XtPointer)search_data);
|
||
}
|
||
} else {
|
||
if (attempts == 0) {
|
||
#ifdef DEBUG
|
||
char buf[1024];
|
||
|
||
sprintf(buf, "Unable to access directory:\n %.900s\n",
|
||
directory);
|
||
fprintf(stderr, buf);
|
||
#endif
|
||
XBell(XtDisplay(widget), 0); /* emulate Motif */
|
||
}
|
||
|
||
if (dir_list)
|
||
XtFree((char *) dir_list);
|
||
|
||
if (directory[0] == '\0' || strcmp(directory, "/") == 0)
|
||
return; /* I give in! */
|
||
|
||
while ((p = strrchr(directory, '/')) != NULL) {
|
||
if (p[1] == '\0') { /* "/" at end */
|
||
p[0] = '\0';
|
||
} else {
|
||
p[1] = '\0';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ndirs > 1)
|
||
XP_QSORT((void *)dir_list, ndirs, sizeof(char *), _XmOSFileCompare);
|
||
|
||
xm_string_dir_list = (XmString *)XtMalloc(ndirs * sizeof(XmString));
|
||
|
||
for (m = n = 0; n < ndirs; n++) {
|
||
if (strcmp(dir_list[n], ".") == 0) /* don't want that */
|
||
continue;
|
||
xm_string_dir_list[m++] = XmStringLtoRCreate(dir_list[n],
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
mdirs = m;
|
||
|
||
/* Update the list widget */
|
||
n = 0;
|
||
XtSetArg(args[n], XmNdirListItems, xm_string_dir_list); n++;
|
||
XtSetArg(args[n], XmNdirListItemCount, mdirs); n++;
|
||
XtSetArg(args[n], XmNlistUpdated, TRUE); n++;
|
||
XtSetArg(args[n], XmNdirectoryValid, TRUE); n++;
|
||
XtSetValues(widget, args, n);
|
||
|
||
/* And save directory default for next time */
|
||
xm_directory = XmStringLtoRCreate(directory, XmFONTLIST_DEFAULT_TAG);
|
||
if (fe_file_selection_directory)
|
||
XmStringFree(fe_file_selection_directory);
|
||
fe_file_selection_directory = xm_directory;
|
||
|
||
/*
|
||
* Cleanup.
|
||
*/
|
||
for (n = 0; n < mdirs; n++) {
|
||
XmStringFree(xm_string_dir_list[n]);
|
||
}
|
||
for (n = 0; n < ndirs; n++) {
|
||
XtFree(dir_list[n]);
|
||
}
|
||
|
||
XtFree((char *)xm_string_dir_list);
|
||
XtFree((char *)directory);
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_qualify_search_data_proc(Widget widget,
|
||
XtPointer sd, XtPointer qsd)
|
||
{
|
||
XmFileSelectionBoxCallbackStruct* s_data
|
||
= (XmFileSelectionBoxCallbackStruct *)sd;
|
||
XmFileSelectionBoxCallbackStruct* qs_data
|
||
= (XmFileSelectionBoxCallbackStruct *)qsd;
|
||
String mask_string = _XmStringGetTextConcat(s_data->mask);
|
||
String dir_string = _XmStringGetTextConcat(s_data->dir);
|
||
String pattern_string = _XmStringGetTextConcat(s_data->pattern);
|
||
String dir_part = NULL;
|
||
String pattern_part = NULL;
|
||
String q_dir_string = NULL;
|
||
String q_mask_string = NULL;
|
||
String q_pattern_string = NULL;
|
||
String dir_free_string = NULL;
|
||
String pattern_free_string = NULL;
|
||
String p;
|
||
XmString xm_directory;
|
||
XmString xm_pattern;
|
||
XmString xm_dir_spec;
|
||
|
||
if (dir_string != NULL) {
|
||
if (dir_string[0] == '/') {
|
||
dir_part = dir_string;
|
||
} else {
|
||
XtVaGetValues(widget, XmNdirectory, &xm_directory, 0);
|
||
if (xm_directory != NULL) {
|
||
dir_part = _XmStringGetTextConcat(xm_directory);
|
||
p = (String)XtMalloc(strlen(dir_part) +
|
||
strlen(dir_string) + 2);
|
||
strcpy(p, dir_part);
|
||
strcat(p, dir_string);
|
||
XtFree(dir_string);
|
||
XtFree(dir_part);
|
||
dir_part = dir_string = p;
|
||
}
|
||
}
|
||
} else {
|
||
if (mask_string != NULL) { /* use filter value */
|
||
pattern_part = _XmOSFindPatternPart(mask_string);
|
||
|
||
if (pattern_part != mask_string) {
|
||
pattern_part[-1] = '\0'; /* zap dir trailing '/' */
|
||
/* "" or "/" */
|
||
if (*mask_string == '\0') {
|
||
dir_part = "/";
|
||
} else if (*mask_string == '/' && mask_string[1] == '\0') {
|
||
dir_part = "//";
|
||
} else {
|
||
dir_part = mask_string;
|
||
}
|
||
}
|
||
} else { /* use XmNdirectory */
|
||
XtVaGetValues(widget, XmNdirectory, &xm_directory, 0);
|
||
if (xm_directory != NULL) {
|
||
dir_part = _XmStringGetTextConcat(xm_directory);
|
||
dir_free_string = dir_part; /* to force free */
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pattern_string != NULL) {
|
||
pattern_part = pattern_string;
|
||
} else {
|
||
if (mask_string != NULL) {
|
||
if (!pattern_part)
|
||
pattern_part = _XmOSFindPatternPart(mask_string);
|
||
} else {
|
||
XtVaGetValues(widget, XmNpattern, &xm_pattern, 0);
|
||
if (xm_pattern != NULL) {
|
||
pattern_part = _XmStringGetTextConcat(xm_pattern);
|
||
pattern_free_string = pattern_part; /* so it gets freed */
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* It's ok for dir_part to be NULL, as _XmOSQualifyFileSpec
|
||
* will just use the cwd.
|
||
*/
|
||
_XmOSQualifyFileSpec(dir_part, pattern_part,
|
||
&q_dir_string, &q_pattern_string);
|
||
|
||
qs_data->reason = s_data->reason ;
|
||
qs_data->event = s_data->event ;
|
||
if (s_data->value) {
|
||
qs_data->value = XmStringCopy(s_data->value);
|
||
} else {
|
||
XtVaGetValues(widget, XmNdirSpec, &xm_dir_spec, 0);
|
||
qs_data->value = XmStringCopy(xm_dir_spec);
|
||
}
|
||
qs_data->length = XmStringLength(qs_data->value) ;
|
||
q_mask_string = (String)XtMalloc(strlen(q_dir_string) +
|
||
strlen(q_pattern_string) + 1);
|
||
strcpy(q_mask_string, q_dir_string);
|
||
strcat(q_mask_string, q_pattern_string);
|
||
qs_data->mask = XmStringLtoRCreate(q_mask_string, XmFONTLIST_DEFAULT_TAG);
|
||
qs_data->mask_length = XmStringLength(qs_data->mask);
|
||
qs_data->dir = XmStringLtoRCreate(q_dir_string, XmFONTLIST_DEFAULT_TAG);
|
||
qs_data->dir_length = XmStringLength(qs_data->dir) ;
|
||
qs_data->pattern = XmStringLtoRCreate(q_pattern_string,
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
qs_data->pattern_length = XmStringLength(qs_data->pattern);
|
||
|
||
if (dir_free_string)
|
||
XtFree(dir_free_string);
|
||
if (pattern_free_string)
|
||
XtFree(pattern_free_string);
|
||
if (dir_string)
|
||
XtFree(dir_string);
|
||
if (pattern_string)
|
||
XtFree(pattern_string);
|
||
if (mask_string)
|
||
XtFree(mask_string);
|
||
if (q_dir_string)
|
||
XtFree(q_dir_string);
|
||
if (q_pattern_string)
|
||
XtFree(q_pattern_string);
|
||
if (q_mask_string)
|
||
XtFree(q_mask_string);
|
||
}
|
||
|
||
static char* fe_file_selection_home = 0;
|
||
|
||
static char*
|
||
fe_file_selection_gethome()
|
||
{
|
||
if (!fe_file_selection_home) {
|
||
char* foo = getenv("HOME");
|
||
char* p;
|
||
|
||
if (!foo)
|
||
foo = "/"; /* hah */
|
||
|
||
fe_file_selection_home = XP_STRDUP(foo);
|
||
|
||
p = strrchr(fe_file_selection_home, '/');
|
||
if (p != NULL && p != fe_file_selection_home && p[1] == '\0')
|
||
*p = '\0';
|
||
}
|
||
|
||
return fe_file_selection_home;
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_dirspec_cb(Widget widget, XtPointer closure, XtPointer cb)
|
||
{
|
||
XmTextVerifyCallbackStruct* vd = (XmTextVerifyCallbackStruct*)cb;
|
||
Widget fsb = (Widget)closure;
|
||
XmString xm_directory;
|
||
String directory;
|
||
String ptr;
|
||
|
||
if (vd->startPos == 0 && vd->text->ptr != NULL) {
|
||
if (vd->text->ptr[0] == '~') { /* expand $HOME */
|
||
|
||
char* home = fe_file_selection_gethome();
|
||
|
||
ptr = (String)XtMalloc(strlen(home) + strlen(vd->text->ptr) + 2);
|
||
|
||
strcpy(ptr, home);
|
||
strcat(ptr, "/");
|
||
if (vd->text->length > 1)
|
||
strcat(ptr, &vd->text->ptr[1]);
|
||
|
||
XtFree(vd->text->ptr);
|
||
vd->text->ptr = ptr;
|
||
vd->text->length = strlen(ptr);
|
||
|
||
} else if (vd->text->ptr[0] != '/') {
|
||
XtVaGetValues(fsb, XmNdirectory, &xm_directory, 0);
|
||
if (xm_directory != NULL) {
|
||
directory = _XmStringGetTextConcat(xm_directory);
|
||
|
||
ptr = (String)XtMalloc(strlen(directory) +
|
||
strlen(vd->text->ptr) + 2);
|
||
strcpy(ptr, directory);
|
||
strcat(ptr, vd->text->ptr);
|
||
|
||
XtFree(vd->text->ptr);
|
||
vd->text->ptr = ptr;
|
||
vd->text->length = strlen(ptr);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_filter_cb(Widget apply, XtPointer closure, XtPointer cbd)
|
||
{
|
||
Widget fsb = (Widget)closure;
|
||
Widget dir = XmFileSelectionBoxGetChild(fsb, XmDIALOG_DIR_LIST);
|
||
int* position_list;
|
||
int position_count;
|
||
|
||
if (XmListGetSelectedPos(dir, &position_list, &position_count)) {
|
||
|
||
if (position_count == 1 && position_list[0] == 1)
|
||
XmListSelectPos(dir, 1, True);
|
||
|
||
if (position_count > 0 && position_list != NULL)
|
||
XtFree((char*)position_list);
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_directory_up_action(Widget widget,
|
||
XEvent* event,
|
||
String* av, Cardinal* ac)
|
||
{
|
||
XmString xm_directory;
|
||
String directory;
|
||
String p;
|
||
|
||
while (!XtIsSubclass(widget, xmFileSelectionBoxWidgetClass)) {
|
||
widget = XtParent(widget);
|
||
if (!widget)
|
||
return;
|
||
}
|
||
|
||
XtVaGetValues(widget, XmNdirectory, &xm_directory, 0);
|
||
|
||
if (xm_directory != NULL) {
|
||
int len;
|
||
|
||
directory = _XmStringGetTextConcat(xm_directory);
|
||
|
||
len = XP_STRLEN(directory);
|
||
|
||
if (len > 0 && directory[len-1] == '/')
|
||
directory[len-1] = '\0';
|
||
|
||
if ((p = XP_STRRCHR(directory, '/')) != NULL) {
|
||
p[1] = '\0';
|
||
|
||
xm_directory = XmStringCreateSimple(directory);
|
||
|
||
XtVaSetValues(widget, XmNdirectory, xm_directory, 0);
|
||
|
||
XmStringFree(xm_directory);
|
||
}
|
||
XtFree(directory);
|
||
}
|
||
}
|
||
|
||
static XtActionsRec fe_file_selection_actions[] =
|
||
{
|
||
{ "FileSelectionBoxCdDotDot", fe_file_selection_directory_up_action },
|
||
};
|
||
|
||
static _XmConst char fe_file_selection_accelerators[] =
|
||
"~Alt Meta<Key>osfUp: FileSelectionBoxCdDotDot()\n"
|
||
"Alt ~Meta<Key>osfUp: FileSelectionBoxCdDotDot()";
|
||
|
||
static unsigned fe_file_selection_add_actions_done;
|
||
|
||
static XtPointer
|
||
fe_file_selection_register_actions_mappee(Widget widget, XtPointer data)
|
||
{
|
||
XtOverrideTranslations(widget, (XtTranslations)data);
|
||
return 0;
|
||
}
|
||
|
||
static void
|
||
fe_file_selection_register_actions(Widget widget)
|
||
{
|
||
if (!fe_file_selection_add_actions_done) {
|
||
XtAppAddActions(fe_XtAppContext,
|
||
fe_file_selection_actions,
|
||
countof(fe_file_selection_actions));
|
||
fe_file_selection_add_actions_done++;
|
||
}
|
||
|
||
fe_WidgetTreeWalk(widget,
|
||
fe_file_selection_register_actions_mappee,
|
||
(XtPointer) XtParseTranslationTable(fe_file_selection_accelerators));
|
||
}
|
||
|
||
typedef struct {
|
||
Boolean hack;
|
||
Boolean cde;
|
||
} fe_fsb_res_st;
|
||
|
||
static XtResource fe_fsb_resources[] =
|
||
{
|
||
{
|
||
"nsMotifFSBHacks", XtCBoolean, XtRBoolean, sizeof(Boolean),
|
||
XtOffset(fe_fsb_res_st *, hack), XtRImmediate,
|
||
#ifdef IRIX
|
||
/* Irix has the nice enhanced FSB, so they don't need it */
|
||
(XtPointer)False
|
||
#else
|
||
(XtPointer)True
|
||
#endif
|
||
},
|
||
{
|
||
"nsMotifFSBCdeMode", XtCBoolean, XtRBoolean, sizeof(Boolean),
|
||
XtOffset(fe_fsb_res_st *, cde), XtRImmediate, (XtPointer)False
|
||
}
|
||
};
|
||
|
||
typedef enum {
|
||
FSB_LOSING,
|
||
FSB_HACKS,
|
||
FSB_CDE,
|
||
FSB_CDE_PLUS
|
||
} fe_fsb_mode;
|
||
|
||
static fe_fsb_mode
|
||
fe_file_selection_box_get_resources(Widget parent)
|
||
{
|
||
static Boolean done;
|
||
static fe_fsb_res_st result;
|
||
|
||
if (!done) {
|
||
|
||
while (!XtIsTopLevelShell(parent))
|
||
parent = XtParent(parent);
|
||
|
||
XtGetApplicationResources(parent,
|
||
(XtPointer)&result,
|
||
fe_fsb_resources, XtNumber(fe_fsb_resources),
|
||
0, 0);
|
||
done++;
|
||
}
|
||
|
||
if (result.hack && result.cde)
|
||
return FSB_CDE_PLUS;
|
||
else if (result.hack && !result.cde)
|
||
return FSB_HACKS;
|
||
else if (!result.hack && result.cde)
|
||
return FSB_CDE;
|
||
else
|
||
return FSB_LOSING;
|
||
}
|
||
#endif /*USE_WINNING_FILE_SELECTION*/
|
||
|
||
static void
|
||
fe_file_selection_save_directory_cb(Widget widget, XtPointer a, XtPointer b)
|
||
{
|
||
XmString xm_directory;
|
||
XmString xm_dirspec;
|
||
/* And save directory default for next time */
|
||
XtVaGetValues(widget,
|
||
XmNdirectory, &xm_directory,
|
||
XmNdirSpec, &xm_dirspec,
|
||
0);
|
||
|
||
if (xm_dirspec != 0) {
|
||
char* directory = _XmStringGetTextConcat(xm_dirspec);
|
||
|
||
if (directory != NULL) {
|
||
if (directory[0] == '/') {
|
||
|
||
char* end = strrchr(directory, '/');
|
||
|
||
if (end != NULL) {
|
||
if (end != directory)
|
||
*end = '\0';
|
||
|
||
if (xm_directory != NULL)
|
||
XmStringFree(xm_directory);
|
||
|
||
xm_directory = XmStringCreateLocalized(directory);
|
||
}
|
||
}
|
||
XtFree(directory);
|
||
}
|
||
}
|
||
|
||
if (xm_directory != 0) {
|
||
if (fe_file_selection_directory)
|
||
XmStringFree(fe_file_selection_directory);
|
||
fe_file_selection_directory = xm_directory;
|
||
}
|
||
}
|
||
|
||
Widget
|
||
fe_CreateFileSelectionBox(Widget parent, char* name,
|
||
Arg* p_args, Cardinal p_n)
|
||
{
|
||
Arg args[32];
|
||
Cardinal n;
|
||
Cardinal i;
|
||
Widget fsb;
|
||
Boolean directory_set = FALSE;
|
||
#ifdef USE_WINNING_FILE_SELECTION
|
||
Boolean dir_search_set = FALSE;
|
||
Boolean file_search_set = FALSE;
|
||
Boolean qualify_set = FALSE;
|
||
Widget dir_list;
|
||
Widget file_list;
|
||
Widget dirspec;
|
||
Widget filter;
|
||
Widget filter_button;
|
||
fe_fsb_mode mode = fe_file_selection_box_get_resources(parent);
|
||
#endif /*USE_WINNING_FILE_SELECTION*/
|
||
|
||
for (n = 0, i = 0; i < p_n && i < 30; i++) {
|
||
if (p_args[i].name == XmNdirectory)
|
||
directory_set = TRUE;
|
||
|
||
#ifdef USE_WINNING_FILE_SELECTION
|
||
if (mode == FSB_HACKS) {
|
||
if (p_args[i].name == XmNdirSearchProc)
|
||
dir_search_set = TRUE;
|
||
else if (p_args[i].name == XmNfileSearchProc)
|
||
file_search_set = TRUE;
|
||
else if (p_args[i].name == XmNqualifySearchDataProc)
|
||
qualify_set = TRUE;
|
||
else
|
||
args[n++] = p_args[i];
|
||
}
|
||
else
|
||
#endif /*USE_WINNING_FILE_SELECTION*/
|
||
{
|
||
args[n++] = p_args[i];
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Add last visited directory
|
||
*/
|
||
if (!directory_set) {
|
||
XtSetArg(args[n], XmNdirectory, fe_file_selection_directory); n++;
|
||
}
|
||
|
||
#ifdef USE_WINNING_FILE_SELECTION
|
||
if (mode == FSB_CDE || mode == FSB_CDE_PLUS) {
|
||
XtSetArg(args[n], "pathMode", 1); n++;
|
||
}
|
||
|
||
if (mode == FSB_HACKS) {
|
||
|
||
if (!dir_search_set) {
|
||
XtSetArg(args[n], XmNdirSearchProc,
|
||
fe_file_selection_dir_search_proc); n++;
|
||
}
|
||
|
||
if (!file_search_set) {
|
||
XtSetArg(args[n], XmNfileSearchProc,
|
||
fe_file_selection_file_search_proc); n++;
|
||
}
|
||
|
||
if (!qualify_set) {
|
||
XtSetArg(args[n], XmNqualifySearchDataProc,
|
||
fe_file_selection_qualify_search_data_proc); n++;
|
||
}
|
||
|
||
#ifdef FEATURE_MOTIF_FSB_CLASS_HACKING
|
||
/*
|
||
* This routine is now in the Xm patches tree, as it requires
|
||
* access to the Motif source...djw
|
||
*/
|
||
fe_FileSelectionBoxHackClassRecord(parent);
|
||
#endif /*FEATURE_MOTIF_FSB_CLASS_HACKING*/
|
||
|
||
fsb = XmCreateFileSelectionBox(parent, name, args, n);
|
||
|
||
/*
|
||
* XmCreateFileSelectionBox() sets directory list
|
||
* XmNscrollBarDisplayPolicy to STATIC which always shows
|
||
* the horizontal scrollbar. Bye...
|
||
*/
|
||
dir_list = XmFileSelectionBoxGetChild(fsb, XmDIALOG_DIR_LIST);
|
||
XtVaSetValues(dir_list, XmNscrollBarDisplayPolicy, XmAS_NEEDED, 0);
|
||
file_list = XmFileSelectionBoxGetChild(fsb, XmDIALOG_LIST);
|
||
XtVaSetValues(file_list, XmNscrollBarDisplayPolicy, XmAS_NEEDED, 0);
|
||
dirspec = XmFileSelectionBoxGetChild(fsb, XmDIALOG_TEXT);
|
||
XtAddCallback(dirspec, XmNmodifyVerifyCallback,
|
||
fe_file_selection_dirspec_cb, (XtPointer)fsb);
|
||
filter = XmFileSelectionBoxGetChild(fsb, XmDIALOG_FILTER_TEXT);
|
||
XtAddCallback(filter, XmNmodifyVerifyCallback,
|
||
fe_file_selection_dirspec_cb, (XtPointer)fsb);
|
||
|
||
}
|
||
else
|
||
#endif /*USE_WINNING_FILE_SELECTION*/
|
||
{
|
||
fsb = XmCreateFileSelectionBox(parent, name, args, n);
|
||
}
|
||
|
||
#ifdef IRIX
|
||
#ifndef IRIX5_3
|
||
/* FIX 98019
|
||
*
|
||
* For IRIX 6.2 and later:
|
||
* Reset filetype mask to suit custom Sgm file dialog.
|
||
* (otherwise directories don't show up in the list.)
|
||
*/
|
||
XtVaSetValues(fsb,XmNfileTypeMask,XmFILE_ANY_TYPE,NULL);
|
||
#endif
|
||
#endif
|
||
|
||
|
||
#ifdef IRIX
|
||
#ifndef IRIX5_3
|
||
/* FIX 98019
|
||
*
|
||
* For IRIX 6.2 and later:
|
||
* Reset filetype mask to suit custom Sgm file dialog.
|
||
* (otherwise directories don't show up in the list.)
|
||
*/
|
||
XtVaSetValues(fsb,XmNfileTypeMask,XmFILE_ANY_TYPE,NULL);
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef USE_WINNING_FILE_SELECTION
|
||
if (mode == FSB_HACKS || mode == FSB_CDE_PLUS) {
|
||
filter_button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_APPLY_BUTTON);
|
||
XtAddCallback(filter_button, XmNactivateCallback,
|
||
fe_file_selection_filter_cb, fsb);
|
||
|
||
fe_file_selection_register_actions(fsb);
|
||
}
|
||
#endif /*USE_WINNING_FILE_SELECTION*/
|
||
|
||
XtAddCallback(fsb, XmNokCallback,
|
||
fe_file_selection_save_directory_cb, NULL);
|
||
|
||
return fsb;
|
||
}
|
||
|
||
Widget
|
||
fe_CreateFileSelectionDialog(Widget parent,
|
||
String name,
|
||
Arg* fsb_args,
|
||
Cardinal fsb_n)
|
||
{
|
||
Widget fsb; /* new fsb widget */
|
||
Widget ds; /* DialogShell */
|
||
ArgList ds_args; /* arglist for shell */
|
||
char ds_name[256];
|
||
|
||
/*
|
||
* Create DialogShell parent.
|
||
*/
|
||
XP_STRCPY(ds_name, name);
|
||
XP_STRCAT(ds_name, "_popup"); /* motif compatible */
|
||
|
||
ds_args = (ArgList)XtMalloc(sizeof(Arg) * (fsb_n + 1));
|
||
XP_MEMCPY(ds_args, fsb_args, (sizeof(Arg) * fsb_n));
|
||
XtSetArg(ds_args[fsb_n], XmNallowShellResize, True);
|
||
ds = XmCreateDialogShell(parent, ds_name, ds_args, fsb_n + 1);
|
||
|
||
XtFree((char*)ds_args);
|
||
|
||
/*
|
||
* Create FileSelectionBox.
|
||
*/
|
||
fsb = fe_CreateFileSelectionBox(ds, name, fsb_args, fsb_n);
|
||
XtAddCallback(fsb, XmNdestroyCallback, _XmDestroyParentCallback, NULL);
|
||
|
||
return(fsb) ;
|
||
}
|
||
|
||
static void fe_file_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_file_destroy_cb (Widget, XtPointer, XtPointer);
|
||
static void fe_file_type_cb (Widget, XtPointer, XtPointer);
|
||
|
||
#ifdef NEW_DECODERS
|
||
static void fe_file_type_hack_extension (struct fe_file_type_data *ftd);
|
||
#endif /* NEW_DECODERS */
|
||
|
||
/*
|
||
* fe_ReadFilename_2
|
||
* context:
|
||
* If context is non-null, it uses context's data to display the fsb.
|
||
* iparent, filebp, ftdp:
|
||
* If context is NULL, then this uses these to create the file
|
||
* selection box.
|
||
* 'iparent' is the parent shell under which the FSB will be created.
|
||
* 'filebp' is a pointer to the file selection box widget. [CANT BE NULL]
|
||
* 'ftdp' is a pointer to file type data used by FSB code. [CANT BE NULL]
|
||
* We allocate one and return it back to the caller.
|
||
* Everytime we are called with the same filebp, we need to
|
||
* be called with the same ftdp.
|
||
*
|
||
* WARNING: 1. Allocates *ftdp
|
||
* 2. filebp and ftdp go together. For every filebp we need to
|
||
* use the ftdp that was created with it.
|
||
*
|
||
* Just another form of fe_ReadFileName() so that other parts of fe
|
||
* eg. bookmarks can use this as they dont have a context and I
|
||
* think making a dummy context is bad.
|
||
* - dp
|
||
*
|
||
* Akkana note: bug 82924 was fixed in FE_PromptForFileName()
|
||
* (in src/context_funcs.cpp), but has not yet been fixed here.
|
||
* The three filename prompting routines need to be integrated into one;
|
||
* see comment under FE_PromptForFileName().
|
||
*/
|
||
char *
|
||
fe_ReadFileName_2 ( MWContext* context,
|
||
Widget iparent, Widget* filebp,
|
||
struct fe_file_type_data **ftdp,
|
||
const char *title, const char *default_url,
|
||
Boolean must_match, int *save_as_type)
|
||
{
|
||
Widget fileb;
|
||
struct fe_file_type_data *ftd;
|
||
struct fe_confirm_data data;
|
||
Widget sabox, samenu, sabutton;
|
||
|
||
if (context) {
|
||
fileb = CONTEXT_DATA (context)->file_dialog;
|
||
ftd = CONTEXT_DATA (context)->ftd;
|
||
}
|
||
else {
|
||
fileb = *filebp;
|
||
ftd = *ftdp;
|
||
}
|
||
|
||
if (! title) title = XP_GetString(XFE_OPEN_FILE);
|
||
|
||
if (! fileb)
|
||
{
|
||
Arg av [20];
|
||
int ac, i;
|
||
Widget shell;
|
||
Widget parent;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
|
||
if (context) parent = CONTEXT_WIDGET (context);
|
||
else parent = iparent;
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
/* XtSetArg (av[ac], XmNallowShellResize, True); ac++;*/
|
||
shell = XmCreateDialogShell (parent, "fileSelector_popup", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);
|
||
ac++;
|
||
ftd = (struct fe_file_type_data *)
|
||
calloc (sizeof (struct fe_file_type_data), 1);
|
||
if (context) CONTEXT_DATA (context)->ftd = ftd;
|
||
else *ftdp = ftd;
|
||
XtSetArg (av[ac], XmNuserData, ftd); ac++;
|
||
fileb = fe_CreateFileSelectionBox (shell, "fileSelector", av, ac);
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XtNameToWidget (fileb, "*Help"));
|
||
#endif
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
sabox = XmCreateFrame (fileb, "frame", av, ac);
|
||
samenu = XmCreatePulldownMenu (sabox, "formatType", av, ac);
|
||
ac = 0;
|
||
|
||
#ifdef NEW_DECODERS
|
||
ftd->fileb = fileb;
|
||
#endif /* NEW_DECODERS */
|
||
ftd->options [fe_FILE_TYPE_TEXT] =
|
||
XmCreatePushButtonGadget (samenu, "text", av, ac);
|
||
ftd->options [fe_FILE_TYPE_HTML] =
|
||
XmCreatePushButtonGadget (samenu, "html", av, ac);
|
||
#ifdef SAVE_ALL
|
||
ftd->options [fe_FILE_TYPE_HTML_AND_IMAGES] =
|
||
XmCreatePushButtonGadget (samenu, "tree", av, ac);
|
||
#endif /* SAVE_ALL */
|
||
ftd->options [fe_FILE_TYPE_PS] =
|
||
XmCreatePushButtonGadget (samenu, "ps", av, ac);
|
||
/* ftd->selected_option = fe_FILE_TYPE_TEXT; */
|
||
/* Make the default "save as" type html (ie, source) */
|
||
ftd->selected_option = fe_FILE_TYPE_HTML;
|
||
XtVaSetValues (samenu, XmNmenuHistory,
|
||
ftd->options [ftd->selected_option], 0);
|
||
ac = 0;
|
||
XtSetArg (av [ac], XmNsubMenuId, samenu); ac++;
|
||
sabutton = fe_CreateOptionMenu (sabox, "formatType", av, ac);
|
||
for (i = 0; i < countof (ftd->options); i++)
|
||
if (ftd->options[i])
|
||
{
|
||
XtAddCallback (ftd->options[i], XmNactivateCallback,
|
||
fe_file_type_cb, ftd);
|
||
XtManageChild (ftd->options[i]);
|
||
}
|
||
XtManageChild (sabutton);
|
||
|
||
if (context) CONTEXT_DATA (context)->file_dialog = fileb;
|
||
else *filebp = fileb;
|
||
|
||
fe_HackDialogTranslations (fileb);
|
||
}
|
||
else
|
||
{
|
||
/* Without this the "*fileSelector.width:" resource doesn't work
|
||
on subsequent invocations of this box. Don't ask me why. I
|
||
tried permutations of allowShellResize as well with no effect.
|
||
(It's better to keep the widgets themselves around, if not the
|
||
windows, so that the default text is persistent.)
|
||
*/
|
||
#if 0
|
||
XtUnrealizeWidget (fileb);
|
||
#endif
|
||
sabox = XtNameToWidget (fileb, "*frame");
|
||
|
||
/*
|
||
* Restore the values saved in fe_file_selection_save_directory_cb()
|
||
*/
|
||
if (fe_file_selection_directory != 0) {
|
||
XtVaSetValues(fileb, XmNdirectory, fe_file_selection_directory, 0);
|
||
}
|
||
}
|
||
|
||
#ifdef NEW_DECODERS
|
||
ftd->orig_url = default_url;
|
||
ftd->conversion_allowed_p = (save_as_type != 0);
|
||
#endif /* NEW_DECODERS */
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
XtRemoveAllCallbacks (fileb, XmNnoMatchCallback);
|
||
XtRemoveAllCallbacks (fileb, XmNokCallback);
|
||
XtRemoveAllCallbacks (fileb, XmNapplyCallback);
|
||
XtRemoveAllCallbacks (fileb, XmNcancelCallback);
|
||
XtRemoveAllCallbacks (fileb, XmNdestroyCallback);
|
||
|
||
XtAddCallback (fileb, XmNnoMatchCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNokCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNcancelCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNdestroyCallback, fe_file_destroy_cb, &data);
|
||
|
||
XtVaSetValues (XtParent (fileb), XmNtitle, title, 0);
|
||
#if 0 /* mustMatch doesn't work! */
|
||
XtVaSetValues (fileb, XmNmustMatch, must_match, 0);
|
||
#else
|
||
XtVaSetValues (fileb, XmNmustMatch, False, 0);
|
||
data.must_match = must_match;
|
||
#endif
|
||
|
||
{
|
||
String dirmask = 0;
|
||
XmString xms;
|
||
char *s, *tail;
|
||
char buf [2048];
|
||
const char *def;
|
||
|
||
if (! default_url)
|
||
def = 0;
|
||
else if ((def = strrchr (default_url, '/')))
|
||
def++;
|
||
else
|
||
def = default_url;
|
||
|
||
XtVaGetValues (fileb, XmNdirSpec, &xms, 0);
|
||
XmStringGetLtoR (xms, XmFONTLIST_DEFAULT_TAG, &s); /* s - is XtMalloc */
|
||
XmStringFree (xms);
|
||
|
||
/* Take the file name part off of `s', leaving only the dir. */
|
||
tail = strrchr (s, '/');
|
||
if (tail) *tail = 0;
|
||
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/%.900s", s, (def ? def : ""));
|
||
if (def)
|
||
{
|
||
/* Grab the file name part (it's sitting right after the end of `s')
|
||
and map out the characters which ought not go into file names.
|
||
Also, terminate the file name at ? or #, since those aren't
|
||
really a part of the URL's file, but are modifiers to it.
|
||
*/
|
||
for (tail = buf+strlen(s)+1; *tail; tail++)
|
||
if (*tail == '?' || *tail == '#')
|
||
*tail = 0;
|
||
else if (*tail < '+' || *tail > 'z' ||
|
||
*tail == ':' || *tail == ';' ||
|
||
*tail == '<' || *tail == '>' ||
|
||
*tail == '\\' || *tail == '^' ||
|
||
*tail == '\'' || *tail == '`' ||
|
||
*tail == ',')
|
||
*tail = '_';
|
||
}
|
||
XtFree (s);
|
||
|
||
/* If the dialog already existed, its data is out of date. Resync. */
|
||
XtVaGetValues (fileb, XmNdirMask, &dirmask, 0);
|
||
XmFileSelectionDoSearch (fileb, dirmask);
|
||
|
||
/* Change the default file name. */
|
||
xms = XmStringCreate (buf, XmFONTLIST_DEFAULT_TAG);
|
||
XtVaSetValues (fileb, XmNdirSpec, xms, 0);
|
||
XmStringFree (xms);
|
||
|
||
#ifdef NEW_DECODERS
|
||
fe_file_type_hack_extension (ftd);
|
||
#endif /* NEW_DECODERS */
|
||
}
|
||
|
||
data.context = context;
|
||
data.answer = Answer_Invalid;
|
||
data.return_value = 0;
|
||
|
||
if (save_as_type)
|
||
XtManageChild (sabox);
|
||
else
|
||
XtUnmanageChild (sabox);
|
||
|
||
fe_NukeBackingStore (fileb);
|
||
XtManageChild (fileb);
|
||
/* #### check for unmanagement here */
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer != Answer_Destroy) {
|
||
/* Call the ok -> save directory callback because it's been removed */
|
||
fe_file_selection_save_directory_cb(fileb, NULL, NULL);
|
||
XtUnmanageChild(fileb);
|
||
XtRemoveCallback(fileb, XmNdestroyCallback, fe_file_destroy_cb, &data);
|
||
}
|
||
|
||
|
||
if (save_as_type)
|
||
*save_as_type = ftd->selected_option;
|
||
|
||
if (data.answer == Answer_Destroy) {
|
||
if (!data.context) {
|
||
XP_ASSERT(filebp && ftdp);
|
||
*filebp = 0;
|
||
*ftdp = 0;
|
||
}
|
||
if (ftd) {
|
||
/*
|
||
* If the context got destroyed, this could have been freed by the
|
||
* context. Our destroy routine checks for the parent context being
|
||
* freed and sets the return_value to -1 if the context was destroyed.
|
||
*/
|
||
if (data.return_value != (void *)-1)
|
||
XP_FREE(ftd);
|
||
}
|
||
data.answer = Answer_Cancel; /* Simulate CANCEL */
|
||
data.return_value = 0;
|
||
}
|
||
|
||
return (char *) data.return_value;
|
||
}
|
||
|
||
char *
|
||
fe_ReadFileName (MWContext *context, const char *title,
|
||
const char *default_url,
|
||
Boolean must_match,
|
||
int *save_as_type)
|
||
{
|
||
char *ret = NULL;
|
||
|
||
fe_ProtectContext(context);
|
||
ret = fe_ReadFileName_2( context, NULL, NULL, NULL,
|
||
title, default_url, must_match, save_as_type);
|
||
fe_UnProtectContext(context);
|
||
if (fe_IsContextDestroyed(context)) {
|
||
free(CONTEXT_DATA(context));
|
||
free(context);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
static void
|
||
fe_file_destroy_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
if (data->answer == Answer_Invalid) {
|
||
data->answer = Answer_Destroy;
|
||
/* Reset the context file dialog storage. Be sure that this destroy isnt
|
||
* a result of the context itself being destroyed.
|
||
*/
|
||
if (data->context)
|
||
if (!XfeIsAlive(CONTEXT_WIDGET(data->context))) {
|
||
/* Indicates the context was destroyed too */
|
||
data->return_value = (void *)-1;
|
||
}
|
||
else {
|
||
CONTEXT_DATA(data->context)->file_dialog = 0;
|
||
CONTEXT_DATA(data->context)->ftd = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_file_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
XmFileSelectionBoxCallbackStruct *sbc =
|
||
(XmFileSelectionBoxCallbackStruct *) call_data;
|
||
|
||
switch (sbc->reason)
|
||
{
|
||
case XmCR_NO_MATCH:
|
||
{
|
||
NOMATCH:
|
||
XBell (XtDisplay (widget), 0);
|
||
break;
|
||
}
|
||
case XmCR_OK:
|
||
{
|
||
XmStringGetLtoR (sbc->value, XmFONTLIST_DEFAULT_TAG,
|
||
(char **) &data->return_value);
|
||
#if 1
|
||
/* mustMatch doesn't work!! */
|
||
{
|
||
struct stat st;
|
||
if (data->must_match &&
|
||
data->return_value &&
|
||
stat (data->return_value, &st))
|
||
{
|
||
free (data->return_value);
|
||
data->return_value = 0;
|
||
goto NOMATCH;
|
||
}
|
||
}
|
||
#endif
|
||
data->answer = Answer_OK;
|
||
break;
|
||
}
|
||
case XmCR_CANCEL:
|
||
{
|
||
data->answer = Answer_Cancel;
|
||
data->return_value = 0;
|
||
break;
|
||
}
|
||
default:
|
||
abort ();
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_file_type_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_file_type_data *ftd = (struct fe_file_type_data *) closure;
|
||
int i;
|
||
ftd->selected_option = -1;
|
||
for (i = 0; i < countof (ftd->options); i++)
|
||
if (ftd->options [i] == widget)
|
||
{
|
||
ftd->selected_option = i;
|
||
break;
|
||
}
|
||
#ifdef NEW_DECODERS
|
||
fe_file_type_hack_extension (ftd);
|
||
#endif /* NEW_DECODERS */
|
||
}
|
||
|
||
#ifdef NEW_DECODERS
|
||
static void
|
||
fe_file_type_hack_extension_1 (struct fe_file_type_data *ftd,
|
||
Boolean dirspec_p)
|
||
{
|
||
int desired_type;
|
||
const char *default_file_name = "index.html";
|
||
XmString xm_file = 0;
|
||
char *file = 0;
|
||
char *name_part = 0;
|
||
char *ext = 0;
|
||
char *orig_ext = 0;
|
||
const char *new_ext = 0;
|
||
char *orig_url_copy = 0;
|
||
|
||
if (!ftd || !ftd->fileb)
|
||
return;
|
||
|
||
if (ftd->conversion_allowed_p)
|
||
desired_type = ftd->selected_option;
|
||
else
|
||
desired_type = fe_FILE_TYPE_HTML;
|
||
|
||
/* Find a default file name.
|
||
If this URL ends in a file part, use that, otherwise, assume "index.html".
|
||
Then, once we've got a default file name, set the default extension to
|
||
use for "Save As Source" from that.
|
||
*/
|
||
if (ftd->orig_url)
|
||
{
|
||
const char *orig_name_part;
|
||
char *s;
|
||
|
||
orig_url_copy = strdup (ftd->orig_url);
|
||
|
||
/* take off form and anchor data. */
|
||
if ((s = strchr (orig_url_copy, '?')))
|
||
*s = 0;
|
||
if ((s = strchr (orig_url_copy, '#')))
|
||
*s = 0;
|
||
|
||
orig_name_part = strrchr (orig_url_copy, '/');
|
||
if (! orig_name_part)
|
||
orig_name_part = strrchr (orig_url_copy, ':');
|
||
if (orig_name_part)
|
||
orig_name_part++;
|
||
else if (orig_url_copy && *orig_url_copy)
|
||
orig_name_part = orig_url_copy;
|
||
|
||
if (orig_name_part && *orig_name_part)
|
||
default_file_name = orig_name_part;
|
||
|
||
orig_ext = strrchr (default_file_name, '.');
|
||
|
||
if (!orig_ext && !dirspec_p)
|
||
{
|
||
/* If we're up in the filter area, and there is as yet no
|
||
orig_ext, then that means that there was file name without
|
||
an extension (as opposed to no file name, when we would
|
||
have defaulted to "index.html".) So, for the purposes
|
||
of the filter, set the extension to ".*".
|
||
*/
|
||
orig_ext = ".*";
|
||
}
|
||
}
|
||
|
||
/* Get `file' from what's currently typed into the text field.
|
||
*/
|
||
XtVaGetValues (ftd->fileb,
|
||
(dirspec_p ? XmNdirSpec : XmNdirMask), &xm_file, 0);
|
||
if (! xm_file) return;
|
||
XmStringGetLtoR (xm_file, XmFONTLIST_DEFAULT_TAG, &file); /* file- XtMalloc */
|
||
XmStringFree (xm_file);
|
||
|
||
/* If the file ends in "/" then stick the default file name on the end. */
|
||
if (dirspec_p && file && *file && file [strlen (file) - 1] == '/')
|
||
{
|
||
char *file2 = (char *) malloc (strlen (file) +
|
||
strlen (default_file_name) + 1);
|
||
strcpy (file2, file);
|
||
strcat (file2, default_file_name);
|
||
XtFree (file);
|
||
file = file2;
|
||
}
|
||
|
||
name_part = strrchr (file, '/');
|
||
if (! name_part)
|
||
name_part = strrchr (file, ':');
|
||
if (name_part)
|
||
name_part++;
|
||
|
||
if (!name_part || !*name_part)
|
||
name_part = 0;
|
||
|
||
if (name_part)
|
||
ext = strrchr (name_part, '.');
|
||
|
||
switch (desired_type)
|
||
{
|
||
case fe_FILE_TYPE_HTML:
|
||
case fe_FILE_TYPE_HTML_AND_IMAGES:
|
||
new_ext = orig_ext;
|
||
break;
|
||
case fe_FILE_TYPE_TEXT:
|
||
case fe_FILE_TYPE_FORMATTED_TEXT:
|
||
/* The user has selected "text". Change the extension to "txt"
|
||
only if the original URL had extension "html" or "htm". */
|
||
if (orig_ext &&
|
||
(!strcasecomp (orig_ext, ".html") ||
|
||
!strcasecomp (orig_ext, ".htm")))
|
||
new_ext = ".txt";
|
||
else
|
||
new_ext = orig_ext;
|
||
break;
|
||
case fe_FILE_TYPE_PS:
|
||
new_ext = ".ps";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (ext && new_ext /* && !!strcasecomp (ext, new_ext) */ )
|
||
{
|
||
char *file2;
|
||
*ext = 0;
|
||
file2 = (char *) malloc (strlen (file) + strlen (new_ext) + 1);
|
||
strcpy (file2, file);
|
||
strcat (file2, new_ext);
|
||
xm_file = XmStringCreateLtoR (file2, XmFONTLIST_DEFAULT_TAG);
|
||
|
||
if (dirspec_p)
|
||
{
|
||
XtVaSetValues (ftd->fileb, XmNdirSpec, xm_file, 0);
|
||
}
|
||
else
|
||
{
|
||
XmString saved_value = 0;
|
||
|
||
/* Don't let what's currently typed into the `Selection' field
|
||
to change as a result of running this search again -- that's
|
||
totally bogus. */
|
||
XtVaGetValues (ftd->fileb, XmNdirSpec, &saved_value, 0);
|
||
|
||
XtVaSetValues (ftd->fileb, XmNdirMask, xm_file, 0);
|
||
XmFileSelectionDoSearch (ftd->fileb, xm_file);
|
||
if (saved_value)
|
||
{
|
||
XtVaSetValues (ftd->fileb, XmNdirSpec, saved_value, 0);
|
||
XmStringFree (saved_value);
|
||
}
|
||
}
|
||
|
||
XmStringFree (xm_file);
|
||
free (file2);
|
||
}
|
||
|
||
if (orig_url_copy)
|
||
free (orig_url_copy);
|
||
|
||
XtFree (file);
|
||
}
|
||
|
||
|
||
static void
|
||
fe_file_type_hack_extension (struct fe_file_type_data *ftd)
|
||
{
|
||
fe_file_type_hack_extension_1 (ftd, False);
|
||
fe_file_type_hack_extension_1 (ftd, True);
|
||
}
|
||
|
||
#endif /* NEW_DECODERS */
|
||
|
||
|
||
|
||
/* Open URL - prompts asynchronously
|
||
*/
|
||
|
||
static char *last_open_url_text = 0;
|
||
|
||
struct fe_open_url_data {
|
||
MWContext *context;
|
||
Widget widget;
|
||
Widget text;
|
||
#ifdef EDITOR
|
||
Widget in_editor;
|
||
#endif
|
||
Widget in_browser;
|
||
};
|
||
|
||
static char*
|
||
cleanup_selection(char* target, char* source, unsigned max_size)
|
||
{
|
||
char* p;
|
||
char* q;
|
||
char* end;
|
||
|
||
for (p = source; isspace(*p); p++) /* skip beginning whitespace */
|
||
;
|
||
|
||
end = &p[max_size-1];
|
||
q = target;
|
||
|
||
while (p < end) {
|
||
/*
|
||
* Stop if we detect an unprintable, or newline.
|
||
*/
|
||
if (!isprint(*p) || *p == '\n' || *p == '\r')
|
||
break;
|
||
|
||
if (isspace(*p))
|
||
*q++ = ' ', p++;
|
||
else
|
||
*q++ = *p++;
|
||
}
|
||
/* strip trailing whitespace */
|
||
while (q > target && isspace(q[-1]))
|
||
q--;
|
||
|
||
*q = '\0';
|
||
|
||
return target;
|
||
}
|
||
|
||
static void
|
||
file_dialog_get_url(MWContext* context, char* address, MWContextType ge_type)
|
||
{
|
||
if (address != NULL) {
|
||
if (ge_type == MWContextBrowser) {
|
||
fe_BrowserGetURL(context, address);
|
||
}
|
||
#ifdef EDITOR
|
||
else if (ge_type == MWContextEditor) {
|
||
fe_EditorEdit(context, NULL, NULL, address); /* try to re-use */
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_open_url_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_open_url_data *data = (struct fe_open_url_data *) closure;
|
||
char* text = NULL;
|
||
MWContext* context;
|
||
MWContextType ge_type = MWContextAny;
|
||
|
||
if (call_data == NULL || /* when it's a destroy callback */
|
||
!XfeIsAlive(widget) || /* on it's way */
|
||
data == NULL) /* data from hell */
|
||
return;
|
||
|
||
context = data->context;
|
||
|
||
if (widget == data->in_browser
|
||
#ifdef EDITOR
|
||
|| widget == data->in_editor
|
||
#endif
|
||
) {
|
||
|
||
text = fe_GetTextField(data->text);
|
||
|
||
if (! text)
|
||
return;
|
||
|
||
cleanup_selection(text, text, strlen(text)+1);
|
||
|
||
if (*text != '\0') {
|
||
|
||
if (last_open_url_text)
|
||
XtFree(last_open_url_text);
|
||
|
||
last_open_url_text = text;
|
||
|
||
if (widget == data->in_browser)
|
||
ge_type = MWContextBrowser;
|
||
#ifdef EDITOR
|
||
else if (widget == data->in_editor)
|
||
ge_type = MWContextEditor;
|
||
#endif
|
||
}
|
||
}
|
||
|
||
XtUnmanageChild(data->widget);
|
||
XtDestroyWidget(data->widget);
|
||
free(data);
|
||
|
||
/*
|
||
* Call common routine to divert the get_url()
|
||
*/
|
||
file_dialog_get_url(context, text, ge_type);
|
||
}
|
||
|
||
static void
|
||
fe_open_url_browse_cb(Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_open_url_data* data = (struct fe_open_url_data *)closure;
|
||
|
||
fe_browse_file_of_text(data->context, data->text, False);
|
||
}
|
||
|
||
void
|
||
fe_OpenURLDialog(MWContext* context)
|
||
{
|
||
struct fe_open_url_data *data;
|
||
Widget dialog;
|
||
Widget label;
|
||
Widget text;
|
||
Widget in_browser;
|
||
#ifdef EDITOR
|
||
Widget in_editor;
|
||
#endif
|
||
Widget form;
|
||
Widget browse;
|
||
Arg args[20];
|
||
int n;
|
||
char* string;
|
||
|
||
dialog = fe_CreatePromptDialog(context, "openURLDialog",
|
||
FALSE, TRUE, TRUE, TRUE, TRUE);
|
||
|
||
n = 0;
|
||
form = XmCreateForm(dialog, "form", args, n);
|
||
XtManageChild(form);
|
||
|
||
n = 0;
|
||
XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
|
||
XtSetArg(args [n], XmNtopAttachment, XmATTACH_FORM); n++;
|
||
XtSetArg(args [n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
|
||
label = XmCreateLabelGadget(form, "label", args, n);
|
||
XtManageChild(label);
|
||
|
||
n = 0;
|
||
XtSetArg(args [n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
||
XtSetArg(args [n], XmNtopWidget, label); n++;
|
||
XtSetArg(args [n], XmNrightAttachment, XmATTACH_FORM); n++;
|
||
XtSetArg(args [n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
||
browse = XmCreatePushButtonGadget(form, "choose", args, n);
|
||
XtManageChild(browse);
|
||
|
||
string = last_open_url_text? last_open_url_text : "";
|
||
|
||
n = 0;
|
||
XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
|
||
XtSetArg(args [n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
||
XtSetArg(args [n], XmNtopWidget, label); n++;
|
||
XtSetArg(args [n], XmNrightAttachment, XmATTACH_WIDGET); n++;
|
||
XtSetArg(args [n], XmNrightWidget, browse); n++;
|
||
XtSetArg(args [n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
||
XtSetArg(args [n], XmNeditable, True); n++;
|
||
XtSetArg(args [n], XmNcursorPositionVisible, True); n++;
|
||
text = fe_CreateTextField(form, "openURLText", args, n);
|
||
fe_SetTextField(text, string);
|
||
XtManageChild(text);
|
||
|
||
n = 0;
|
||
#ifdef MOZ_MAIL_NEWS
|
||
in_browser = XmCreatePushButtonGadget(dialog, "openInBrowser", args, n);
|
||
#else
|
||
in_browser = XmCreatePushButtonGadget(dialog, "OK", args, n);
|
||
#endif
|
||
XtManageChild(in_browser);
|
||
|
||
#ifdef EDITOR
|
||
n = 0;
|
||
XtSetArg(args[n], XmNsensitive, !fe_IsEditorDisabled()); n++;
|
||
in_editor = XmCreatePushButtonGadget(dialog, "openInEditor", args, n);
|
||
XtManageChild(in_editor);
|
||
#endif
|
||
|
||
data = (struct fe_open_url_data *)calloc(sizeof(struct fe_open_url_data), 1);
|
||
data->context = context;
|
||
data->widget = dialog;
|
||
data->text = text;
|
||
data->in_browser = in_browser;
|
||
#ifdef EDITOR
|
||
data->in_editor = in_editor;
|
||
|
||
if (context->type == MWContextEditor)
|
||
XtVaSetValues(dialog, XmNdefaultButton, in_editor, 0);
|
||
else
|
||
#endif
|
||
XtVaSetValues(dialog, XmNdefaultButton, in_browser, 0);
|
||
|
||
XtAddCallback(browse, XmNactivateCallback,fe_open_url_browse_cb, data);
|
||
#ifdef EDITOR
|
||
XtAddCallback(in_editor, XmNactivateCallback, fe_open_url_cb, data);
|
||
#endif
|
||
XtAddCallback(in_browser, XmNactivateCallback, fe_open_url_cb, data);
|
||
XtAddCallback(dialog, XmNcancelCallback, fe_open_url_cb, data);
|
||
XtAddCallback(dialog, XmNdestroyCallback, fe_open_url_cb, data);
|
||
XtAddCallback(dialog, XmNapplyCallback, fe_clear_text_cb, text);
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
}
|
||
|
||
void
|
||
fe_OpenURLChooseFileDialog (MWContext *context)
|
||
{
|
||
char *text;
|
||
|
||
if (!context) return;
|
||
|
||
text = fe_ReadFileName (context,
|
||
XP_GetString(XFE_OPEN_FILE),
|
||
last_open_url_text,
|
||
FALSE, /* must match */
|
||
0); /* save_as_type */
|
||
|
||
file_dialog_get_url(context, text, context->type);
|
||
}
|
||
|
||
|
||
|
||
|
||
/* Prompt the user for their password. The message string is displayed
|
||
* to the user so they know what they are giving their password for.
|
||
* The characters of the password are not echoed.
|
||
*/
|
||
char *
|
||
XFE_PromptPassword (MWContext *context, const char *message)
|
||
{
|
||
return (char *) fe_dialog (CONTEXT_WIDGET (context),
|
||
"password", message, TRUE, "", TRUE, FALSE,
|
||
((char **) 1));
|
||
}
|
||
|
||
/*
|
||
* Yet Another front end function that
|
||
* noone told us we were supposed to implement.
|
||
*/
|
||
char *XP_PromptPassword(MWContext *context, const char *message)
|
||
{
|
||
return XFE_PromptPassword(context, message);
|
||
}
|
||
|
||
/* Prompt for a username and password
|
||
*
|
||
* message is a prompt message.
|
||
*
|
||
* if username and password are not NULL they should be used
|
||
* as default values and NOT MODIFIED. New values should be malloc'd
|
||
* and put in their place.
|
||
*
|
||
* If the User hit's cancel FALSE should be returned, otherwise
|
||
* TRUE should be returned.
|
||
*/
|
||
XP_Bool
|
||
XFE_PromptUsernameAndPassword (MWContext *context,
|
||
const char *message,
|
||
char **username,
|
||
char **password)
|
||
{
|
||
char *pw = "";
|
||
char *un = (char *) fe_dialog (CONTEXT_WIDGET (context),
|
||
"password", message, TRUE,
|
||
(*username ? *username : ""), TRUE, FALSE,
|
||
&pw);
|
||
if (pw)
|
||
{
|
||
*username = un;
|
||
*password = XP_STRDUP(pw);
|
||
return(TRUE);
|
||
}
|
||
else
|
||
{
|
||
*username = 0;
|
||
*password = 0;
|
||
return(FALSE);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Yet Another front end function that
|
||
* noone told us we were supposed to implement.
|
||
*/
|
||
PRBool XP_PromptUsernameAndPassword (MWContext *window_id,
|
||
const char *message,
|
||
char **username,
|
||
char **password)
|
||
{
|
||
return XFE_PromptUsernameAndPassword(window_id, message, username, password);
|
||
}
|
||
|
||
|
||
/* Prompting for visuals
|
||
*/
|
||
|
||
static void fe_visual_cb (Widget, XtPointer, XtPointer);
|
||
|
||
Visual *
|
||
fe_ReadVisual (MWContext *context)
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Display *dpy = XtDisplay (mainw);
|
||
Screen *screen = XtScreen (mainw);
|
||
Arg av [20];
|
||
int ac;
|
||
int i;
|
||
Widget shell;
|
||
XmString *items;
|
||
int item_count;
|
||
int default_item = 0;
|
||
XVisualInfo vi_in, *vi_out;
|
||
struct fe_confirm_data data;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
vi_in.screen = fe_ScreenNumber (screen);
|
||
vi_out = XGetVisualInfo (dpy, VisualScreenMask, &vi_in, &item_count);
|
||
if (! vi_out) item_count = 0;
|
||
items = (XmString *) calloc (sizeof (XmString), item_count + 1);
|
||
for (i = 0; i < item_count; i++)
|
||
{
|
||
char *vdesc = fe_VisualDescription (screen, vi_out [i].visual);
|
||
items[i] = XmStringCreate (vdesc, XmFONTLIST_DEFAULT_TAG);
|
||
free (vdesc);
|
||
if (vi_out [i].visual == v)
|
||
default_item = i;
|
||
}
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
/* XtSetArg (av[ac], XmNautoUnmanage, False); ac++;*/
|
||
XtSetArg (av[ac], XmNlistItems, items); ac++;
|
||
XtSetArg (av[ac], XmNlistItemCount, item_count); ac++;
|
||
shell = XmCreateSelectionDialog (mainw, "visual", av, ac);
|
||
|
||
XtAddCallback (shell, XmNokCallback, fe_visual_cb, &data);
|
||
XtAddCallback (shell, XmNcancelCallback, fe_visual_cb, &data);
|
||
XtAddCallback (shell, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_APPLY_BUTTON));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_TEXT));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell,
|
||
XmDIALOG_SELECTION_LABEL));
|
||
|
||
{
|
||
Widget list = XmSelectionBoxGetChild (shell, XmDIALOG_LIST);
|
||
XtVaSetValues (list,
|
||
XmNselectedItems, (items + default_item),
|
||
XmNselectedItemCount, 1,
|
||
0);
|
||
}
|
||
|
||
data.context = context;
|
||
data.widget = shell;
|
||
data.answer = Answer_Invalid;
|
||
data.return_value = 0;
|
||
|
||
fe_NukeBackingStore (shell);
|
||
XtManageChild (shell);
|
||
|
||
/* #### check for destruction here */
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
for (i = 0; i < item_count; i++)
|
||
XmStringFree (items [i]);
|
||
free (items);
|
||
|
||
if (vi_out)
|
||
{
|
||
int index = (int) data.return_value;
|
||
Visual *v = (data.answer == 1 ? vi_out [index].visual : 0);
|
||
XFree ((char *) vi_out);
|
||
return v;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static void fe_visual_cb (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
struct fe_confirm_data *data = (struct fe_confirm_data *) closure;
|
||
XmSelectionBoxCallbackStruct *cb =
|
||
(XmSelectionBoxCallbackStruct *) call_data;
|
||
XmString *items;
|
||
int count;
|
||
int i;
|
||
XtVaGetValues (data->widget,
|
||
XmNlistItems, &items,
|
||
XmNlistItemCount, &count,
|
||
0);
|
||
switch (cb->reason)
|
||
{
|
||
case XmCR_OK:
|
||
case XmCR_APPLY:
|
||
{
|
||
data->answer = 1;
|
||
data->return_value = (void *) -1;
|
||
for (i = 0; i < count; i++)
|
||
if (XmStringCompare (items[i], cb->value))
|
||
data->return_value = (void *) i;
|
||
if (data->return_value == (void *) -1)
|
||
abort ();
|
||
break;
|
||
}
|
||
case XmCR_CANCEL:
|
||
data->answer = 0;
|
||
break;
|
||
default:
|
||
abort ();
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
/* Displaying source
|
||
*/
|
||
|
||
struct fe_source_data
|
||
{
|
||
Widget dialog;
|
||
Widget name, url, text;
|
||
};
|
||
|
||
#if 0
|
||
static void
|
||
fe_close_source_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
MWContext *context = (MWContext *) closure;
|
||
if (! CONTEXT_DATA (context)->sd) return;
|
||
XtUnmanageChild (CONTEXT_DATA (context)->sd->dialog);
|
||
}
|
||
|
||
static void
|
||
fe_source_save_as_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
MWContext *context = (MWContext *) closure;
|
||
char *url = 0;
|
||
URL_Struct *url_struct;
|
||
if (! CONTEXT_DATA (context)->sd) return;
|
||
url = fe_GetTextField (CONTEXT_DATA (context)->sd->url);
|
||
if (! url) return;
|
||
url_struct = NET_CreateURLStruct (url, FALSE);
|
||
fe_SaveURL (context, url_struct);
|
||
}
|
||
#endif
|
||
|
||
#if 0 /* This is history. Should remove this code out later. */
|
||
Widget
|
||
fe_ViewSourceDialog (MWContext *context, const char *title, const char *url)
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
struct fe_source_data *sd = CONTEXT_DATA (context)->sd;
|
||
|
||
if (! sd)
|
||
{
|
||
Widget shell, form, text;
|
||
Widget url_label, url_text, title_label, title_text;
|
||
Widget ok_button, save_button;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
sd = (struct fe_source_data *) calloc(sizeof (struct fe_source_data), 1);
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
|
||
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_INFORMATION); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
shell = XmCreateTemplateDialog (mainw, "source", av, ac);
|
||
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_OK_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell,
|
||
XmDIALOG_CANCEL_BUTTON));
|
||
/* fe_UnmanageChild_safe (XmMessageBoxGetChild (shell,
|
||
XmDIALOG_APPLY_BUTTON));*/
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell,
|
||
XmDIALOG_DEFAULT_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell,
|
||
XmDIALOG_HELP_BUTTON));
|
||
|
||
ac = 0;
|
||
save_button = XmCreatePushButtonGadget (shell, "save", av, ac);
|
||
ok_button = XmCreatePushButtonGadget (shell, "OK", av, ac);
|
||
|
||
ac = 0;
|
||
form = XmCreateForm (shell, "form", av, ac);
|
||
|
||
ac = 0;
|
||
title_label = XmCreateLabelGadget (form, "titleLabel", av, ac);
|
||
url_label = XmCreateLabelGadget (form, "urlLabel", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av [ac], XmNeditable, False); ac++;
|
||
XtSetArg (av [ac], XmNcursorPositionVisible, False); ac++;
|
||
title_text = fe_CreateTextField (form, "titleText", av, ac);
|
||
url_text = fe_CreateTextField (form, "urlText", av, ac);
|
||
|
||
ac = 0;
|
||
XtSetArg (av [ac], XmNeditable, False); ac++;
|
||
XtSetArg (av [ac], XmNcursorPositionVisible, False); ac++;
|
||
XtSetArg (av[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
|
||
text = XmCreateScrolledText (form, "text", av, ac);
|
||
fe_HackDialogTranslations (text);
|
||
|
||
XtVaSetValues (title_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, title_text,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, title_text,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, title_text,
|
||
0);
|
||
XtVaSetValues (url_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, url_text,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, url_text,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, url_text,
|
||
0);
|
||
|
||
XtVaSetValues (title_text,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (url_text,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, title_text,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, title_text,
|
||
XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNrightWidget, title_text,
|
||
0);
|
||
XtVaSetValues (XtParent (text),
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, url_text,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
|
||
fe_attach_field_to_labels (title_text, title_label, url_label, 0);
|
||
|
||
XtAddCallback (save_button, XmNactivateCallback,
|
||
fe_source_save_as_cb, context);
|
||
XtAddCallback (ok_button, XmNactivateCallback,
|
||
fe_close_source_cb, context);
|
||
|
||
XtVaSetValues (shell, XmNdefaultButton, save_button, 0);
|
||
|
||
XtManageChild (title_label);
|
||
XtManageChild (title_text);
|
||
XtManageChild (url_label);
|
||
XtManageChild (url_text);
|
||
XtManageChild (text);
|
||
XtManageChild (form);
|
||
XtManageChild (save_button);
|
||
XtManageChild (ok_button);
|
||
|
||
sd->dialog = shell;
|
||
sd->text = text;
|
||
sd->url = url_text;
|
||
sd->name = title_text;
|
||
CONTEXT_DATA (context)->sd = sd;
|
||
}
|
||
|
||
XtVaSetValues (sd->text, XmNcursorPosition, 0);
|
||
fe_SetTextField (sd->text, "");
|
||
XtVaSetValues (sd->name, XmNcursorPosition, 0, 0);
|
||
fe_SetTextField (sd->name, (title ? title : ""));
|
||
XtVaSetValues (sd->url, XmNcursorPosition, 0, 0);
|
||
fe_SetTextField (sd->url, (url ? url : ""));
|
||
|
||
fe_NukeBackingStore (sd->dialog);
|
||
XtManageChild (sd->dialog);
|
||
return sd->text;
|
||
}
|
||
#endif /* 0 */
|
||
|
||
|
||
/* User information
|
||
*/
|
||
|
||
#include <pwd.h>
|
||
#include <netdb.h>
|
||
|
||
void
|
||
fe_DefaultUserInfo (char **uid, char **name, Boolean really_default_p)
|
||
{
|
||
struct passwd *pw = getpwuid (geteuid ());
|
||
char *user_name, *tmp;
|
||
char *real_uid = (pw ? pw->pw_name : "");
|
||
char *user_uid = 0;
|
||
|
||
if (really_default_p)
|
||
{
|
||
user_uid = real_uid;
|
||
}
|
||
else
|
||
{
|
||
user_uid = getenv ("LOGNAME");
|
||
if (! user_uid) user_uid = getenv ("USER");
|
||
if (! user_uid) user_uid = real_uid;
|
||
|
||
/* If the env vars claim a different user, get the real name of
|
||
that user instead of the actual user. */
|
||
if (strcmp (user_uid, real_uid))
|
||
{
|
||
struct passwd *pw2 = getpwnam (user_uid);
|
||
if (pw2) pw = pw2;
|
||
}
|
||
}
|
||
|
||
user_uid = strdup (user_uid);
|
||
user_name = strdup ((pw && pw->pw_gecos ? pw->pw_gecos : "&"));
|
||
|
||
/* Terminate the string at the first comma, to lose phone numbers and crap
|
||
like that. This may lose for "Jr."s, but who cares: Unix sucks. */
|
||
if ((tmp = strchr (user_name, ',')))
|
||
*tmp = 0;
|
||
|
||
if ((tmp = strchr (user_name, '&')))
|
||
{
|
||
int i, j;
|
||
char *new = (char *) malloc (strlen (user_name) + strlen (user_uid) + 1);
|
||
for (i = 0, j = 0; user_name[i]; i++)
|
||
if (tmp == user_name + i)
|
||
{
|
||
strcpy (new + j, user_uid);
|
||
new[j] = toupper (new[j]);
|
||
j += strlen (user_uid);
|
||
tmp = 0;
|
||
}
|
||
else
|
||
{
|
||
new[j++] = user_name[i];
|
||
}
|
||
free (user_name);
|
||
user_name = new;
|
||
}
|
||
|
||
*uid = user_uid;
|
||
*name = user_name;
|
||
}
|
||
|
||
|
||
/* Synchronous loading of a URL
|
||
Internally, we use the URL mechanism to do some things during which time
|
||
we want the interface to be blocked - for example, formatting a document
|
||
for inclusion in a mail window, and printing, and so on. This code lets
|
||
us put up a dialog box with a status message and a cancel button, and
|
||
bring it down when the event is over.
|
||
*/
|
||
|
||
/* #define SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
|
||
#ifdef SYNCHRONOUS_URL_DIALOG_WORKS
|
||
static void
|
||
fe_synchronous_url_cancel_cb (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
MWContext *context = (MWContext *) closure;
|
||
XP_InterruptContext (context);
|
||
}
|
||
|
||
/*
|
||
* Make sure the the popped up modal dialog receives at least
|
||
* on FocusIn event, because Motif seems to expect/require it.
|
||
*/
|
||
static void
|
||
fe_dialog_expose_eh (Widget widget, XtPointer closure, XEvent *event)
|
||
{
|
||
MWContext *context = (MWContext *) closure;
|
||
Widget dialog = CONTEXT_DATA (context)->synchronous_url_dialog;
|
||
|
||
XtRemoveEventHandler(dialog, ExposureMask, FALSE,
|
||
(XtEventHandler)fe_dialog_expose_eh, context);
|
||
XSetInputFocus(XtDisplay (dialog), XtWindow(dialog),
|
||
RevertToParent, CurrentTime);
|
||
XSync (XtDisplay (dialog), False);
|
||
}
|
||
#endif /* SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
void
|
||
fe_LowerSynchronousURLDialog (MWContext *context)
|
||
{
|
||
if (CONTEXT_DATA (context)->synchronous_url_dialog)
|
||
{
|
||
#ifdef SYNCHRONOUS_URL_DIALOG_WORKS
|
||
Widget shell = XtParent (CONTEXT_DATA (context)->synchronous_url_dialog);
|
||
|
||
/* Don't call XP_InterruptContext a (possibly) second time. */
|
||
XtRemoveCallback (CONTEXT_DATA (context)->synchronous_url_dialog,
|
||
XtNdestroyCallback,
|
||
fe_synchronous_url_cancel_cb, context);
|
||
XtUnmanageChild (CONTEXT_DATA (context)->synchronous_url_dialog);
|
||
XSync (XtDisplay (shell), False);
|
||
XtDestroyWidget (shell);
|
||
#endif /* SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
CONTEXT_DATA (context)->synchronous_url_dialog = 0;
|
||
|
||
/* If this context was destroyed, do not proceed furthur */
|
||
if (fe_IsContextDestroyed(context))
|
||
return;
|
||
|
||
assert (CONTEXT_DATA (context)->active_url_count > 0);
|
||
if (CONTEXT_DATA (context)->active_url_count > 0)
|
||
CONTEXT_DATA (context)->active_url_count--;
|
||
if (CONTEXT_DATA (context)->active_url_count <= 0)
|
||
XFE_AllConnectionsComplete (context);
|
||
fe_SetCursor (context, False);
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_synchronous_url_exit (URL_Struct *url, int status, MWContext *context)
|
||
{
|
||
if (status == MK_CHANGING_CONTEXT)
|
||
return;
|
||
fe_LowerSynchronousURLDialog (context);
|
||
if (status < 0 && url->error_msg)
|
||
{
|
||
FE_Alert (context, url->error_msg);
|
||
}
|
||
NET_FreeURLStruct (url);
|
||
CONTEXT_DATA (context)->synchronous_url_exit_status = status;
|
||
}
|
||
|
||
void
|
||
fe_RaiseSynchronousURLDialog (MWContext *context, Widget parent,
|
||
const char *title)
|
||
{
|
||
#ifdef SYNCHRONOUS_URL_DIALOG_WORKS
|
||
Widget shell, dialog;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
char title2 [255];
|
||
Boolean popped_up;
|
||
#endif /* SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
CONTEXT_DATA (context)->active_url_count++;
|
||
if (CONTEXT_DATA (context)->active_url_count == 1)
|
||
{
|
||
CONTEXT_DATA (context)->clicking_blocked = True;
|
||
fe_StartProgressGraph (context);
|
||
fe_SetCursor (context, False);
|
||
}
|
||
|
||
#ifndef SYNCHRONOUS_URL_DIALOG_WORKS
|
||
|
||
CONTEXT_DATA (context)->synchronous_url_dialog = (Widget) ~0;
|
||
CONTEXT_DATA (context)->synchronous_url_exit_status = 0;
|
||
|
||
#else /* SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
strcpy (title2, title);
|
||
strcat (title2, "_popup");
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, parent); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
shell = XmCreateDialogShell (parent, title2, av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_WORKING); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
dialog = XmCreateMessageBox (shell, (char *) title, av, ac);
|
||
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_cb, shell);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cb, shell);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_synchronous_url_cancel_cb,
|
||
context);
|
||
XtAddEventHandler(dialog, ExposureMask, FALSE,
|
||
(XtEventHandler)fe_dialog_expose_eh, context);
|
||
|
||
CONTEXT_DATA (context)->synchronous_url_dialog = dialog;
|
||
CONTEXT_DATA (context)->synchronous_url_exit_status = 0;
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
XSync (XtDisplay (dialog), False);
|
||
|
||
/*
|
||
* We wait here until we KNOW the dialog is popped up,
|
||
* otherwise Motif will misbehave.
|
||
*/
|
||
popped_up = FALSE;
|
||
while (!popped_up)
|
||
{
|
||
XEvent event;
|
||
|
||
XtAppNextEvent(XtWidgetToApplicationContext(dialog), &event);
|
||
if ((event.type == Expose)&&(event.xexpose.window == XtWindow(dialog)))
|
||
{
|
||
popped_up = TRUE;
|
||
}
|
||
XtDispatchEvent(&event);
|
||
}
|
||
#endif /* SYNCHRONOUS_URL_DIALOG_WORKS */
|
||
|
||
}
|
||
|
||
|
||
int
|
||
fe_await_synchronous_url (MWContext *context)
|
||
{
|
||
/* Loop dispatching X events until the dialog box goes down as a result
|
||
of the exit routine being called (which may be a result of the Cancel
|
||
button being hit. */
|
||
int status;
|
||
|
||
fe_ProtectContext(context);
|
||
while (CONTEXT_DATA (context)->synchronous_url_dialog)
|
||
fe_EventLoop ();
|
||
fe_UnProtectContext(context);
|
||
status = CONTEXT_DATA (context)->synchronous_url_exit_status;
|
||
if (fe_IsContextDestroyed(context)) {
|
||
free(CONTEXT_DATA(context));
|
||
free(context);
|
||
}
|
||
return (status);
|
||
}
|
||
|
||
|
||
int
|
||
fe_GetSynchronousURL (MWContext *context,
|
||
Widget widget_to_grab,
|
||
const char *title,
|
||
URL_Struct *url,
|
||
int output_format,
|
||
void *call_data)
|
||
{
|
||
int status;
|
||
url->fe_data = call_data;
|
||
fe_RaiseSynchronousURLDialog (context, widget_to_grab, title);
|
||
status = NET_GetURL (url, output_format, context, fe_synchronous_url_exit);
|
||
if (status < 0)
|
||
return status;
|
||
else
|
||
return fe_await_synchronous_url (context);
|
||
}
|
||
|
||
|
||
#if defined(MOZ_MAIL_NEWS) || defined(MOZ_MAIL_COMPOSE)
|
||
|
||
/* Sending mail
|
||
*/
|
||
|
||
void fe_mail_text_modify_cb (Widget, XtPointer, XtPointer);
|
||
|
||
Boolean
|
||
fe_CheckDeferredMail (void)
|
||
{
|
||
#ifdef MOZ_MAIL_NEWS
|
||
struct fe_MWContext_cons* rest;
|
||
Boolean haveQueuedMail = False;
|
||
int numMsgs = 0;
|
||
MSG_ViewIndex row = 0;
|
||
|
||
for (rest = fe_all_MWContexts; rest; rest = rest->next) {
|
||
MWContext* context = rest->context;
|
||
fe_MailNewsContextData* d = MAILNEWS_CONTEXT_DATA(context);
|
||
if (context->type == MWContextMail) {
|
||
MSG_CommandStatus (d->folderpane, MSG_DeliverQueuedMessages, NULL, 0,
|
||
&haveQueuedMail, NULL, NULL, NULL);
|
||
if (haveQueuedMail) {
|
||
MSG_FolderLine line;
|
||
/* ###tw This is just too vile for words. */
|
||
while (MSG_GetFolderLineByIndex(d->folderpane, row, 1, &line)) {
|
||
if (line.flags & MSG_FOLDER_FLAG_QUEUE) {
|
||
numMsgs = line.total;
|
||
break;
|
||
}
|
||
row++;
|
||
}
|
||
if (numMsgs) {
|
||
char buf [256];
|
||
void * sendNow = 0;
|
||
if (numMsgs == 1)
|
||
sendNow = fe_dialog (CONTEXT_WIDGET (fe_all_MWContexts->context),
|
||
"sendNow",
|
||
XP_GetString (XFE_OUTBOX_CONTAINS_MSG),
|
||
TRUE, 0, TRUE, FALSE, 0);
|
||
else {
|
||
PR_snprintf (buf, 256, XP_GetString (XFE_OUTBOX_CONTAINS_MSGS), numMsgs);
|
||
sendNow = fe_dialog (CONTEXT_WIDGET (fe_all_MWContexts->context),
|
||
"sendNow", buf, TRUE, 0, TRUE, FALSE, 0);
|
||
}
|
||
if (sendNow) {
|
||
MSG_Command (d->folderpane, MSG_DeliverQueuedMessages, NULL, 0);
|
||
return False;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endif /* MOZ_MAIL_NEWS */
|
||
/* return True means no mail - weird, but consistent
|
||
* with fe_CheckUnsentMail below. We can change them
|
||
* later.
|
||
*/
|
||
return True;
|
||
}
|
||
|
||
Boolean
|
||
fe_CheckUnsentMail (void)
|
||
{
|
||
struct fe_MWContext_cons* rest;
|
||
for (rest = fe_all_MWContexts; rest; rest = rest->next) {
|
||
MWContext* context = rest->context;
|
||
if (context->type == MWContextMessageComposition) {
|
||
return XFE_Confirm(fe_all_MWContexts->context,
|
||
fe_globalData.unsent_mail_message);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
#if 0
|
||
static char* fe_last_attach_type = NULL;
|
||
|
||
static void
|
||
fe_del_attachment(struct fe_mail_attach_data *mad, int pos)
|
||
{
|
||
if (pos > mad->nattachments) return;
|
||
else XP_ASSERT(pos <= mad->nattachments);
|
||
|
||
pos--;
|
||
if (mad->attachments[pos].url)
|
||
XP_FREE((char *)mad->attachments[pos].url);
|
||
pos++;
|
||
while (pos < mad->nattachments) {
|
||
mad->attachments[pos-1] = mad->attachments[pos];
|
||
pos++;
|
||
}
|
||
mad->nattachments--;
|
||
}
|
||
|
||
static void
|
||
fe_add_attachmentData(struct fe_mail_attach_data *mad,
|
||
const struct MSG_AttachmentData *data)
|
||
{
|
||
struct MSG_AttachmentData *m;
|
||
char *name = (char *)data->url;
|
||
XmString xmstr;
|
||
|
||
if (!name || !*name) return;
|
||
|
||
if (mad->nattachments >= XFE_MAX_ATTACHMENTS) return;
|
||
else XP_ASSERT(mad->nattachments < XFE_MAX_ATTACHMENTS);
|
||
|
||
xmstr = XmStringCreate(name, XmFONTLIST_DEFAULT_TAG);
|
||
XmListAddItem(mad->list, xmstr, 0);
|
||
|
||
m = &mad->attachments[mad->nattachments];
|
||
*m = *data;
|
||
m->url = XP_STRDUP(data->url);
|
||
|
||
mad->nattachments++;
|
||
if (mad->nattachments == 1)
|
||
XmListSelectPos(mad->list, 1, True);
|
||
|
||
XmListSelectItem(mad->list, xmstr, TRUE);
|
||
XmStringFree(xmstr);
|
||
}
|
||
|
||
|
||
static void
|
||
fe_add_attachment(struct fe_mail_attach_data *mad, char *name)
|
||
{
|
||
struct MSG_AttachmentData m = {0};
|
||
Boolean b;
|
||
XmString xmstr;
|
||
|
||
if (!name || !*name) return;
|
||
|
||
if(mad->nattachments >= XFE_MAX_ATTACHMENTS) return;
|
||
else XP_ASSERT(mad->nattachments < XFE_MAX_ATTACHMENTS);
|
||
|
||
xmstr = XmStringCreate(name, XmFONTLIST_DEFAULT_TAG);
|
||
XmListAddItem(mad->list, xmstr, 0);
|
||
|
||
XtVaGetValues (mad->text_p, XmNset, &b, 0);
|
||
if (b)
|
||
m.desired_type = TEXT_PLAIN;
|
||
else {
|
||
XtVaGetValues (mad->postscript_p, XmNset, &b, 0);
|
||
if (b)
|
||
m.desired_type = APPLICATION_POSTSCRIPT;
|
||
}
|
||
m.url = name;
|
||
|
||
mad->attachments[mad->nattachments] = m;
|
||
mad->nattachments++;
|
||
|
||
XmListSelectItem(mad->list, xmstr, TRUE);
|
||
XmStringFree(xmstr);
|
||
}
|
||
|
||
/***********************************
|
||
* Location popup related routines *
|
||
***********************************/
|
||
|
||
static void
|
||
fe_locationOk_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
char *url = fe_GetTextField(mad->location_text);
|
||
|
||
if (url && *url)
|
||
fe_add_attachment(mad, url);
|
||
else
|
||
if (url) XtFree(url);
|
||
XtUnmanageChild(mad->location_shell);
|
||
}
|
||
static void
|
||
fe_locationClear_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
fe_SetTextField (mad->location_text, "");
|
||
/* Focus on the text widget after this, since otherwise you have to
|
||
click again. */
|
||
XmProcessTraversal (mad->location_text, XmTRAVERSE_CURRENT);
|
||
}
|
||
|
||
static void
|
||
fe_locationCancel_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
XtUnmanageChild(mad->location_shell);
|
||
}
|
||
|
||
static void
|
||
fe_attach_make_location(struct fe_mail_attach_data *mad)
|
||
{
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
|
||
Widget shell;
|
||
Widget parent;
|
||
Widget form;
|
||
Widget label, location_label, location_text;
|
||
Widget ok_button, clear_button, cancel_button;
|
||
|
||
Widget kids [20];
|
||
int i;
|
||
|
||
if (mad->location_shell) return;
|
||
|
||
#ifdef dp_DEBUG
|
||
fprintf(stderr, "Making attach_location widgets : fe_attach_make_location().\n");
|
||
#endif
|
||
|
||
parent = CONTEXT_WIDGET(mad->context);
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
/* XtSetArg (av[ac], XmNallowShellResize, True); ac++; */
|
||
/* XtSetArg (av[ac], XmNtransientFor, parent); ac++; */
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmUNMAP); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
|
||
shell = XmCreateTemplateDialog (parent, "location_popup", av, ac);
|
||
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_OK_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_CANCEL_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_DEFAULT_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_HELP_BUTTON));
|
||
|
||
ac = 0;
|
||
ok_button = XmCreatePushButtonGadget (shell, "OK", av, ac);
|
||
clear_button = XmCreatePushButtonGadget (shell, "clear", av, ac);
|
||
cancel_button = XmCreatePushButtonGadget (shell, "cancel", av, ac);
|
||
|
||
ac = 0;
|
||
form = XmCreateForm(shell, "form", av, ac);
|
||
label = XmCreateLabelGadget( form, "label", av, ac);
|
||
location_label = XmCreateLabelGadget( form, "locationLabel", av, ac);
|
||
location_text = fe_CreateTextField( form, "locationText", av, ac);
|
||
|
||
if (fe_globalData.nonterminal_text_translations)
|
||
XtOverrideTranslations (location_text, fe_globalData.
|
||
nonterminal_text_translations);
|
||
|
||
XtVaSetValues (label,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (location_label,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, label,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (location_text,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, label,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, location_label,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
|
||
_XfeHeight(location_label) = _XfeHeight(location_text);
|
||
|
||
XtAddCallback(ok_button, XmNactivateCallback, fe_locationOk_cb, mad);
|
||
XtAddCallback(clear_button, XmNactivateCallback, fe_locationClear_cb, mad);
|
||
XtAddCallback(cancel_button, XmNactivateCallback, fe_locationCancel_cb, mad);
|
||
|
||
{
|
||
const char *str = MSG_GetAssociatedURL (mad->comppane);
|
||
fe_SetTextFieldAndCallBack (location_text, (char *) (str ? str : ""));
|
||
}
|
||
|
||
fe_HackDialogTranslations (form);
|
||
|
||
mad->location_shell = shell;
|
||
i = 0;
|
||
kids[i++] = mad->location_text = location_text;
|
||
kids[i++] = location_label;
|
||
kids[i++] = label;
|
||
XtManageChildren(kids, i);
|
||
i = 0;
|
||
kids[i++] = ok_button;
|
||
kids[i++] = clear_button;
|
||
kids[i++] = cancel_button;
|
||
XtManageChildren(kids, i);
|
||
|
||
XtManageChild(form);
|
||
XtManageChild(shell);
|
||
}
|
||
|
||
/*************************
|
||
* File Attachment popup *
|
||
*************************/
|
||
static void
|
||
fe_attachFile_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
XmFileSelectionBoxCallbackStruct *sbc =
|
||
(XmFileSelectionBoxCallbackStruct *) call_data;
|
||
char *file;
|
||
char *msg;
|
||
|
||
switch (sbc->reason) {
|
||
case XmCR_NO_MATCH:
|
||
XBell (XtDisplay (widget), 0);
|
||
break;
|
||
|
||
case XmCR_OK:
|
||
XmStringGetLtoR (sbc->value, XmFONTLIST_DEFAULT_TAG, &file);
|
||
if (!fe_isFileExist(file)) {
|
||
msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_DOESNT_EXIST ), file);
|
||
if (msg) {
|
||
fe_Alert_2(XtParent(mad->file_shell), msg);
|
||
XP_FREE(msg);
|
||
}
|
||
}
|
||
else if (!fe_isFileReadable(file)) {
|
||
msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_NOT_READABLE ) , file);
|
||
if (msg) {
|
||
fe_Alert_2(XtParent(mad->file_shell), msg);
|
||
XP_FREE(msg);
|
||
}
|
||
}
|
||
else if (fe_isDir(file)) {
|
||
msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_IS_A_DIRECTORY ), file);
|
||
if (msg) {
|
||
fe_Alert_2(XtParent(mad->file_shell), msg);
|
||
if (msg) XP_FREE(msg);
|
||
}
|
||
}
|
||
else {
|
||
fe_add_attachment(mad, file);
|
||
XtUnmanageChild(mad->file_shell);
|
||
}
|
||
break;
|
||
|
||
case XmCR_CANCEL:
|
||
XtUnmanageChild(mad->file_shell);
|
||
break;
|
||
default:
|
||
abort ();
|
||
}
|
||
}
|
||
|
||
static void
|
||
fe_attach_make_file(struct fe_mail_attach_data *mad)
|
||
{
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
Widget shell;
|
||
Widget parent;
|
||
Widget fileb;
|
||
Boolean dirp = False;
|
||
|
||
if (mad->file_shell) return;
|
||
|
||
#ifdef dp_DEBUG
|
||
fprintf(stderr, "Making attach_file widgets : fe_attach_make_file().\n");
|
||
#endif
|
||
|
||
parent = CONTEXT_WIDGET (mad->context);
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
/* XtSetArg (av[ac], XmNallowShellResize, True); ac++;*/
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmUNMAP); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
|
||
shell = XmCreateDialogShell (parent, "fileBrowser_popup", av, ac);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNfileTypeMask,
|
||
(dirp ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++;
|
||
fileb = fe_CreateFileSelectionBox (shell, "fileBrowser", av, ac);
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
XtAddCallback(fileb, XmNnoMatchCallback, fe_attachFile_cb, mad);
|
||
XtAddCallback(fileb, XmNokCallback, fe_attachFile_cb, mad);
|
||
XtAddCallback(fileb, XmNcancelCallback, fe_attachFile_cb, mad);
|
||
|
||
mad->file_shell = fileb;
|
||
|
||
fe_HackDialogTranslations (fileb);
|
||
|
||
fe_NukeBackingStore (fileb);
|
||
XtManageChild (fileb);
|
||
}
|
||
|
||
static void
|
||
fe_attach_doc_type_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
int *poslist, npos;
|
||
int attach_pos = -1;
|
||
|
||
if (XmListGetSelectedPos(mad->list, &poslist, &npos)) {
|
||
attach_pos = poslist[npos - 1] - 1;
|
||
XP_FREE(poslist);
|
||
}
|
||
|
||
/*
|
||
* my how intuitive, if the file is attach as source, desired type = NULL.
|
||
*/
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
if (widget == mad->text_p) {
|
||
XtVaSetValues (mad->source_p, XmNset, False, 0);
|
||
XtVaSetValues (mad->postscript_p, XmNset, False, 0);
|
||
if (attach_pos >= 0)
|
||
mad->attachments[attach_pos].desired_type = TEXT_PLAIN;
|
||
}
|
||
else if (widget == mad->source_p) {
|
||
XtVaSetValues (mad->text_p, XmNset, False, 0);
|
||
XtVaSetValues (mad->postscript_p, XmNset, False, 0);
|
||
if (attach_pos >= 0)
|
||
mad->attachments[attach_pos].desired_type = NULL;
|
||
}
|
||
else if (widget == mad->postscript_p) {
|
||
XtVaSetValues (mad->source_p, XmNset, False, 0);
|
||
XtVaSetValues (mad->text_p, XmNset, False, 0);
|
||
if (attach_pos >= 0)
|
||
mad->attachments[attach_pos].desired_type = APPLICATION_POSTSCRIPT;
|
||
}
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
static void
|
||
fe_attachDestroy_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
int i;
|
||
|
||
#ifdef dp_DEBUG
|
||
fprintf(stderr, "fe_attachDestroy_cb()\n");
|
||
fprintf(stderr, "Destroying fe_mail_attach_data...\n");
|
||
#endif
|
||
|
||
/* Free the list of attachments too */
|
||
for(i=0; i<mad->nattachments; i++) {
|
||
XP_FREE((char *)mad->attachments[i].url);
|
||
}
|
||
if (mad->location_shell)
|
||
XtDestroyWidget(mad->location_shell);
|
||
if (mad->file_shell)
|
||
XtDestroyWidget(XtParent(mad->file_shell));
|
||
CONTEXT_DATA(mad->context) ->mad = NULL;
|
||
free (mad);
|
||
}
|
||
|
||
static void
|
||
fe_attachCancel_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
|
||
/* We dont need to delete all the attachments that we have as they will
|
||
be deleted either the next time we show the attach window (or) when
|
||
the message composition context gets destroyed */
|
||
|
||
XtUnmanageChild(mad->shell);
|
||
if (mad->location_shell)
|
||
XtUnmanageChild(mad->location_shell);
|
||
if (mad->file_shell)
|
||
XtUnmanageChild(mad->file_shell);
|
||
}
|
||
|
||
static void
|
||
fe_attachOk_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
const char* ptr;
|
||
|
||
mad->attachments[mad->nattachments].url = NULL;
|
||
MSG_SetAttachmentList(mad->comppane, mad->attachments);
|
||
ptr = MSG_GetCompHeader(mad->comppane, MSG_ATTACHMENTS_HEADER_MASK);
|
||
fe_SetTextFieldAndCallBack(CONTEXT_DATA(mad->context)->mcAttachments,
|
||
ptr ? (char*) ptr : "");
|
||
|
||
/* We dont need to delete all the attachments that we have as they will
|
||
be deleted either the next time we show the attach window (or) when
|
||
the message composition context gets destroyed */
|
||
|
||
XtUnmanageChild(mad->shell);
|
||
if (mad->location_shell)
|
||
XtUnmanageChild(mad->location_shell);
|
||
if (mad->file_shell)
|
||
XtUnmanageChild(mad->file_shell);
|
||
}
|
||
|
||
static void
|
||
fe_attach_location_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
|
||
if (!mad->location_shell) fe_attach_make_location(mad);
|
||
|
||
XtManageChild(mad->location_shell);
|
||
XMapRaised(XtDisplay(mad->location_shell), XtWindow(mad->location_shell));
|
||
}
|
||
|
||
static void
|
||
fe_attach_file_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
|
||
if (!mad->file_shell) fe_attach_make_file(mad);
|
||
|
||
XtManageChild(mad->file_shell);
|
||
XMapRaised(XtDisplay(mad->file_shell), XtWindow(mad->file_shell));
|
||
}
|
||
|
||
static void
|
||
fe_attach_delete_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
int *poslist, npos;
|
||
int i, pos;
|
||
|
||
if (XmListGetSelectedPos(mad->list, &poslist, &npos)) {
|
||
for(i=0; i<npos; i++) {
|
||
XmListDeletePos(mad->list, poslist[i]);
|
||
fe_del_attachment(mad, poslist[i]);
|
||
}
|
||
/*
|
||
* After deleting an item from the list, select the
|
||
* previous item in the list (or the last if it was
|
||
* the first.)
|
||
*/
|
||
pos = poslist[npos - 1] - 1;
|
||
if (pos < 0)
|
||
pos = 0;
|
||
XmListSelectPos(mad->list, pos, TRUE);
|
||
XP_FREE(poslist);
|
||
}
|
||
|
||
/*
|
||
* If nothing left in the list selected, desensitize
|
||
* the delete button.
|
||
*/
|
||
if (!XmListGetSelectedPos(mad->list, &poslist, &npos)) {
|
||
XtVaSetValues(mad->delete, XmNsensitive, False, 0);
|
||
}
|
||
else XP_FREE(poslist);
|
||
}
|
||
|
||
static void
|
||
fe_attach_select_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
|
||
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
|
||
const char *s;
|
||
Widget which_w = 0;
|
||
|
||
if (cbs->item_position > mad->nattachments) return;
|
||
else XP_ASSERT(cbs->item_position <= mad->nattachments);
|
||
|
||
s = mad->attachments[cbs->item_position-1].desired_type;
|
||
|
||
if (!s || !*s)
|
||
which_w = mad->source_p;
|
||
else if (!XP_STRCMP(s, APPLICATION_POSTSCRIPT))
|
||
which_w = mad->postscript_p;
|
||
else if (!XP_STRCMP(s, TEXT_PLAIN))
|
||
which_w = mad->text_p;
|
||
|
||
if (which_w == 0) return;
|
||
else XP_ASSERT (which_w != 0);
|
||
fe_attach_doc_type_cb(which_w, mad, NULL);
|
||
|
||
XtVaSetValues(mad->delete, XmNsensitive, True, 0);
|
||
}
|
||
|
||
static void
|
||
fe_make_attach_dialog(MWContext* context)
|
||
{
|
||
fe_ContextData* data = CONTEXT_DATA(context);
|
||
Widget shell, form;
|
||
Widget list;
|
||
Widget messb;
|
||
Widget attach_location, attach_file, delete;
|
||
Widget label;
|
||
Widget text_p, source_p, postscript_p;
|
||
Widget ok_button, cancel_button;
|
||
Widget kids [50];
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
struct fe_mail_attach_data *mad = data->mad;
|
||
|
||
XP_ASSERT(context->type == MWContextMessageComposition);
|
||
|
||
if (mad && mad->shell)
|
||
return;
|
||
|
||
XtVaGetValues (CONTEXT_WIDGET(context), XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, CONTEXT_WIDGET(context)); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
shell = XmCreateTemplateDialog (CONTEXT_WIDGET(context), "attach", av, ac);
|
||
/* fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_SEPARATOR)); */
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_OK_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_CANCEL_BUTTON));
|
||
/* fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_APPLY_BUTTON));*/
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_DEFAULT_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_HELP_BUTTON));
|
||
|
||
ac = 0;
|
||
ok_button = XmCreatePushButtonGadget (shell, "OK", av, ac);
|
||
cancel_button = XmCreatePushButtonGadget (shell, "cancel", av, ac);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
|
||
form = XmCreateForm (shell, "form", av, ac);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_WORK_AREA); ac++;
|
||
XtSetArg (av[ac], XmNresizePolicy, XmRESIZE_GROW); ac++;
|
||
messb = XmCreateMessageBox(form, "messagebox", av, ac);
|
||
fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_OK_BUTTON));
|
||
fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_CANCEL_BUTTON));
|
||
fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_HELP_BUTTON));
|
||
ac = 0;
|
||
list = XmCreateList(messb, "list", av, ac);
|
||
attach_location = XmCreatePushButtonGadget(messb, "attachLocation", av, ac);
|
||
attach_file = XmCreatePushButtonGadget(messb, "attachFile", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNsensitive, False); ac++;
|
||
delete = XmCreatePushButtonGadget(messb, "delete", av, ac);
|
||
|
||
ac = 0;
|
||
label = XmCreateLabelGadget (form, "label", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNset, False); ac++;
|
||
source_p = XmCreateToggleButtonGadget (form, "sourceToggle", av, ac);
|
||
text_p = XmCreateToggleButtonGadget (form, "textToggle", av, ac);
|
||
postscript_p = XmCreateToggleButtonGadget (form, "postscriptToggle", av, ac);
|
||
|
||
/* Making the attachments in such a way that the list would grow is
|
||
the height of the dialog is increased */
|
||
XtVaSetValues (messb,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (label,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (source_p,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, label,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, label,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (text_p,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, label,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, source_p,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (postscript_p,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, label,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, text_p,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
|
||
#ifdef dp_DEBUG
|
||
fprintf(stderr, "Creating new fe_mail_attach_data...\n");
|
||
#endif
|
||
data->mad = mad = (struct fe_mail_attach_data *)
|
||
calloc (sizeof (struct fe_mail_attach_data), 1);
|
||
mad->nattachments = 0;
|
||
|
||
mad->context = context;
|
||
mad->shell = shell;
|
||
mad->list = list;
|
||
mad->comppane = data->comppane;
|
||
|
||
XtManageChild(list);
|
||
ac = 0;
|
||
kids [ac++] = attach_location;
|
||
kids [ac++] = mad->attach_file = attach_file;
|
||
kids [ac++] = mad->delete = delete;
|
||
XtManageChildren (kids, ac);
|
||
ac = 0;
|
||
kids [ac++] = messb;
|
||
kids [ac++] = label;
|
||
kids [ac++] = mad->source_p = source_p;
|
||
kids [ac++] = mad->text_p = text_p;
|
||
kids [ac++] = mad->postscript_p = postscript_p;
|
||
|
||
XtManageChildren (kids, ac);
|
||
|
||
XtManageChild (form);
|
||
XtManageChild (ok_button);
|
||
XtManageChild (cancel_button);
|
||
|
||
XtAddCallback (ok_button, XmNactivateCallback, fe_attachOk_cb, mad);
|
||
XtAddCallback (cancel_button, XmNactivateCallback, fe_attachCancel_cb, mad);
|
||
XtAddCallback (shell, XtNdestroyCallback, fe_attachDestroy_cb, mad);
|
||
|
||
XtAddCallback (attach_location, XmNactivateCallback,
|
||
fe_attach_location_cb, mad);
|
||
XtAddCallback (attach_file, XmNactivateCallback, fe_attach_file_cb, mad);
|
||
XtAddCallback (delete, XmNactivateCallback, fe_attach_delete_cb, mad);
|
||
XtAddCallback (list, XmNbrowseSelectionCallback, fe_attach_select_cb, mad);
|
||
|
||
XtAddCallback (text_p, XmNvalueChangedCallback,
|
||
fe_attach_doc_type_cb, mad);
|
||
XtAddCallback (source_p, XmNvalueChangedCallback,
|
||
fe_attach_doc_type_cb, mad);
|
||
XtAddCallback (postscript_p, XmNvalueChangedCallback,
|
||
fe_attach_doc_type_cb, mad);
|
||
|
||
/* Remember the last attachment typed used. */
|
||
XtVaSetValues((fe_last_attach_type == NULL ? source_p :
|
||
strcmp(fe_last_attach_type, TEXT_PLAIN) == 0 ? text_p :
|
||
strcmp(fe_last_attach_type,
|
||
APPLICATION_POSTSCRIPT) == 0 ? postscript_p :
|
||
source_p),
|
||
XmNset, True, 0);
|
||
|
||
#if 0
|
||
/* Decide whether to attach a file or a URL based on what the URL is.
|
||
If there's something in the Attachement: field already, use that.
|
||
Otherwise, use the document associated with this mail window.
|
||
*/
|
||
{
|
||
char *string = 0;
|
||
const char *url = 0;
|
||
const char *file;
|
||
|
||
string = fe_GetTextField (data->mcAttachments);
|
||
|
||
url = fe_StringTrim(string);
|
||
if (url && !*url) {
|
||
url = 0;
|
||
}
|
||
|
||
if (!url) {
|
||
url = MSG_GetAssociatedURL(context);
|
||
}
|
||
|
||
if (! url)
|
||
file = 0;
|
||
else if (url[0] == '/')
|
||
file = url;
|
||
else if (!strncasecomp (url, "file://localhost/", 17))
|
||
file = url + 16;
|
||
else if (!strncasecomp (url, "file://", 7))
|
||
file = 0;
|
||
else if (!strncasecomp (url, "file:/", 6))
|
||
file = url + 5;
|
||
else
|
||
file = 0;
|
||
|
||
if (file)
|
||
fe_SetTextField (file_text, file);
|
||
|
||
XtVaSetValues (doc_p, XmNset, True, 0);
|
||
fe_SetTextField (doc_text, url);
|
||
if (string) free (string);
|
||
}
|
||
#endif
|
||
|
||
fe_NukeBackingStore (shell);
|
||
XtManageChild (shell);
|
||
}
|
||
|
||
|
||
/* Prompts for attachment info.
|
||
*/
|
||
void
|
||
fe_mailto_attach_dialog(MWContext* context)
|
||
{
|
||
struct fe_mail_attach_data *mad = CONTEXT_DATA(context)->mad;
|
||
const struct MSG_AttachmentData *list;
|
||
int i;
|
||
|
||
XP_ASSERT(context->type == MWContextMessageComposition);
|
||
|
||
if (!mad || !mad->shell) {
|
||
fe_make_attach_dialog(context);
|
||
mad = CONTEXT_DATA(context)->mad;
|
||
}
|
||
|
||
/* Free the existing list of attachments */
|
||
XmListDeleteAllItems(mad->list);
|
||
for(i=0; i<mad->nattachments; i++) {
|
||
XP_FREE((char *)mad->attachments[i].url);
|
||
}
|
||
mad->nattachments = 0;
|
||
|
||
/* Refresh the list of attachments */
|
||
list = MSG_GetAttachmentList(mad->comppane);
|
||
while (list && list->url != NULL) {
|
||
fe_add_attachmentData(mad, list);
|
||
list++;
|
||
}
|
||
|
||
XtManageChild(mad->shell);
|
||
XMapRaised(XtDisplay(mad->shell), XtWindow(mad->shell));
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
void
|
||
fe_attach_dropfunc(Widget dropw, void* closure, fe_dnd_Event type,
|
||
fe_dnd_Source* source, XEvent* event)
|
||
{
|
||
MWContext *compose_context;
|
||
MWContext *src_context;
|
||
const struct MSG_AttachmentData *old_list, *a;
|
||
struct MSG_AttachmentData *new_list;
|
||
Boolean sensitive_p = False;
|
||
char **urls, **ss;
|
||
const char* s;
|
||
int old_count = 0;
|
||
int new_count = 0;
|
||
int i;
|
||
|
||
if (type != FE_DND_DROP)
|
||
return;
|
||
|
||
compose_context = (MWContext *) closure;
|
||
if (!compose_context) return;
|
||
XP_ASSERT(compose_context->type == MWContextMessageComposition);
|
||
if (compose_context->type != MWContextMessageComposition)
|
||
return;
|
||
|
||
XtVaGetValues(CONTEXT_DATA(compose_context)->mcAttachments,
|
||
XmNsensitive, &sensitive_p, 0);
|
||
if (!sensitive_p)
|
||
{
|
||
/* If the Attachments field is not sensitive, then that means that
|
||
an attachment (or delivery?) is in progress, and bad things would
|
||
happen were we to try and attach things right now. So just beep.
|
||
*/
|
||
XBell (XtDisplay (CONTEXT_WIDGET(compose_context)), 0);
|
||
return;
|
||
}
|
||
|
||
src_context = fe_WidgetToMWContext((Widget) source->closure);
|
||
if (!src_context) return;
|
||
switch (src_context->type)
|
||
{
|
||
case MWContextMail:
|
||
case MWContextNews:
|
||
/* ###tw Should get a list of all the selected URLs from the mail/news
|
||
window...*/
|
||
urls = 0;
|
||
break;
|
||
case MWContextBookmarks:
|
||
/* #### Get a list of all the selected URLs out of the bookmarks
|
||
window... */
|
||
urls = 0;
|
||
break;
|
||
default:
|
||
XP_ASSERT(0);
|
||
urls = 0;
|
||
break;
|
||
}
|
||
if (!urls)
|
||
{
|
||
XBell (XtDisplay (CONTEXT_WIDGET(compose_context)), 0);
|
||
return;
|
||
}
|
||
|
||
new_count = 0;
|
||
for (ss = urls; *ss; ss++)
|
||
new_count++;
|
||
XP_ASSERT(new_count > 0);
|
||
if (new_count <= 0) return; /* #### leaks `urls'; but it already asserted. */
|
||
|
||
old_list = MSG_GetAttachmentList(CONTEXT_DATA(compose_context)->comppane);
|
||
old_count = 0;
|
||
if (old_list)
|
||
for (a = old_list; a->url; a++)
|
||
old_count++;
|
||
|
||
new_list = (struct MSG_AttachmentData *)
|
||
XP_ALLOC(sizeof(struct MSG_AttachmentData) * (old_count + new_count + 1));
|
||
|
||
for (i = 0; i < old_count; i++)
|
||
{
|
||
XP_MEMSET(&new_list[i], 0, sizeof(new_list[i]));
|
||
if (old_list[i].url)
|
||
new_list[i].url = XP_STRDUP(old_list[i].url);
|
||
if (old_list[i].desired_type)
|
||
new_list[i].desired_type = XP_STRDUP(old_list[i].desired_type);
|
||
if (old_list[i].real_type)
|
||
new_list[i].real_type = XP_STRDUP(old_list[i].real_type);
|
||
if (old_list[i].real_encoding)
|
||
new_list[i].real_encoding = XP_STRDUP(old_list[i].real_encoding);
|
||
if (old_list[i].real_name)
|
||
new_list[i].real_name = XP_STRDUP(old_list[i].real_name);
|
||
if (old_list[i].description)
|
||
new_list[i].description = XP_STRDUP(old_list[i].description);
|
||
if (old_list[i].x_mac_type)
|
||
new_list[i].x_mac_type = XP_STRDUP(old_list[i].x_mac_type);
|
||
if (old_list[i].x_mac_creator)
|
||
new_list[i].x_mac_creator = XP_STRDUP(old_list[i].x_mac_creator);
|
||
}
|
||
|
||
if (new_count > 0)
|
||
XP_MEMSET(new_list + old_count, 0,
|
||
sizeof(struct MSG_AttachmentData) * (new_count + 1));
|
||
|
||
i = old_count;
|
||
for (ss = urls; *ss; ss++)
|
||
new_list[i++].url = *ss;
|
||
|
||
MSG_SetAttachmentList(CONTEXT_DATA(compose_context)->comppane, new_list);
|
||
|
||
for (i = 0; i < old_count; i++)
|
||
{
|
||
if (new_list[i].url) XP_FREE((char*)new_list[i].url);
|
||
if (new_list[i].desired_type) XP_FREE((char*)new_list[i].desired_type);
|
||
if (new_list[i].real_type) XP_FREE((char*)new_list[i].real_type);
|
||
if (new_list[i].real_encoding) XP_FREE((char*)new_list[i].real_encoding);
|
||
if (new_list[i].real_name) XP_FREE((char*)new_list[i].real_name);
|
||
if (new_list[i].description) XP_FREE((char*)new_list[i].description);
|
||
if (new_list[i].x_mac_type) XP_FREE((char*)new_list[i].x_mac_type);
|
||
if (new_list[i].x_mac_creator) XP_FREE((char*)new_list[i].x_mac_creator);
|
||
}
|
||
XP_FREE (new_list);
|
||
for (ss = urls; *ss; ss++)
|
||
XP_FREE(*ss);
|
||
XP_FREE(urls);
|
||
|
||
/* Now they're attached; update the display. */
|
||
s = MSG_GetCompHeader(CONTEXT_DATA(compose_context)->comppane,
|
||
MSG_ATTACHMENTS_HEADER_MASK);
|
||
fe_SetTextFieldAndCallBack(CONTEXT_DATA(compose_context)->mcAttachments,
|
||
s ? (char*) s : "");
|
||
}
|
||
|
||
#endif /* 0 */
|
||
|
||
int
|
||
FE_GetMessageBody (MSG_Pane* comppane,
|
||
char **body,
|
||
uint32 *body_size,
|
||
MSG_FontCode **font_changes)
|
||
{
|
||
MWContext* context = MSG_GetContext(comppane);
|
||
if (context->type != MWContextMessageComposition) return -1;
|
||
fe_getMessageBody(context, body, body_size, font_changes);
|
||
return 0;
|
||
}
|
||
|
||
void
|
||
FE_DoneWithMessageBody(MSG_Pane* comppane, char* body, uint32 body_size)
|
||
{
|
||
MWContext* context = MSG_GetContext(comppane);
|
||
fe_doneWithMessageBody(context, body, body_size);
|
||
}
|
||
|
||
|
||
void
|
||
fe_mail_text_modify_cb (Widget text, XtPointer client_data,
|
||
XtPointer call_data)
|
||
{
|
||
MWContext* context = (MWContext*) client_data;
|
||
CONTEXT_DATA(context)->mcCitedAndUnedited = False;
|
||
CONTEXT_DATA(context)->mcEdited = True;
|
||
/* MSG_MessageBodyEdited(CONTEXT_DATA(context)->comppane); */
|
||
}
|
||
|
||
#endif /* MOZ_MAIL_NEWS || MOZ_MAIL_COMPOSE */
|
||
|
||
#define cite_abort 0
|
||
#define cite_protect_me_from_myself 1
|
||
#define cite_let_me_be_a_loser 2
|
||
|
||
#if 0
|
||
static int
|
||
FE_BogusQuotationQuery (MWContext *context, Boolean double_p)
|
||
{
|
||
struct fe_confirm_data data;
|
||
Widget dialog;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
Widget parent = CONTEXT_WIDGET (context);
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, parent); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
dialog = XmCreatePromptDialog (parent, (double_p ?
|
||
"citationQuery"
|
||
: "doubleCitationQuery")
|
||
, av, ac);
|
||
|
||
/* fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_SEPARATOR));*/
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_TEXT));
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL));
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_APPLY_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
XtManageChild (dialog);
|
||
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_ok_cb, &data);
|
||
XtAddCallback (dialog, XmNapplyCallback, fe_destroy_apply_cb, &data);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
data.context = context;
|
||
data.widget = dialog;
|
||
data.answer = Answer_Invalid;
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
return (data.answer == 0 ? cite_abort :
|
||
data.answer == 1 ? cite_protect_me_from_myself :
|
||
data.answer == 2 ? cite_let_me_be_a_loser : 99);
|
||
}
|
||
#endif
|
||
|
||
|
||
/* Print setup
|
||
*/
|
||
|
||
struct fe_print_data
|
||
{
|
||
MWContext *context;
|
||
History_entry *hist;
|
||
Widget shell;
|
||
Widget printer, file, command_text, file_text, browse;
|
||
Widget first, last;
|
||
Widget portrait, landscape;
|
||
Widget grey, color;
|
||
Widget letter, legal, exec, a4;
|
||
};
|
||
|
||
static void
|
||
fe_print_to_toggle_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
if (!cb->set)
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
else if (widget == fpd->printer)
|
||
{
|
||
XtVaSetValues (fpd->file, XmNset, False, 0);
|
||
XtVaSetValues (fpd->browse, XmNsensitive, False, 0);
|
||
XtVaSetValues (fpd->file_text, XmNsensitive, False, 0);
|
||
XtVaSetValues (fpd->command_text, XmNsensitive, True, 0);
|
||
XmProcessTraversal (fpd->command_text, XmTRAVERSE_CURRENT);
|
||
}
|
||
else if (widget == fpd->file)
|
||
{
|
||
XtVaSetValues (fpd->printer, XmNset, False, 0);
|
||
XtVaSetValues (fpd->browse, XmNsensitive, True, 0);
|
||
XtVaSetValues (fpd->file_text, XmNsensitive, True, 0);
|
||
XtVaSetValues (fpd->command_text, XmNsensitive, False, 0);
|
||
XmProcessTraversal (fpd->file_text, XmTRAVERSE_CURRENT);
|
||
}
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
static void
|
||
fe_print_order_toggle_cb (Widget widget, XtPointer closure,XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
if (!cb->set)
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
else if (widget == fpd->first)
|
||
XtVaSetValues (fpd->last, XmNset, False, 0);
|
||
else if (widget == fpd->last)
|
||
XtVaSetValues (fpd->first, XmNset, False, 0);
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
static void
|
||
fe_print_orientation_toggle_cb (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
if (!cb->set)
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
else if (widget == fpd->portrait)
|
||
XtVaSetValues (fpd->landscape, XmNset, False, 0);
|
||
else if (widget == fpd->landscape)
|
||
XtVaSetValues (fpd->portrait, XmNset, False, 0);
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
static void
|
||
fe_print_color_toggle_cb (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
if (!cb->set)
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
else if (widget == fpd->grey)
|
||
XtVaSetValues (fpd->color, XmNset, False, 0);
|
||
else if (widget == fpd->color)
|
||
XtVaSetValues (fpd->grey, XmNset, False, 0);
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
static void
|
||
fe_print_paper_toggle_cb (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
if (!cb->set)
|
||
XtVaSetValues (widget, XmNset, True, 0);
|
||
else if (widget == fpd->letter)
|
||
{
|
||
XtVaSetValues (fpd->legal, XmNset, False, 0);
|
||
XtVaSetValues (fpd->exec, XmNset, False, 0);
|
||
XtVaSetValues (fpd->a4, XmNset, False, 0);
|
||
}
|
||
else if (widget == fpd->legal)
|
||
{
|
||
XtVaSetValues (fpd->letter, XmNset, False, 0);
|
||
XtVaSetValues (fpd->exec, XmNset, False, 0);
|
||
XtVaSetValues (fpd->a4, XmNset, False, 0);
|
||
}
|
||
else if (widget == fpd->exec)
|
||
{
|
||
XtVaSetValues (fpd->letter, XmNset, False, 0);
|
||
XtVaSetValues (fpd->legal, XmNset, False, 0);
|
||
XtVaSetValues (fpd->a4, XmNset, False, 0);
|
||
}
|
||
else if (widget == fpd->a4)
|
||
{
|
||
XtVaSetValues (fpd->letter, XmNset, False, 0);
|
||
XtVaSetValues (fpd->legal, XmNset, False, 0);
|
||
XtVaSetValues (fpd->exec, XmNset, False, 0);
|
||
}
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
void
|
||
fe_browse_file_of_text (MWContext *context, Widget text_field, Boolean dirp)
|
||
{
|
||
char *text = 0;
|
||
XmString xmpat, xmfile;
|
||
char buf [1024];
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
Widget shell;
|
||
Widget parent;
|
||
Widget fileb;
|
||
struct fe_confirm_data data;
|
||
data.context = context;
|
||
|
||
/* Find the top level window of which this text field is a descendant,
|
||
and make the file requester be a transient for that. */
|
||
parent = text_field;
|
||
while (parent && !XtIsShell (parent))
|
||
parent = XtParent (parent);
|
||
assert (parent);
|
||
if (! parent)
|
||
parent = CONTEXT_WIDGET (context);
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
text = fe_GetTextField(text_field);
|
||
text = fe_StringTrim (text);
|
||
|
||
|
||
if ( text && *text )
|
||
text = XP_STRTOK(text, " ");
|
||
|
||
if (!text || !*text)
|
||
{
|
||
xmpat = 0;
|
||
xmfile = 0;
|
||
}
|
||
else if (dirp)
|
||
{
|
||
if (text [strlen (text) - 1] == '/')
|
||
text [strlen (text) - 1] = 0;
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
xmpat = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
xmfile = XmStringCreateLtoR (text, XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
else
|
||
{
|
||
char *f;
|
||
if (text [strlen (text) - 1] == '/')
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
else
|
||
PR_snprintf (buf, sizeof (buf), "%.900s", text);
|
||
xmfile = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
if (text[0] == '/') /* only do this for absolute path */
|
||
f = strrchr (text, '/');
|
||
else
|
||
f = NULL;
|
||
if (f && f != text)
|
||
*f = 0;
|
||
if (f) {
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
xmpat = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
else {
|
||
/* do not change dirmask and pattern if input is a file;
|
||
* otherwise, the text widget in the file selection box
|
||
* will insert the file name at the wrong position.
|
||
* Windows version has similar behavior if a relative file
|
||
* is entered.
|
||
*/
|
||
buf[0] = '\0'; /* input was just a file. no '/' in it. */
|
||
xmpat = 0;
|
||
}
|
||
}
|
||
if (text) free (text);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
/* XtSetArg (av[ac], XmNallowShellResize, True); ac++;*/
|
||
shell = XmCreateDialogShell (parent, "fileBrowser_popup", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNfileTypeMask,
|
||
(dirp ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++;
|
||
fileb = fe_CreateFileSelectionBox (shell, "fileBrowser", av, ac);
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
if (xmpat)
|
||
{
|
||
XtVaSetValues (fileb,
|
||
XmNdirMask, xmpat,
|
||
XmNpattern, xmpat, 0);
|
||
#if 0
|
||
/*
|
||
* The XtVaSetValues on dirMask/pattern will cause this anyway.
|
||
*/
|
||
XmFileSelectionDoSearch (fileb, xmpat);
|
||
#endif
|
||
XtVaSetValues (fileb, XmNdirSpec, xmfile, 0);
|
||
XmStringFree (xmpat);
|
||
XmStringFree (xmfile);
|
||
}
|
||
|
||
XtAddCallback (fileb, XmNnoMatchCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNokCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNcancelCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
data.answer = Answer_Invalid;
|
||
data.return_value = 0;
|
||
|
||
fe_HackDialogTranslations (fileb);
|
||
|
||
fe_NukeBackingStore (fileb);
|
||
XtManageChild (fileb);
|
||
/* #### check for destruction here */
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_OK)
|
||
if (data.return_value)
|
||
{
|
||
fe_SetTextField(text_field, data.return_value);
|
||
free (data.return_value);
|
||
}
|
||
if (data.answer != Answer_Destroy)
|
||
XtDestroyWidget(shell);
|
||
}
|
||
|
||
void
|
||
fe_browse_file_of_text_in_url (MWContext *context, Widget text_field, Boolean dirp)
|
||
{
|
||
char *orig_text = 0;
|
||
char *text = 0;
|
||
XmString xmpat, xmfile;
|
||
char buf [1024];
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
Widget shell;
|
||
Widget parent;
|
||
Widget fileb;
|
||
struct fe_confirm_data data;
|
||
data.context = context;
|
||
|
||
/* Find the top level window of which this text field is a descendant,
|
||
and make the file requester be a transient for that. */
|
||
|
||
parent = text_field;
|
||
while (parent && !XtIsShell (parent))
|
||
parent = XtParent (parent);
|
||
assert (parent);
|
||
if (! parent)
|
||
parent = CONTEXT_WIDGET (context);
|
||
|
||
XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
text = fe_GetTextField(text_field);
|
||
orig_text = text;
|
||
text = fe_StringTrim (text);
|
||
|
||
if (!strncasecomp (text, "http://", 7)) {
|
||
/* ignore url using http */
|
||
free(orig_text);
|
||
orig_text = 0;
|
||
text = 0;
|
||
}
|
||
|
||
if (text) {
|
||
if (!strncasecomp (text, "file://", 7)) {
|
||
/* get to the absolute file path */
|
||
text += 7;
|
||
}
|
||
}
|
||
|
||
if ( text && *text )
|
||
text = XP_STRTOK(text, " ");
|
||
|
||
if (!text || !*text){
|
||
xmpat = 0;
|
||
xmfile = 0;
|
||
}
|
||
else if (dirp){
|
||
if (text [strlen (text) - 1] == '/')
|
||
text [strlen (text) - 1] = 0;
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
xmpat = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
xmfile = XmStringCreateLtoR (text, XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
else {
|
||
char *f;
|
||
if (text [strlen (text) - 1] == '/')
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
else
|
||
PR_snprintf (buf, sizeof (buf), "%.900s", text);
|
||
xmfile = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
if (text[0] == '/') /* only do this for absolute path */
|
||
f = strrchr (text, '/');
|
||
else
|
||
f = NULL;
|
||
if (f && f != text)
|
||
*f = 0;
|
||
if (f) {
|
||
PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
|
||
xmpat = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
|
||
}
|
||
else {
|
||
/* Do not change dirmask and pattern if input is a file;
|
||
* otherwise, the text widget in the file selection box
|
||
* will insert the file name at the wrong position.
|
||
* Windows version has similar behavior if a relative file
|
||
* is entered.
|
||
*/
|
||
buf[0] = '\0'; /* input was just a file. no '/' in it. */
|
||
xmpat = 0;
|
||
}
|
||
}
|
||
if (orig_text) free (orig_text);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
/* XtSetArg (av[ac], XmNallowShellResize, True); ac++;*/
|
||
shell = XmCreateDialogShell (parent, "fileBrowser_popup", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNfileTypeMask, (dirp ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++;
|
||
fileb = fe_CreateFileSelectionBox (shell, "fileBrowser", av, ac);
|
||
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
if (xmpat) {
|
||
XtVaSetValues (fileb,
|
||
XmNdirMask, xmpat,
|
||
XmNpattern, xmpat, 0);
|
||
#if 0
|
||
/*
|
||
* The XtVaSetValues on dirMask/pattern will cause this anyway.
|
||
*/
|
||
XmFileSelectionDoSearch (fileb, xmpat);
|
||
#endif
|
||
XtVaSetValues (fileb, XmNdirSpec, xmfile, 0);
|
||
XmStringFree (xmpat);
|
||
XmStringFree (xmfile);
|
||
}
|
||
|
||
XtAddCallback (fileb, XmNnoMatchCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNokCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNcancelCallback, fe_file_cb, &data);
|
||
XtAddCallback (fileb, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
data.answer = Answer_Invalid;
|
||
data.return_value = 0;
|
||
|
||
fe_HackDialogTranslations (fileb);
|
||
|
||
fe_NukeBackingStore (fileb);
|
||
XtManageChild (fileb);
|
||
/* #### check for destruction here */
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_OK)
|
||
if (data.return_value) {
|
||
/* prepend the answer with file url */
|
||
char path[1025];
|
||
sprintf(path, "file://%s", data.return_value);
|
||
fe_SetTextField (text_field, path);
|
||
free (data.return_value);
|
||
}
|
||
if (data.answer != Answer_Destroy)
|
||
XtDestroyWidget(shell);
|
||
}
|
||
|
||
|
||
static void
|
||
fe_print_browse_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
fe_browse_file_of_text (fpd->context, fpd->file_text, False);
|
||
}
|
||
|
||
|
||
#define XFE_DEFAULT_PRINT_FILENAME "netscape.ps"
|
||
static char *last_print_file_name = 0;
|
||
static Boolean last_to_file_p = False;
|
||
|
||
static void
|
||
ps_pipe_close (PrintSetup *p)
|
||
{
|
||
fe_synchronous_url_exit (p->url, 0, (MWContext *) p->carg);
|
||
pclose (p->out);
|
||
}
|
||
|
||
static void
|
||
ps_file_close (PrintSetup *p)
|
||
{
|
||
fe_synchronous_url_exit (p->url, 0, (MWContext *) p->carg);
|
||
fclose (p->out);
|
||
}
|
||
|
||
void
|
||
XFE_InitializePrintSetup (PrintSetup *p)
|
||
{
|
||
int i;
|
||
|
||
XL_InitializePrintSetup (p);
|
||
p->reverse = fe_globalPrefs.print_reversed;
|
||
p->color = fe_globalPrefs.print_color;
|
||
p->landscape = fe_globalPrefs.print_landscape;
|
||
/* #### p->n_up = fe_globalPrefs.print_n_up;*/
|
||
|
||
/* @@@ need to fix this -- erik */
|
||
p->bigger = 0; /* -1 = small, 0 = medium, 1 = large, 2 = huge */
|
||
|
||
if (fe_globalPrefs.print_paper_size == 0)
|
||
{
|
||
p->width = 8.5 * 72;
|
||
p->height = 11 * 72;
|
||
}
|
||
else if (fe_globalPrefs.print_paper_size == 1)
|
||
{
|
||
p->width = 8.5 * 72;
|
||
p->height = 14 * 72;
|
||
}
|
||
else if (fe_globalPrefs.print_paper_size == 2)
|
||
{
|
||
p->width = 7.5 * 72;
|
||
p->height = 10 * 72;
|
||
}
|
||
else if (fe_globalPrefs.print_paper_size == 3)
|
||
{
|
||
p->width = 210 * 0.039 * 72;
|
||
p->height = 297 * 0.039 * 72;
|
||
}
|
||
p->paper_size = fe_globalPrefs.print_paper_size;
|
||
|
||
/* initialize things related to other font to be NULL */
|
||
for (i=0; i<N_FONTS; i++) {
|
||
p->otherFontName[i] = NULL;
|
||
p->otherFontInfo[i] = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
void
|
||
fe_Print(MWContext *context, URL_Struct *url, Boolean last_to_file_p,
|
||
char *last_print_file_name)
|
||
{
|
||
SHIST_SavedData saved_data;
|
||
PrintSetup p;
|
||
char *type = NULL;
|
||
char name[1024];
|
||
char clas[1024];
|
||
char mimecharset[48];
|
||
XrmValue value;
|
||
XrmDatabase db = XtDatabase(XtDisplay(CONTEXT_WIDGET(context)));
|
||
INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context);
|
||
|
||
FILE *afmfile; /* AFM (font metrics) file descriptor */
|
||
char *measures[2] = { "variable", "fixed" };
|
||
char *styles[4] = { "normal", "bold", "italic", "boldItalic" };
|
||
int measure, style, i; /* Loop variable */
|
||
|
||
XFE_InitializePrintSetup (&p);
|
||
|
||
if (last_to_file_p)
|
||
{
|
||
if (! *last_print_file_name)
|
||
{
|
||
FE_Alert (context, fe_globalData.no_file_message);
|
||
return;
|
||
}
|
||
|
||
/* If the file exists, confirm overwriting it. */
|
||
{
|
||
XP_StatStruct st;
|
||
char buf [2048];
|
||
if (!stat (last_print_file_name, &st))
|
||
{
|
||
PR_snprintf (buf, sizeof (buf),
|
||
fe_globalData.overwrite_file_message,
|
||
last_print_file_name);
|
||
if (!FE_Confirm (context, buf))
|
||
return;
|
||
}
|
||
}
|
||
|
||
p.out = fopen (last_print_file_name, "w");
|
||
if (! p.out)
|
||
{
|
||
char buf [2048];
|
||
PR_snprintf (buf, sizeof (buf),
|
||
XP_GetString(XFE_ERROR_OPENING_FILE),
|
||
last_print_file_name);
|
||
fe_perror (context, buf);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
fe_globalPrefs.print_command =
|
||
fe_StringTrim (fe_globalPrefs.print_command);
|
||
if (! *fe_globalPrefs.print_command)
|
||
{
|
||
FE_Alert (context, fe_globalData.no_print_command_message);
|
||
return;
|
||
}
|
||
p.out = popen (fe_globalPrefs.print_command, "w");
|
||
if (! p.out)
|
||
{
|
||
char buf [2048];
|
||
PR_snprintf (buf, sizeof (buf),
|
||
XP_GetString(XFE_ERROR_OPENING_PIPE),
|
||
fe_globalPrefs.print_command);
|
||
fe_perror (context, buf);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* Make sure layout saves the current state. */
|
||
LO_SaveFormData(context);
|
||
|
||
/* Hold on to the saved data. */
|
||
XP_MEMCPY(&saved_data, &url->savedData, sizeof(SHIST_SavedData));
|
||
|
||
/* make damn sure the form_data slot is zero'd or else all
|
||
* hell will break loose
|
||
*/
|
||
XP_MEMSET (&url->savedData, 0, sizeof (SHIST_SavedData));
|
||
NPL_PreparePrint(context, &url->savedData);
|
||
|
||
INTL_CharSetIDToName(INTL_GetCSIWinCSID(c), mimecharset);
|
||
|
||
PR_snprintf(clas, sizeof (clas),
|
||
"%s.DocumentFonts.Charset.PSCode", fe_progclass);
|
||
PR_snprintf(name, sizeof (name),
|
||
"%s.documentFonts.%s.pscode", fe_progclass, mimecharset);
|
||
if (XrmGetResource(db, name, clas, &type, &value))
|
||
p.otherFontCharSetID = INTL_CharSetNameToID(value.addr);
|
||
|
||
/* read in font spec from the resource
|
||
NOTE: Currently eight fonts styles are used
|
||
*/
|
||
for (measure = 0; measure < 2; measure++)
|
||
for (style = 0; style < 4; style++) {
|
||
int index = measure * 4 + style;
|
||
|
||
PR_snprintf(clas, sizeof (clas),
|
||
"%s.DocumentFonts.Charset.Measure.Style.PSName", fe_progclass);
|
||
PR_snprintf(name, sizeof (name),
|
||
"%s.documentFonts.%s.%s.%s.psname", fe_progclass, mimecharset,
|
||
measures[measure], styles[style]);
|
||
|
||
if (XrmGetResource(db, name, clas, &type, &value)
|
||
&& XP_STRLEN(value.addr) > 0 ) {
|
||
/* read in font name for this style */
|
||
p.otherFontName[index] = (char*)malloc(strlen(value.addr)+1);
|
||
strncpy(p.otherFontName[index], value.addr, XP_STRLEN(value.addr)+1);
|
||
|
||
/* Read and parse AFM file if psafmfile is specified */
|
||
PR_snprintf(clas, sizeof (clas),
|
||
"%s.DocumentFonts.Charset.Measure.Style.PSAFMFile", fe_progclass);
|
||
PR_snprintf(name, sizeof (name),
|
||
"%s.documentFonts.%s.%s.%s.psafmfile", fe_progclass,
|
||
mimecharset, measures[measure], styles[style]);
|
||
|
||
if (XrmGetResource(db, name, clas, &type, &value)
|
||
&& XP_STRLEN(value.addr) > 0) {
|
||
/* open the file according to the name */
|
||
afmfile = fopen(value.addr, "r");
|
||
if (!afmfile) {
|
||
/* fail to open file */
|
||
char buf [2048];
|
||
PR_snprintf(buf, sizeof (buf),
|
||
XP_GetString(XFE_ERROR_OPENING_FILE),
|
||
value.addr);
|
||
fprintf(stderr, buf);
|
||
fprintf(stderr, "\n");
|
||
}
|
||
else { /* parse the afm file */
|
||
int err;
|
||
if (err = XP_parseAFMFile(afmfile,
|
||
&(p.otherFontInfo[index]))) {
|
||
/* error in parsing */
|
||
char buf [2048];
|
||
if (p.otherFontInfo[index] != NULL)
|
||
free(p.otherFontInfo[index]);
|
||
p.otherFontInfo[index] = NULL;
|
||
fclose(afmfile);
|
||
PR_snprintf(buf, sizeof (buf),
|
||
XP_GetString(XFE_CANNOT_READ_FILE),
|
||
value.addr);
|
||
fprintf(stderr, buf);
|
||
fprintf(stderr, "\n");
|
||
fprintf(stderr, "Error code is %d\n", err);
|
||
}
|
||
else /* successfully parsed */
|
||
fclose(afmfile);
|
||
}
|
||
}
|
||
else { /* no psafmfile, then look for psmetric */
|
||
PR_snprintf(clas, sizeof (clas),
|
||
"%s.DocumentFonts.Charset.Measure.Style.PSMetric", fe_progclass);
|
||
PR_snprintf(name, sizeof (name),
|
||
"%s.documentFonts.%s.%s.%s.psmetric", fe_progclass,
|
||
mimecharset, measures[measure], styles[style]);
|
||
|
||
if (XrmGetResource(db, name, clas, &type, &value)) {
|
||
int params[4];
|
||
int param = 0;
|
||
int len = XP_STRLEN(value.addr);
|
||
char *start = value.addr;
|
||
i = params[0] = params[1] = params[2] = params[3] = 0;
|
||
while (i <= len) {
|
||
if (i != 0 && !isdigit(*(value.addr+i))
|
||
&& isdigit(*(value.addr+i-1)) ) {
|
||
*(value.addr+i) = '\0';
|
||
params[param++] = atoi(start);
|
||
start = value.addr + i + 1;
|
||
}
|
||
i++;
|
||
}
|
||
if (param > 0) {
|
||
p.otherFontInfo[index] = (PS_FontInfo *)
|
||
malloc(sizeof(PS_FontInfo));
|
||
p.otherFontInfo[index]->chars[0].wx = params[0];
|
||
p.otherFontInfo[index]->chars[0].wy = params[1];
|
||
p.otherFontInfo[index]->fontBBox.ury = params[2];
|
||
p.otherFontInfo[index]->fontBBox.lly = params[3];
|
||
for (i=1; i<256; i++)
|
||
p.otherFontInfo[index]->chars[i] =
|
||
p.otherFontInfo[index]->chars[0];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/* end of reading font specifications */
|
||
|
||
/* post-parsing process, to map unspecified fonts to specified fonts */
|
||
if (p.otherFontName[LO_FONT_NORMAL] == NULL)
|
||
p.otherFontName[LO_FONT_NORMAL] = p.otherFontName[LO_FONT_FIXED];
|
||
else if (p.otherFontName[LO_FONT_FIXED] == NULL)
|
||
p.otherFontName[LO_FONT_FIXED] = p.otherFontName[LO_FONT_NORMAL];
|
||
|
||
|
||
for (i=0; i<N_FONTS; i++) {
|
||
if (p.otherFontName[i] == NULL)
|
||
p.otherFontName[i] = p.otherFontName[i & LO_FONT_FIXED];
|
||
}
|
||
|
||
if (last_to_file_p)
|
||
p.completion = ps_file_close;
|
||
else
|
||
p.completion = ps_pipe_close;
|
||
|
||
p.carg = context;
|
||
fe_RaiseSynchronousURLDialog (context, CONTEXT_WIDGET (context),
|
||
XP_GetString(XFE_DIALOGS_PRINTING));
|
||
XL_TranslatePostscript (context, url, &saved_data, &p);
|
||
fe_await_synchronous_url (context);
|
||
|
||
/* dispose used memory blocks */
|
||
for (i=0; i<N_FONTS; i++) {
|
||
if (p.otherFontName[i] != NULL) {
|
||
int j;
|
||
for (j = i+1; j < N_FONTS; j++)
|
||
if (p.otherFontName[i] == p.otherFontName[j])
|
||
p.otherFontName[j] = NULL;
|
||
free(p.otherFontName[i]);
|
||
p.otherFontName[i] = NULL;
|
||
}
|
||
if (p.otherFontInfo[i] != NULL) {
|
||
int j;
|
||
for (j = i+1; j < N_FONTS; j++)
|
||
if (p.otherFontInfo[i] == p.otherFontInfo[j])
|
||
p.otherFontInfo[j] = NULL;
|
||
free(p.otherFontInfo[i]);
|
||
p.otherFontInfo[i] = NULL;
|
||
}
|
||
} /* end of dispose */
|
||
|
||
/* XXX do we need to delete the URL ? */
|
||
}
|
||
|
||
|
||
static void
|
||
fe_print_destroy_cb(Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
if (!fpd) return;
|
||
|
||
/* Remove this callback so that we make absolutely sure we wont
|
||
* free the fpd again.
|
||
*/
|
||
XtRemoveCallback(widget, XmNdestroyCallback, fe_print_destroy_cb, fpd);
|
||
free(fpd);
|
||
}
|
||
|
||
static void
|
||
fe_print_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
||
{
|
||
struct fe_print_data *fpd = (struct fe_print_data *) closure;
|
||
URL_Struct *url;
|
||
Boolean b;
|
||
|
||
/*
|
||
* Pop down the print dialog immediately.
|
||
*/
|
||
fe_UnmanageChild_safe (fpd->shell);
|
||
|
||
XtVaGetValues (fpd->printer, XmNset, &b, 0);
|
||
last_to_file_p = !b;
|
||
if (fe_globalPrefs.print_command) free (fe_globalPrefs.print_command);
|
||
XtVaGetValues (fpd->command_text, XmNvalue, &fe_globalPrefs.print_command,0);
|
||
if (last_print_file_name) free (last_print_file_name);
|
||
last_print_file_name = fe_GetTextField(fpd->file_text);
|
||
XtVaGetValues (fpd->portrait, XmNset, &b, 0);
|
||
fe_globalPrefs.print_landscape = !b;
|
||
XtVaGetValues (fpd->last, XmNset, &b, 0);
|
||
fe_globalPrefs.print_reversed = b;
|
||
XtVaGetValues (fpd->grey, XmNset, &b, 0);
|
||
fe_globalPrefs.print_color = !b;
|
||
XtVaGetValues (fpd->letter, XmNset, &b, 0);
|
||
if (b) fe_globalPrefs.print_paper_size = 0;
|
||
XtVaGetValues (fpd->legal, XmNset, &b, 0);
|
||
if (b) fe_globalPrefs.print_paper_size = 1;
|
||
XtVaGetValues (fpd->exec, XmNset, &b, 0);
|
||
if (b) fe_globalPrefs.print_paper_size = 2;
|
||
XtVaGetValues (fpd->a4, XmNset, &b, 0);
|
||
if (b) fe_globalPrefs.print_paper_size = 3;
|
||
|
||
url = SHIST_CreateWysiwygURLStruct (fpd->context, fpd->hist);
|
||
if (url) {
|
||
last_print_file_name = fe_StringTrim (last_print_file_name);
|
||
|
||
fe_Print(fpd->context, url, last_to_file_p, last_print_file_name);
|
||
} else {
|
||
FE_Alert(fpd->context, fe_globalData.no_url_loaded_message);
|
||
}
|
||
|
||
/* We need this check to see if this widget is being_destroyed
|
||
* or not in its ok_callback because fe_Print() goes off and
|
||
* calls fe_await_synchronous_url() while has a mini eventloop
|
||
* in it. This could cause a destroy of this widget. Motif, in
|
||
* all its smartness, keeps this widget's memory around. This
|
||
* is the only think we can check. context, shell, fpd all might
|
||
* have been destroyed and deallocated.
|
||
*/
|
||
if (XfeIsAlive(widget)) {
|
||
XtDestroyWidget (fpd->shell);
|
||
}
|
||
}
|
||
|
||
|
||
void
|
||
fe_PrintDialog (MWContext *context)
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget kids [50];
|
||
Arg av [20];
|
||
int ac, i, labels_width;
|
||
Widget shell, form;
|
||
Widget print_to_label, print_command_label;
|
||
Widget print_command_text, file_name_label, file_name_text;
|
||
Widget browse_button, line, print_label;
|
||
Widget first_first_toggle, last_first_toggle, orientation_label;
|
||
Widget portrait_toggle, landscape_toggle;
|
||
Widget print_color_label, greyscale_toggle;
|
||
Widget color_toggle, paper_size_label, paper_size_radio_box, letter_toggle;
|
||
Widget legal_toggle, executive_toggle, a4_toggle;
|
||
Widget to_printer_toggle, to_file_toggle;
|
||
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
|
||
struct fe_print_data *fpd = (struct fe_print_data *)
|
||
calloc (sizeof (struct fe_print_data), 1);
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNuserData, False); ac++;
|
||
shell = XmCreatePromptDialog (mainw, "printSetup", av, ac);
|
||
|
||
XtAddCallback (shell, XmNokCallback, fe_print_cb, fpd);
|
||
XtAddCallback (shell, XmNcancelCallback, fe_destroy_cb, shell);
|
||
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell,
|
||
XmDIALOG_SELECTION_LABEL));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_TEXT));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_APPLY_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (shell, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
XtAddCallback (shell, XmNdestroyCallback, fe_print_destroy_cb, fpd);
|
||
|
||
i = 0;
|
||
ac = 0;
|
||
form = XmCreateForm (shell, "form", av, ac);
|
||
kids [i++] = print_to_label =
|
||
XmCreateLabelGadget (form, "printToLabel", av, ac);
|
||
kids [i++] = to_printer_toggle =
|
||
XmCreateToggleButtonGadget (form, "toPrinterToggle", av, ac);
|
||
kids [i++] = to_file_toggle =
|
||
XmCreateToggleButtonGadget (form, "toFileToggle", av, ac);
|
||
kids [i++] = print_command_label =
|
||
XmCreateLabelGadget (form, "printCommandLabel", av, ac);
|
||
kids [i++] = print_command_text =
|
||
fe_CreateTextField (form, "printCommandText", av, ac);
|
||
kids [i++] = file_name_label =
|
||
XmCreateLabelGadget (form, "fileNameLabel", av, ac);
|
||
kids [i++] = file_name_text =
|
||
fe_CreateTextField (form, "fileNameText", av, ac);
|
||
kids [i++] = browse_button =
|
||
XmCreatePushButtonGadget (form, "browseButton", av, ac);
|
||
kids [i++] = line = XmCreateSeparator (form, "line", av, ac);
|
||
kids [i++] = print_label = XmCreateLabelGadget (form, "printLabel", av, ac);
|
||
kids [i++] = first_first_toggle =
|
||
XmCreateToggleButtonGadget (form, "firstFirstToggle", av, ac);
|
||
kids [i++] = last_first_toggle =
|
||
XmCreateToggleButtonGadget (form, "lastFirstToggle", av, ac);
|
||
kids [i++] = orientation_label =
|
||
XmCreateLabelGadget (form, "orientationLabel", av, ac);
|
||
kids [i++] = portrait_toggle =
|
||
XmCreateToggleButtonGadget (form, "portraitToggle", av, ac);
|
||
kids [i++] = landscape_toggle =
|
||
XmCreateToggleButtonGadget (form, "landscapeToggle", av, ac);
|
||
kids [i++] = print_color_label =
|
||
XmCreateLabelGadget (form, "printColorLabel", av, ac);
|
||
kids [i++] = greyscale_toggle =
|
||
XmCreateToggleButtonGadget (form, "greyscaleToggle", av, ac);
|
||
kids [i++] = color_toggle =
|
||
XmCreateToggleButtonGadget (form, "colorToggle", av, ac);
|
||
kids [i++] = paper_size_label =
|
||
XmCreateLabelGadget (form, "paperSizeLabel", av, ac);
|
||
kids [i++] = paper_size_radio_box =
|
||
XmCreateRadioBox (form, "paperSizeRadioBox", av, ac);
|
||
kids [i++] = letter_toggle =
|
||
XmCreateToggleButtonGadget (form, "letterToggle", av, ac);
|
||
kids [i++] = legal_toggle =
|
||
XmCreateToggleButtonGadget (form, "legalToggle", av, ac);
|
||
kids [i++] = executive_toggle =
|
||
XmCreateToggleButtonGadget (form, "executiveToggle", av, ac);
|
||
kids [i++] = a4_toggle =
|
||
XmCreateToggleButtonGadget (form, "a4Toggle", av, ac);
|
||
|
||
labels_width = XfeVaGetWidestWidget(print_to_label, print_command_label,
|
||
file_name_label, 0);
|
||
|
||
XtVaSetValues (print_to_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, to_printer_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, to_printer_toggle,
|
||
RIGHT_JUSTIFY_VA_ARGS(print_to_label,labels_width),
|
||
0);
|
||
XtVaSetValues (to_printer_toggle,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNleftOffset, labels_width,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (to_file_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, to_printer_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, to_printer_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, to_printer_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (print_command_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, print_command_text,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, print_command_text,
|
||
RIGHT_JUSTIFY_VA_ARGS(print_command_label,labels_width),
|
||
0);
|
||
XtVaSetValues (print_command_text,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, to_printer_toggle,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, to_printer_toggle,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (file_name_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, file_name_text,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, file_name_text,
|
||
RIGHT_JUSTIFY_VA_ARGS(file_name_label,labels_width),
|
||
0);
|
||
XtVaSetValues (file_name_text,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, print_command_text,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, print_command_text,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, browse_button,
|
||
0);
|
||
XtVaSetValues (browse_button,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, print_command_text,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_NONE,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
|
||
XtVaSetValues (browse_button, XmNheight, _XfeHeight(file_name_text), 0);
|
||
|
||
XtVaSetValues (line,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, file_name_text,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
|
||
XtVaSetValues (print_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, first_first_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, first_first_toggle,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, first_first_toggle,
|
||
0);
|
||
XtVaSetValues (first_first_toggle,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, line,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, print_command_text,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (last_first_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, first_first_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, first_first_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, first_first_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
|
||
XtVaSetValues (orientation_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, portrait_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, portrait_toggle,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, portrait_toggle,
|
||
0);
|
||
XtVaSetValues (portrait_toggle,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, first_first_toggle,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, first_first_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (landscape_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, portrait_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, portrait_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, portrait_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
|
||
XtVaSetValues (print_color_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, greyscale_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, greyscale_toggle,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, greyscale_toggle,
|
||
0);
|
||
XtVaSetValues (greyscale_toggle,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, portrait_toggle,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, portrait_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (color_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, greyscale_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, greyscale_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, greyscale_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
|
||
XtVaSetValues (paper_size_label,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, letter_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, letter_toggle,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_WIDGET,
|
||
XmNrightWidget, letter_toggle,
|
||
0);
|
||
XtVaSetValues (letter_toggle,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, greyscale_toggle,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, greyscale_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (legal_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, letter_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, letter_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, letter_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (executive_toggle,
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, letter_toggle,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNleftWidget, letter_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
XtVaSetValues (a4_toggle,
|
||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNtopWidget, executive_toggle,
|
||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||
XmNbottomWidget, executive_toggle,
|
||
XmNleftAttachment, XmATTACH_WIDGET,
|
||
XmNleftWidget, executive_toggle,
|
||
XmNrightAttachment, XmATTACH_NONE,
|
||
0);
|
||
|
||
XtAddCallback (to_printer_toggle, XmNvalueChangedCallback,
|
||
fe_print_to_toggle_cb, fpd);
|
||
XtAddCallback (to_file_toggle, XmNvalueChangedCallback,
|
||
fe_print_to_toggle_cb, fpd);
|
||
|
||
XtAddCallback (browse_button, XmNactivateCallback,
|
||
fe_print_browse_cb, fpd);
|
||
|
||
XtAddCallback (first_first_toggle, XmNvalueChangedCallback,
|
||
fe_print_order_toggle_cb, fpd);
|
||
XtAddCallback (last_first_toggle, XmNvalueChangedCallback,
|
||
fe_print_order_toggle_cb, fpd);
|
||
|
||
XtAddCallback (portrait_toggle, XmNvalueChangedCallback,
|
||
fe_print_orientation_toggle_cb, fpd);
|
||
XtAddCallback (landscape_toggle, XmNvalueChangedCallback,
|
||
fe_print_orientation_toggle_cb, fpd);
|
||
|
||
XtAddCallback (greyscale_toggle, XmNvalueChangedCallback,
|
||
fe_print_color_toggle_cb, fpd);
|
||
XtAddCallback (color_toggle, XmNvalueChangedCallback,
|
||
fe_print_color_toggle_cb, fpd);
|
||
|
||
XtAddCallback (letter_toggle, XmNvalueChangedCallback,
|
||
fe_print_paper_toggle_cb, fpd);
|
||
XtAddCallback (legal_toggle, XmNvalueChangedCallback,
|
||
fe_print_paper_toggle_cb, fpd);
|
||
XtAddCallback (executive_toggle, XmNvalueChangedCallback,
|
||
fe_print_paper_toggle_cb, fpd);
|
||
XtAddCallback (a4_toggle, XmNvalueChangedCallback,
|
||
fe_print_paper_toggle_cb, fpd);
|
||
|
||
XtVaSetValues (print_command_text, XmNvalue, fe_globalPrefs.print_command,0);
|
||
if (!last_print_file_name || !*last_print_file_name) {
|
||
/* Use a default file name. We need to strdup here as we free this
|
||
later. */
|
||
last_print_file_name = strdup( XFE_DEFAULT_PRINT_FILENAME );
|
||
}
|
||
fe_SetTextField(file_name_text, last_print_file_name);
|
||
if (last_to_file_p)
|
||
{
|
||
XtVaSetValues (to_file_toggle, XmNset, True, 0);
|
||
XtVaSetValues (print_command_text, XmNsensitive, False, 0);
|
||
XtVaSetValues (shell, XmNinitialFocus, file_name_text, 0);
|
||
}
|
||
else
|
||
{
|
||
XtVaSetValues (to_printer_toggle, XmNset, True, 0);
|
||
XtVaSetValues (file_name_text, XmNsensitive, False, 0);
|
||
XtVaSetValues (browse_button, XmNsensitive, False, 0);
|
||
XtVaSetValues (shell, XmNinitialFocus, print_command_text, 0);
|
||
}
|
||
XtVaSetValues ((fe_globalPrefs.print_reversed
|
||
? last_first_toggle : first_first_toggle),
|
||
XmNset, True, 0);
|
||
XtVaSetValues ((fe_globalPrefs.print_landscape
|
||
? landscape_toggle : portrait_toggle),
|
||
XmNset, True, 0);
|
||
XtVaSetValues ((fe_globalPrefs.print_color
|
||
? color_toggle : greyscale_toggle),
|
||
XmNset, True, 0);
|
||
XtVaSetValues ((fe_globalPrefs.print_paper_size == 0 ? letter_toggle :
|
||
fe_globalPrefs.print_paper_size == 1 ? legal_toggle :
|
||
fe_globalPrefs.print_paper_size == 2 ? executive_toggle :
|
||
a4_toggle),
|
||
XmNset, True, 0);
|
||
|
||
|
||
XtManageChildren (kids, i);
|
||
XtManageChild (form);
|
||
|
||
fpd->context = context;
|
||
fpd->hist = SHIST_GetCurrent (&context->hist);
|
||
fpd->shell = shell;
|
||
fpd->printer = to_printer_toggle;
|
||
fpd->file = to_file_toggle;
|
||
fpd->command_text = print_command_text;
|
||
fpd->file_text = file_name_text;
|
||
fpd->browse = browse_button;
|
||
fpd->first = first_first_toggle;
|
||
fpd->last = last_first_toggle;
|
||
fpd->portrait = portrait_toggle;
|
||
fpd->landscape = landscape_toggle;
|
||
fpd->grey = greyscale_toggle;
|
||
fpd->color = color_toggle;
|
||
fpd->letter = letter_toggle;
|
||
fpd->legal = legal_toggle;
|
||
fpd->exec = executive_toggle;
|
||
fpd->a4 = a4_toggle;
|
||
|
||
fe_NukeBackingStore (shell);
|
||
XtManageChild (shell);
|
||
}
|
||
|
||
|
||
|
||
/* Streaming audio
|
||
*/
|
||
|
||
int
|
||
FE_AskStreamQuestion (MWContext *context)
|
||
{
|
||
struct fe_confirm_data data;
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget dialog;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
dialog = XmCreatePromptDialog (mainw, "streamingAudioQuery", av, ac);
|
||
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_TEXT));
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL));
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_APPLY_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_ok_cb, &data);
|
||
XtAddCallback (dialog, XmNapplyCallback, fe_destroy_apply_cb, &data);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
data.context = context;
|
||
data.widget = dialog;
|
||
data.answer = Answer_Invalid;
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_Cancel || data.answer == Answer_Destroy)
|
||
return -1;
|
||
else if (data.answer == Answer_OK)
|
||
return 1;
|
||
else if (data.answer == Answer_Apply)
|
||
return 0;
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
|
||
/* Care and feeding of lawyers and other parasites */
|
||
|
||
static XtErrorHandler old_xt_warning_handler = NULL;
|
||
|
||
static void
|
||
xt_warning_handler(String msg)
|
||
{
|
||
if (!msg)
|
||
{
|
||
return;
|
||
}
|
||
|
||
#ifndef DEBUG
|
||
/* Ignore warnings that contain "Actions not found" (non debug only) */
|
||
if (XP_STRSTR(msg,"Actions not found"))
|
||
{
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
(*old_xt_warning_handler)(msg);
|
||
}
|
||
|
||
void
|
||
fe_LicenseDialog (MWContext *context)
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget dialog;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
Widget form, label1, text, label2;
|
||
Widget accept, reject;
|
||
|
||
char crockery [1024];
|
||
PR_snprintf (crockery, sizeof (crockery), "%d ", getuid ());
|
||
strcat (crockery, fe_version);
|
||
|
||
if (fe_VendorAnim)
|
||
return;
|
||
|
||
if (fe_globalPrefs.license_accepted &&
|
||
!strcmp (crockery, fe_globalPrefs.license_accepted))
|
||
return;
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNdefaultButton, 0); ac++;
|
||
dialog = XmCreateTemplateDialog (mainw, "licenseDialog", av, ac);
|
||
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON));
|
||
/* fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_APPLY_BUTTON));*/
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog,XmDIALOG_DEFAULT_BUTTON));
|
||
fe_UnmanageChild_safe (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
|
||
|
||
ac = 0;
|
||
accept = XmCreatePushButtonGadget (dialog, "accept", av, ac);
|
||
reject = XmCreatePushButtonGadget (dialog, "reject", av, ac);
|
||
form = XmCreateForm (dialog, "form", av, ac);
|
||
label1 = XmCreateLabelGadget (form, "label1", av, ac);
|
||
|
||
XtSetArg (av [ac], XmNeditable, False); ac++;
|
||
XtSetArg (av [ac], XmNcursorPositionVisible, False); ac++;
|
||
XtSetArg (av[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
|
||
text = XmCreateScrolledText (form, "text", av, ac);
|
||
fe_HackDialogTranslations (text);
|
||
ac = 0;
|
||
label2 = XmCreateLabelGadget (form, "label2", av, ac);
|
||
|
||
XtVaSetValues (label1,
|
||
XmNtopAttachment, XmATTACH_FORM,
|
||
XmNbottomAttachment, XmATTACH_NONE,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (XtParent (text),
|
||
XmNtopAttachment, XmATTACH_WIDGET,
|
||
XmNtopWidget, label1,
|
||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||
XmNbottomWidget, label2,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
XtVaSetValues (label2,
|
||
XmNtopAttachment, XmATTACH_NONE,
|
||
XmNbottomAttachment, XmATTACH_FORM,
|
||
XmNleftAttachment, XmATTACH_FORM,
|
||
XmNrightAttachment, XmATTACH_FORM,
|
||
0);
|
||
|
||
{
|
||
char *license = 0;
|
||
int32 length = 0;
|
||
char *ctype = 0;
|
||
void *data = FE_AboutData ("license", &license, &length, &ctype);
|
||
if (!license || length < 300)
|
||
{
|
||
license = "Please fill in";
|
||
/* abort (); */
|
||
}
|
||
XtVaSetValues (text, XmNvalue, license, 0);
|
||
if (data) free (data);
|
||
}
|
||
|
||
XtManageChild (label1);
|
||
XtManageChild (text);
|
||
XtManageChild (XtParent (text));
|
||
XtManageChild (label2);
|
||
XtManageChild (form);
|
||
XtManageChild (accept);
|
||
XtManageChild (reject);
|
||
|
||
{
|
||
struct fe_confirm_data data;
|
||
XtVaSetValues (dialog, XmNdefaultButton, accept, 0);
|
||
XtAddCallback (accept, XmNactivateCallback, fe_destroy_ok_cb, &data);
|
||
XtAddCallback (reject, XmNactivateCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb, &data);
|
||
|
||
data.context = context;
|
||
data.widget = dialog;
|
||
data.answer = Answer_Invalid;
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
|
||
/* Install a warning handler that ignores translation warnings */
|
||
old_xt_warning_handler = XtAppSetWarningHandler(fe_XtAppContext,
|
||
xt_warning_handler);
|
||
|
||
XtManageChild (dialog);
|
||
|
||
/* Restore the original warning handler after the dialog is managed */
|
||
XtAppSetWarningHandler(fe_XtAppContext,old_xt_warning_handler);
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_Cancel || data.answer == Answer_Destroy)
|
||
{
|
||
if (fe_pidlock) unlink (fe_pidlock);
|
||
exit (0);
|
||
}
|
||
else if (data.answer == Answer_OK)
|
||
{
|
||
/* Store crockery into preferences, and save. */
|
||
StrAllocCopy (fe_globalPrefs.license_accepted, crockery);
|
||
if (!XFE_UpgradePrefs ((char *) fe_globalData.user_prefs_file,
|
||
&fe_globalPrefs))
|
||
fe_perror (context, XP_GetString(XFE_CANT_SAVE_PREFS));
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
abort ();
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
fe_UpdateDocInfoDialog (MWContext *context)
|
||
{
|
||
/* nada for now */
|
||
}
|
||
|
||
static void
|
||
fe_security_dialog_toggle (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
XP_Bool *prefs_toggle = (XP_Bool *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
*prefs_toggle = cb->set;
|
||
return;
|
||
}
|
||
|
||
static void
|
||
fe_movemail_dialog_toggle (Widget widget, XtPointer closure,
|
||
XtPointer call_data)
|
||
{
|
||
XP_Bool *prefs_toggle = (XP_Bool *) closure;
|
||
XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call_data;
|
||
*prefs_toggle = cb->set;
|
||
if (!XFE_SavePrefs ((char *) fe_globalData.user_prefs_file, &fe_globalPrefs))
|
||
fe_perror (fe_all_MWContexts->context,
|
||
XP_GetString( XFE_ERROR_SAVING_OPTIONS ) );
|
||
}
|
||
|
||
#ifdef MOZ_MAIL_NEWS
|
||
/*
|
||
* fe_MovemailWarning
|
||
* Stolen from FE_SecurityDialog
|
||
*/
|
||
extern Boolean
|
||
fe_MovemailWarning(MWContext *context)
|
||
{
|
||
if ( fe_globalPrefs.movemail_warn == True ) {
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget dialog;
|
||
Widget form;
|
||
Widget toggle;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
XmString ok_label;
|
||
XmString cancel_label;
|
||
XmString selection_label;
|
||
XmString toggle_label;
|
||
struct fe_confirm_data data;
|
||
char buf[256];
|
||
char* from;
|
||
const char* to;
|
||
|
||
from = fe_mn_getmailbox();
|
||
to = FE_GetFolderDirectory(context);
|
||
|
||
/*
|
||
* This dialog should probably be popped up in fe_mn_getmailbox()
|
||
* instead. Otherwise, we have to check everywhere it's used.
|
||
* (Only two places at this point, though.)
|
||
*/
|
||
if ( from == NULL ) {
|
||
FE_Alert(context, XP_GetString(XFE_MAIL_SPOOL_UNKNOWN));
|
||
return False;
|
||
}
|
||
|
||
PR_snprintf(buf, sizeof(buf), XP_GetString(XFE_MOVEMAIL_EXPLANATION),
|
||
from, to, from);
|
||
|
||
ok_label = XmStringCreateLtoR(XP_GetString(XFE_CONTINUE_MOVEMAIL),
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
cancel_label = XmStringCreateLtoR(XP_GetString(XFE_CANCEL_MOVEMAIL),
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
selection_label = XmStringCreateLtoR(buf,
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
toggle_label = XmStringCreateLtoR(XP_GetString(XFE_SHOW_NEXT_TIME),
|
||
XmFONTLIST_DEFAULT_TAG);
|
||
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle,
|
||
XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNchildPlacement, XmPLACE_BELOW_SELECTION); ac++;
|
||
XtSetArg (av[ac], XmNokLabelString, ok_label); ac++;
|
||
XtSetArg (av[ac], XmNcancelLabelString, cancel_label); ac++;
|
||
XtSetArg (av[ac], XmNselectionLabelString, selection_label); ac++;
|
||
dialog = XmCreatePromptDialog (mainw, "movemailWarnDialog", av, ac);
|
||
|
||
if ( ok_label ) XmStringFree(ok_label);
|
||
if ( cancel_label ) XmStringFree(cancel_label);
|
||
if ( selection_label ) XmStringFree(selection_label);
|
||
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_TEXT));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog,
|
||
XmDIALOG_APPLY_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog,
|
||
XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
|
||
ac = 0;
|
||
form = XmCreateForm (dialog, "form", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNset, fe_globalPrefs.movemail_warn); ac++;
|
||
XtSetArg (av[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
|
||
XtSetArg (av[ac], XmNlabelString, toggle_label); ac++;
|
||
toggle = XmCreateToggleButtonGadget (form, "toggle", av, ac);
|
||
if ( toggle_label ) XmStringFree(toggle_label);
|
||
|
||
XtAddCallback (toggle, XmNvalueChangedCallback,
|
||
fe_movemail_dialog_toggle, &fe_globalPrefs.movemail_warn);
|
||
XtManageChild (toggle);
|
||
XtManageChild (form);
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_ok_cb, &data);
|
||
XtAddCallback (dialog, XmNapplyCallback, fe_destroy_apply_cb, &data);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb,&data);
|
||
|
||
data.context = context;
|
||
data.widget = dialog;
|
||
data.answer = Answer_Invalid;
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_Cancel || data.answer == Answer_Destroy)
|
||
return False;
|
||
else if (data.answer == Answer_OK)
|
||
return True;
|
||
else
|
||
abort ();
|
||
}
|
||
|
||
return True;
|
||
}
|
||
#endif /* MOZ_MAIL_NEWS */
|
||
|
||
|
||
extern Bool
|
||
FE_SecurityDialog (MWContext *context, int state, XP_Bool *prefs_toggle)
|
||
{
|
||
char *name;
|
||
Bool cancel_p = True;
|
||
Bool cancel_default_p = False;
|
||
switch (state)
|
||
{
|
||
case SD_INSECURE_POST_FROM_SECURE_DOC:
|
||
name = "insecurePostFromSecureDocDialog";
|
||
cancel_p = True;
|
||
cancel_default_p = True;
|
||
break;
|
||
case SD_INSECURE_POST_FROM_INSECURE_DOC:
|
||
name = "insecurePostFromInsecureDocDialog";
|
||
cancel_p = True;
|
||
break;
|
||
case SD_ENTERING_SECURE_SPACE:
|
||
name = "enteringSecureDialog";
|
||
cancel_p = False;
|
||
break;
|
||
case SD_LEAVING_SECURE_SPACE:
|
||
name = "leavingSecureDialog";
|
||
cancel_p = True;
|
||
break;
|
||
case SD_INSECURE_DOCS_WITHIN_SECURE_DOCS_NOT_SHOWN:
|
||
name = "mixedSecurityDialog";
|
||
cancel_p = False;
|
||
break;
|
||
case SD_REDIRECTION_TO_INSECURE_DOC:
|
||
name = "redirectionToInsecureDialog";
|
||
cancel_p = True;
|
||
break;
|
||
case SD_REDIRECTION_TO_SECURE_SITE:
|
||
name = "redirectionToSecureDialog";
|
||
cancel_p = True;
|
||
break;
|
||
default:
|
||
abort ();
|
||
}
|
||
|
||
if (prefs_toggle && !*prefs_toggle)
|
||
return True;
|
||
|
||
{
|
||
Widget mainw = CONTEXT_WIDGET (context);
|
||
Widget dialog;
|
||
Arg av [20];
|
||
int ac;
|
||
Visual *v = 0;
|
||
Colormap cmap = 0;
|
||
Cardinal depth = 0;
|
||
XtVaGetValues (mainw, XtNvisual, &v, XtNcolormap, &cmap,
|
||
XtNdepth, &depth, 0);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNvisual, v); ac++;
|
||
XtSetArg (av[ac], XmNdepth, depth); ac++;
|
||
XtSetArg (av[ac], XmNcolormap, cmap); ac++;
|
||
XtSetArg (av[ac], XmNallowShellResize, TRUE); ac++;
|
||
XtSetArg (av[ac], XmNtransientFor, mainw); ac++;
|
||
XtSetArg (av[ac], XmNdialogStyle,
|
||
XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
|
||
if (cancel_p)
|
||
{
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_QUESTION); ac++;
|
||
}
|
||
else
|
||
{
|
||
XtSetArg (av[ac], XmNdialogType, XmDIALOG_INFORMATION); ac++;
|
||
}
|
||
XtSetArg (av[ac], XmNdeleteResponse, XmDESTROY); ac++;
|
||
XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
|
||
XtSetArg (av[ac], XmNchildPlacement, XmPLACE_BELOW_SELECTION); ac++;
|
||
dialog = XmCreatePromptDialog (mainw, name, av, ac);
|
||
|
||
XtManageChild (XmSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_SEPARATOR));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog, XmDIALOG_TEXT));
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog,
|
||
XmDIALOG_APPLY_BUTTON));
|
||
#ifdef NO_HELP
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog,
|
||
XmDIALOG_HELP_BUTTON));
|
||
#endif
|
||
if (! cancel_p)
|
||
fe_UnmanageChild_safe (XmSelectionBoxGetChild (dialog,
|
||
XmDIALOG_CANCEL_BUTTON));
|
||
|
||
if (prefs_toggle)
|
||
{
|
||
Widget form, toggle;
|
||
ac = 0;
|
||
form = XmCreateForm (dialog, "form", av, ac);
|
||
ac = 0;
|
||
XtSetArg (av[ac], XmNset, *prefs_toggle); ac++;
|
||
XtSetArg (av[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
|
||
XtSetArg (av[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
|
||
toggle = XmCreateToggleButtonGadget (form, "toggle", av, ac);
|
||
XtAddCallback (toggle, XmNvalueChangedCallback,
|
||
fe_security_dialog_toggle, prefs_toggle);
|
||
XtManageChild (toggle);
|
||
XtManageChild (form);
|
||
}
|
||
|
||
if (cancel_default_p)
|
||
{
|
||
Widget c = XmSelectionBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON);
|
||
if (!c) abort ();
|
||
XtVaSetValues (dialog, XmNdefaultButton, c, XmNinitialFocus, c, 0);
|
||
}
|
||
|
||
fe_NukeBackingStore (dialog);
|
||
XtManageChild (dialog);
|
||
|
||
{
|
||
struct fe_confirm_data data;
|
||
XtAddCallback (dialog, XmNokCallback, fe_destroy_ok_cb, &data);
|
||
if (cancel_p)
|
||
{
|
||
XtAddCallback (dialog, XmNapplyCallback, fe_destroy_apply_cb, &data);
|
||
XtAddCallback (dialog, XmNcancelCallback, fe_destroy_cancel_cb, &data);
|
||
XtAddCallback (dialog, XmNdestroyCallback, fe_destroy_finish_cb,&data);
|
||
}
|
||
|
||
data.context = context;
|
||
data.widget = dialog;
|
||
data.answer = Answer_Invalid;
|
||
|
||
while (data.answer == Answer_Invalid)
|
||
fe_EventLoop ();
|
||
|
||
if (data.answer == Answer_Cancel || data.answer == Answer_Destroy)
|
||
return False;
|
||
else if (data.answer == Answer_OK)
|
||
return True;
|
||
else
|
||
abort ();
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Temporary stub. */
|
||
XP_Bool
|
||
XFE_SelectDialog(MWContext *pContext,
|
||
const char *pMessage,
|
||
const char **pList,
|
||
int16 *pCount)
|
||
{
|
||
int i;
|
||
char *message = 0;
|
||
for (i = 0; i < *pCount; i++) {
|
||
StrAllocCopy(message, pMessage);
|
||
StrAllocCat(message, " = ");
|
||
StrAllocCat(message, pList[i]);
|
||
if (FE_Confirm(pContext, message)) {
|
||
/* user selected this one */
|
||
XP_FREE(message);
|
||
*pCount = i;
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
/* user rejected all */
|
||
XP_FREE(message);
|
||
return FALSE;
|
||
}
|
||
|
||
/*
|
||
* temporary UI until FE implements this function as a single dialog box
|
||
*/
|
||
XP_Bool
|
||
XFE_CheckConfirm(MWContext *pContext,
|
||
const char *pConfirmMessage,
|
||
const char *pCheckMessage,
|
||
const char *pOKMessage, /* text on the OK button */
|
||
const char *pCancelMessage, /* text on the cancel button */
|
||
XP_Bool *pChecked)
|
||
{
|
||
Bool userHasAccepted = FE_Confirm(pContext, pConfirmMessage);
|
||
*pChecked = FE_Confirm (pContext, pCheckMessage);
|
||
return userHasAccepted;
|
||
}
|