home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / HistoryMenu.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.4 KB  |  322 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.    History.cpp -- class for doing the dynamic history menus
  20.    Created: Chris Toshok <toshok@netscape.com>, 19-Dec-1996.
  21.  */
  22.  
  23.  
  24.  
  25. #include "HistoryMenu.h"
  26. #include "HTMLView.h"
  27. #include "felocale.h"
  28. #include "intl_csi.h"
  29.  
  30. #include "xpgetstr.h"            // for XP_GetString()
  31. extern int XFE_UNTITLED;
  32.  
  33. #define MAX_ITEM_WIDTH 40
  34.  
  35. typedef struct HistoryCons {
  36.     XFE_HistoryMenu *menu;
  37.     int entry;
  38. } HistoryCons;
  39.  
  40. XFE_HistoryMenu::XFE_HistoryMenu(Widget w, XFE_Frame *frame)
  41. {
  42.   m_cascade = w;
  43.   m_parentFrame = frame;
  44.  
  45.   XtAddCallback(m_cascade, XmNdestroyCallback, destroy_cb, this);
  46.   
  47.   XtVaGetValues(m_cascade,
  48.         XmNsubMenuId, &m_submenu,
  49.         NULL);
  50.  
  51.   XtVaGetValues(m_submenu,
  52.         XmNnumChildren, &m_firstslot,
  53.         NULL);
  54.  
  55.   XP_ASSERT(m_submenu);
  56.  
  57.   m_parentFrame->registerInterest(XFE_HTMLView::newURLLoading,
  58.                   this,
  59.                   (XFE_FunctionNotification)historyHasChanged_cb);
  60.  
  61.   // make sure we initially install an update callback
  62.   historyHasChanged(NULL, NULL, NULL);
  63. }
  64.  
  65. XFE_HistoryMenu::~XFE_HistoryMenu()
  66. {
  67.   m_parentFrame->unregisterInterest(XFE_HTMLView::newURLLoading,
  68.                     this,
  69.                     (XFE_FunctionNotification)historyHasChanged_cb);
  70. }
  71.  
  72. void
  73. XFE_HistoryMenu::generate(Widget cascade, XtPointer /*clientData*/, XFE_Frame *frame)
  74. {
  75.   XFE_HistoryMenu *obj;
  76.  
  77.   obj = new XFE_HistoryMenu(cascade, frame);
  78. }
  79.  
  80. void
  81. XFE_HistoryMenu::activate_cb(Widget, XtPointer cd, XtPointer)
  82. {
  83.     HistoryCons *cons = (HistoryCons*)cd;
  84.     XFE_HistoryMenu *obj = cons->menu;
  85.     MWContext *context = obj->m_parentFrame->getContext();
  86.     History_entry *h;
  87.     URL_Struct *url;
  88.     int index = cons->entry;
  89.  
  90.     if (index < 0) return;
  91.     
  92.     h = SHIST_GetObjectNum (&context->hist, index);
  93.     
  94.     if (! h) return;
  95.     
  96.     url = SHIST_CreateURLStructFromHistoryEntry (context, h);
  97.     
  98.     if (obj->m_parentFrame->handlesCommand(xfeCmdOpenUrl, (void*)url))
  99.         obj->m_parentFrame->doCommand(xfeCmdOpenUrl, (void*)url);
  100. }
  101.  
  102. void
  103. XFE_HistoryMenu::arm_cb(Widget, XtPointer cd, XtPointer)
  104. {    
  105.     HistoryCons *cons = (HistoryCons*)cd;
  106.     XFE_HistoryMenu *obj = cons->menu;
  107.     MWContext *context = obj->m_parentFrame->getContext();
  108.     History_entry *h;
  109.     char *address;
  110.     int index = cons->entry;
  111.  
  112.     if (index < 0) return;
  113.     
  114.     h = SHIST_GetObjectNum (&context->hist, index);
  115.     
  116.     if (! h) return;
  117.     
  118.     address = h->address;
  119.     
  120.     if (!address) return;
  121.     
  122.     obj->m_parentFrame->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)address);
  123. }
  124.  
  125. void
  126. XFE_HistoryMenu::disarm_cb(Widget widget, XtPointer cd, XtPointer)
  127. {
  128.     HistoryCons *cons = (HistoryCons*)cd;
  129.     XFE_HistoryMenu *obj = cons->menu;
  130.     MWContext *context = obj->m_parentFrame->getContext();
  131.     History_entry *h;
  132.     char *address;
  133.     int index = cons->entry;
  134.  
  135.     XtVaGetValues (widget, XmNuserData, &index, 0);
  136.     
  137.     if (index < 0) return;
  138.     
  139.     h = SHIST_GetObjectNum (&context->hist, index);
  140.     
  141.     if (! h) return;
  142.     
  143.     address = h->address;
  144.     
  145.     if (!address) return;
  146.     
  147.     obj->m_parentFrame->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)"");
  148. }
  149.  
  150. void
  151. XFE_HistoryMenu::update()
  152. {
  153.   MWContext *context = m_parentFrame->getContext();
  154.   XP_List *history = SHIST_GetList (context);
  155.   XP_List *h;
  156.   History_entry *current;
  157.   History_entry *e;
  158.   int i;
  159. //  int cpos = 0;
  160.   int length = 0;
  161.   int menu_length;
  162.   Widget *kids = 0;
  163.   Cardinal nkids = 0;
  164.   Arg av [20];
  165.   int ac;
  166.   int max_length = 30;       /* spurious statistics up 15% this year. */
  167.   XmFontList font_list;
  168.   INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context);
  169.  
  170.   if (! history) return;
  171.   length = XP_ListCount (history);
  172.  
  173.   history = history->next;    /* How stupid!!! */
  174.   current = SHIST_GetCurrent (&context->hist);
  175.  
  176.   XtUnrealizeWidget (m_submenu);
  177.  
  178.   XtVaGetValues (m_submenu, XmNchildren, &kids, XmNnumChildren, &nkids, 0);
  179.  
  180.   if (nkids)
  181.     {
  182.       kids = &(kids[m_firstslot]);
  183.       nkids -= m_firstslot;
  184.      
  185.       if (nkids)
  186.         { 
  187.           XtUnmanageChildren (kids, nkids);
  188.       
  189.           fe_DestroyWidgetTree(kids, nkids);
  190.         }
  191.     }
  192.  
  193.   if (length > max_length)
  194.     menu_length = max_length;
  195.   else
  196.     menu_length = length;
  197.  
  198.   h = history;
  199.  
  200.   /* i is the history index and starts at 1.
  201.      pos is the index in the menu, with 0 being the first (topmost) item. */
  202.   for (i = length; i > 0; i--)
  203.       {
  204.           int pos = length - i;
  205.           XmString label;
  206.           char *title, *url;
  207.           char name [1024];
  208.           Widget button = NULL;
  209.           
  210.           e = SHIST_GetObjectNum (&context->hist, i);
  211.           if (! e) abort ();
  212.           
  213.           title = e->title;
  214.           url = e->address;
  215.           
  216.           if (title && !strcmp (title, XP_GetString(XFE_UNTITLED)))
  217.               title = 0;   /* You losers, don't do that to me! */
  218.           
  219.           ac = 0;
  220.           /* NULL in userData so the menu updating stuff will use XtName for the command string */
  221.           XtSetArg (av [ac], XmNuserData, NULL); ac++;
  222.  
  223.           /* The pulldown menu */
  224.           if (pos == menu_length - 1 && menu_length < length)
  225.               {
  226.                   button = XmCreateLabelGadget (m_submenu, "historyTruncated", av, ac);
  227.               }
  228.           else if (pos < menu_length)
  229.               {
  230.                   HistoryCons *cons = XP_NEW_ZAP(HistoryCons);
  231.  
  232.                   cons->menu = this;
  233.                   cons->entry = i;
  234.  
  235.                   fe_FormatDocTitle (title, url, name, 1024);
  236.                   INTL_MidTruncateString (INTL_GetCSIWinCSID(c), name, name,
  237.                                           MAX_ITEM_WIDTH);
  238.                   
  239.                   label = fe_ConvertToXmString ((unsigned char *) name,
  240.                                                 INTL_GetCSIWinCSID(c), NULL, XmFONT_IS_FONT, &font_list);
  241.                   XtSetArg (av [ac], XmNlabelString, label); ac++;
  242.                   if (e == current)
  243.                       {
  244.                           XtSetArg (av [ac], XmNset, True); ac++;
  245.                           XtSetArg (av [ac], XmNvisibleWhenOff, False); ac++;
  246.                           XtSetArg (av [ac], XmNindicatorType, XmN_OF_MANY); ac++;
  247.                           button = XmCreateToggleButtonGadget(m_submenu, xfeCmdOpenUrl, av, ac);
  248.                           // must be xfeCmdOpenUrl or sensitivity becomes a problem
  249.                           XtAddCallback (button, XmNvalueChangedCallback,
  250.                                          activate_cb, cons);
  251.                           XtAddCallback (button, XmNarmCallback,
  252.                                          arm_cb, cons);
  253.                           XtAddCallback (button, XmNdisarmCallback,
  254.                                          disarm_cb, cons);
  255.                       }
  256.                   else
  257.                       {
  258.                           button = XmCreatePushButtonGadget (m_submenu, xfeCmdOpenUrl, av, ac);
  259.                           XtAddCallback (button, XmNarmCallback, arm_cb,
  260.                                          cons);
  261.                           XtAddCallback (button, XmNdisarmCallback, disarm_cb,
  262.                                          cons);
  263.                           XtAddCallback (button, XmNactivateCallback, activate_cb,
  264.                                          cons);
  265.                       }
  266.  
  267.                   XtAddCallback(button, XmNdestroyCallback, free_cons_cb, cons);
  268.  
  269.                   XmStringFree (label);
  270.               }
  271.  
  272.           if (button != NULL)
  273.           {
  274.               XtManageChild(button);
  275.           }
  276.           
  277. //           if (e == current)
  278. //               cpos = length - i + 1;
  279.           h = h->next;
  280.       }
  281.   
  282.   XtRealizeWidget (m_submenu);
  283.   XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  284. }
  285.  
  286. void
  287. XFE_HistoryMenu::update_cb(Widget, XtPointer clientData, XtPointer)
  288. {
  289.   XFE_HistoryMenu *obj = (XFE_HistoryMenu*)clientData;
  290.  
  291.   obj->update();
  292. }
  293.  
  294. void
  295. XFE_HistoryMenu::destroy_cb(Widget, XtPointer clientData, XtPointer)
  296. {
  297.   XFE_HistoryMenu *obj = (XFE_HistoryMenu*)clientData;
  298.  
  299.   delete obj;
  300. }
  301.  
  302. void
  303. XFE_HistoryMenu::free_cons_cb(Widget, XtPointer clientData, XtPointer)
  304. {
  305.     XP_FREE(clientData);
  306. }
  307.  
  308. XFE_CALLBACK_DEFN(XFE_HistoryMenu, historyHasChanged)(XFE_NotificationCenter *,
  309.                               void *,
  310.                               void *)
  311. {
  312.   // This may seem stupid, but it keeps us from having more than
  313.   // one reference to this particular callback without having
  314.   // to worry about other cascadingCallbacks.
  315.  
  316.   // remove it if it's already there
  317.   XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  318.  
  319.   // and then add it back.
  320.   XtAddCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  321. }
  322.