/* -*- Mode: C++; tab-width: 4; 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. */ /* context_funcs.cpp --- Functions the backend invokes from the MWContext->funcs vtable */ #include "il_types.h" #include "layers.h" #include "jsapi.h" #include "prefapi.h" #include "MozillaApp.h" #include "Frame.h" #include "ViewGlue.h" #include "View.h" #include "HTMLView.h" #include #ifdef MOZ_MAIL_NEWS #include "MsgFrame.h" #include "addrbk.h" #include "dirprefs.h" #endif #include "DisplayFactory.h" #include "Logo.h" #include "Dashboard.h" #include "mozilla.h" #include "xfe.h" #include "xp_thrmo.h" #include "fe_proto.h" #include "xfe2_extern.h" #include "Netcaster.h" #include "NavCenterView.h" #include "xpgetstr.h" #if defined(IRIX) || defined(OSF1) || defined(SOLARIS) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC) #include /* for statvfs() */ #define STATFS statvfs #elif defined(SCO_SV) #define _SVID3 /* for statvfs.h */ #include /* for statvfs() */ #define STATFS statvfs #elif defined(HPUX) #include /* for statfs() */ #define STATFS statfs #elif defined(LINUX) #include /* for statfs() */ #define STATFS statfs #elif defined(SUNOS4) #include /* for statfs() */ extern "C" int statfs(char *, struct statfs *); #define STATFS statfs #elif defined(BSDI) #include /* for statfs() */ #define STATFS statfs #else #include /* for statfs() */ #define STATFS statfs extern "C" int statfs(char *, struct statfs *); #endif #if defined(OSF1) extern "C" int statvfs(const char *, struct statvfs *); #endif extern int XFE_NO_SUBJECT; extern int XFE_DOCUMENT_DONE; extern int XFE_ERROR_SAVING_PASSWORD; extern int XFE_STDERR_DIAGNOSTICS_HAVE_BEEN_TRUNCATED; extern int XFE_ERROR_CREATING_PIPE; extern int XFE_COULD_NOT_DUP_STDERR; extern int XFE_COULD_NOT_FDOPEN_STDERR; extern int XFE_COULD_NOT_DUP_A_NEW_STDERR; extern int XFE_COULD_NOT_DUP_A_STDOUT; extern int XFE_COULD_NOT_FDOPEN_THE_NEW_STDOUT; extern int XFE_COULD_NOT_DUP_A_NEW_STDOUT; extern int MK_UNABLE_TO_LOCATE_FILE; #ifdef MOZ_LDAP extern "C" void fe_ldapsearch_finished(MWContext *context); #endif #ifndef NO_WEB_FONTS /* Webfonts related routines defined in fonts.c */ extern "C" int fe_WebfontsNeedReload(MWContext *context); #endif /* NO_WEB_FONTS */ extern "C" char * _XmStringGetTextConcat(XmString); #if DEBUG_slamm_ #define D(x) x #else #define D(x) #endif // // // Setup redirection of stdout and stderr to a dialog // /* stderr hackery - Why Unix Sucks, reason number 32767. */ #include static char stderr_buffer [1024]; static char *stderr_tail = 0; static time_t stderr_last_read = 0; static XtIntervalId stderr_dialog_timer = 0; extern FILE *real_stderr; FILE *real_stdout = stdout; static void fe_stderr_dialog_timer (XtPointer /* closure */, XtIntervalId * /* id */) { char *s = fe_StringTrim (stderr_buffer); if (*s) { /* If too much data was printed, then something has gone haywire, so truncate it. */ char *trailer = XP_GetString(XFE_STDERR_DIAGNOSTICS_HAVE_BEEN_TRUNCATED); size_t max = sizeof (stderr_buffer)/sizeof(char) - strlen (trailer) - 5; if (XP_STRLEN (s) > max) XP_STRCPY (s + max, trailer); /* Now show the user. Possibly we should do something about not popping this up more often than every few seconds or something. */ fe_stderr (fe_all_MWContexts->context, s); } stderr_tail = stderr_buffer; stderr_dialog_timer = 0; } static void fe_stderr_callback (XtPointer /* closure */, int *fd, XtIntervalId * /* id */) { char *s; int left; int size; int read_this_time = 0; if (stderr_tail == 0) stderr_tail = stderr_buffer; left = ((sizeof (stderr_buffer) - 2) - (stderr_tail - stderr_buffer)); s = stderr_tail; *s = 0; /* Read as much data from the fd as we can, up to our buffer size. */ if (left > 0) { #if 1 while ((size = read (*fd, (void *) s, left)) > 0) { left -= size; s += size; read_this_time += size; } #else size = read (*fd, (void *) s, left); left -= size; s += size; read_this_time += size; #endif *s = 0; } else { char buf2 [1024]; /* The buffer is full; flush the rest of it. */ while (read (*fd, (void *) buf2, sizeof (buf2)) > 0) ; } stderr_tail = s; stderr_last_read = time ((time_t *) 0); /* Now we have read some data that we would like to put up in a dialog box. But more data may still be coming in - so don't pop up the dialog right now, but instead, start a timer that will pop it up a second from now. Should more data come in in the meantime, we will be called again, and will reset that timer again. So the dialog will only pop up when a second has elapsed with no new data being written to stderr. However, if the buffer is full (meaning lots of data has been written) then we don't reset the timer. */ if (read_this_time > 0) { if (stderr_dialog_timer) XtRemoveTimeOut (stderr_dialog_timer); stderr_dialog_timer = XtAppAddTimeOut (fe_XtAppContext, 1 * 1000, fe_stderr_dialog_timer, 0); } } static void fe_initialize_stderr (void) { static Boolean done = False; int fds [2]; int in, out; int new_stdout, new_stderr; int stdout_fd = 1; int stderr_fd = 2; int flags; if (done) return; real_stderr = stderr; real_stdout = stdout; #ifdef DEBUG // Don't use dialogs for stderr & stdout on debug builds. return; #else if (!fe_globalData.stderr_dialog_p && !fe_globalData.stdout_dialog_p) return; #endif done = True; if (pipe (fds)) { fe_perror (fe_all_MWContexts->context, XP_GetString( XFE_ERROR_CREATING_PIPE) ); return; } in = fds [0]; out = fds [1]; # ifdef O_NONBLOCK flags = O_NONBLOCK; # else # ifdef O_NDELAY flags = O_NDELAY; # else ERROR!! neither O_NONBLOCK nor O_NDELAY are defined. # endif # endif /* Set both sides of the pipe to nonblocking - this is so that our reads (in fe_stderr_callback) will terminate, and so that out writes (in net_ExtViewWrite) will silently fail when the pipe is full, instead of hosing the program. */ if (fcntl (in, F_SETFL, flags) != 0) { fe_perror (fe_all_MWContexts->context, "fcntl:"); return; } if (fcntl (out, F_SETFL, flags) != 0) { fe_perror (fe_all_MWContexts->context, "fcntl:"); return; } if (fe_globalData.stderr_dialog_p) { FILE *new_stderr_file; new_stderr = dup (stderr_fd); if (new_stderr < 0) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_DUP_STDERR)); return; } if (! (new_stderr_file = fdopen (new_stderr, "w"))) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_FDOPEN_STDERR)); return; } real_stderr = new_stderr_file; close (stderr_fd); if (dup2 (out, stderr_fd) < 0) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_DUP_A_NEW_STDERR)); return; } } if (fe_globalData.stdout_dialog_p) { FILE *new_stdout_file; new_stdout = dup (stdout_fd); if (new_stdout < 0) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_DUP_A_STDOUT)); return; } if (! (new_stdout_file = fdopen (new_stdout, "w"))) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_FDOPEN_THE_NEW_STDOUT)); return; } real_stdout = new_stdout_file; close (stdout_fd); if (dup2 (out, stdout_fd) < 0) { fe_perror (fe_all_MWContexts->context, XP_GetString(XFE_COULD_NOT_DUP_A_NEW_STDOUT)); return; } } XtAppAddInput (fe_XtAppContext, in, (XtPointer) (XtInputReadMask /* | XtInputExceptMask */), fe_stderr_callback, 0); } // Sanity check on the context. Throughout the progress stuff below, // the context (and fe_data) needs to be checked for validity before // dereferencing the members. #define CHECK_CONTEXT_AND_DATA(c) \ ((c) && CONTEXT_DATA(c) && !CONTEXT_DATA(context)->being_destroyed) #if defined(GLUE_COMPO_CONTEXT) // // Return either the context's component or the current active component // static XFE_Component * fe_compoFromMWContext(MWContext *context) { XFE_Component * compo = NULL; // Sanity check for possible invocation of this function from a compo // that was just destroyed (or is being destroyed) if (!CHECK_CONTEXT_AND_DATA(context)) { return NULL; } // Try to use context's frame compo = ViewGlue_getCompo(XP_GetNonGridContext(context)); // Make sure the frame is alive if (compo && !compo->isAlive()) { compo = NULL; } return compo; } #endif /* GLUE_COMPO_CONTEXT */ // // Return either the context's frame or the current active frame // XFE_Frame * fe_frameFromMWContext(MWContext *context) { XFE_Frame * frame = NULL; // Sanity check for possible invocation of this function from a frame // that was just destroyed (or is being destroyed) if (!CHECK_CONTEXT_AND_DATA(context)) { return NULL; } // Try to use context's frame frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); // Try to use the active frame // if (!frame) // { // frame = XFE_Frame::getActiveFrame(); // } // Make sure the frame is alive if (frame && !frame->isAlive()) { frame = NULL; } return frame; } extern "C" void FE_DestroyWindow(MWContext *context) { XFE_Frame *frame; if (!context) return; /* * Recursively destroy any dependent children first */ if (context->js_dependent_list) { MWContext *dependent; XP_List *list; list = context->js_dependent_list; /* NOTE: XP_ListNextObject is a macro which modifies 'list' */ for( dependent = (MWContext*)XP_ListNextObject(list); dependent; dependent = (MWContext*)XP_ListNextObject(list)) { dependent->js_parent = 0; /* prevents recursive call from invoking XP_ListRemoveObject */ FE_DestroyWindow(dependent); } /* * XP_ListDestroy does *not* free the objects on the list (Apr-97) * They are destroyed here by calls to FE_DestroyWindow() above. */ XP_ListDestroy(context->js_dependent_list); context->js_dependent_list = 0; } /* * This code is invoked when a dependent window is not being destroyed by * its parent. */ if (context->js_parent && context->js_parent->js_dependent_list) XP_ListRemoveObject(context->js_parent->js_dependent_list, context); /* * Now destroy the window */ frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); XP_ASSERT(frame); if (frame == NULL) return; frame->app_delete_response(); } extern "C" void XFE_EnableClicking(MWContext *context) { MWContext *top = XP_GetNonGridContext (context); XFE_Frame *f; XP_Bool running_p; // this is very evil but has been known to happen if (top == NULL) return; f = ViewGlue_getFrame(top); running_p = XP_IsContextBusy (top); D( printf("XFE_EnableClicking(context = 0x%x) running_p = %d\n", context, running_p); ) if (f && f->isAlive()) { f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdStopLoading); f->notifyInterested(running_p? XFE_Frame::frameBusyCallback: XFE_Frame::frameNotBusyCallback); } else { if (CONTEXT_DATA (top)->show_toolbar_p && CONTEXT_DATA (top)->toolbar) { if (CONTEXT_DATA (top)->abort_button) XtVaSetValues (CONTEXT_DATA (top)->abort_button, XmNsensitive, fe_IsContextStoppable(top), 0); } if (CONTEXT_DATA (top)->show_menubar_p && CONTEXT_DATA (top)->menubar) { if (CONTEXT_DATA (top)->abort_menuitem) XtVaSetValues (CONTEXT_DATA (top)->abort_menuitem, XmNsensitive, fe_IsContextStoppable(top), 0); } } if (! running_p) fe_StopProgressGraph (context); if (CONTEXT_DATA (context)->clicking_blocked) { CONTEXT_DATA (context)->clicking_blocked = False; /* #### set to link cursor if over link. */ fe_SetCursor (context, False); } } extern "C" void FE_UpdateStopState(MWContext *context) { MWContext *top = XP_GetNonGridContext (context); XFE_Frame *f; // this is very evil but has been known to happen if (top == NULL) return; f = ViewGlue_getFrame(top); if (f) { D( printf("FE_UpdateStopState(context = 0x%x)\n", context); ) f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdStopLoading); // Brendan says this should check for stoppable, not busyness...mcafee // But, I talked to him, and he agreed that I was right all along..djw // Save time: trust David. hee hee. Ok, here is the scoop. Because, // this call is made in FE_UpdateStopState(), which is really exists // to control the stop button, so you'd think all the stuff in here // should be using XP_IsContextStoppable(). Fair enough. The thing is // this call to the busy notification dependencies (notably the cursor), // has nothing to do with the stop button, etc. It's just that this // is a good salient point to update the cursor. So, calling // XP_IsContextBusy() is the right thing. Either that or take the whole // thing out, say "what was I trying", and get on with your // life. Hmmm, actually that sounds pretty good, cheers...djw f->notifyInterested(XP_IsContextBusy(context)? XFE_Frame::frameBusyCallback: XFE_Frame::frameNotBusyCallback); } else { if (context->type == MWContextPostScript) return; if (CONTEXT_DATA (top)->show_toolbar_p && CONTEXT_DATA (top)->toolbar) { if (CONTEXT_DATA (top)->abort_button) XtVaSetValues (CONTEXT_DATA (top)->abort_button, XmNsensitive, fe_IsContextStoppable(top), 0); } if (CONTEXT_DATA (top)->show_menubar_p && CONTEXT_DATA (top)->menubar) { if (CONTEXT_DATA (top)->abort_menuitem) XtVaSetValues (CONTEXT_DATA (top)->abort_menuitem, XmNsensitive, fe_IsContextStoppable(top), 0); } } } extern "C" void XFE_AllConnectionsComplete(MWContext *context) { MWContext *top = XP_GetNonGridContext (context); #if defined(GLUE_COMPO_CONTEXT) XFE_Component *f = 0; #else XFE_Frame *f; #endif /* GLUE_COMPO_CONTEXT */ // this is evil and vile but it's been known to happen if (top == NULL) return; #if defined(GLUE_COMPO_CONTEXT) f = ViewGlue_getCompo(top); #else f = ViewGlue_getFrame(top); #endif /* GLUE_COMPO_CONTEXT */ if (CONTEXT_DATA (context)->being_destroyed) return; D( printf("XFE_AllConnectionsComplete(context = 0x%x)\n",context); ) /* #### ARRGH, when generating PostScript, this assert gets tripped! I guess this is because of the goofy games it plays with invoking callbacks in the "other" context... assert (CONTEXT_DATA (context)->active_url_count == 0); */ /* If a title was never specified, clear the old one. */ if ((context->type != MWContextBookmarks) && (context->type != MWContextAddressBook) && (context->type != MWContextSearch) && (context->type != MWContextSearchLdap) && (CONTEXT_DATA (context)->active_url_count == 0) && (context->title == 0)) XFE_SetDocTitle (context, 0); /* This shouldn't be necessary, but it doesn't hurt. */ XFE_EnableClicking (context); fe_RefreshAllAnchors (); /* If either the user resized during layout or there was a webfont that was being downloaded while rendering the page, reload the document right now (it will come from the cache.) */ #ifndef NO_WEB_FONTS if (fe_WebfontsNeedReload(context)) { CONTEXT_DATA (context)->relayout_required = False; LO_InvalidateFontData(context); fe_ReLayout (context, NET_RESIZE_RELOAD); } else #endif /* NO_WEB_FONTS */ if (CONTEXT_DATA (context)->relayout_required) { if (! XP_IsContextBusy (context)) { CONTEXT_DATA (context)->relayout_required = False; /* As vidur suggested in Bug 59214: because JS generated content was not put into wysiwyg, hence this source was not be shown on a resize. The fix was to make the reload policy for Mail/News contexts NET_NORMAL_RELOAD. This would fix exceed server problem too. Exceed server sends redraw events on each resize movement */ if ( (context->type == MWContextNews) || (context->type == MWContextMail) || (context->type == MWContextNewsMsg) || (context->type == MWContextMailMsg) ) fe_ReLayout (context, NET_NORMAL_RELOAD); else fe_ReLayout (context, NET_RESIZE_RELOAD); } } else if (context->is_grid_cell && CONTEXT_DATA (top)->relayout_required) { if (! XP_IsContextBusy (top)) { CONTEXT_DATA (top)->relayout_required = False; /* As vidur suggested in Bug 59214: because JS generated content was not put into wysiwyg, hence this source was not be shown on a resize. The fix was to make the reload policy for Mail/News contexts NET_NORMAL_RELOAD. This would fix exceed server problem too. Exceed server sends redraw events on each resize movement */ if ( (context->type == MWContextNews) || (context->type == MWContextMail) || (context->type == MWContextNewsMsg) || (context->type == MWContextMailMsg) ) fe_ReLayout (top, NET_NORMAL_RELOAD); else fe_ReLayout (top, NET_RESIZE_RELOAD); } } else if((context->type != MWContextSearch) && (context->type != MWContextSearchLdap) ) { XFE_Progress (top, XP_GetString(XFE_DOCUMENT_DONE)); } if (f && f->isAlive()) // if (f && f->getBaseWidget() && f->getBaseWidget()->core.being_destroyed == False) { #if defined(GLUE_COMPO_CONTEXT) if (f->isClassOf("Frame")) ((XFE_Frame *) f)->allConnectionsComplete(context); else if (f->isClassOf("View")) ((XFE_View *) f)->allConnectionsComplete(context); #else f->allConnectionsComplete(context); #endif /* GLUE_COMPO_CONTEXT */ } else { #if 0 printf ("ConnectionsComplete: 0x%x; grid: %d; busy: %d, relayout: %d\n", context, context->is_grid_cell, XP_IsContextBusy (context), CONTEXT_DATA (context)->relayout_required); #endif if (context->type == MWContextSaveToDisk) /* gag gag gag */ fe_DestroySaveToDiskContext (context); } } /* Prompt the user for a string. If the user selects "Cancel", 0 is returned. Otherwise, a newly-allocated string is returned. A pointer to the prompt-string is not retained. */ extern "C" char * XFE_Prompt (MWContext *context, const char *message, const char *deflt) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) return f->prompt("prompt", message, deflt); else return (char *) fe_prompt (context, CONTEXT_WIDGET (context), "prompt", message, TRUE, (deflt ? deflt : ""), TRUE, FALSE, 0); } extern "C" char * XFE_PromptWithCaption(MWContext *context, const char *caption, const char *message, const char *deflt) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) return f->prompt(caption, message, deflt); else return (char *) fe_dialog(CONTEXT_WIDGET(context), caption, message, TRUE, (deflt ? deflt : ""), TRUE, FALSE, 0); } extern "C" char * FE_PromptMessageSubject (MWContext *context) { const char *def = XP_GetString( XFE_NO_SUBJECT ); XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) return f->prompt("promptSubject", 0, def); else return (char *) fe_dialog (CONTEXT_WIDGET (context), "promptSubject", 0, TRUE, def, TRUE, TRUE, 0); } // Some History functions that we need to implement here now. extern "C" int FE_EnableBackButton (MWContext *context) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdBack); return 0; } extern "C" int FE_DisableBackButton (MWContext *context) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdBack); return 0; } extern "C" int FE_EnableForwardButton (MWContext *context) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdForward); return 0; } extern "C" int FE_DisableForwardButton (MWContext *context) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdForward); return 0; } extern "C" void fe_MidTruncatedProgress(MWContext *context, const char *message) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) { if (message == 0 || *message == '\0') message = context->defaultStatus; f->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)message); } } extern "C" void fe_SetURLString (MWContext *context, URL_Struct *url) { XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (f) f->notifyInterested(XFE_HTMLView::newURLLoading, url); } typedef enum { Answer_Invalid = -1, Answer_Cancel = 0, Answer_OK, Answer_Apply, Answer_Destroy } Answers; struct fe_fileprompt_data { Answers answer; char *return_value; Boolean must_match; }; static void fe_fileprompt_finish_cb (Widget /*widget*/, XtPointer closure, XtPointer /*call_data*/) { struct fe_fileprompt_data *data = (struct fe_fileprompt_data *) closure; if (data->answer == Answer_Invalid) data->answer = Answer_Destroy; } static void fe_fileprompt_cb (Widget widget, XtPointer closure, XtPointer call_data) { fe_fileprompt_data *data = (fe_fileprompt_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); /* 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; } } data->answer = Answer_OK; break; } case XmCR_CANCEL: { data->answer = Answer_Cancel; data->return_value = 0; break; } default: abort (); } } extern "C" char* FE_GetTempFileFor(MWContext* /*context*/, const char* fname, XP_FileType ftype, XP_FileType* rettype) { char* actual = WH_FileName(fname, ftype); int len; char* result; if (!actual) return NULL; len = strlen(actual) + 10; result = (char*)XP_ALLOC(len); if (!result) return NULL; PR_snprintf(result, len, "%s-XXXXXX", actual); XP_FREE(actual); mktemp(result); *rettype = xpMailFolder; /* Ought to be harmless enough. */ return result; } /* * Status of filename prompting: * We have three routines, FE_PromptForFileName() here, and * fe_ReadFileName() and fe_ReadFileName_2() in dialogs.c. * FE_PromptForFileName() is the one called by the backend; * the other two are called at various points in the XFE. * fe_ReadFileName() immediately calls fe_ReadFileName_2(). * We need to integrate these three routines into one! * ...Akkana 10/20/97 */ extern "C" int FE_PromptForFileName (MWContext *context, const char *prompt_string, const char *default_path, XP_Bool file_must_exist_p, XP_Bool directories_allowed_p, ReadFileNameCallbackFunction fn, void *closure) { #if 0 // Note: this needs to be changed somehow to call fe_ReadFileName_2 ... char *file = fe_ReadFileName (context, prompt_string, default_path, file_must_exist_p, 0); if (!file) return -1; fn (context, file, closure); return 0; #endif Widget parent; Widget shell; Widget fileb; Visual *v = 0; Colormap cmap = 0; Cardinal depth = 0; char *text = 0; char *orig_text = 0; char buf[1024]; XmString xmpat = 0; XmString xmfile = 0; Arg av[20]; int ac; struct fe_fileprompt_data data; /* relative filename */ XmString dirMask; XP_Bool relative_filename = False; parent = CONTEXT_WIDGET(context); XtVaGetValues(parent, XtNvisual, &v, XtNcolormap, &cmap, XtNdepth, &depth, 0); if (default_path && *default_path) { StrAllocCopy(text, default_path); orig_text = text; } if (text && *text) text = XP_STRTOK(text, " "); if (!text || !*text) { xmpat = 0; xmfile = 0; } else if (directories_allowed_p) { if (text[XP_STRLEN(text) - 1] == '/') text[XP_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[XP_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 = XP_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 { relative_filename = True; } } 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++; shell = XmCreateDialogShell(parent, "fileBrowser_popup", av, ac); ac = 0; XtSetArg(av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++; XtSetArg(av[ac], XmNfileTypeMask, (directories_allowed_p ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++; fileb = fe_CreateFileSelectionBox(shell, "fileBrowser", av, ac); XtAddCallback (fileb, XmNokCallback, fe_fileprompt_cb, &data); XtAddCallback (fileb, XmNcancelCallback, fe_fileprompt_cb, &data); XtAddCallback (fileb, XmNdestroyCallback, fe_fileprompt_finish_cb, &data); if (prompt_string && *prompt_string) { XtVaSetValues(shell, XmNtitle, prompt_string, 0); } XtVaSetValues (fileb, XmNmustMatch, False, 0); if (xmpat && !relative_filename) { XtVaSetValues(fileb, XmNdirMask, xmpat, XmNpattern, xmpat, XmNdirSpec, xmfile, 0); XmStringFree(xmpat); XmStringFree(xmfile); } else if (text) { char *basename = XP_STRRCHR(text, '/'); int len = 0; if (!basename) { basename = text; len=XP_STRLEN(basename); }/* if */ else if ((len=XP_STRLEN(basename)) > 1) basename++; XmString xm_directory; XtVaGetValues(fileb, XmNdirectory, &xm_directory, 0); String dir_part = NULL; if (xm_directory != NULL) dir_part = _XmStringGetTextConcat(xm_directory); if (dir_part) { int dir_len = XP_STRLEN(dir_part); len += dir_len; if (dir_part[dir_len-1] != '/') len++; char *filename = (char *) XP_CALLOC(len+1, sizeof(char)); XP_STRCAT(filename, dir_part); if (dir_part[dir_len-1] != '/') XP_STRCAT(filename, "/"); if (basename) XP_STRCAT(filename, basename); xmfile = XmStringCreateLtoR(filename, XmFONTLIST_DEFAULT_TAG); }/* if */ XtVaGetValues (fileb, XmNdirMask, &dirMask, 0); XmFileSelectionDoSearch (fileb, dirMask); XtVaSetValues(fileb, XmNdirSpec, xmfile, 0); XmStringFree(xmfile); }/* else */ if (orig_text) free(orig_text); data.answer = Answer_Invalid; data.return_value = 0; data.must_match = file_must_exist_p; fe_HackDialogTranslations (fileb); fe_NukeBackingStore (fileb); fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON)); XtManageChild (fileb); /* check for destruction here */ loop: while (data.answer == Answer_Invalid) fe_EventLoop (); if (data.answer == Answer_OK) { // Check for invalid directory: char* dirname = XP_STRDUP(data.return_value); char* basename = XP_STRRCHR(dirname, '/'); DIR* dirp; if (basename != 0) { *basename = 0; dirp = opendir(dirname); if (dirp == 0) { char s[256]; sprintf(s, XP_GetString(MK_UNABLE_TO_LOCATE_FILE), dirname); FE_Alert(context, s); if (data.return_value) free(data.return_value); XP_FREE(dirname); data.answer = Answer_Invalid; goto loop; } closedir(dirp); XP_FREE(dirname); } if (data.return_value) { fn(context, data.return_value, closure); free(data.return_value); } } if (data.answer != Answer_Destroy) XtDestroyWidget(shell); return (data.answer== Answer_OK && data.return_value) ? 0 : -1; } extern "C" void FE_QueryChrome(MWContext * context, /* in */ Chrome * chrome) /* out */ /**> * * description: * Fill in a chrome structure, given a context. * * returns: * n/a. The chrome parameter is modified. * */ { XFE_Frame * frame; if (!chrome || !context || context->type != MWContextBrowser) return; frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (frame == NULL) return; frame->queryChrome(chrome); // if this is a grid cell, fix w_hint & h_hint if (context->is_grid_cell) { chrome->w_hint = (int32) CONTEXT_DATA (context)->scrolled_width; chrome->h_hint = (int32) CONTEXT_DATA (context)->scrolled_height; #ifdef DEBUG_spence printf ("QueryChrome: grid cell: w = %d, h = %d\n", chrome->w_hint, chrome->h_hint); #endif } } extern "C" void FE_UpdateChrome(MWContext *context, /* in */ Chrome *chrome) /* in */ /** * * description: * Update a frame based on the chrome. * * returns: * n/a * */ { XFE_Frame * frame; Widget w; if (!chrome || !context || context->type != MWContextBrowser) return; w = CONTEXT_WIDGET(context); if (!XtIsManaged(w)) XtManageChild(w); frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (frame == NULL) return; frame->respectChrome(chrome); } /* This used to be MOZ_MAIL_NEWS (MOZ_LITE actually) in the NOVA branch */ #ifdef MOZ_LDAP extern "C" void FE_RememberPopPassword (MWContext *context, const char *password) { // If we aren't supposed to remember don't save anything XP_Bool passwordProtectLocalCache; PREF_GetBoolPref("mail.password_protect_local_cache", &passwordProtectLocalCache); // Store password into preferences. StrAllocCopy (fe_globalPrefs.pop3_password, password); // If user has already requesting saving it, do that. if (fe_globalPrefs.rememberPswd || passwordProtectLocalCache) { if (!XFE_SavePrefs ((char *) fe_globalData.user_prefs_file, &fe_globalPrefs)) fe_perror (context, XP_GetString( XFE_ERROR_SAVING_PASSWORD ) ); } } #endif /* MOZ_LDAP */ extern "C" void FE_BackCommand(MWContext *context) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return; if (frame->handlesCommand(xfeCmdBack) && frame->isCommandEnabled(xfeCmdBack)) frame->doCommand(xfeCmdBack); } extern "C" void FE_ForwardCommand(MWContext *context) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return; if (frame->handlesCommand(xfeCmdForward) && frame->isCommandEnabled(xfeCmdForward)) frame->doCommand(xfeCmdForward); } extern "C" void FE_HomeCommand(MWContext *context) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return; if (frame->handlesCommand(xfeCmdHome) && frame->isCommandEnabled(xfeCmdHome)) frame->doCommand(xfeCmdHome); } extern "C" void FE_PrintCommand(MWContext *context) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return; if (frame->handlesCommand(xfeCmdPrint) && frame->isCommandEnabled(xfeCmdPrint)) frame->doCommand(xfeCmdPrint); } extern "C" void FE_OpenFileCommand(MWContext*context) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return; if (frame->handlesCommand(xfeCmdOpenPageChooseFile) && frame->isCommandEnabled(xfeCmdOpenPageChooseFile)) frame->doCommand(xfeCmdOpenPageChooseFile); } extern "C" uint32 FE_DiskSpaceAvailable (MWContext* /*context*/, const char* filename) { char curdir [MAXPATHLEN]; struct STATFS fs_buf; if (!filename || !*filename) { (void) getcwd (curdir, MAXPATHLEN); if (! curdir) return 1L << 30; /* hope for the best as we did in cheddar */ } else { PR_snprintf (curdir, MAXPATHLEN, "%.200s", filename); } if (STATFS (curdir, &fs_buf) < 0) { /* fe_perror (context, "Cannot stat current directory\n"); */ return 1L << 30; /* hope for the best as we did in cheddar */ } #ifdef DEBUG_DISK_SPACE printf ("DiskSpaceAvailable: %d bytes\n", fs_buf.f_bsize * (fs_buf.f_bavail - 1)); #endif return (fs_buf.f_bsize * (fs_buf.f_bavail - 1)); } /* * I found this function reporting the document's scroll offset, rather * than the window's location. In fixing it, I found that XGetGeometry() * didn't work--it always reported (0,0)--and any approach that would * work would necessarily involve a round-trip to the X server; so, * instead, I decided to cache the difference between (x_root,y_root) and * (x,y) in incoming events. The cachedPos is updated by * fe_CacheWindowOffset() (see xfe.h and xfe.c), which is called from * fe_stuff_event(), and should maybe be called from other places that * may receive button or motion events. * * It is possible for this information to get out of sync with reality. * If FE_GetWindowOffset() is called at a time when it's been a while * since some event that triggers fe_CacheWindowOffset(), then it may * be wrong. My hypothesis is that FE_GetWindowOffset() isn't called * in too many place (I discovered it was wrong in the context of fixing * JS events; but, in theory, JS events will be triggered by X events, * which should trigger fe_CacheWindowOffset() first). * * -- francis, 9 May 1997 */ extern "C" void FE_GetWindowOffset(MWContext *context, int32 *sx, int32 *sy) { (*sx)=CONTEXT_DATA(context)->cachedPos.x; (*sy)=CONTEXT_DATA(context)->cachedPos.y; } extern "C" void FE_GetScreenSize(MWContext *context, int32 *sx, int32 *sy) { XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (frame == NULL) return; *sx = WidthOfScreen(XtScreen(frame->getBaseWidget())); *sy = HeightOfScreen(XtScreen(frame->getBaseWidget())); } /******************************************************************* * */ extern "C" void FE_GetAvailScreenRect(MWContext *pContext, /* in */ int32 *sx, /* out */ int32 *sy, /* out */ int32 *left, /* out */ int32 *top) /* out */ /* * * description: * This function obtains the rectangular area of the screen available * for use by Mozilla & Co. * On Unix this is the entire screen (implemented here). * On Macintosh this is the screen less the area for the menubar. * On Win95 and Win NT 4.0 this is the screen less area occupied * by the taskbar. * * preconditions: * All arguments must be non-NULL * * returns: * Places the dimensions of the screen in sx, sy, left and top * ****************************************/ { *left = 0; *top = 0; FE_GetScreenSize(pContext, sx, sy); } /* * BUG 57147 June 1997 * * A fix for this bug was implemented which disturbs the existing * code as little as possible at the cost of being kludgy. It would * be nicer to rearchitect all of the find code, but we're too close * to shipping Communicator 4.0 now. * * For the curious, here is a description of what is going on. * * JAVASCRIPT FIND() COMMAND * In Navigator 3.0 days it was only possible to invoke find from the * user interface. One brought up the "find" dialog from a menu, after which * one could invoke the "find again" menu item. With * Communicator 4.0 it is now possible to invoke the find() function * from JavaScript, e.g. * find(); // bring up the find dialog box, aka interactive find * find("cat"); // search for "cat" with no dialog, aka non-interactive find * Another complication is that it must be possible from JavaScript * to invoke find on a named html frame. In the past it was assumed * that a find was to be performed on the frame with focus. With * Communicator 4.0 it must be possible to perform a find regardless * of whether or not a frame has focus. * * IMPLEMENTATION * fe_find_cb() is invoked whenever the user chooses the find menu item. * fe_find_again_cb() is invoked whenever the user chooses the find again * menu item. * FE_FindCommand() is invoked for all calls to JavaScript find(). * The lower level find functions fe_find_refresh_data() and fe_FindDialog() * which eventually get called from both the front end and FE_FindCommand() * use fe_findcommand_context() to determine if they are being called * by JavaScript or by the front end. A call to FE_FindCommand() ensures that * fe_findcommand_context() returns non-NULL. Calls to fe_find_cb() and * fe_find_again_cb() ensure that fe_find_command_context() returns NULL. * */ /* * Written to by FE_FindCommand() and fe_unset_findcommand_context() */ static MWContext * private_fe_findcommand_context = 0; /**************************************** * */ extern "C" MWContext * fe_findcommand_context() /* * returns: * NULL whenever a find is being performed after * fe_find_cb() and fe_find_again_cb() have been called. * This means that these callback functions call * fe_unset_findcommand_context(). Lower level find * functions such as fe_find_refresh_data() and fe_FindDialog() * determine the context which currently has focus to do the find. * * non-NULL whenever a find is being performed as a result * of FE_FindCommand(). Lower level find functions should * use this context for the find. * ****************************************/ { return private_fe_findcommand_context; } /**************************************** * */ extern "C" void fe_unset_findcommand_context() /* * description: * Called by fe_find_cb() and fe_find_again_cb() * so that lower level functions do the same thing * as they did in the past when find and find again * menu items are chosen. * ****************************************/ { private_fe_findcommand_context = 0; } /**************************************** * */ extern "C" XP_Bool FE_FindCommand(MWContext *context, /* in MOD: can this be mail or news? */ char * search_string, /* in: NULL brings up dialog */ XP_Bool b_is_case_sensitive, /* in */ XP_Bool b_search_backwards, /* in */ XP_Bool /* b_wrap */) /* ignored */ /* * description: * Implemented to support the JavaScript * find() function for Communicator 4.0. * * The portion of this function which executes non-interactive * searches endeavors to reproduce the relevant portions of * the code which would be executed by calling * frame->doCommand(xfeCmdFindAgain) without creating the find * dialog box widgets. * * side effects: * The fe_FindData member of the relevant context will be * allocated if it doesn't already exist. * * returns: * If search_string is NULL, always returns FALSE * otherwise returns TRUE or FALSE depending on whether or not * the string was found. * * comments: * No meaningful return value is currently (Apr-97) possible * when a dialog is brought up because the function immediately * returns without waiting for the user to perform a find. * Note that the user may cancel or do any number of searches * before closing the dialog. * ****************************************/ { XP_Bool result = FALSE; XFE_Frame * frame; CL_Layer * layer; frame = ViewGlue_getFrame(XP_GetNonGridContext(context)); if (!frame) return result; private_fe_findcommand_context = context; /* * * BRING UP FIND DIALOG AKA FIND IN OBJECT * * if no search string is specified, * bring up a find dialog aka "find in object" * and return FALSE */ if (!search_string) { if (frame->handlesCommand(xfeCmdFindInObject) && frame->isCommandEnabled(xfeCmdFindInObject)) { /* code adapted from commands.c:fe_find_cb */ MWContext * top_context; top_context = XP_GetNonGridContext(context); if (!top_context) top_context = context; fe_UserActivity (top_context); fe_FindDialog(top_context, False); } } /* * NON-INTERACTIVE SEARCH AKA FIND AGAIN * * If a search string is given, do a non-interactive * search. */ else { MWContext * context_to_find; XFE_View * view; fe_FindData * find_data; int size; XP_Bool b_allocated_locally = FALSE; /* * Get the appropriate context for the search. * This mimics what would be done in the function call stack * for frame->doCommand(xfeCmdFindAgain). */ context_to_find = fe_findcommand_context(); if (!context_to_find) { view = frame->getView(); context_to_find = view->getContext(); } /* ensure that an fe_FindData structure exists */ find_data = CONTEXT_DATA(context_to_find)->find_data; if (!find_data) { /* * This section is modeled after fe_FindDialog() in dialogs.c */ find_data = (fe_FindData *)XP_NEW_ZAP(fe_FindData); /* alloc and zero */ b_allocated_locally = TRUE; CONTEXT_DATA(context_to_find)->find_data = find_data; find_data->context = context_to_find; find_data->find_in_headers = False; /* Q: as of this writing no support for mail/news headers? */ } /* check that contexts point to eachother */ XP_ASSERT(find_data->context == context_to_find); /* * Set the search parameters */ if (find_data->string) XP_FREE(find_data->string); size = XP_STRLEN(search_string) + 1; find_data->string = (char*)XP_ALLOC(size); XP_STRCPY(find_data->string, search_string); find_data->case_sensitive_p = b_is_case_sensitive; find_data->backward_p = b_search_backwards; /* * This section modeled after fe_find() in dialogs.c */ /* Q: what of ifdef EDITOR as in fe_find()? */ LO_GetSelectionEndpoints(context_to_find, &find_data->start_element, &find_data->end_element, &find_data->start_pos, &find_data->end_pos, &layer); result = LO_FindText(context_to_find, find_data->string, &find_data->start_element, &find_data->start_pos, &find_data->end_element, &find_data->end_pos, find_data->case_sensitive_p, !find_data->backward_p); if (result) { /* * This section is an exact cut and paste from fe_find(). Ugh! */ int32 x,y; LO_SelectText (context_to_find, find_data->start_element, find_data->start_pos, find_data->end_element, find_data->end_pos, &x, &y); /* If the found item is not visible on the screen, scroll to it. If we need to scroll, attempt to position the destination coordinate in the middle of the window. */ if (x >= CONTEXT_DATA (context_to_find)->document_x && x <= (CONTEXT_DATA (context_to_find)->document_x + CONTEXT_DATA (context_to_find)->scrolled_width)) x = CONTEXT_DATA (context_to_find)->document_x; else x = x - (CONTEXT_DATA (context_to_find)->scrolled_width / 2); if (y >= CONTEXT_DATA (context_to_find)->document_y && y <= (CONTEXT_DATA (context_to_find)->document_y + CONTEXT_DATA (context_to_find)->scrolled_height)) y = CONTEXT_DATA (context_to_find)->document_y; else y = y - (CONTEXT_DATA (context_to_find)->scrolled_height / 2); if (x + CONTEXT_DATA (context_to_find)->scrolled_width > CONTEXT_DATA (context_to_find)->document_width) x = (CONTEXT_DATA (context_to_find)->document_width - CONTEXT_DATA (context_to_find)->scrolled_width); if (y + CONTEXT_DATA (context_to_find)->scrolled_height > CONTEXT_DATA (context_to_find)->document_height) y = (CONTEXT_DATA (context_to_find)->document_height - CONTEXT_DATA (context_to_find)->scrolled_height); if (x < 0) x = 0; if (y < 0) y = 0; fe_ScrollTo (context_to_find, x, y); } /* * clean up after ourselves so that the widget text * field doesn't get confused during a subsequent * find dialog. */ if (b_allocated_locally) { if (find_data->string) XP_FREE(find_data->string); XP_FREE(find_data); CONTEXT_DATA(context_to_find)->find_data = 0; } } return result; } extern "C" void FE_GetPixelAndColorDepth(MWContext *pContext, /* input parameter */ int32 *pixelDepth, /* output parameter */ int32 *colorDepth) /* output parameter */ /* * description: * Determine pixel depth and color depth. * Pixel depth is the number of bits per pixel. * Color depth is the number of color palette entries * expressed as a power of two. E.g. the color depth is 8 * for a palette with 256 colors. In general the color depth * is greater than or the same as the pixel depth. * * preconditions: * All arguments must be non-NULL. * * returns: * Return values are placed in pixelDepth and colorDepth * */ { XFE_DisplayFactory * factory; XFE_Frame * frame; fe_colormap * colormap; if (!pContext || !pixelDepth || !colorDepth) return; factory = XFE_DisplayFactory::theFactory(); frame = ViewGlue_getFrame(XP_GetNonGridContext(pContext)); if (!factory || !frame) return; colormap = frame->getColormap(); if (!colormap) return; *pixelDepth = factory->getVisualDepth(); *colorDepth = fe_ColorDepth(colormap); } Boolean fe_IsPageLoaded (MWContext *context) { int i = 1; MWContext * child; if (context == NULL) return FALSE; if (NET_AreThereActiveConnectionsForWindow(context)) return FALSE; if (context->mocha_context && JS_IsRunning(context->mocha_context)) return FALSE; while ((child = (MWContext*)XP_ListGetObjectNum (context->grid_children, i++))) if (!fe_IsPageLoaded(child)) return FALSE; return TRUE; } MWContext * xfe2_MakeNewWindow(Widget toplevel, MWContext *context_to_copy, URL_Struct *url, char *window_name, MWContextType type, Boolean /* skip_get_url */, Chrome *decor) { XFE_Frame *parent_frame = context_to_copy ? ViewGlue_getFrame(context_to_copy) : 0; // XP_ASSERT(parent_frame); MWContext *new_context = 0; switch (type) { case MWContextSaveToDisk: { new_context = fe_showDownloadWindow(toplevel, parent_frame); break; } case MWContextBrowser: { new_context = fe_showBrowser(toplevel, parent_frame, decor, url); break; } case MWContextDialog: { new_context = fe_showHTMLDialog(toplevel, parent_frame, decor); break; } #ifdef EDITOR case MWContextEditor: { new_context = fe_showEditor(toplevel, parent_frame, decor, url); break; } #endif #ifdef MOZ_MAIL_NEWS case MWContextMail: case MWContextNews: // shouldn't happen anymore... { MSG_PaneType paneType = url ? MSG_PaneTypeForURL(url->address) : MSG_FOLDERPANE; switch (paneType) { case MSG_FOLDERPANE: { new_context = fe_showFolders(toplevel, parent_frame, decor); break; } case MSG_THREADPANE: { MSG_FolderInfo *folder = MSG_GetFolderInfoFromURL(fe_getMNMaster(), url->address, FALSE); if (folder) new_context = fe_showMessages(toplevel, parent_frame, decor, folder, fe_globalPrefs.reuse_thread_window, FALSE, MSG_MESSAGEKEYNONE); break; } case MSG_MESSAGEPANE: { MSG_FolderInfo *folder = MSG_GetFolderInfoFromURL(fe_getMNMaster(), url->address, TRUE); MSG_MessageLine msgLine; MessageKey key = MSG_MESSAGEKEYNONE; if (MSG_GetMessageLineForURL(fe_getMNMaster(), url->address, &msgLine) >= 0) key = msgLine.messageKey; if (folder != NULL && key != MSG_MESSAGEKEYNONE) { new_context = fe_showMsg(toplevel, parent_frame, decor, folder, key, FALSE); } else { /* let's try and be generous here, since we really *should* pop up a window in this case.*/ XFE_MsgFrame *frame = new XFE_MsgFrame(toplevel, parent_frame, decor); frame->show(); new_context = frame->getContext(); FE_GetURL(new_context, url); } break; } default: // XP_ASSERT(0); #ifdef DEBUG_spence printf ("unknown paneType\n"); #endif break; } } break; case MWContextSearch: { #ifdef DEBUG_dora printf("[Warning]Want to create a search in fe_MakeNewWidget...\n"); #endif /* This should not be called here anymore in the new xfe2 design We may consider remove this line all together.... Do we allow remote stuff to kick off the search without Mail even being invoked?! If not, definitely remove this part here */ new_context = fe_showSearch(toplevel, parent_frame, decor); break; } case MWContextSearchLdap: { #ifdef DEBUG_dora printf("[Warning]Want to create a ldap search in fe_MakeNewWidget...\n"); #endif /* This should not be called here anymore in the new xfe2 design We may consider remove this line all together.... Do we allow remote stuff to kick off the search without Mail even being invoked?! If not, definitely remove this part here */ new_context = fe_showLdapSearch(toplevel, parent_frame, decor); break; } case MWContextMessageComposition: { MSG_Pane *pane; #ifdef DEBUG_dora printf("Calling fe_MakeNewWindow for MWContextMessageComposition\n" ); #endif pane = fe_showCompose(toplevel, decor, context_to_copy, NULL, NULL, False, False); if (pane) new_context = MSG_GetContext(pane); break; } case MWContextAddressBook: { new_context = fe_showAddrBook (toplevel, NULL, decor); break; } #endif // MOZ_MAIL_NEWS default: XP_ASSERT(0); break; } // setup the stderr dialog stuff fe_initialize_stderr (); if (new_context && window_name) new_context->name = strdup (window_name); return new_context; } /**************************************** */ XP_Bool FE_IsNetcasterInstalled(void) /* * description: * * * returns: * TRUE or FALSE * ****************************************/ { return fe_IsNetcasterInstalled(); } /**************************************** */ void FE_RunNetcaster(MWContext * /* context */) /* * description: * The implementation is expected to * be platform-specific, therefore the * code goes here. * ****************************************/ { fe_showNetcaster(FE_GetToplevelWidget()); } #ifdef IRIX /**************************************** * * SGI-specific debugging hack to workaround broken * interaction between NSPR and dbx/cvd. * * When you hit a breakpoint in dbx, type: * "ccall fe_sgiStop()" * * dbx step and next commands will now work as expected * instead of hanging or dumping you in sigtramp() * * After you finish debugging, return to normal thread * operation by typing: * "ccall fe_sgiStart() * * (It's not clear what will go wrong if you fail to restart * SIGALRM processing.) *****************************************/ #include extern "C" void fe_sgiStart() { sigset_t t; sigaddset(&t,SIGALRM); sigprocmask(SIG_UNBLOCK,&t,NULL); } extern "C" void fe_sgiStop() { sigset_t t; sigaddset(&t,SIGALRM); sigprocmask(SIG_BLOCK,&t,NULL); } #endif #if 0 //#if defined(GLUE_COMPO_CONTEXT) ////////////////////////////////////////////////////////////////////////// // // Progress functions. XFE_Component versions // ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyLogoStopAnimation (MWContext *); static void fe_compoNotifyLogoStartAnimation (MWContext *); static void fe_compoNotifyProgressUpdateText (MWContext *,char *); static void fe_compoNotifyProgressUpdatePercent (MWContext *,int); static void fe_compoNotifyProgressTickCylon (MWContext *); static void fe_compoNotifyStatusUpdateText (MWContext *,char *); ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyLogoStartAnimation(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } CONTEXT_DATA(context)->logo_animation_running = True; // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } // Notify the compo to start animating the logo compo->notifyInterested(XFE_Component::logoStartAnimation,(void *) NULL); } ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyLogoStopAnimation(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } CONTEXT_DATA(context)->logo_animation_running = False; // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } // Notify the compo to stop animating the logo compo->notifyInterested(XFE_Component::logoStopAnimation,(void *) NULL); } ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyProgressUpdateText(MWContext * context,char * text) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } // Notify the compo to update the progress text compo->notifyInterested(XFE_Component::progressBarUpdateText,(void *) text); } ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyProgressUpdatePercent(MWContext * context,int percent) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } // Notify the compo to update the progress percent compo->notifyInterested(XFE_Component::progressBarUpdatePercent, (void *) percent); } ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyProgressTickCylon(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } // Notify the compo to tick cyclone mode compo->notifyInterested(XFE_Component::progressBarCylonTick); } ////////////////////////////////////////////////////////////////////////// static void fe_compoNotifyStatusUpdateText(MWContext * context,char * text) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } // Try to get the xfe compo for the context XFE_Component * compo = fe_compoFromMWContext(context); // There will be no compo for biff context so we ignore them if (!compo) { return; } char * message = text; if (message == 0 || *message == '\0') { message = context->defaultStatus; } // Notify the compo to update the status text compo->notifyInterested(XFE_View::statusNeedsUpdating,(void*) message); } #endif /* GLUE_COMPO_CONTEXT */ ////////////////////////////////////////////////////////////////////////// // // Progress functions. Used to live in xfe/thermo.c // ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyLogoStopAnimation (MWContext *); static void fe_frameNotifyLogoStartAnimation (MWContext *); static void fe_frameNotifyProgressUpdateText (MWContext *,char *); static void fe_frameNotifyProgressUpdatePercent (MWContext *,int); static void fe_frameNotifyProgressTickCylon (MWContext *); static void fe_frameNotifyStatusUpdateText (MWContext *,char *); ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyLogoStartAnimation(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } CONTEXT_DATA(context)->logo_animation_running = True; #if defined(GLUE_COMPO_CONTEXT) // Try to get the xfe compo for the context XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; // Notify the frame to start animating the logo compo->notifyInterested(XFE_Component::logoStartAnimation, (void *) NULL); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Notify the frame to start animating the logo frame->notifyInterested(XFE_Frame::logoStartAnimation,(void *) NULL); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyLogoStopAnimation(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } CONTEXT_DATA(context)->logo_animation_running = False; #if defined(GLUE_COMPO_CONTEXT) // Try to get the xfe compo for the context XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; // Notify the compo to stop animating the logo compo->notifyInterested(XFE_Component::logoStopAnimation, (void *) NULL); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Notify the frame to stop animating the logo frame->notifyInterested(XFE_Frame::logoStopAnimation,(void *) NULL); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyProgressUpdateText(MWContext * context,char * text) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } #if defined(GLUE_COMPO_CONTEXT) XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; compo->notifyInterested(XFE_Component::progressBarUpdateText, (void *) text); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Notify the frame to update the progress text frame->notifyInterested(XFE_Frame::progressBarUpdateText,(void *) text); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyProgressUpdatePercent(MWContext * context,int percent) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } #if defined(GLUE_COMPO_CONTEXT) XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; compo->notifyInterested(XFE_Component::progressBarUpdatePercent, (void *) percent); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Notify the frame to update the progress percent frame->notifyInterested(XFE_Frame::progressBarUpdatePercent, (void *) percent); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyProgressTickCylon(MWContext * context) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } #if defined(GLUE_COMPO_CONTEXT) XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; compo->notifyInterested(XFE_Component::progressBarCylonTick); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Notify the frame to tick cyclone mode frame->notifyInterested(XFE_Frame::progressBarCylonTick); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// static void fe_frameNotifyStatusUpdateText(MWContext * context,char * text) { XP_ASSERT( context != NULL ); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } #if defined(GLUE_COMPO_CONTEXT) XFE_Component *compo = fe_compoFromMWContext(context); if (!compo) return; char * message = text; if (message == 0 || *message == '\0') { message = context->defaultStatus; } compo->notifyInterested(XFE_View::statusNeedsUpdating,(void*) message); #else // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(context); // There will be no frame for biff context so we ignore them if (!frame) { return; } char * message = text; if (message == 0 || *message == '\0') { message = context->defaultStatus; } // Notify the frame to update the status text frame->notifyInterested(XFE_View::statusNeedsUpdating,(void*) message); #endif /* GLUE_COMPO_CONTEXT */ } ////////////////////////////////////////////////////////////////////////// /* Print a status message in the wholine. A pointer to the string is not retained. */ ////////////////////////////////////////////////////////////////////////// extern "C" void XFE_Progress(MWContext * context, const char * message) { #ifdef DEBUG_PROGRESS printf("XFE_Progress(%s)\n",message ? message : "BLANK"); #endif fe_frameNotifyStatusUpdateText(context,(char *) message); } ////////////////////////////////////////////////////////////////////////// /* This is so that we (attempt) to update the display at least once a second, even if the network library isn't calling us (as when the remote host is being slow.) */ static void fe_progress_dialog_timer (XtPointer closure, XtIntervalId * /* id */) { MWContext *context = (MWContext *) closure; if (!CHECK_CONTEXT_AND_DATA(context)) { return; } fe_UpdateGraph (context, True); /* If we don't know the total length (meaning cylon-mode) update every 1/10th second to make the slider buzz along. Otherwise, if we know the length, only update every 1/2 second. */ CONTEXT_DATA (context)->thermo_timer_id = XtAppAddTimeOut (fe_XtAppContext, (CONTEXT_DATA (context)->thermo_lo_percent <= 0 ? 100 : 500), fe_progress_dialog_timer, closure); } /* Start blinking the light and drawing the thermometer. This is done before the first call to FE_GraphProgressInit() to make sure that we indicate that we are busy before the first connection has been established. */ extern "C" void fe_StartProgressGraph(MWContext * context) { #ifdef DEBUG_PROGRESS printf("fe_StartProgressGraph()\n"); #endif if (!CHECK_CONTEXT_AND_DATA(context)) { return; } fe_frameNotifyLogoStartAnimation(context); time_t now = time ((time_t *) 0); CONTEXT_DATA (context)->thermo_start_time = now; CONTEXT_DATA (context)->thermo_last_update_time = now; CONTEXT_DATA (context)->thermo_data_start_time = 0; CONTEXT_DATA (context)->thermo_size_unknown_count = 0; CONTEXT_DATA (context)->thermo_total = 0; CONTEXT_DATA (context)->thermo_current = 0; CONTEXT_DATA (context)->thermo_lo_percent = 0; if (!CONTEXT_DATA (context)->thermo_timer_id) { fe_progress_dialog_timer ((XtPointer)context, 0); } } /* Shut off the progress graph and blinking light completely. */ extern "C" void fe_StopProgressGraph(MWContext * context_in) { #ifdef DEBUG_PROGRESS printf("fe_StopProgressGraph()\n"); #endif MWContext * context = XP_GetNonGridContext(context_in); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } if (context == NULL) return; // Stop animating the logo fe_frameNotifyLogoStopAnimation(context); // Clear the progress bar fe_frameNotifyProgressUpdatePercent(context,0); fe_frameNotifyProgressUpdateText(context,""); if (CONTEXT_DATA (context)->thermo_timer_id) { XtRemoveTimeOut (CONTEXT_DATA (context)->thermo_timer_id); CONTEXT_DATA (context)->thermo_timer_id = 0; } /* Kludge to go out of "cylon mode" when we actually reach the end. */ if (CONTEXT_DATA (context)->thermo_size_unknown_count > 0) { int size_guess = (CONTEXT_DATA (context)->thermo_total > CONTEXT_DATA (context)->thermo_current ? CONTEXT_DATA (context)->thermo_total : CONTEXT_DATA (context)->thermo_current); CONTEXT_DATA (context)->thermo_size_unknown_count = 0; CONTEXT_DATA (context)->thermo_total = size_guess; CONTEXT_DATA (context)->thermo_current = size_guess; } /* Get the 100% message. */ fe_UpdateGraph (context, True); /* Now clear the thermometer while not disturbing the text. */ CONTEXT_DATA (context)->thermo_lo_percent = 0; fe_UpdateGraph (context, False); } /* Redraw the graph. If text_too_p, then regenerate the textual message and/or move the cylon one tick if appropriate. (We don't want to do this every time FE_GraphProgress() is called, just once a second or so.) */ extern "C" void fe_UpdateGraph(MWContext * context,Boolean text_too_p) { double ratio_done; time_t now; int total_bytes, bytes_received; Boolean size_known_p; if (!CHECK_CONTEXT_AND_DATA(context)) { return; } now = time ((time_t *) 0); total_bytes = CONTEXT_DATA (context)->thermo_total; bytes_received = CONTEXT_DATA (context)->thermo_current; size_known_p = CONTEXT_DATA (context)->thermo_size_unknown_count <= 0; if (size_known_p && total_bytes > 0 && bytes_received > total_bytes) { #if 0 /* Netlib doesn't take into account the size of the headers, so this can actually go a bit over 100% (not by much, though.) Prevent the user from seeing this bug... But DO print a warning if we're way, way over the limit - more than 1k probably means the server is messed up. */ if (bytes_received > total_bytes + 1024) fprintf (stderr, "%s: received %d bytes but only expected %d??\n", fe_progname, bytes_received, total_bytes); #endif bytes_received = total_bytes; } ratio_done = (size_known_p && total_bytes > 0 ? (((double) bytes_received) / ((double) total_bytes)) : 0); #ifdef DEBUG_PROGRESS printf(" fe_UpdateGraph: %d/%d=%f (%d/%d) %s -or- %d%%\n", bytes_received, total_bytes, ratio_done, CONTEXT_DATA (context)->thermo_size_unknown_count, CONTEXT_DATA (context)->active_url_count, text_too_p ? "text" : "notext", CONTEXT_DATA (context)->thermo_lo_percent); #endif /* Update the thermo each time we're called. */ if (CONTEXT_DATA (context)->thermo_lo_percent >= 0) { int percent = CONTEXT_DATA(context)->thermo_lo_percent; // Update the progress percent fe_frameNotifyProgressUpdatePercent(context,percent); } else { fe_frameNotifyProgressTickCylon(context); } /* Only update text if a second or more has elapsed since last time. Unlike the cylon, which we update each time we are called with text_too_p == True (which is 4x a second or so.) */ if (text_too_p && now >= (CONTEXT_DATA (context)->thermo_last_update_time + CONTEXT_DATA (context)->progress_interval)) { const char *msg = XP_ProgressText ((size_known_p ? total_bytes : 0), bytes_received, CONTEXT_DATA (context)->thermo_start_time, now); CONTEXT_DATA (context)->thermo_last_update_time = now; if (msg && *msg) XFE_Progress (context, msg); #ifdef DEBUG_PROGRESS fprintf (stderr, "====== %s\n", (msg ? msg : "")); #endif } } /* Inform the user that a document is being transferred. URL is the url to which this report relates; bytes_received is how many bytes have been read; content_length is how large this document is (0 if unknown.) This is called from netlib as soon as we know the content length (or know that we don't know.) It is called only once per document. */ extern "C" void XFE_GraphProgressInit(MWContext * context_in, URL_Struct * /* url_struct */, int32 content_length) { #ifdef DEBUG_PROGRESS printf("XFE_GraphProgressInit(%ld)\n",content_length); #endif MWContext * context = XP_GetNonGridContext(context_in); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } if (!CONTEXT_DATA(context)->thermo_timer_id) { /* Hey! How did that get turned off? Turn it back on. */ fe_StartProgressGraph (context); } if (content_length == 0) { CONTEXT_DATA(context)->thermo_size_unknown_count++; } else { CONTEXT_DATA(context)->thermo_total += content_length; } } /* Remove --one-- transfer from the progress graph. */ extern "C" void XFE_GraphProgressDestroy(MWContext * context_in, URL_Struct * /* url */, int32 content_length, int32 total_bytes_read) { #ifdef DEBUG_PROGRESS printf("XFE_GraphProgressDestroy(%ld, %ld)\n", content_length, total_bytes_read); #endif MWContext * context = XP_GetNonGridContext(context_in); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } if (content_length == 0) { /* Now that this transfer is done, we finally know how big it was. This means that maybe we can go out of cylon mode and back into thermometer mode. */ CONTEXT_DATA (context)->thermo_size_unknown_count--; CONTEXT_DATA (context)->thermo_total += total_bytes_read; } } /* Inform the user of current progress, somehow. URL is the url to which this report relates; bytes_received is how many bytes have been read; content_length is how large this document is (0 if unknown.) This is called from netlib, and may be called very frequently. */ extern "C" void XFE_GraphProgress(MWContext * context_in, URL_Struct * /* url_struct */, int32 /* bytes_received */, int32 bytes_since_last_time, int32 /* content_length */) { #ifdef DEBUG_PROGRESS printf("XFE_GraphProgress(%ld, +%ld, %ld)\n", bytes_received, bytes_since_last_time, content_length); #endif MWContext * context = XP_GetNonGridContext(context_in); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } if (CONTEXT_DATA (context)->thermo_data_start_time <= 0) /* This is the first chunk of bits to arrive. */ CONTEXT_DATA (context)->thermo_data_start_time = time ((time_t *) 0); CONTEXT_DATA (context)->thermo_current += bytes_since_last_time; fe_UpdateGraph (context, False); } ////////////////////////////////////////////////////////////////////////// extern "C" void XFE_SetProgressBarPercent(MWContext * context_in,int32 percent) { #ifdef DEBUG_PROGRESS printf("XFE_SetProgressBarPercent(%d)\n",percent); #endif MWContext * context = XP_GetNonGridContext(context_in); if (!CHECK_CONTEXT_AND_DATA(context)) { return; } #ifndef LOU_OR_ERIC_REMOVED_EXPLICIT_CALL_TO_XFE_SETPROGRESSBAR_FROM_LAYOUT // Called during layout for print, do nothing if (CONTEXT_DATA(context) == NULL) { return; } #endif #ifdef EDITOR if (context->is_editor) { /* the editor tells us 100% when it means 0 */ if (percent == 100) { percent = 0; } } #endif /* EDITOR */ // Update the progress percent fe_frameNotifyProgressUpdatePercent(context,percent); // Clear the progress bar text for percent < 0 if (percent < 0) { fe_frameNotifyProgressUpdateText(context,""); } else { if (percent > 100) { percent = 100; } char text[32]; XP_SPRINTF(text,"%d%%",percent); // Update the progress text fe_frameNotifyProgressUpdateText(context,text); } CONTEXT_DATA(context)->thermo_lo_percent = percent; fe_UpdateGraph (context, True); // fe_UpdateGraph (context, False); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // fe_NeutralizeFocus() // // Move focus out of "Location:" and back to top-level. // Unfortunately, just focusing on the top-level doesn't do it - that // assigns focus to its first child, which may be the URL text field, // which is exactly what we're trying to avoid. So, first try assigning // focus to a few other components if they exist. Only try to assign focus // to the top level as a last resort. // ////////////////////////////////////////////////////////////////////////// extern "C" void fe_NeutralizeFocus(MWContext * context) { MWContext * top_context = XP_GetNonGridContext(context); XP_ASSERT( top_context != NULL ); // Try to get the xfe frame for the context XFE_Frame * frame = fe_frameFromMWContext(top_context); // There will be no frame for biff context so we ignore them if (!frame) { return; } // Try the logo XFE_Logo * logo = frame->getLogo(); if (logo && logo->processTraversal(XmTRAVERSE_CURRENT)) { return; } // Try the dash board XFE_Dashboard * dash = frame->getDashboard(); if (dash && dash->processTraversal(XmTRAVERSE_CURRENT)) { return; } // Finally, try the top level widget XmProcessTraversal(CONTEXT_WIDGET(top_context),XmTRAVERSE_CURRENT); } ////////////////////////////////////////////////////////////////////////// extern "C" MWContext *FE_GetRDFContext(void) { MWContext *context = NULL; /* if(theApp.m_pRDFCX) { pRetval = theApp.m_pRDFCX->GetContext(); } */ return(fe_getBookmarkContext()); } /* this is here so that we can get access to frame/component utilities like fe_frameFromMWContext()... */ #ifdef SHACK extern "C" Widget fe_showRDFView (Widget parent, int width, int height) { MWContext *context = fe_WidgetToMWContext (parent); XFE_Component *toplevel = fe_frameFromMWContext (context); XFE_View *view = new XFE_NavCenterView (toplevel, parent, NULL, context); #ifdef DEBUG_spence printf ("fe_showRDFView\n"); #endif if (view == NULL) { #ifdef DEBUG_spence printf ("fe_showRDFView: view creation failed\n"); #endif return NULL; } #ifdef DEBUG_spence printf ("fe_showRDFView: width %d: height %d\n", width, height); #endif XtVaSetValues (view->getBaseWidget(), XmNwidth, width, XmNheight, height, 0); XtRealizeWidget (parent); return (view->getBaseWidget()); } #endif /* SHACK */