home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / context_funcs.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  70.3 KB  |  2,564 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    context_funcs.cpp --- Functions the backend invokes from the 
  20.                          MWContext->funcs vtable
  21.  */
  22.  
  23.  
  24. #include "il_types.h"
  25. #include "layers.h"
  26. #include "jsapi.h"
  27. #include "MozillaApp.h"
  28. #include "Frame.h"
  29. #include "ViewGlue.h"
  30. #include "View.h"
  31. #include "HTMLView.h"
  32. #include <Xm/XmP.h>
  33.  
  34. #ifdef MOZ_MAIL_NEWS
  35. #include "MsgFrame.h"
  36. #include "addrbk.h"
  37. #include "dirprefs.h"
  38. #endif
  39.  
  40. #include "DisplayFactory.h"
  41. #include "Logo.h"
  42. #include "Dashboard.h"
  43. #include "mozilla.h"
  44. #include "xfe.h"
  45. #include "xp_thrmo.h"
  46. #include "fe_proto.h"
  47.  
  48. #include "xfe2_extern.h"
  49.  
  50. #include "Netcaster.h"
  51. #include "NavCenterView.h"
  52.  
  53. #include "xpgetstr.h"
  54.  
  55. #if defined(IRIX) || defined(OSF1) || defined(SOLARIS) || defined(SCO_SV) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC)
  56. #include <sys/statvfs.h> /* for statvfs() */
  57. #define STATFS statvfs
  58. #elif defined(HPUX) 
  59. #include <sys/vfs.h>      /* for statfs() */
  60. #define STATFS statfs
  61. #elif defined(LINUX)
  62. #include <sys/vfs.h>      /* for statfs() */
  63. #define STATFS statfs
  64. #elif defined(SUNOS4)
  65. #include <sys/vfs.h>      /* for statfs() */
  66. extern "C" int statfs(char *, struct statfs *);
  67. #define STATFS statfs
  68. #elif defined(BSDI)
  69. #include <sys/mount.h>    /* for statfs() */
  70. #define STATFS statfs
  71. #else
  72. #include <sys/statfs.h>  /* for statfs() */
  73. #define STATFS statfs
  74. extern "C" int statfs(char *, struct statfs *);
  75. #endif
  76.  
  77. #if defined(OSF1)
  78. extern "C" int statvfs(const char *, struct statvfs *);
  79. #endif
  80.  
  81. extern int XFE_NO_SUBJECT;
  82. extern int XFE_DOCUMENT_DONE;
  83. extern int XFE_ERROR_SAVING_PASSWORD;
  84. extern int XFE_STDERR_DIAGNOSTICS_HAVE_BEEN_TRUNCATED;
  85. extern int XFE_ERROR_CREATING_PIPE;
  86. extern int XFE_COULD_NOT_DUP_STDERR;
  87. extern int XFE_COULD_NOT_FDOPEN_STDERR;
  88. extern int XFE_COULD_NOT_DUP_A_NEW_STDERR;
  89. extern int XFE_COULD_NOT_DUP_A_STDOUT;
  90. extern int XFE_COULD_NOT_FDOPEN_THE_NEW_STDOUT;
  91. extern int XFE_COULD_NOT_DUP_A_NEW_STDOUT;
  92. extern int MK_UNABLE_TO_LOCATE_FILE;
  93.  
  94. #ifdef MOZ_LDAP
  95. extern "C" void fe_ldapsearch_finished(MWContext *context);
  96. extern "C" void fe_AB_AllConnectionsComplete(MWContext *context);
  97. #endif
  98.  
  99. #ifndef NO_WEB_FONTS
  100. /* Webfonts related routines defined in fonts.c */
  101. extern "C" int fe_WebfontsNeedReload(MWContext *context);
  102. #endif /* NO_WEB_FONTS */
  103.  
  104. #if DEBUG_slamm_
  105. #define D(x) x
  106. #else
  107. #define D(x)
  108. #endif
  109.  
  110. //
  111. //
  112. // Setup redirection of stdout and stderr to a dialog
  113. //
  114. /* stderr hackery - Why Unix Sucks, reason number 32767.
  115.  */
  116.  
  117. #include <fcntl.h>
  118.  
  119. static char stderr_buffer [1024];
  120. static char *stderr_tail = 0;
  121. static time_t stderr_last_read = 0;
  122. static XtIntervalId stderr_dialog_timer = 0;
  123.  
  124. extern FILE *real_stderr;
  125. FILE *real_stdout = stdout;
  126.  
  127. static void
  128. fe_stderr_dialog_timer (XtPointer /* closure */, XtIntervalId * /* id */)
  129. {
  130.   char *s = fe_StringTrim (stderr_buffer);
  131.   if (*s)
  132.     {
  133.       /* If too much data was printed, then something has gone haywire,
  134.      so truncate it. */
  135.       char *trailer = XP_GetString(XFE_STDERR_DIAGNOSTICS_HAVE_BEEN_TRUNCATED);
  136.       int max = sizeof (stderr_buffer) - strlen (trailer) - 5;
  137.       if (strlen (s) > max)
  138.     strcpy (s + max, trailer);
  139.  
  140.       /* Now show the user.
  141.      Possibly we should do something about not popping this up
  142.      more often than every few seconds or something.
  143.        */
  144.       fe_stderr (fe_all_MWContexts->context, s);
  145.     }
  146.  
  147.   stderr_tail = stderr_buffer;
  148.   stderr_dialog_timer = 0;
  149. }
  150.  
  151.  
  152. static void
  153. fe_stderr_callback (XtPointer /* closure */, int *fd, XtIntervalId * /* id */)
  154. {
  155.   char *s;
  156.   int left;
  157.   int size;
  158.   int read_this_time = 0;
  159.  
  160.   if (stderr_tail == 0)
  161.     stderr_tail = stderr_buffer;
  162.  
  163.   left = ((sizeof (stderr_buffer) - 2)
  164.       - (stderr_tail - stderr_buffer));
  165.  
  166.   s = stderr_tail;
  167.   *s = 0;
  168.  
  169.   /* Read as much data from the fd as we can, up to our buffer size. */
  170.   if (left > 0)
  171.     {
  172. #if 1
  173.       while ((size = read (*fd, (void *) s, left)) > 0)
  174.     {
  175.       left -= size;
  176.       s += size;
  177.       read_this_time += size;
  178.     }
  179. #else
  180.       size = read (*fd, (void *) s, left);
  181.       left -= size;
  182.       s += size;
  183.       read_this_time += size;
  184. #endif
  185.  
  186.       *s = 0;
  187.     }
  188.   else
  189.     {
  190.       char buf2 [1024];
  191.       /* The buffer is full; flush the rest of it. */
  192.       while (read (*fd, (void *) buf2, sizeof (buf2)) > 0)
  193.     ;
  194.     }
  195.  
  196.   stderr_tail = s;
  197.   stderr_last_read = time ((time_t *) 0);
  198.  
  199.   /* Now we have read some data that we would like to put up in a dialog
  200.      box.  But more data may still be coming in - so don't pop up the
  201.      dialog right now, but instead, start a timer that will pop it up
  202.      a second from now.  Should more data come in in the meantime, we
  203.      will be called again, and will reset that timer again.  So the
  204.      dialog will only pop up when a second has elapsed with no new data
  205.      being written to stderr.
  206.  
  207.      However, if the buffer is full (meaning lots of data has been written)
  208.      then we don't reset the timer.
  209.    */
  210.   if (read_this_time > 0)
  211.     {
  212.       if (stderr_dialog_timer)
  213.     XtRemoveTimeOut (stderr_dialog_timer);
  214.  
  215.       stderr_dialog_timer =
  216.     XtAppAddTimeOut (fe_XtAppContext, 1 * 1000,
  217.              fe_stderr_dialog_timer, 0);
  218.     }
  219. }
  220.  
  221. static void
  222. fe_initialize_stderr (void)
  223. {
  224.   static Boolean done = False;
  225.   int fds [2];
  226.   int in, out;
  227.   int new_stdout, new_stderr;
  228.   int stdout_fd = 1;
  229.   int stderr_fd = 2;
  230.   int flags;
  231.  
  232.   if (done) return;
  233.  
  234.   real_stderr = stderr;
  235.   real_stdout = stdout;
  236.  
  237. #ifdef DEBUG
  238.   // Don't use dialogs for stderr & stdout on debug builds.
  239.   return;
  240. #else
  241.   if (!fe_globalData.stderr_dialog_p && !fe_globalData.stdout_dialog_p)
  242.     return;
  243. #endif
  244.  
  245.   done = True;
  246.  
  247.   if (pipe (fds))
  248.     {
  249.       fe_perror (fe_all_MWContexts->context,
  250.                  XP_GetString( XFE_ERROR_CREATING_PIPE) );
  251.       return;
  252.     }
  253.  
  254.   in = fds [0];
  255.   out = fds [1];
  256.  
  257. # ifdef O_NONBLOCK
  258.   flags = O_NONBLOCK;
  259. # else
  260. #  ifdef O_NDELAY
  261.   flags = O_NDELAY;
  262. #  else
  263.   ERROR!! neither O_NONBLOCK nor O_NDELAY are defined.
  264. #  endif
  265. # endif
  266.  
  267.     /* Set both sides of the pipe to nonblocking - this is so that
  268.        our reads (in fe_stderr_callback) will terminate, and so that
  269.        out writes (in net_ExtViewWrite) will silently fail when the
  270.        pipe is full, instead of hosing the program. */
  271.   if (fcntl (in, F_SETFL, flags) != 0)
  272.     {
  273.       fe_perror (fe_all_MWContexts->context, "fcntl:");
  274.       return;
  275.     }
  276.   if (fcntl (out, F_SETFL, flags) != 0)
  277.     {
  278.       fe_perror (fe_all_MWContexts->context, "fcntl:");
  279.       return;
  280.     }
  281.  
  282.   if (fe_globalData.stderr_dialog_p)
  283.     {
  284.       FILE *new_stderr_file;
  285.       new_stderr = dup (stderr_fd);
  286.       if (new_stderr < 0)
  287.     {
  288.       fe_perror (fe_all_MWContexts->context,
  289.                  XP_GetString(XFE_COULD_NOT_DUP_STDERR));
  290.       return;
  291.     }
  292.       if (! (new_stderr_file = fdopen (new_stderr, "w")))
  293.     {
  294.       fe_perror (fe_all_MWContexts->context,
  295.                  XP_GetString(XFE_COULD_NOT_FDOPEN_STDERR));
  296.       return;
  297.     }
  298.       real_stderr = new_stderr_file;
  299.  
  300.       close (stderr_fd);
  301.       if (dup2 (out, stderr_fd) < 0)
  302.     {
  303.       fe_perror (fe_all_MWContexts->context,
  304.                  XP_GetString(XFE_COULD_NOT_DUP_A_NEW_STDERR));
  305.       return;
  306.     }
  307.     }
  308.  
  309.   if (fe_globalData.stdout_dialog_p)
  310.     {
  311.       FILE *new_stdout_file;
  312.       new_stdout = dup (stdout_fd);
  313.       if (new_stdout < 0)
  314.     {
  315.       fe_perror (fe_all_MWContexts->context,
  316.                  XP_GetString(XFE_COULD_NOT_DUP_A_STDOUT));
  317.       return;
  318.     }
  319.       if (! (new_stdout_file = fdopen (new_stdout, "w")))
  320.     {
  321.       fe_perror (fe_all_MWContexts->context,
  322.                  XP_GetString(XFE_COULD_NOT_FDOPEN_THE_NEW_STDOUT));
  323.       return;
  324.     }
  325.       real_stdout = new_stdout_file;
  326.  
  327.       close (stdout_fd);
  328.       if (dup2 (out, stdout_fd) < 0)
  329.     {
  330.       fe_perror (fe_all_MWContexts->context,
  331.                  XP_GetString(XFE_COULD_NOT_DUP_A_NEW_STDOUT));
  332.       return;
  333.     }
  334.     }
  335.  
  336.   XtAppAddInput (fe_XtAppContext, in,
  337.          (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
  338.          fe_stderr_callback, 0);
  339. }
  340.  
  341.  
  342. // Sanity check on the context.  Throughout the progress stuff below,
  343. // the context (and fe_data) needs to be checked for validity before
  344. // dereferencing the members.
  345. #define CHECK_CONTEXT_AND_DATA(c) \
  346. ((c) && CONTEXT_DATA(c) && !CONTEXT_DATA(context)->being_destroyed)
  347.  
  348. //
  349. // Return either the context's frame or the current active frame
  350. //
  351. XFE_Frame * 
  352. fe_frameFromMWContext(MWContext *context)
  353. {
  354.     XFE_Frame * frame = NULL;
  355.  
  356.     // Sanity check for possible invocation of this function from a frame
  357.     // that was just destroyed (or is being destroyed)
  358.     if (!CHECK_CONTEXT_AND_DATA(context))
  359.     {
  360.         return NULL;
  361.     }
  362.  
  363.     // Try to use context's frame
  364.     frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  365.     
  366.     // Try to use the active frame
  367. //     if (!frame)
  368. //     {
  369. //          frame = XFE_Frame::getActiveFrame();
  370. //     }
  371.  
  372.     // Make sure the frame is alive
  373.     if (frame && !frame->isAlive())
  374.     {
  375.         frame = NULL;
  376.     }
  377.  
  378.     return frame;
  379. }
  380.  
  381. extern "C" void
  382. FE_DestroyWindow(MWContext *context)
  383. {
  384.   XFE_Frame *frame;
  385.  
  386.   if (!context)
  387.     return;
  388.  
  389.   /*
  390.    * Recursively destroy any dependent children first
  391.    */
  392.   if (context->js_dependent_list) {
  393.     MWContext *dependent;
  394.     XP_List   *list;
  395.  
  396.     list = context->js_dependent_list;
  397.  
  398.     /* NOTE: XP_ListNextObject is a macro which modifies 'list' */
  399.     for( dependent = (MWContext*)XP_ListNextObject(list);
  400.      dependent;
  401.      dependent = (MWContext*)XP_ListNextObject(list)) {
  402.       dependent->js_parent = 0; /* prevents recursive call from invoking XP_ListRemoveObject */
  403.       FE_DestroyWindow(dependent);
  404.     }
  405.  
  406.     /*
  407.      * XP_ListDestroy does *not* free the objects on the list (Apr-97)
  408.      * They are destroyed here by calls to FE_DestroyWindow() above.
  409.      */
  410.     XP_ListDestroy(context->js_dependent_list);
  411.     context->js_dependent_list = 0;
  412.   }
  413.  
  414.   /*
  415.    * This code is invoked when a dependent window is not being destroyed by
  416.    * its parent.
  417.    */
  418.   if (context->js_parent && context->js_parent->js_dependent_list)
  419.     XP_ListRemoveObject(context->js_parent->js_dependent_list, context);
  420.  
  421.  
  422.   /*
  423.    * Now destroy the window
  424.    */
  425.   frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  426.   XP_ASSERT(frame);
  427.   if (frame == NULL) return;
  428.  
  429.   frame->app_delete_response();
  430.  
  431. }
  432.  
  433. extern "C" void
  434. XFE_EnableClicking(MWContext *context)
  435. {
  436.   MWContext *top = XP_GetNonGridContext (context);
  437.   XFE_Frame *f;
  438.   XP_Bool running_p;
  439.  
  440.   // this is very evil but has been known to happen
  441.   if (top == NULL) return;
  442.  
  443.   f = ViewGlue_getFrame(top);
  444.  
  445.   running_p = XP_IsContextBusy (top);
  446.  
  447.   D( printf("XFE_EnableClicking(context = 0x%x) running_p = %d\n",
  448.             context, running_p); )
  449.  
  450.   if (f)
  451.     {
  452.       f->notifyInterested(XFE_View::commandNeedsUpdating,
  453.                            (void*)xfeCmdStopLoading);
  454.  
  455.       f->notifyInterested(running_p ?
  456.                           XFE_Frame::frameBusyCallback:
  457.                           XFE_Frame::frameNotBusyCallback);
  458.     }
  459.   else
  460.     {
  461.       if (CONTEXT_DATA (top)->show_toolbar_p && CONTEXT_DATA (top)->toolbar) {
  462.     if (CONTEXT_DATA (top)->abort_button)
  463.       XtVaSetValues (CONTEXT_DATA (top)->abort_button,
  464.              XmNsensitive, fe_IsContextStoppable(top), 0);
  465.       }
  466.       if (CONTEXT_DATA (top)->show_menubar_p && CONTEXT_DATA (top)->menubar) {
  467.     if (CONTEXT_DATA (top)->abort_menuitem)
  468.       XtVaSetValues (CONTEXT_DATA (top)->abort_menuitem,
  469.              XmNsensitive, fe_IsContextStoppable(top), 0);
  470.       }
  471.     }
  472.  
  473.   if (! running_p)
  474.     fe_StopProgressGraph (context);
  475.  
  476.   if (CONTEXT_DATA (context)->clicking_blocked)
  477.     {
  478.       CONTEXT_DATA (context)->clicking_blocked = False;
  479.       /* #### set to link cursor if over link. */
  480.       fe_SetCursor (context, False);
  481.     }
  482. }
  483.  
  484. extern "C" void
  485. FE_UpdateStopState(MWContext *context)
  486. {
  487.   MWContext *top = XP_GetNonGridContext (context);
  488.   XFE_Frame *f;
  489.  
  490.   // this is very evil but has been known to happen
  491.   if (top == NULL) return;
  492.  
  493.   f = ViewGlue_getFrame(top);
  494.  
  495.   if (f)
  496.     {
  497. D( printf("FE_UpdateStopState(context = 0x%x)\n", context); )
  498.  
  499.       f->notifyInterested(XFE_View::commandNeedsUpdating,
  500.                            (void*)xfeCmdStopLoading);
  501.       
  502.       // Brendan says this should check for stoppable, not busyness...mcafee
  503.       // But, I talked to him, and he agreed that I was right all along..djw
  504.       // Save time: trust David. hee hee. Ok, here is the scoop. Because,
  505.       // this call is made in FE_UpdateStopState(), which is really exists
  506.       // to control the stop button, so you'd think all the stuff in here
  507.       // should be using XP_IsContextStoppable(). Fair enough. The thing is
  508.       // this call to the busy notification dependencies (notably the cursor),
  509.       // has nothing to do with the stop button, etc. It's just that this
  510.       // is a good salient point to update the cursor. So, calling 
  511.       // XP_IsContextBusy() is the right thing. Either that or take the whole
  512.       // thing out, say "what was I trying", and get on with your
  513.       // life. Hmmm, actually that sounds pretty good, cheers...djw
  514.       f->notifyInterested(XP_IsContextBusy(context)?
  515.                           XFE_Frame::frameBusyCallback:
  516.                           XFE_Frame::frameNotBusyCallback);
  517.     }
  518.   else
  519.     {
  520.       if (context->type == MWContextPostScript) return;
  521.       
  522.       if (CONTEXT_DATA (top)->show_toolbar_p && CONTEXT_DATA (top)->toolbar) {
  523.     if (CONTEXT_DATA (top)->abort_button)
  524.       XtVaSetValues (CONTEXT_DATA (top)->abort_button,
  525.              XmNsensitive, fe_IsContextStoppable(top), 0);
  526.       }
  527.       if (CONTEXT_DATA (top)->show_menubar_p && CONTEXT_DATA (top)->menubar) {
  528.     if (CONTEXT_DATA (top)->abort_menuitem)
  529.       XtVaSetValues (CONTEXT_DATA (top)->abort_menuitem,
  530.              XmNsensitive, fe_IsContextStoppable(top), 0);
  531.       }
  532.     }
  533. }
  534.  
  535. extern "C" void
  536. XFE_AllConnectionsComplete(MWContext *context)
  537. {
  538.   MWContext *top = XP_GetNonGridContext (context);
  539.   XFE_Frame *f;
  540.  
  541.   // this is evil and vile but it's been known to happen
  542.   if (top == NULL) return;
  543.  
  544.   f = ViewGlue_getFrame(top);
  545.  
  546.   if (CONTEXT_DATA (context)->being_destroyed) return;
  547.  
  548.   D( printf("XFE_AllConnectionsComplete(context = 0x%x)\n",context); )
  549.  
  550.   /* #### ARRGH, when generating PostScript, this assert gets tripped!
  551.      I guess this is because of the goofy games it plays with invoking
  552.      callbacks in the "other" context...
  553.      assert (CONTEXT_DATA (context)->active_url_count == 0);
  554.      */
  555.   
  556.   /* If a title was never specified, clear the old one. */
  557.   if ((context->type != MWContextBookmarks) &&
  558.       (context->type != MWContextAddressBook) &&
  559.       (context->type != MWContextSearch) &&
  560.       (context->type != MWContextSearchLdap) &&
  561.       (CONTEXT_DATA (context)->active_url_count == 0) &&
  562.       (context->title == 0))
  563.     XFE_SetDocTitle (context, 0);
  564.   
  565.   /* This shouldn't be necessary, but it doesn't hurt. */
  566.   XFE_EnableClicking (context);
  567.   
  568.   fe_RefreshAllAnchors ();
  569.   
  570.   /* If either the user resized during layout or there was a webfont that
  571.      was being downloaded while rendering the page, reload the document right
  572.      now (it will come from the cache.) */
  573. #ifndef NO_WEB_FONTS
  574.   if (fe_WebfontsNeedReload(context))
  575.     {
  576.       CONTEXT_DATA (context)->relayout_required = False;
  577.       LO_InvalidateFontData(context);
  578.       fe_ReLayout (context, NET_RESIZE_RELOAD);
  579.     }
  580.   else
  581. #endif /* NO_WEB_FONTS */
  582.   if (CONTEXT_DATA (context)->relayout_required)
  583.     {
  584.       if (! XP_IsContextBusy (context))
  585.     {
  586.       CONTEXT_DATA (context)->relayout_required = False;
  587.         /*  As vidur suggested in Bug 59214: because JS generated content
  588.         was not put into wysiwyg, hence this source was not be shown on a resize.
  589.         The fix was to make the reload policy for Mail/News contexts NET_NORMAL_RELOAD.
  590.         This would fix exceed server problem too. Exceed server sends redraw events on
  591.     each resize movement */
  592.         if ( (context->type == MWContextNews) 
  593.          || (context->type == MWContextMail)
  594.              || (context->type == MWContextNewsMsg) 
  595.          || (context->type == MWContextMailMsg) )
  596.           fe_ReLayout (context, NET_NORMAL_RELOAD);
  597.         else
  598.           fe_ReLayout (context, NET_RESIZE_RELOAD);
  599.     }
  600.     }
  601.   else if (context->is_grid_cell && CONTEXT_DATA (top)->relayout_required)
  602.     {
  603.       if (! XP_IsContextBusy (top))
  604.     {
  605.       CONTEXT_DATA (top)->relayout_required = False;
  606.           /*  As vidur suggested in Bug 59214: because JS generated content
  607.           was not put into wysiwyg, hence this source was not be shown on a resize.
  608.           The fix was to make the reload policy for Mail/News contexts NET_NORMAL_RELOAD.
  609.           This would fix exceed server problem too. Exceed server sends redraw events on
  610.       each resize movement */
  611.           if ( (context->type == MWContextNews) 
  612.          || (context->type == MWContextMail)
  613.              || (context->type == MWContextNewsMsg) 
  614.          || (context->type == MWContextMailMsg) )
  615.             fe_ReLayout (top, NET_NORMAL_RELOAD);
  616.           else
  617.             fe_ReLayout (top, NET_RESIZE_RELOAD);
  618.     }
  619.     }
  620.   else if((context->type != MWContextSearch) 
  621.     && (context->type != MWContextSearchLdap) )
  622.     {
  623.       XFE_Progress (top, XP_GetString(XFE_DOCUMENT_DONE));
  624.     }
  625.   
  626.   if (f && f->isAlive())
  627.     {
  628.       f->allConnectionsComplete();
  629.     }
  630.   else
  631.     {
  632. #if 0
  633.       printf ("ConnectionsComplete: 0x%x; grid: %d; busy: %d, relayout: %d\n",
  634.           context, context->is_grid_cell, XP_IsContextBusy (context),
  635.           CONTEXT_DATA (context)->relayout_required);
  636. #endif
  637.       
  638.       if (context->type == MWContextSaveToDisk) /* gag gag gag */
  639.     fe_DestroySaveToDiskContext (context);
  640.       else if ( context->type == MWContextSearchLdap) 
  641.     {
  642. #ifdef UNIX_LDAP 
  643. //      fe_ldapsearch_finished(context);
  644. #endif
  645.     }
  646. #ifdef MOZ_LDAP
  647.       else if ( context->type == MWContextAddressBook) /* AB ldap search */
  648.     {
  649.       fe_AB_AllConnectionsComplete(context);
  650.     }
  651. #endif  // MOZ_LDAP
  652.     }
  653. }
  654.  
  655. /* Prompt the user for a string.
  656.    If the user selects "Cancel", 0 is returned.
  657.    Otherwise, a newly-allocated string is returned.
  658.    A pointer to the prompt-string is not retained.
  659.  */
  660. extern "C" char *
  661. XFE_Prompt (MWContext *context, const char *message, const char *deflt)
  662. {
  663.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  664.  
  665.   if (f)
  666.     return f->prompt("prompt", message, deflt);
  667.   else
  668.     return (char *) fe_prompt (context, CONTEXT_WIDGET (context),
  669.                                "prompt", message,
  670.                                TRUE, (deflt ? deflt : ""),
  671.                                TRUE, FALSE, 0);
  672. }
  673.  
  674. extern "C" char *
  675. XFE_PromptWithCaption(MWContext *context, const char *caption,
  676.               const char *message, const char *deflt)
  677. {
  678.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  679.  
  680.   if (f)
  681.     return f->prompt(caption, message, deflt);
  682.   else
  683.     return (char *) fe_dialog(CONTEXT_WIDGET(context), caption, message,
  684.                   TRUE, (deflt ? deflt : ""), TRUE, FALSE, 0);
  685.  
  686. }
  687.  
  688. extern "C" char *
  689. FE_PromptMessageSubject (MWContext *context)
  690. {
  691.   const char *def = XP_GetString( XFE_NO_SUBJECT );
  692.  
  693.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  694.  
  695.   if (f)
  696.     return f->prompt("promptSubject", 0, def);
  697.   else
  698.     return (char *) fe_dialog (CONTEXT_WIDGET (context), "promptSubject",
  699.                    0, TRUE, def, TRUE, TRUE, 0);
  700. }
  701.  
  702. // Some History functions that we need to implement here now.
  703. extern "C" int
  704. FE_EnableBackButton (MWContext *context)
  705. {
  706.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  707.  
  708.   if (f)
  709.     f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdBack);
  710.  
  711.   return 0;
  712. }
  713.  
  714. extern "C" int
  715. FE_DisableBackButton (MWContext *context)
  716. {
  717.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  718.  
  719.   if (f)
  720.     f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdBack);
  721.  
  722.   return 0;
  723. }
  724.  
  725. extern "C" int
  726. FE_EnableForwardButton (MWContext *context)
  727. {
  728.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  729.  
  730.   if (f)
  731.     f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdForward);
  732.  
  733.   return 0;
  734. }
  735.  
  736. extern "C" int
  737. FE_DisableForwardButton (MWContext *context)
  738. {
  739.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  740.  
  741.   if (f)
  742.     f->notifyInterested(XFE_View::commandNeedsUpdating, (void*)xfeCmdForward);
  743.  
  744.   return 0;
  745. }
  746.  
  747. extern "C" void
  748. fe_MidTruncatedProgress(MWContext *context, const char *message)
  749. {
  750.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  751.  
  752.   if (f)
  753.       {
  754.           if (message == 0 || *message == '\0')
  755.               message = context->defaultStatus;
  756.  
  757.           f->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)message);
  758.       }
  759. }
  760.  
  761. extern "C" void
  762. fe_SetURLString (MWContext *context, URL_Struct *url)
  763. {
  764.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  765.  
  766.   if (f)
  767.     f->notifyInterested(XFE_HTMLView::newURLLoading, url);
  768. }
  769.  
  770. typedef enum {
  771.     Answer_Invalid = -1,
  772.     Answer_Cancel = 0,
  773.     Answer_OK,
  774.     Answer_Apply,
  775.     Answer_Destroy 
  776. } Answers;
  777.  
  778. struct fe_fileprompt_data {
  779.     Answers answer;
  780.     char *return_value;
  781.     Boolean must_match;
  782. };
  783.  
  784. static void
  785. fe_fileprompt_finish_cb (Widget /*widget*/, XtPointer closure, XtPointer /*call_data*/)
  786. {
  787.   struct fe_fileprompt_data *data = (struct fe_fileprompt_data *) closure;
  788.   if (data->answer == Answer_Invalid)
  789.       data->answer = Answer_Destroy;
  790. }
  791.  
  792. static void
  793. fe_fileprompt_cb (Widget widget, XtPointer closure, XtPointer call_data)
  794. {
  795.     fe_fileprompt_data *data = (fe_fileprompt_data *)closure;
  796.     XmFileSelectionBoxCallbackStruct *sbc = (XmFileSelectionBoxCallbackStruct *) call_data;
  797.  
  798.     switch (sbc->reason)
  799.     {
  800.     case XmCR_NO_MATCH:
  801.       {
  802.       NOMATCH:
  803.           XBell (XtDisplay (widget), 0);
  804.           break;
  805.       }
  806.     case XmCR_OK:
  807.         {
  808.             XmStringGetLtoR (sbc->value, XmFONTLIST_DEFAULT_TAG,
  809.                              (char **) &data->return_value);
  810.             /* mustMatch doesn't work!! */
  811.             {
  812.                 struct stat st;
  813.                 if (data->must_match &&
  814.                     data->return_value &&
  815.                     stat (data->return_value, &st)){
  816.                     free (data->return_value);
  817.                     data->return_value = 0;
  818.                     goto NOMATCH;
  819.                 }
  820.             }
  821.             data->answer = Answer_OK;
  822.             break;
  823.         }
  824.     case XmCR_CANCEL:
  825.         {
  826.             data->answer = Answer_Cancel;
  827.             data->return_value = 0;
  828.             break;
  829.         }
  830.     default:
  831.         abort ();
  832.     }
  833. }
  834.  
  835. extern "C" char* 
  836. FE_GetTempFileFor(MWContext* /*context*/, const char* fname,
  837.           XP_FileType ftype, XP_FileType* rettype)
  838. {
  839.   char* actual = WH_FileName(fname, ftype);
  840.   int len;
  841.   char* result;
  842.   if (!actual) return NULL;
  843.   len = strlen(actual) + 10;
  844.   result = (char*)XP_ALLOC(len);
  845.   if (!result) return NULL;
  846.   PR_snprintf(result, len, "%s-XXXXXX", actual);
  847.   XP_FREE(actual);
  848.   mktemp(result);
  849.   *rettype = xpMailFolder;    /* Ought to be harmless enough. */
  850.   return result;
  851. }
  852.  
  853.  
  854. /*
  855.  * Status of filename prompting:
  856.  * We have three routines, FE_PromptForFileName() here, and
  857.  * fe_ReadFileName() and fe_ReadFileName_2() in dialogs.c.
  858.  * FE_PromptForFileName() is the one called by the backend;
  859.  * the other two are called at various points in the XFE.
  860.  * fe_ReadFileName() immediately calls fe_ReadFileName_2().
  861.  * We need to integrate these three routines into one!
  862.  *      ...Akkana 10/20/97
  863.  */
  864. extern "C" int
  865. FE_PromptForFileName (MWContext *context,
  866.               const char *prompt_string,
  867.               const char *default_path,
  868.               XP_Bool file_must_exist_p,
  869.               XP_Bool directories_allowed_p,
  870.               ReadFileNameCallbackFunction fn,
  871.               void *closure)
  872. {
  873. #if 0
  874.     // Note: this needs to be changed somehow to call fe_ReadFileName_2 ...
  875.   char *file = fe_ReadFileName (context, prompt_string, default_path,
  876.                 file_must_exist_p, 0);
  877.   if (!file)
  878.     return -1;
  879.  
  880.   fn (context, file, closure);
  881.   return 0;
  882. #endif
  883.  
  884.   Widget    parent;
  885.   Widget    shell;
  886.   Widget    fileb;
  887.   Visual   *v = 0;
  888.   Colormap  cmap = 0;
  889.   Cardinal  depth = 0;
  890.   char     *text = 0;
  891.   char     *orig_text = 0;
  892.   char      buf[1024];
  893.   XmString  xmpat = 0;
  894.   XmString  xmfile = 0;
  895.   Arg       av[20];
  896.   int       ac;
  897.   struct    fe_fileprompt_data data;
  898.  
  899.   /* relative filename
  900.    */
  901.   XmString dirMask;
  902.   XP_Bool relative_filename = False;
  903.  
  904.   parent = CONTEXT_WIDGET(context);
  905.  
  906.   XtVaGetValues(parent,
  907.                 XtNvisual, &v,
  908.                 XtNcolormap, &cmap,
  909.                 XtNdepth, &depth, 0);
  910.  
  911.   if (default_path && *default_path) {    
  912.       StrAllocCopy(text, default_path);
  913.       orig_text = text;
  914.   }
  915.  
  916.   if (text && *text)
  917.       text = XP_STRTOK(text, " ");
  918.  
  919.   if (!text || !*text) {
  920.       xmpat = 0;
  921.       xmfile = 0;
  922.   }
  923.   else if (directories_allowed_p) {
  924.       if (text[XP_STRLEN(text) - 1] == '/')
  925.           text[XP_STRLEN(text) - 1] = 0;
  926.       PR_snprintf(buf, sizeof(buf), "%.900s/*", text);
  927.       xmpat = XmStringCreateLtoR(buf, XmFONTLIST_DEFAULT_TAG);
  928.       xmfile = XmStringCreateLtoR(text, XmFONTLIST_DEFAULT_TAG);
  929.   }
  930.   else {
  931.       char *f;
  932.       if (text[XP_STRLEN(text) - 1] == '/')
  933.           PR_snprintf(buf, sizeof (buf), "%.900s/*", text);
  934.       else
  935.           PR_snprintf(buf, sizeof (buf), "%.900s", text);
  936.       xmfile = XmStringCreateLtoR(buf, XmFONTLIST_DEFAULT_TAG);
  937.       if (text[0] == '/') /* only do this for absolute path */
  938.           f = XP_STRRCHR(text, '/');
  939.       else
  940.           f = NULL;
  941.  
  942.       if (f && f != text)
  943.           *f = 0;
  944.  
  945.       if (f) {
  946.           PR_snprintf(buf, sizeof (buf), "%.900s/*", text);
  947.           xmpat = XmStringCreateLtoR(buf, XmFONTLIST_DEFAULT_TAG);
  948.       }
  949.       else {
  950.           relative_filename = True;
  951.       }
  952.   }
  953.   ac = 0;
  954.   XtSetArg(av[ac], XmNvisual, v); ac++;
  955.   XtSetArg(av[ac], XmNdepth, depth); ac++;
  956.   XtSetArg(av[ac], XmNcolormap, cmap); ac++;
  957.   XtSetArg(av[ac], XmNdeleteResponse, XmDESTROY); ac++;
  958.   shell = XmCreateDialogShell(parent, "fileBrowser_popup", av, ac);
  959.  
  960.   ac = 0;
  961.   XtSetArg(av[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
  962.   XtSetArg(av[ac], XmNfileTypeMask,
  963.            (directories_allowed_p ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++;
  964.   fileb = fe_CreateFileSelectionBox(shell, "fileBrowser", av, ac);
  965.  
  966.   XtAddCallback (fileb, XmNokCallback,      fe_fileprompt_cb, &data);
  967.   XtAddCallback (fileb, XmNcancelCallback,  fe_fileprompt_cb, &data);
  968.   XtAddCallback (fileb, XmNdestroyCallback, fe_fileprompt_finish_cb, &data);
  969.  
  970.   if (prompt_string && *prompt_string) {
  971.       XtVaSetValues(shell, XmNtitle, prompt_string, 0);
  972.   }
  973.  
  974.   XtVaSetValues (fileb, XmNmustMatch, False, 0);
  975.  
  976.   if (xmpat && !relative_filename) {
  977.       XtVaSetValues(fileb,
  978.                     XmNdirMask, xmpat,
  979.                     XmNpattern, xmpat, 
  980.                     XmNdirSpec, xmfile, 
  981.                     0);
  982.       XmStringFree(xmpat);
  983.       XmStringFree(xmfile);
  984.   }
  985.   else if (text) {
  986.       char *basename = XP_STRRCHR(text, '/');
  987.       int len = 0;
  988.       if (!basename) {
  989.           basename = text;
  990.           len=XP_STRLEN(basename);
  991.       }/* if */
  992.       else if ((len=XP_STRLEN(basename)) > 1)
  993.           basename++;
  994.               
  995.       XmString xm_directory;
  996.       XtVaGetValues(fileb, XmNdirectory, &xm_directory, 0);
  997.  
  998.       String dir_part = NULL;
  999.       if (xm_directory != NULL)
  1000.           dir_part = _XmStringGetTextConcat(xm_directory);
  1001.  
  1002.       if (dir_part) {
  1003.           int dir_len = XP_STRLEN(dir_part);
  1004.           len += dir_len;
  1005.           if (dir_part[dir_len-1] != '/')
  1006.               len++;
  1007.           char *filename = (char *) XP_CALLOC(len+1, sizeof(char));
  1008.           XP_STRCAT(filename, dir_part);
  1009.           if (dir_part[dir_len-1] != '/')
  1010.               XP_STRCAT(filename, "/");
  1011.           if (basename)
  1012.               XP_STRCAT(filename, basename);
  1013.           xmfile = XmStringCreateLtoR(filename, XmFONTLIST_DEFAULT_TAG);
  1014.       }/* if */
  1015.       XtVaGetValues (fileb, XmNdirMask, &dirMask, 0);
  1016.  
  1017.       XmFileSelectionDoSearch (fileb, dirMask);
  1018.       XtVaSetValues(fileb, XmNdirSpec, xmfile, 0);
  1019.       XmStringFree(xmfile);
  1020.   }/* else */
  1021.   if (orig_text) free(orig_text);
  1022.  
  1023.  
  1024.   data.answer = Answer_Invalid;
  1025.   data.return_value = 0;
  1026.   data.must_match = file_must_exist_p;
  1027.  
  1028.   fe_HackDialogTranslations (fileb);
  1029.  
  1030.   fe_NukeBackingStore (fileb);
  1031.  
  1032.   fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
  1033.   XtManageChild (fileb);
  1034.  
  1035.   /* check for destruction here */
  1036. loop:
  1037.   while (data.answer == Answer_Invalid)
  1038.       fe_EventLoop ();
  1039.  
  1040.   if (data.answer == Answer_OK) {
  1041.       // Check for invalid directory:
  1042.       char* dirname = XP_STRDUP(data.return_value);
  1043.       char* basename = XP_STRRCHR(dirname, '/');
  1044.       DIR* dirp;
  1045.  
  1046.       if (basename != 0) {
  1047.           *basename = 0;
  1048.           dirp = opendir(dirname);
  1049.           if (dirp == 0) {
  1050.               char s[256];
  1051.               sprintf(s, XP_GetString(MK_UNABLE_TO_LOCATE_FILE), dirname);
  1052.               FE_Alert(context, s);
  1053.               if (data.return_value)
  1054.                   free(data.return_value);
  1055.               XP_FREE(dirname);
  1056.               data.answer = Answer_Invalid;
  1057.               goto loop;
  1058.           }
  1059.           closedir(dirp);
  1060.           XP_FREE(dirname);
  1061.       }
  1062.  
  1063.       if (data.return_value) {
  1064.           fn(context, data.return_value, closure);
  1065.           free(data.return_value);
  1066.       }
  1067.   }
  1068.  
  1069.   if (data.answer != Answer_Destroy)
  1070.       XtDestroyWidget(shell);
  1071.   
  1072.   return (data.answer== Answer_OK && data.return_value) ? 0 : -1;
  1073. }
  1074.  
  1075. extern "C" void
  1076. FE_QueryChrome(MWContext * context,  /* in */
  1077.            Chrome * chrome) /* out */
  1078.  
  1079. /**>
  1080.  *
  1081.  * description:
  1082.  *    Fill in a chrome structure, given a context.
  1083.  *
  1084.  * returns:
  1085.  *    n/a.  The chrome parameter is modified.
  1086.  *
  1087.  */
  1088. {
  1089.   XFE_Frame *       frame;
  1090.  
  1091.   if (!chrome || !context || context->type != MWContextBrowser)
  1092.     return;
  1093.  
  1094.   frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1095.   if (frame == NULL) return;
  1096.  
  1097.   frame->queryChrome(chrome);
  1098.  
  1099.   // if this is a grid cell, fix w_hint & h_hint
  1100.   if (context->is_grid_cell) {
  1101.     chrome->w_hint = (int32) CONTEXT_DATA (context)->scrolled_width;
  1102.     chrome->h_hint = (int32) CONTEXT_DATA (context)->scrolled_height;
  1103. #ifdef DEBUG_spence
  1104.     printf ("QueryChrome: grid cell: w = %d, h = %d\n",
  1105.         chrome->w_hint, chrome->h_hint);
  1106. #endif    
  1107.   }
  1108. }
  1109.  
  1110.  
  1111.  
  1112. extern "C" void
  1113. FE_UpdateChrome(MWContext *context, /* in */
  1114.         Chrome *chrome) /* in */
  1115.  
  1116. /**
  1117.  *
  1118.  * description:
  1119.  *    Update a frame based on the chrome.
  1120.  *
  1121.  * returns:
  1122.  *    n/a
  1123.  *
  1124.  */
  1125. {
  1126.   XFE_Frame * frame;
  1127.   Widget      w;
  1128.  
  1129.   if (!chrome || !context || context->type != MWContextBrowser)
  1130.     return;
  1131.  
  1132.   w = CONTEXT_WIDGET(context);
  1133.   if (!XtIsManaged(w))
  1134.     XtManageChild(w);
  1135.  
  1136.   frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1137.   if (frame == NULL) return;
  1138.  
  1139.   frame->respectChrome(chrome);
  1140.   frame->doAttachments();
  1141. }
  1142.  
  1143. #ifdef MOZ_LDAP
  1144. extern "C" void
  1145. FE_RememberPopPassword (MWContext *context, const char *password)
  1146. {
  1147.   /* Store password into preferences. */
  1148.   StrAllocCopy (fe_globalPrefs.pop3_password, password);
  1149.  
  1150.   /* If user has already requesting saving it, do that. */
  1151.   if (fe_globalPrefs.rememberPswd)
  1152.     {
  1153.       if (!XFE_SavePrefs ((char *) fe_globalData.user_prefs_file,
  1154.               &fe_globalPrefs))
  1155.     fe_perror (context, XP_GetString( XFE_ERROR_SAVING_PASSWORD ) );
  1156.     }
  1157. }
  1158. #endif
  1159.  
  1160. extern "C" void
  1161. FE_BackCommand(MWContext *context)
  1162. {
  1163.         XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1164.  
  1165.         if (!frame)
  1166.                 return;
  1167.  
  1168.         if (frame->handlesCommand(xfeCmdBack)
  1169.                 && frame->isCommandEnabled(xfeCmdBack))
  1170.                 frame->doCommand(xfeCmdBack);
  1171. }
  1172.  
  1173. extern "C" void
  1174. FE_ForwardCommand(MWContext *context)
  1175. {
  1176.         XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1177.  
  1178.         if (!frame)
  1179.                 return;
  1180.  
  1181.         if (frame->handlesCommand(xfeCmdForward)
  1182.                 && frame->isCommandEnabled(xfeCmdForward))
  1183.                 frame->doCommand(xfeCmdForward);
  1184. }
  1185.  
  1186. extern "C" void
  1187. FE_HomeCommand(MWContext *context)
  1188. {
  1189.         XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1190.  
  1191.         if (!frame)
  1192.                 return;
  1193.  
  1194.         if (frame->handlesCommand(xfeCmdHome)
  1195.                 && frame->isCommandEnabled(xfeCmdHome))
  1196.                 frame->doCommand(xfeCmdHome);
  1197. }
  1198.  
  1199. extern "C" void
  1200. FE_PrintCommand(MWContext *context)
  1201. {
  1202.         XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1203.  
  1204.         if (!frame)
  1205.                 return;
  1206.  
  1207.         if (frame->handlesCommand(xfeCmdPrint)
  1208.                 && frame->isCommandEnabled(xfeCmdPrint))
  1209.                 frame->doCommand(xfeCmdPrint);
  1210. }
  1211.  
  1212. extern "C" void
  1213. FE_OpenFileCommand(MWContext*context)
  1214. {
  1215.         XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1216.  
  1217.         if (!frame)
  1218.                 return;
  1219.  
  1220.         if (frame->handlesCommand(xfeCmdOpenPageChooseFile)
  1221.                 && frame->isCommandEnabled(xfeCmdOpenPageChooseFile))
  1222.                 frame->doCommand(xfeCmdOpenPageChooseFile);
  1223. }
  1224.  
  1225. extern "C" uint32
  1226. FE_DiskSpaceAvailable (MWContext* /*context*/, const char* filename)
  1227. {
  1228.   char curdir [MAXPATHLEN];
  1229.   struct STATFS fs_buf;
  1230.  
  1231.   if (!filename || !*filename) {
  1232.     (void) getcwd (curdir, MAXPATHLEN);
  1233.     if (! curdir) return 1L << 30;  /* hope for the best as we did in cheddar */
  1234.   } else {
  1235.     PR_snprintf (curdir, MAXPATHLEN, "%.200s", filename);
  1236.   }
  1237.  
  1238.   if (STATFS (curdir, &fs_buf) < 0) {
  1239.     /*    fe_perror (context, "Cannot stat current directory\n"); */
  1240.     return 1L << 30; /* hope for the best as we did in cheddar */
  1241.   }
  1242.  
  1243. #ifdef DEBUG_DISK_SPACE
  1244.   printf ("DiskSpaceAvailable: %d bytes\n", 
  1245.       fs_buf.f_bsize * (fs_buf.f_bavail - 1));
  1246. #endif
  1247.   return (fs_buf.f_bsize * (fs_buf.f_bavail - 1));
  1248. }
  1249.  
  1250.  
  1251. /*
  1252.  * I found this function reporting the document's scroll offset, rather
  1253.  *  than the window's location.  In fixing it, I found that XGetGeometry()
  1254.  *  didn't work--it always reported (0,0)--and any approach that would
  1255.  *  work would necessarily involve a round-trip to the X server; so,
  1256.  *  instead, I decided to cache the difference between (x_root,y_root) and
  1257.  *  (x,y) in incoming events.  The cachedPos is updated by
  1258.  *  fe_CacheWindowOffset() (see xfe.h and xfe.c), which is called from
  1259.  *  fe_stuff_event(), and should maybe be called from other places that
  1260.  *  may receive button or motion events.
  1261.  *
  1262.  * It is possible for this information to get out of sync with reality.
  1263.  *  If FE_GetWindowOffset() is called at a time when it's been a while
  1264.  *  since some event that triggers fe_CacheWindowOffset(), then it may
  1265.  *  be wrong.  My hypothesis is that FE_GetWindowOffset() isn't called
  1266.  *  in too many place (I discovered it was wrong in the context of fixing
  1267.  *  JS events; but, in theory, JS events will be triggered by X events,
  1268.  *  which should trigger fe_CacheWindowOffset() first).
  1269.  *
  1270.  * -- francis, 9 May 1997
  1271.  */
  1272. extern "C" void
  1273. FE_GetWindowOffset(MWContext *context, int32 *sx, int32 *sy)
  1274. {
  1275.   (*sx)=CONTEXT_DATA(context)->cachedPos.x;
  1276.   (*sy)=CONTEXT_DATA(context)->cachedPos.y;
  1277. }
  1278.  
  1279. extern "C" void
  1280. FE_GetScreenSize(MWContext *context, int32 *sx, int32 *sy)
  1281. {
  1282.     XFE_Frame *frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1283.  
  1284.     if (frame == NULL) return;
  1285.  
  1286.     *sx = WidthOfScreen(XtScreen(frame->getBaseWidget()));
  1287.     *sy = HeightOfScreen(XtScreen(frame->getBaseWidget()));
  1288. }
  1289.  
  1290. /*******************************************************************
  1291.  * 
  1292.  */
  1293.  
  1294. extern "C" void
  1295. FE_GetAvailScreenRect(MWContext *pContext, /* in */
  1296.               int32 *sx,   /* out */
  1297.               int32 *sy,   /* out */
  1298.               int32 *left, /* out */
  1299.               int32 *top)  /* out */
  1300.  
  1301. /*
  1302.  *
  1303.  * description:
  1304.  *    This function obtains the rectangular area of the screen available
  1305.  *    for use by Mozilla & Co.
  1306.  *    On Unix this is the entire screen (implemented here).
  1307.  *    On Macintosh this is the screen less the area for the menubar.
  1308.  *    On Win95 and Win NT 4.0 this is the screen less area occupied
  1309.  *    by the taskbar.
  1310.  *
  1311.  * preconditions:
  1312.  *    All arguments must be non-NULL
  1313.  *
  1314.  * returns:
  1315.  *    Places the dimensions of the screen in sx, sy, left and top
  1316.  *    
  1317.  ****************************************/
  1318. {
  1319.   *left = 0;
  1320.   *top  = 0;
  1321.   FE_GetScreenSize(pContext, sx, sy);
  1322. }
  1323.  
  1324.  
  1325. /*
  1326.  * BUG 57147 June 1997
  1327.  *
  1328.  * A fix for this bug was implemented which disturbs the existing
  1329.  * code as little as possible at the cost of being kludgy.  It would
  1330.  * be nicer to rearchitect all of the find code, but we're too close
  1331.  * to shipping Communicator 4.0 now.
  1332.  *
  1333.  * For the curious, here is a description of what is going on.
  1334.  *
  1335.  * JAVASCRIPT FIND() COMMAND
  1336.  * In Navigator 3.0 days it was only possible to invoke find from the
  1337.  * user interface.  One brought up the "find" dialog from a menu, after which
  1338.  * one could invoke the "find again" menu item.  With
  1339.  * Communicator 4.0 it is now possible to invoke the find() function
  1340.  * from JavaScript, e.g.
  1341.  *    find();      // bring up the find dialog box, aka interactive find
  1342.  *    find("cat"); // search for "cat" with no dialog, aka non-interactive find
  1343.  * Another complication is that it must be possible from JavaScript
  1344.  * to invoke find on a named html frame.  In the past it was assumed
  1345.  * that a find was to be performed on the frame with focus.  With
  1346.  * Communicator 4.0 it must be possible to perform a find regardless
  1347.  * of whether or not a frame has focus.
  1348.  *
  1349.  * IMPLEMENTATION
  1350.  * fe_find_cb() is invoked whenever the user chooses the find menu item.
  1351.  * fe_find_again_cb() is invoked whenever the user chooses the find again
  1352.  * menu item.
  1353.  * FE_FindCommand() is invoked for all calls to JavaScript find().
  1354.  * The lower level find functions fe_find_refresh_data() and fe_FindDialog()
  1355.  * which eventually get called from both the front end and FE_FindCommand()
  1356.  * use fe_findcommand_context() to determine if they are being called
  1357.  * by JavaScript or by the front end.  A call to FE_FindCommand() ensures that
  1358.  * fe_findcommand_context() returns non-NULL.  Calls to fe_find_cb() and
  1359.  * fe_find_again_cb() ensure that fe_find_command_context() returns NULL.
  1360.  *
  1361.  */
  1362.  
  1363.  
  1364. /*
  1365.  *  Written to by FE_FindCommand() and fe_unset_findcommand_context()
  1366.  */
  1367. static MWContext * private_fe_findcommand_context = 0;
  1368.  
  1369.  
  1370. /****************************************
  1371.  *
  1372.  */
  1373.  
  1374. extern "C" MWContext * fe_findcommand_context()
  1375.  
  1376. /*
  1377.  * returns:
  1378.  *    NULL whenever a find is being performed after
  1379.  *    fe_find_cb() and fe_find_again_cb() have been called.
  1380.  *    This means that these callback functions call
  1381.  *    fe_unset_findcommand_context().  Lower level find
  1382.  *    functions such as fe_find_refresh_data() and fe_FindDialog()
  1383.  *    determine the context which currently has focus to do the find.
  1384.  *
  1385.  *    non-NULL whenever a find is being performed as a result
  1386.  *    of FE_FindCommand().  Lower level find functions should
  1387.  *    use this context for the find.
  1388.  *
  1389.  ****************************************/
  1390. {
  1391.   return private_fe_findcommand_context;
  1392. }
  1393.  
  1394.  
  1395. /****************************************
  1396.  *
  1397.  */
  1398.  
  1399. extern "C" void fe_unset_findcommand_context()
  1400.  
  1401. /*
  1402.  * description:
  1403.  *    Called by fe_find_cb() and fe_find_again_cb()
  1404.  *    so that lower level functions do the same thing
  1405.  *    as they did in the past when find and find again
  1406.  *    menu items are chosen.
  1407.  *
  1408.  ****************************************/
  1409. {
  1410.   private_fe_findcommand_context = 0;
  1411. }
  1412.  
  1413.  
  1414.  
  1415. /****************************************
  1416.  *
  1417.  */
  1418.  
  1419. extern "C" XP_Bool
  1420. FE_FindCommand(MWContext *context,          /* in MOD: can this be mail or news? */
  1421.            char *  search_string,       /* in: NULL brings up dialog */
  1422.            XP_Bool b_is_case_sensitive, /* in */
  1423.            XP_Bool b_search_backwards,  /* in */
  1424.            XP_Bool /* b_wrap */)             /* ignored */
  1425.  
  1426. /*
  1427.  * description:
  1428.  *    Implemented to support the JavaScript
  1429.  *    find() function for Communicator 4.0.
  1430.  *
  1431.  *    The portion of this function which executes non-interactive
  1432.  *    searches endeavors to reproduce the relevant portions of
  1433.  *    the code which would be executed by calling
  1434.  *    frame->doCommand(xfeCmdFindAgain) without creating the find
  1435.  *    dialog box widgets.
  1436.  *
  1437.  * side effects:
  1438.  *    The fe_FindData member of the relevant context will be
  1439.  *    allocated if it doesn't already exist.
  1440.  *
  1441.  * returns:
  1442.  *    If search_string is NULL, always returns FALSE
  1443.  *    otherwise returns TRUE or FALSE depending on whether or not
  1444.  *    the string was found.
  1445.  *
  1446.  * comments:
  1447.  *    No meaningful return value is currently (Apr-97) possible
  1448.  *    when a dialog is brought up because the function immediately
  1449.  *    returns without waiting for the user to perform a find.
  1450.  *    Note that the user may cancel or do any number of searches
  1451.  *    before closing the dialog.
  1452.  *
  1453.  ****************************************/
  1454. {
  1455.   XP_Bool     result = FALSE;
  1456.   XFE_Frame * frame;
  1457.   CL_Layer  * layer;
  1458.  
  1459.   frame = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1460.   if (!frame)
  1461.     return result;
  1462.  
  1463.  
  1464.   private_fe_findcommand_context = context;
  1465.  
  1466.   /*
  1467.    *
  1468.    * BRING UP FIND DIALOG AKA FIND IN OBJECT
  1469.    *
  1470.    * if no search string is specified,
  1471.    * bring up a find dialog aka "find in object"
  1472.    * and return FALSE
  1473.    */
  1474.   if (!search_string) {
  1475.     if (frame->handlesCommand(xfeCmdFindInObject)
  1476.     && frame->isCommandEnabled(xfeCmdFindInObject)) {
  1477.       /* code adapted from commands.c:fe_find_cb */
  1478.       MWContext * top_context;
  1479.  
  1480.       top_context = XP_GetNonGridContext(context);
  1481.       if (!top_context)
  1482.     top_context = context;
  1483.  
  1484.       fe_UserActivity (top_context);
  1485.       fe_FindDialog(top_context, False);
  1486.     }
  1487.   }
  1488.   /*
  1489.    * NON-INTERACTIVE SEARCH AKA FIND AGAIN
  1490.    *
  1491.    * If a search string is given, do a non-interactive
  1492.    * search.
  1493.    */
  1494.   else {
  1495.     MWContext *   context_to_find;
  1496.     XFE_View *    view;
  1497.     fe_FindData * find_data;
  1498.     int           size;
  1499.     XP_Bool       b_allocated_locally = FALSE;
  1500.  
  1501.     /*
  1502.      * Get the appropriate context for the search.
  1503.      * This mimics what would be done in the function call stack
  1504.      * for frame->doCommand(xfeCmdFindAgain).
  1505.      */
  1506.     context_to_find = fe_findcommand_context();
  1507.     if (!context_to_find) {
  1508.       view = frame->getView();
  1509.       context_to_find = view->getContext();
  1510.     }
  1511.  
  1512.     /* ensure that an fe_FindData structure exists */
  1513.     find_data = CONTEXT_DATA(context_to_find)->find_data;
  1514.     if (!find_data) {
  1515.       /*
  1516.        * This section is modeled after fe_FindDialog() in dialogs.c
  1517.        */
  1518.       find_data = (fe_FindData *)XP_NEW_ZAP(fe_FindData); /* alloc and zero */
  1519.       b_allocated_locally = TRUE;
  1520.       CONTEXT_DATA(context_to_find)->find_data = find_data;
  1521.  
  1522.       find_data->context = context_to_find;
  1523.       find_data->find_in_headers = False;
  1524.       /* Q: as of this writing no support for mail/news headers? */
  1525.  
  1526.     }
  1527.     /* check that contexts point to eachother */
  1528.     XP_ASSERT(find_data->context == context_to_find);
  1529.  
  1530.     /*
  1531.      * Set the search parameters
  1532.      */
  1533.     if (find_data->string)
  1534.       XP_FREE(find_data->string);
  1535.     size = XP_STRLEN(search_string) + 1;
  1536.     find_data->string = (char*)XP_ALLOC(size);
  1537.     XP_STRCPY(find_data->string, search_string);
  1538.     find_data->case_sensitive_p  = b_is_case_sensitive;
  1539.     find_data->backward_p        = b_search_backwards;
  1540.  
  1541.     /*
  1542.      * This section modeled after fe_find() in dialogs.c
  1543.      */
  1544.     /* Q: what of ifdef EDITOR as in fe_find()? */
  1545.     LO_GetSelectionEndpoints(context_to_find,
  1546.                  &find_data->start_element,
  1547.                  &find_data->end_element,
  1548.                  &find_data->start_pos,
  1549.                  &find_data->end_pos,
  1550.                              &layer);
  1551.  
  1552.     result = LO_FindText(context_to_find, find_data->string,
  1553.              &find_data->start_element, &find_data->start_pos, 
  1554.              &find_data->end_element, &find_data->end_pos,
  1555.              find_data->case_sensitive_p, !find_data->backward_p);
  1556.     if (result) {
  1557.       /*
  1558.        * This section is an exact cut and paste from fe_find().  Ugh!
  1559.        */
  1560.       int32 x, y;
  1561.       LO_SelectText (context_to_find,
  1562.              find_data->start_element, find_data->start_pos,
  1563.              find_data->end_element, find_data->end_pos,
  1564.              &x, &y);
  1565.  
  1566.       /* If the found item is not visible on the screen, scroll to it.
  1567.      If we need to scroll, attempt to position the destination
  1568.      coordinate in the middle of the window.
  1569.      */
  1570.       if (x >= CONTEXT_DATA (context_to_find)->document_x &&
  1571.       x <= (CONTEXT_DATA (context_to_find)->document_x +
  1572.         CONTEXT_DATA (context_to_find)->scrolled_width))
  1573.     x = CONTEXT_DATA (context_to_find)->document_x;
  1574.       else
  1575.     x = x - (CONTEXT_DATA (context_to_find)->scrolled_width / 2);
  1576.  
  1577.       if (y >= CONTEXT_DATA (context_to_find)->document_y &&
  1578.       y <= (CONTEXT_DATA (context_to_find)->document_y +
  1579.         CONTEXT_DATA (context_to_find)->scrolled_height))
  1580.     y = CONTEXT_DATA (context_to_find)->document_y;
  1581.       else
  1582.     y = y - (CONTEXT_DATA (context_to_find)->scrolled_height / 2);
  1583.  
  1584.       if (x + CONTEXT_DATA (context_to_find)->scrolled_width
  1585.       > CONTEXT_DATA (context_to_find)->document_width)
  1586.     x = (CONTEXT_DATA (context_to_find)->document_width -
  1587.          CONTEXT_DATA (context_to_find)->scrolled_width);
  1588.  
  1589.       if (y + CONTEXT_DATA (context_to_find)->scrolled_height
  1590.       > CONTEXT_DATA (context_to_find)->document_height)
  1591.     y = (CONTEXT_DATA (context_to_find)->document_height -
  1592.          CONTEXT_DATA (context_to_find)->scrolled_height);
  1593.  
  1594.       if (x < 0) x = 0;
  1595.       if (y < 0) y = 0;
  1596.  
  1597.       fe_ScrollTo (context_to_find, x, y);
  1598.     }
  1599.  
  1600.     /*
  1601.      * clean up after ourselves so that the widget text
  1602.      * field doesn't get confused during a subsequent
  1603.      * find dialog.
  1604.      */
  1605.     if (b_allocated_locally) {
  1606.       if (find_data->string)
  1607.     XP_FREE(find_data->string);
  1608.       XP_FREE(find_data);
  1609.       CONTEXT_DATA(context_to_find)->find_data = 0;
  1610.     }
  1611.   }
  1612.     
  1613.     
  1614.  
  1615.   return result;
  1616. }
  1617.  
  1618.  
  1619. extern "C" void
  1620. FE_GetPixelAndColorDepth(MWContext *pContext, /* input parameter */
  1621.              int32 *pixelDepth, /* output parameter */
  1622.              int32 *colorDepth) /* output parameter */
  1623. /*
  1624.  * description:
  1625.  *    Determine pixel depth and color depth.
  1626.  *    Pixel depth is the number of bits per pixel.
  1627.  *    Color depth is the number of color palette entries
  1628.  *    expressed as a power of two.  E.g. the color depth is 8
  1629.  *    for a palette with 256 colors.  In general the color depth
  1630.  *    is greater than or the same as the pixel depth.
  1631.  *
  1632.  * preconditions:
  1633.  *    All arguments must be non-NULL.
  1634.  *
  1635.  * returns:
  1636.  *    Return values are placed in pixelDepth and colorDepth
  1637.  *
  1638.  */
  1639. {
  1640.   XFE_DisplayFactory * factory;
  1641.   XFE_Frame *          frame;
  1642.   fe_colormap *        colormap;
  1643.  
  1644.   if (!pContext || !pixelDepth || !colorDepth)
  1645.     return;
  1646.  
  1647.   factory = XFE_DisplayFactory::theFactory();
  1648.   frame   = ViewGlue_getFrame(XP_GetNonGridContext(pContext));
  1649.   if (!factory || !frame)
  1650.     return;
  1651.  
  1652.   colormap = frame->getColormap();
  1653.   if (!colormap)
  1654.     return;
  1655.  
  1656.   *pixelDepth = factory->getVisualDepth();
  1657.   *colorDepth = fe_ColorDepth(colormap);
  1658. }
  1659.  
  1660.  
  1661. Boolean
  1662. fe_IsPageLoaded (MWContext *context)
  1663. {
  1664.   int i = 1;
  1665.   MWContext * child;
  1666.   
  1667.   if (context == NULL)
  1668.     return FALSE;
  1669.   
  1670.   if (NET_AreThereActiveConnectionsForWindow(context))
  1671.     return FALSE;
  1672.   
  1673.   if (context->mocha_context && JS_IsRunning(context->mocha_context))
  1674.     return FALSE;
  1675.   
  1676.   while ((child = (MWContext*)XP_ListGetObjectNum (context->grid_children,
  1677.                            i++)))
  1678.     if (!fe_IsPageLoaded(child))
  1679.       return FALSE;
  1680.   
  1681.   return TRUE;
  1682. }
  1683.  
  1684. MWContext *
  1685. xfe2_MakeNewWindow(Widget toplevel, MWContext *context_to_copy,
  1686.                    URL_Struct *url, char *window_name, MWContextType type,
  1687.                    Boolean /* skip_get_url */, Chrome *decor)
  1688. {
  1689.     XFE_Frame *parent_frame = context_to_copy ? ViewGlue_getFrame(context_to_copy) : 0;
  1690.     MWContext *new_context = 0;
  1691.  
  1692.     switch (type)
  1693.         {
  1694.         case MWContextSaveToDisk:
  1695.             {
  1696.                 new_context = fe_showDownloadWindow(toplevel, parent_frame);
  1697.                 break;
  1698.             }
  1699.         case MWContextBrowser:
  1700.             {
  1701.                 new_context = fe_showBrowser(toplevel, parent_frame, decor, url);
  1702.                 break;
  1703.             }
  1704.         case MWContextDialog:
  1705.             {
  1706.                 new_context = fe_showHTMLDialog(toplevel, parent_frame, decor);
  1707.                 break;
  1708.             }
  1709. #ifdef EDITOR
  1710.         case MWContextEditor:
  1711.             {
  1712.                 new_context = fe_showEditor(toplevel, parent_frame, decor, url);
  1713.                 break;
  1714.             }
  1715. #endif
  1716. #ifdef MOZ_MAIL_NEWS
  1717.         case MWContextMail:
  1718.         case MWContextNews: // shouldn't happen anymore...
  1719.             {
  1720.                 MSG_PaneType paneType = url ? MSG_PaneTypeForURL(url->address) : MSG_FOLDERPANE;
  1721.  
  1722.                 switch (paneType)
  1723.                     {
  1724.                     case MSG_FOLDERPANE:
  1725.                         {
  1726.                             new_context = fe_showFolders(toplevel, parent_frame, decor);
  1727.                             break;
  1728.                         }
  1729.                     case MSG_THREADPANE:
  1730.                         {
  1731.                             MSG_FolderInfo *folder = MSG_GetFolderInfoFromURL(fe_getMNMaster(), url->address);
  1732.                             if (folder)
  1733.                                 new_context = fe_showMessages(toplevel, parent_frame, decor, 
  1734.                                                        folder, fe_globalPrefs.reuse_thread_window, FALSE, MSG_MESSAGEKEYNONE);
  1735.                             break;
  1736.                         }
  1737.                     case MSG_MESSAGEPANE:
  1738.                         {
  1739.                             MSG_FolderInfo *folder = MSG_GetFolderInfoFromURL(fe_getMNMaster(), url->address);
  1740.                             MSG_MessageLine msgLine;
  1741.                             MessageKey key = MSG_MESSAGEKEYNONE;
  1742.  
  1743.                             if (MSG_GetMessageLineForURL(fe_getMNMaster(), url->address, &msgLine) >= 0)
  1744.                                 key = msgLine.messageKey;
  1745.  
  1746.                             if (folder != NULL
  1747.                                 && key != MSG_MESSAGEKEYNONE)
  1748.                                 {
  1749.                                     new_context = fe_showMsg(toplevel, parent_frame, decor, 
  1750.                                                              folder, key,
  1751.                                                              FALSE);
  1752.                                 }
  1753.                             else
  1754.                                 {
  1755.                                     /* let's try and be generous here, since we really *should* pop up a window
  1756.                                        in this case.*/
  1757.                                     XFE_MsgFrame *frame = new XFE_MsgFrame(toplevel, parent_frame, decor);
  1758.  
  1759.                                     frame->show();
  1760.  
  1761.                                     new_context = frame->getContext();
  1762.  
  1763.                                     FE_GetURL(new_context, url);
  1764.                                 }
  1765.                             break;
  1766.                         }
  1767.                     default:
  1768.                       // XP_ASSERT(0);
  1769. #ifdef DEBUG_spence                      
  1770.                             printf ("unknown paneType\n");
  1771. #endif
  1772.                         break;
  1773.                     }
  1774.             }
  1775.             break;
  1776.         case MWContextSearch:
  1777.             {
  1778. #ifdef DEBUG_dora
  1779.                 printf("[Warning]Want to create a search in fe_MakeNewWidget...\n");
  1780. #endif
  1781.                 /* This should not be called here anymore in the new xfe2 design
  1782.                    We may consider remove this line all together....
  1783.                    Do we allow remote stuff to kick off the search without
  1784.                    Mail even being invoked?! If not, definitely remove this part here
  1785.                    */
  1786.                 new_context = fe_showSearch(toplevel, parent_frame, decor);
  1787.                 break;
  1788.             }
  1789.         case MWContextSearchLdap:
  1790.             {
  1791. #ifdef DEBUG_dora
  1792.                 printf("[Warning]Want to create a ldap search in fe_MakeNewWidget...\n");
  1793. #endif
  1794.                 /* This should not be called here anymore in the new xfe2 design
  1795.                    We may consider remove this line all together....
  1796.                    Do we allow remote stuff to kick off the search without
  1797.                    Mail even being invoked?! If not, definitely remove this part here
  1798.                    */
  1799.                 new_context = fe_showLdapSearch(toplevel, parent_frame, decor);
  1800.                 break;
  1801.             }
  1802.         case MWContextMessageComposition:
  1803.             {
  1804.                 MSG_Pane *pane;
  1805. #ifdef DEBUG_dora
  1806.                 printf("Calling fe_MakeNewWindow for MWContextMessageComposition\n" );
  1807. #endif
  1808.                 pane = fe_showCompose(toplevel, decor, context_to_copy, NULL, NULL, False, False);
  1809.                 if (pane) 
  1810.                     new_context = MSG_GetContext(pane);
  1811.                 break;
  1812.             }
  1813.         case MWContextAddressBook:
  1814.             {
  1815.                 new_context = fe_showAddrBook (toplevel, NULL, decor);
  1816.                 break;
  1817.             }
  1818. #endif  // MOZ_MAIL_NEWS
  1819.         default:
  1820.             XP_ASSERT(0);
  1821.             break;
  1822.         }
  1823.  
  1824.     // setup the stderr dialog stuff
  1825.     fe_initialize_stderr ();
  1826.  
  1827.     if (new_context && window_name)
  1828.       new_context->name = strdup (window_name);
  1829.     return new_context;
  1830. }
  1831.  
  1832.  
  1833. /****************************************
  1834.  */
  1835.  
  1836. XP_Bool FE_IsNetcasterInstalled(void)
  1837.  
  1838. /*
  1839.  * description:
  1840.  *
  1841.  *
  1842.  * returns:
  1843.  *    TRUE or FALSE
  1844.  *
  1845.  ****************************************/
  1846. {
  1847.   return fe_IsNetcasterInstalled();
  1848. }
  1849.  
  1850.  
  1851. /****************************************
  1852.  */
  1853.  
  1854. void FE_RunNetcaster(MWContext * /* context */)
  1855.  
  1856. /*
  1857.  * description:
  1858.  *    The implementation is expected to
  1859.  *    be platform-specific, therefore the
  1860.  *    code goes here.
  1861.  *
  1862.  ****************************************/
  1863. {
  1864.   fe_showNetcaster(FE_GetToplevelWidget());
  1865. }
  1866.  
  1867. #ifdef IRIX
  1868. /****************************************
  1869.  *
  1870.  * SGI-specific debugging hack to workaround broken
  1871.  * interaction between NSPR and dbx/cvd.
  1872.  *
  1873.  * When you hit a breakpoint in dbx, type:
  1874.  *     "ccall fe_sgiStop()"
  1875.  *
  1876.  * dbx step and next commands will now work as expected
  1877.  * instead of hanging or dumping you in sigtramp()
  1878.  *
  1879.  * After you finish debugging, return to normal thread
  1880.  * operation by typing:
  1881.  *      "ccall fe_sgiStart()
  1882.  *
  1883.  * (It's not clear what will go wrong if you fail to restart
  1884.  * SIGALRM processing.)
  1885.  *****************************************/
  1886. #include <signal.h>
  1887.  
  1888. extern "C" void fe_sgiStart()
  1889. {
  1890.     sigset_t t;
  1891.     sigaddset(&t,SIGALRM);    
  1892.     sigprocmask(SIG_UNBLOCK,&t,NULL);
  1893.     
  1894. }
  1895.  
  1896. extern "C" void fe_sgiStop()
  1897. {
  1898.     sigset_t t;
  1899.     sigaddset(&t,SIGALRM);
  1900.     sigprocmask(SIG_BLOCK,&t,NULL);
  1901. }
  1902.  
  1903. #endif
  1904.  
  1905.  
  1906. //////////////////////////////////////////////////////////////////////////
  1907. //
  1908. // Progress functions.  Used to live in xfe/thermo.c
  1909. //
  1910. //////////////////////////////////////////////////////////////////////////
  1911.  
  1912. static void fe_frameNotifyLogoStopAnimation        (MWContext *);
  1913. static void fe_frameNotifyLogoStartAnimation    (MWContext *);
  1914.  
  1915. static void fe_frameNotifyProgressUpdateText    (MWContext *,char *);
  1916. static void fe_frameNotifyProgressUpdatePercent    (MWContext *,int);
  1917.  
  1918. static void    fe_frameNotifyProgressTickCylon        (MWContext *);
  1919.  
  1920. static void fe_frameNotifyStatusUpdateText        (MWContext *,char *);
  1921.  
  1922. //////////////////////////////////////////////////////////////////////////
  1923. static void
  1924. fe_frameNotifyLogoStartAnimation(MWContext * context)
  1925. {
  1926.     XP_ASSERT( context != NULL );
  1927.  
  1928.     if (!CHECK_CONTEXT_AND_DATA(context))
  1929.     {
  1930.         return;
  1931.     }
  1932.  
  1933.     CONTEXT_DATA(context)->logo_animation_running = True;
  1934.  
  1935.     // Try to get the xfe frame for the context
  1936.     XFE_Frame * frame = fe_frameFromMWContext(context);
  1937.     
  1938.     // There will be no frame for biff context so we ignore them
  1939.     if (!frame)
  1940.     {
  1941.         return;
  1942.     }
  1943.  
  1944.     // Notify the frame to start animating the logo
  1945.     frame->notifyInterested(XFE_Frame::logoStartAnimation,(void *) NULL);
  1946. }
  1947. //////////////////////////////////////////////////////////////////////////
  1948. static void
  1949. fe_frameNotifyLogoStopAnimation(MWContext * context)
  1950. {
  1951.     XP_ASSERT( context != NULL );
  1952.  
  1953.     if (!CHECK_CONTEXT_AND_DATA(context))
  1954.     {
  1955.         return;
  1956.     }
  1957.  
  1958.     CONTEXT_DATA(context)->logo_animation_running = False;
  1959.  
  1960.     // Try to get the xfe frame for the context
  1961.     XFE_Frame * frame = fe_frameFromMWContext(context);
  1962.     
  1963.     // There will be no frame for biff context so we ignore them
  1964.     if (!frame)
  1965.     {
  1966.         return;
  1967.     }
  1968.  
  1969.     // Notify the frame to stop animating the logo
  1970.     frame->notifyInterested(XFE_Frame::logoStopAnimation,(void *) NULL);
  1971. }
  1972. //////////////////////////////////////////////////////////////////////////
  1973. static void
  1974. fe_frameNotifyProgressUpdateText(MWContext * context,char * text)
  1975. {
  1976.     XP_ASSERT( context != NULL );
  1977.  
  1978.     if (!CHECK_CONTEXT_AND_DATA(context))
  1979.     {
  1980.         return;
  1981.     }
  1982.  
  1983.     // Try to get the xfe frame for the context
  1984.     XFE_Frame * frame = fe_frameFromMWContext(context);
  1985.     
  1986.     // There will be no frame for biff context so we ignore them
  1987.     if (!frame)
  1988.     {
  1989.         return;
  1990.     }
  1991.  
  1992.     // Notify the frame to update the progress text
  1993.     frame->notifyInterested(XFE_Frame::progressBarUpdateText,(void *) text);
  1994. }
  1995. //////////////////////////////////////////////////////////////////////////
  1996. static void
  1997. fe_frameNotifyProgressUpdatePercent(MWContext * context,int percent)
  1998. {
  1999.     XP_ASSERT( context != NULL );
  2000.  
  2001.     if (!CHECK_CONTEXT_AND_DATA(context))
  2002.     {
  2003.         return;
  2004.     }
  2005.  
  2006.     // Try to get the xfe frame for the context
  2007.     XFE_Frame * frame = fe_frameFromMWContext(context);
  2008.     
  2009.     // There will be no frame for biff context so we ignore them
  2010.     if (!frame)
  2011.     {
  2012.         return;
  2013.     }
  2014.  
  2015.     // Notify the frame to update the progress percent
  2016.     frame->notifyInterested(XFE_Frame::progressBarUpdatePercent,
  2017.                             (void *) percent);
  2018. }
  2019.  
  2020. //////////////////////////////////////////////////////////////////////////
  2021. static void
  2022. fe_frameNotifyProgressTickCylon(MWContext * context)
  2023. {
  2024.     XP_ASSERT( context != NULL );
  2025.  
  2026.     if (!CHECK_CONTEXT_AND_DATA(context))
  2027.     {
  2028.         return;
  2029.     }
  2030.  
  2031.     // Try to get the xfe frame for the context
  2032.     XFE_Frame * frame = fe_frameFromMWContext(context);
  2033.     
  2034.     // There will be no frame for biff context so we ignore them
  2035.     if (!frame)
  2036.     {
  2037.         return;
  2038.     }
  2039.  
  2040.     // Notify the frame to tick cylon mode
  2041.     frame->notifyInterested(XFE_Frame::progressBarCylonTick);
  2042. }
  2043. //////////////////////////////////////////////////////////////////////////
  2044. static void
  2045. fe_frameNotifyStatusUpdateText(MWContext * context,char * text)
  2046. {
  2047.     XP_ASSERT( context != NULL );
  2048.  
  2049.     if (!CHECK_CONTEXT_AND_DATA(context))
  2050.     {
  2051.         return;
  2052.     }
  2053.  
  2054.     // Try to get the xfe frame for the context
  2055.     XFE_Frame * frame = fe_frameFromMWContext(context);
  2056.     
  2057.     // There will be no frame for biff context so we ignore them
  2058.     if (!frame)
  2059.     {
  2060.         return;
  2061.     }
  2062.  
  2063.     char * message = text;
  2064.  
  2065.     if (message == 0 || *message == '\0')
  2066.     {
  2067.         message = context->defaultStatus;
  2068.     }
  2069.     
  2070.     // Notify the frame to update the status text
  2071.     frame->notifyInterested(XFE_View::statusNeedsUpdating,(void*) message);
  2072. }
  2073. //////////////////////////////////////////////////////////////////////////
  2074.  
  2075.  
  2076. /* Print a status message in the wholine.
  2077.    A pointer to the string is not retained.
  2078.    */
  2079. //////////////////////////////////////////////////////////////////////////
  2080. extern "C" void
  2081. XFE_Progress(MWContext * context, const char * message)
  2082. {
  2083.  
  2084. #ifdef DEBUG_PROGRESS
  2085.     printf("XFE_Progress(%s)\n",message ? message : "BLANK");
  2086. #endif
  2087.  
  2088.     fe_frameNotifyStatusUpdateText(context,(char *) message);
  2089. }
  2090. //////////////////////////////////////////////////////////////////////////
  2091.  
  2092.  
  2093. /* This is so that we (attempt) to update the display at least once a second,
  2094.    even if the network library isn't calling us (as when the remote host is
  2095.    being slow.) 
  2096.    */
  2097. static void
  2098. fe_progress_dialog_timer (XtPointer closure, XtIntervalId * /* id */)
  2099. {
  2100.   MWContext *context = (MWContext *) closure;
  2101.  
  2102.   if (!CHECK_CONTEXT_AND_DATA(context))
  2103.   {
  2104.       return;
  2105.   }
  2106.  
  2107.   fe_UpdateGraph (context, True);
  2108.   /* If we don't know the total length (meaning cylon-mode) update every
  2109.      1/10th second to make the slider buzz along.  Otherwise, if we know
  2110.      the length, only update every 1/2 second.
  2111.    */
  2112.   CONTEXT_DATA (context)->thermo_timer_id =
  2113.       XtAppAddTimeOut (fe_XtAppContext,
  2114.                        (CONTEXT_DATA (context)->thermo_lo_percent <= 0
  2115.                         ? 100
  2116.                         : 500),
  2117.                        fe_progress_dialog_timer, closure);
  2118. }
  2119.  
  2120. /* Start blinking the light and drawing the thermometer.
  2121.    This is done before the first call to FE_GraphProgressInit()
  2122.    to make sure that we indicate that we are busy before the
  2123.    first connection has been established.
  2124.  */
  2125. extern "C" void
  2126. fe_StartProgressGraph(MWContext * context)
  2127. {
  2128. #ifdef DEBUG_PROGRESS
  2129.     printf("fe_StartProgressGraph()\n");
  2130. #endif
  2131.  
  2132.     if (!CHECK_CONTEXT_AND_DATA(context))
  2133.     {
  2134.         return;
  2135.     }
  2136.     
  2137.     fe_frameNotifyLogoStartAnimation(context);
  2138.  
  2139.     time_t now = time ((time_t *) 0);
  2140.  
  2141.     CONTEXT_DATA (context)->thermo_start_time = now;
  2142.     CONTEXT_DATA (context)->thermo_last_update_time = now;
  2143.     CONTEXT_DATA (context)->thermo_data_start_time = 0;
  2144.  
  2145.     CONTEXT_DATA (context)->thermo_size_unknown_count = 0;
  2146.     CONTEXT_DATA (context)->thermo_total = 0;
  2147.     CONTEXT_DATA (context)->thermo_current = 0;
  2148.     CONTEXT_DATA (context)->thermo_lo_percent = 0;
  2149.  
  2150.     if (!CONTEXT_DATA (context)->thermo_timer_id)
  2151.     {
  2152.         fe_progress_dialog_timer ((XtPointer)context, 0);
  2153.     }
  2154. }
  2155.  
  2156. /* Shut off the progress graph and blinking light completely.
  2157.  */
  2158. extern "C" void
  2159. fe_StopProgressGraph(MWContext * context_in)
  2160. {
  2161. #ifdef DEBUG_PROGRESS
  2162.     printf("fe_StopProgressGraph()\n");
  2163. #endif
  2164.  
  2165.     MWContext * context = XP_GetNonGridContext(context_in);
  2166.  
  2167.     if (!CHECK_CONTEXT_AND_DATA(context))
  2168.     {
  2169.         return;
  2170.     }
  2171.  
  2172.     if (context == NULL) return;
  2173.  
  2174.     // Stop animating the logo
  2175.     fe_frameNotifyLogoStopAnimation(context);
  2176.  
  2177.     // Clear the progress bar
  2178.     fe_frameNotifyProgressUpdatePercent(context,0);
  2179.     fe_frameNotifyProgressUpdateText(context,"");
  2180.  
  2181.     if (CONTEXT_DATA (context)->thermo_timer_id)
  2182.     {
  2183.         XtRemoveTimeOut (CONTEXT_DATA (context)->thermo_timer_id);
  2184.  
  2185.         CONTEXT_DATA (context)->thermo_timer_id = 0;
  2186.     }
  2187.  
  2188.     /* Kludge to go out of "cylon mode" when we actually reach the end. */
  2189.     if (CONTEXT_DATA (context)->thermo_size_unknown_count > 0)
  2190.     {
  2191.         int size_guess = (CONTEXT_DATA (context)->thermo_total >
  2192.                           CONTEXT_DATA (context)->thermo_current
  2193.                           ? CONTEXT_DATA (context)->thermo_total
  2194.                           : CONTEXT_DATA (context)->thermo_current);
  2195.         CONTEXT_DATA (context)->thermo_size_unknown_count = 0;
  2196.         CONTEXT_DATA (context)->thermo_total = size_guess;
  2197.         CONTEXT_DATA (context)->thermo_current = size_guess;
  2198.     }
  2199.     /* Get the 100% message. */
  2200.     fe_UpdateGraph (context, True);
  2201.  
  2202.     /* Now clear the thermometer while not disturbing the text. */
  2203.     CONTEXT_DATA (context)->thermo_lo_percent = 0;
  2204.  
  2205.     fe_UpdateGraph (context, False);
  2206. }
  2207.  
  2208.  
  2209. /* Redraw the graph.  If text_too_p, then regenerate the textual message
  2210.    and/or move the cylon one tick if appropriate.  (We don't want to do
  2211.    this every time FE_GraphProgress() is called, just once a second or so.)
  2212.  */
  2213. extern "C" void 
  2214. fe_UpdateGraph(MWContext * context,Boolean text_too_p)
  2215. {
  2216.     double ratio_done;
  2217.     time_t now;
  2218.     int total_bytes, bytes_received;
  2219.     Boolean size_known_p;
  2220.  
  2221.     if (!CHECK_CONTEXT_AND_DATA(context))
  2222.     {
  2223.         return;
  2224.     }
  2225.  
  2226.     now = time ((time_t *) 0);
  2227.     total_bytes     = CONTEXT_DATA (context)->thermo_total;
  2228.     bytes_received  = CONTEXT_DATA (context)->thermo_current;
  2229.     size_known_p    = CONTEXT_DATA (context)->thermo_size_unknown_count <= 0;
  2230.  
  2231.     if (size_known_p && total_bytes > 0 && bytes_received > total_bytes)
  2232.     {
  2233. #if 0
  2234.         /* Netlib doesn't take into account the size of the headers, so this
  2235.            can actually go a bit over 100% (not by much, though.)  Prevent
  2236.            the user from seeing this bug...   But DO print a warning if we're
  2237.            way, way over the limit - more than 1k probably means the server
  2238.            is messed up. */
  2239.         if (bytes_received > total_bytes + 1024)
  2240.             fprintf (stderr, "%s: received %d bytes but only expected %d??\n",
  2241.                      fe_progname, bytes_received, total_bytes);
  2242. #endif
  2243.         bytes_received = total_bytes;
  2244.     }
  2245.  
  2246.     ratio_done = (size_known_p && total_bytes > 0
  2247.                   ? (((double) bytes_received) / ((double) total_bytes))
  2248.                   : 0);
  2249.  
  2250. #ifdef DEBUG_PROGRESS
  2251.     printf(" fe_UpdateGraph: %d/%d=%f (%d/%d) %s  -or-  %d%%\n",
  2252.            bytes_received, total_bytes,
  2253.            ratio_done,
  2254.            CONTEXT_DATA (context)->thermo_size_unknown_count,
  2255.            CONTEXT_DATA (context)->active_url_count,
  2256.            text_too_p ? "text" : "notext",
  2257.            CONTEXT_DATA (context)->thermo_lo_percent);
  2258. #endif
  2259.  
  2260.     /* Update the thermo each time we're called. */
  2261.  
  2262.     if (CONTEXT_DATA (context)->thermo_lo_percent >= 0)
  2263.         {
  2264.             int percent = CONTEXT_DATA(context)->thermo_lo_percent;
  2265.  
  2266.             // Update the progress percent
  2267.             fe_frameNotifyProgressUpdatePercent(context,percent);
  2268.         }
  2269.         else
  2270.         {
  2271.             fe_frameNotifyProgressTickCylon(context);
  2272.         }
  2273.  
  2274.     /* Only update text if a second or more has elapsed since last time.
  2275.      Unlike the cylon, which we update each time we are called with
  2276.      text_too_p == True (which is 4x a second or so.)
  2277.    */
  2278.     if (text_too_p && now >= (CONTEXT_DATA (context)->thermo_last_update_time +
  2279.                               CONTEXT_DATA (context)->progress_interval))
  2280.     {
  2281.         const char *msg = XP_ProgressText ((size_known_p ? total_bytes : 0),
  2282.                                            bytes_received, 
  2283.                                            CONTEXT_DATA (context)->thermo_start_time,
  2284.                                            now);
  2285.  
  2286.         CONTEXT_DATA (context)->thermo_last_update_time = now;
  2287.  
  2288.         if (msg && *msg)
  2289.             XFE_Progress (context, msg);
  2290.  
  2291. #ifdef DEBUG_PROGRESS
  2292.         fprintf (stderr, "====== %s\n", (msg ? msg : ""));
  2293. #endif
  2294.     }
  2295. }
  2296.  
  2297.  
  2298. /* Inform the user that a document is being transferred.
  2299.    URL is the url to which this report relates;
  2300.    bytes_received is how many bytes have been read;
  2301.    content_length is how large this document is (0 if unknown.)
  2302.    This is called from netlib as soon as we know the content length
  2303.     (or know that we don't know.)  It is called only once per document.
  2304.  */
  2305. extern "C" void
  2306. XFE_GraphProgressInit(MWContext *    context_in,
  2307.                       URL_Struct *    /* url_struct */,
  2308.                       int32            content_length)
  2309. {
  2310. #ifdef DEBUG_PROGRESS
  2311.     printf("XFE_GraphProgressInit(%ld)\n",content_length);
  2312. #endif
  2313.  
  2314.     MWContext * context = XP_GetNonGridContext(context_in);
  2315.  
  2316.     if (!CHECK_CONTEXT_AND_DATA(context))
  2317.     {
  2318.         return;
  2319.     }
  2320.  
  2321.     if (!CONTEXT_DATA(context)->thermo_timer_id)
  2322.     {
  2323.         /* Hey!  How did that get turned off?  Turn it back on. */
  2324.         fe_StartProgressGraph (context);
  2325.     }
  2326.     
  2327.     if (content_length == 0)
  2328.     {
  2329.         CONTEXT_DATA(context)->thermo_size_unknown_count++;
  2330.     }
  2331.     else
  2332.     {
  2333.         CONTEXT_DATA(context)->thermo_total += content_length;
  2334.     }
  2335. }
  2336.  
  2337. /* Remove --one-- transfer from the progress graph.
  2338.  */
  2339. extern "C" void
  2340. XFE_GraphProgressDestroy(MWContext *    context_in,
  2341.                          URL_Struct *    /* url */,
  2342.                          int32            content_length,
  2343.                          int32            total_bytes_read)
  2344. {
  2345. #ifdef DEBUG_PROGRESS
  2346.     printf("XFE_GraphProgressDestroy(%ld, %ld)\n",
  2347.            content_length, 
  2348.            total_bytes_read);
  2349. #endif
  2350.     
  2351.     MWContext * context = XP_GetNonGridContext(context_in);
  2352.     
  2353.     if (!CHECK_CONTEXT_AND_DATA(context))
  2354.     {
  2355.         return;
  2356.     }
  2357.     
  2358.     if (content_length == 0)
  2359.     {
  2360.         /* Now that this transfer is done, we finally know how big it was.
  2361.            This means that maybe we can go out of cylon mode and back into
  2362.            thermometer mode. */
  2363.         CONTEXT_DATA (context)->thermo_size_unknown_count--;
  2364.         CONTEXT_DATA (context)->thermo_total += total_bytes_read;
  2365.     }
  2366. }
  2367.  
  2368.  
  2369. /* Inform the user of current progress, somehow.
  2370.    URL is the url to which this report relates;
  2371.    bytes_received is how many bytes have been read;
  2372.    content_length is how large this document is (0 if unknown.)
  2373.    This is called from netlib, and may be called very frequently.
  2374.  */
  2375. extern "C" void
  2376. XFE_GraphProgress(MWContext *    context_in,
  2377.                   URL_Struct *    /* url_struct */,
  2378.                   int32            /* bytes_received */,
  2379.                   int32            bytes_since_last_time,
  2380.                   int32            /* content_length */)
  2381. {
  2382. #ifdef DEBUG_PROGRESS
  2383.     printf("XFE_GraphProgress(%ld, +%ld, %ld)\n",
  2384.            bytes_received, 
  2385.            bytes_since_last_time, 
  2386.            content_length);
  2387. #endif
  2388.     
  2389.     MWContext * context = XP_GetNonGridContext(context_in);
  2390.  
  2391.     if (!CHECK_CONTEXT_AND_DATA(context))
  2392.     {
  2393.         return;
  2394.     }
  2395.  
  2396.     if (CONTEXT_DATA (context)->thermo_data_start_time <= 0)
  2397.         /* This is the first chunk of bits to arrive. */
  2398.         CONTEXT_DATA (context)->thermo_data_start_time = time ((time_t *) 0);
  2399.     
  2400.     CONTEXT_DATA (context)->thermo_current += bytes_since_last_time;
  2401.  
  2402.     fe_UpdateGraph (context, False);
  2403. }
  2404.  
  2405. //////////////////////////////////////////////////////////////////////////
  2406. extern "C" void
  2407. XFE_SetProgressBarPercent(MWContext * context_in,int32 percent)
  2408. {
  2409. #ifdef DEBUG_PROGRESS
  2410.     printf("XFE_SetProgressBarPercent(%d)\n",percent);
  2411. #endif
  2412.  
  2413.     MWContext * context = XP_GetNonGridContext(context_in);
  2414.  
  2415.     if (!CHECK_CONTEXT_AND_DATA(context))
  2416.     {
  2417.         return;
  2418.     }
  2419.  
  2420. #ifndef LOU_OR_ERIC_REMOVED_EXPLICIT_CALL_TO_XFE_SETPROGRESSBAR_FROM_LAYOUT
  2421.     // Called during layout for print, do nothing
  2422.     if (CONTEXT_DATA(context) == NULL)
  2423.     {
  2424.         return;
  2425.     }
  2426. #endif
  2427.  
  2428. #ifdef EDITOR
  2429.     if (context->is_editor) 
  2430.     {
  2431.         /* the editor tells us 100% when it means 0 */
  2432.         if (percent == 100)
  2433.         {
  2434.             percent = 0;
  2435.         }
  2436.     }
  2437. #endif /* EDITOR */
  2438.  
  2439.     // Update the progress percent
  2440.     fe_frameNotifyProgressUpdatePercent(context,percent);
  2441.  
  2442.     // Clear the progress bar text for percent < 0
  2443.     if (percent < 0)
  2444.     {
  2445.         fe_frameNotifyProgressUpdateText(context,"");
  2446.     }
  2447.     else
  2448.     {
  2449.         if (percent > 100)
  2450.         {
  2451.             percent = 100;
  2452.         }
  2453.  
  2454.         char text[32];
  2455.         
  2456.         XP_SPRINTF(text,"%d%%",percent);
  2457.         
  2458.         // Update the progress text
  2459.         fe_frameNotifyProgressUpdateText(context,text);
  2460.     }
  2461.  
  2462.     CONTEXT_DATA(context)->thermo_lo_percent = percent;
  2463.  
  2464.     fe_UpdateGraph (context, True);
  2465. //    fe_UpdateGraph (context, False);
  2466. }
  2467. //////////////////////////////////////////////////////////////////////////
  2468.  
  2469. //////////////////////////////////////////////////////////////////////////
  2470. //
  2471. //   fe_NeutralizeFocus()
  2472. //
  2473. //   Move focus out of "Location:" and back to top-level.
  2474. //   Unfortunately, just focusing on the top-level doesn't do it - that
  2475. //   assigns focus to its first child, which may be the URL text field,
  2476. //   which is exactly what we're trying to avoid.  So, first try assigning
  2477. //   focus to a few other components if they exist.  Only try to assign focus
  2478. //   to the top level as a last resort.
  2479. //
  2480. //////////////////////////////////////////////////////////////////////////
  2481. extern "C" void
  2482. fe_NeutralizeFocus(MWContext * context)
  2483. {
  2484.     MWContext * top_context = XP_GetNonGridContext(context);
  2485.  
  2486.     XP_ASSERT( top_context != NULL );
  2487.  
  2488.     // Try to get the xfe frame for the context
  2489.     XFE_Frame * frame = fe_frameFromMWContext(top_context);
  2490.  
  2491.     // There will be no frame for biff context so we ignore them
  2492.     if (!frame)
  2493.     {
  2494.         return;
  2495.     }
  2496.  
  2497.     // Try the logo
  2498.     XFE_Logo * logo = frame->getLogo();
  2499.  
  2500.     if (logo && logo->processTraversal(XmTRAVERSE_CURRENT))
  2501.     {
  2502.         return;
  2503.     }
  2504.  
  2505.     // Try the dash board
  2506.     XFE_Dashboard * dash = frame->getDashboard();
  2507.  
  2508.     if (dash && dash->processTraversal(XmTRAVERSE_CURRENT))
  2509.     {
  2510.         return;
  2511.     }
  2512.  
  2513.     // Finally, try the top level widget
  2514.     XmProcessTraversal(CONTEXT_WIDGET(top_context),XmTRAVERSE_CURRENT);
  2515. }
  2516. //////////////////////////////////////////////////////////////////////////
  2517. extern "C" MWContext *FE_GetRDFContext(void) {
  2518.     MWContext *context = NULL;
  2519.     
  2520. /*    if(theApp.m_pRDFCX) {
  2521.         pRetval = theApp.m_pRDFCX->GetContext();
  2522.     }
  2523. */    
  2524.     return(fe_getBookmarkContext());
  2525. }
  2526.  
  2527. /* this is here so that we can get access to frame/component utilities
  2528.    like fe_frameFromMWContext()...
  2529.    */
  2530.  
  2531. #ifdef SHACK
  2532.  
  2533. extern "C" void
  2534. fe_showRDFView (Widget parent, int width, int height)
  2535. {
  2536. #ifdef DEBUG_spence
  2537.   printf ("fe_showRDFView\n");
  2538. #endif
  2539.  
  2540. #if 0
  2541.   XtVaSetValues (parent, XmNwidth, width, XmNheight, height, 0);
  2542.   XtRealizeWidget (parent);
  2543. #endif
  2544.  
  2545.   MWContext *context = fe_WidgetToMWContext (parent);
  2546.   XFE_Component *toplevel = fe_frameFromMWContext (context);
  2547.   XFE_View *view = new XFE_NavCenterView (toplevel, parent, NULL, context);
  2548.  
  2549.   if (view == NULL) {
  2550. #ifdef DEBUG_spence
  2551.     printf ("fe_showRDFView: view creation failed\n");
  2552. #endif
  2553.   }
  2554.  
  2555. #ifdef DEBUG_spence
  2556.   printf ("fe_showRDFView: width %d: height %d\n", width, height);
  2557. #endif
  2558.  
  2559.   XtVaSetValues (view->getBaseWidget(), XmNwidth, width, XmNheight, height, 0);
  2560.   XtRealizeWidget (parent);
  2561. }
  2562.  
  2563. #endif /* SHACK */
  2564.