No code changes, only comments. Makes the xfe LXR pages better. Approved by don. Thanks do Dawn Endico <dawn@cannibal.mi.org> for providing the patch. git-svn-id: svn://10.0.0.236/trunk@5087 18797224-902f-48f8-a5cc-f745e15eee43
325 lines
8.2 KiB
C++
325 lines
8.2 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
/*
|
|
HistoryMenu.cpp -- class for doing the dynamic history menus
|
|
Created: Chris Toshok <toshok@netscape.com>, 19-Dec-1996.
|
|
*/
|
|
|
|
|
|
|
|
#include "HistoryMenu.h"
|
|
#include "HTMLView.h"
|
|
#include "felocale.h"
|
|
#include "intl_csi.h"
|
|
|
|
#include <Xfe/MenuUtil.h> // for XfeDestroyMenuWidgetTree()
|
|
|
|
#include "xpgetstr.h" // for XP_GetString()
|
|
extern int XFE_UNTITLED;
|
|
|
|
|
|
#define MAX_ITEM_WIDTH 40
|
|
|
|
typedef struct HistoryCons {
|
|
XFE_HistoryMenu *menu;
|
|
int entry;
|
|
} HistoryCons;
|
|
|
|
XFE_HistoryMenu::XFE_HistoryMenu(Widget w, XFE_Frame *frame)
|
|
{
|
|
m_cascade = w;
|
|
m_parentFrame = frame;
|
|
|
|
XtAddCallback(m_cascade, XmNdestroyCallback, destroy_cb, this);
|
|
|
|
XtVaGetValues(m_cascade,
|
|
XmNsubMenuId, &m_submenu,
|
|
NULL);
|
|
|
|
XtVaGetValues(m_submenu,
|
|
XmNnumChildren, &m_firstslot,
|
|
NULL);
|
|
|
|
XP_ASSERT(m_submenu);
|
|
|
|
m_parentFrame->registerInterest(XFE_HTMLView::newURLLoading,
|
|
this,
|
|
(XFE_FunctionNotification)historyHasChanged_cb);
|
|
|
|
// make sure we initially install an update callback
|
|
historyHasChanged(NULL, NULL, NULL);
|
|
}
|
|
|
|
XFE_HistoryMenu::~XFE_HistoryMenu()
|
|
{
|
|
m_parentFrame->unregisterInterest(XFE_HTMLView::newURLLoading,
|
|
this,
|
|
(XFE_FunctionNotification)historyHasChanged_cb);
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::generate(Widget cascade, XtPointer /*clientData*/, XFE_Frame *frame)
|
|
{
|
|
XFE_HistoryMenu *obj;
|
|
|
|
obj = new XFE_HistoryMenu(cascade, frame);
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::activate_cb(Widget, XtPointer cd, XtPointer)
|
|
{
|
|
HistoryCons *cons = (HistoryCons*)cd;
|
|
XFE_HistoryMenu *obj = cons->menu;
|
|
MWContext *context = obj->m_parentFrame->getContext();
|
|
History_entry *h;
|
|
URL_Struct *url;
|
|
int index = cons->entry;
|
|
|
|
if (index < 0) return;
|
|
|
|
h = SHIST_GetObjectNum (&context->hist, index);
|
|
|
|
if (! h) return;
|
|
|
|
url = SHIST_CreateURLStructFromHistoryEntry (context, h);
|
|
|
|
if (obj->m_parentFrame->handlesCommand(xfeCmdOpenUrl, (void*)url))
|
|
obj->m_parentFrame->doCommand(xfeCmdOpenUrl, (void*)url);
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::arm_cb(Widget, XtPointer cd, XtPointer)
|
|
{
|
|
HistoryCons *cons = (HistoryCons*)cd;
|
|
XFE_HistoryMenu *obj = cons->menu;
|
|
MWContext *context = obj->m_parentFrame->getContext();
|
|
History_entry *h;
|
|
char *address;
|
|
int index = cons->entry;
|
|
|
|
if (index < 0) return;
|
|
|
|
h = SHIST_GetObjectNum (&context->hist, index);
|
|
|
|
if (! h) return;
|
|
|
|
address = h->address;
|
|
|
|
if (!address) return;
|
|
|
|
obj->m_parentFrame->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)address);
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::disarm_cb(Widget widget, XtPointer cd, XtPointer)
|
|
{
|
|
HistoryCons *cons = (HistoryCons*)cd;
|
|
XFE_HistoryMenu *obj = cons->menu;
|
|
MWContext *context = obj->m_parentFrame->getContext();
|
|
History_entry *h;
|
|
char *address;
|
|
int index = cons->entry;
|
|
|
|
XtVaGetValues (widget, XmNuserData, &index, 0);
|
|
|
|
if (index < 0) return;
|
|
|
|
h = SHIST_GetObjectNum (&context->hist, index);
|
|
|
|
if (! h) return;
|
|
|
|
address = h->address;
|
|
|
|
if (!address) return;
|
|
|
|
obj->m_parentFrame->notifyInterested(XFE_View::statusNeedsUpdatingMidTruncated, (void*)"");
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::update()
|
|
{
|
|
MWContext *context = m_parentFrame->getContext();
|
|
XP_List *history = SHIST_GetList (context);
|
|
XP_List *h;
|
|
History_entry *current;
|
|
History_entry *e;
|
|
int i;
|
|
// int cpos = 0;
|
|
int length = 0;
|
|
int menu_length;
|
|
Widget *kids = 0;
|
|
Cardinal nkids = 0;
|
|
Arg av [20];
|
|
int ac;
|
|
int max_length = 30; /* spurious statistics up 15% this year. */
|
|
XmFontList font_list;
|
|
INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context);
|
|
|
|
if (! history) return;
|
|
length = XP_ListCount (history);
|
|
|
|
history = history->next; /* How stupid!!! */
|
|
current = SHIST_GetCurrent (&context->hist);
|
|
|
|
XtUnrealizeWidget (m_submenu);
|
|
|
|
XtVaGetValues (m_submenu, XmNchildren, &kids, XmNnumChildren, &nkids, 0);
|
|
|
|
if (nkids)
|
|
{
|
|
kids = &(kids[m_firstslot]);
|
|
nkids -= m_firstslot;
|
|
|
|
if (nkids)
|
|
{
|
|
XtUnmanageChildren (kids, nkids);
|
|
|
|
XfeDestroyMenuWidgetTree(kids, nkids,False);
|
|
}
|
|
}
|
|
|
|
if (length > max_length)
|
|
menu_length = max_length;
|
|
else
|
|
menu_length = length;
|
|
|
|
h = history;
|
|
|
|
/* i is the history index and starts at 1.
|
|
pos is the index in the menu, with 0 being the first (topmost) item. */
|
|
for (i = length; i > 0; i--)
|
|
{
|
|
int pos = length - i;
|
|
XmString label;
|
|
char *title, *url;
|
|
char name [1024];
|
|
Widget button = NULL;
|
|
|
|
e = SHIST_GetObjectNum (&context->hist, i);
|
|
if (! e) abort ();
|
|
|
|
title = e->title;
|
|
url = e->address;
|
|
|
|
if (title && !strcmp (title, XP_GetString(XFE_UNTITLED)))
|
|
title = 0; /* You losers, don't do that to me! */
|
|
|
|
ac = 0;
|
|
/* NULL in userData so the menu updating stuff will use XtName for the command string */
|
|
XtSetArg (av [ac], XmNuserData, NULL); ac++;
|
|
|
|
/* The pulldown menu */
|
|
if (pos == menu_length - 1 && menu_length < length)
|
|
{
|
|
button = XmCreateLabelGadget (m_submenu, "historyTruncated", av, ac);
|
|
}
|
|
else if (pos < menu_length)
|
|
{
|
|
HistoryCons *cons = XP_NEW_ZAP(HistoryCons);
|
|
|
|
cons->menu = this;
|
|
cons->entry = i;
|
|
|
|
fe_FormatDocTitle (title, url, name, 1024);
|
|
INTL_MidTruncateString (INTL_GetCSIWinCSID(c), name, name,
|
|
MAX_ITEM_WIDTH);
|
|
|
|
label = fe_ConvertToXmString ((unsigned char *) name,
|
|
INTL_GetCSIWinCSID(c), NULL, XmFONT_IS_FONT, &font_list);
|
|
XtSetArg (av [ac], XmNlabelString, label); ac++;
|
|
if (e == current)
|
|
{
|
|
XtSetArg (av [ac], XmNset, True); ac++;
|
|
XtSetArg (av [ac], XmNvisibleWhenOff, False); ac++;
|
|
XtSetArg (av [ac], XmNindicatorType, XmN_OF_MANY); ac++;
|
|
button = XmCreateToggleButtonGadget(m_submenu, xfeCmdOpenUrl, av, ac);
|
|
// must be xfeCmdOpenUrl or sensitivity becomes a problem
|
|
XtAddCallback (button, XmNvalueChangedCallback,
|
|
activate_cb, cons);
|
|
XtAddCallback (button, XmNarmCallback,
|
|
arm_cb, cons);
|
|
XtAddCallback (button, XmNdisarmCallback,
|
|
disarm_cb, cons);
|
|
}
|
|
else
|
|
{
|
|
button = XmCreatePushButtonGadget (m_submenu, xfeCmdOpenUrl, av, ac);
|
|
XtAddCallback (button, XmNarmCallback, arm_cb,
|
|
cons);
|
|
XtAddCallback (button, XmNdisarmCallback, disarm_cb,
|
|
cons);
|
|
XtAddCallback (button, XmNactivateCallback, activate_cb,
|
|
cons);
|
|
}
|
|
|
|
XtAddCallback(button, XmNdestroyCallback, free_cons_cb, cons);
|
|
|
|
XmStringFree (label);
|
|
}
|
|
|
|
if (button != NULL)
|
|
{
|
|
XtManageChild(button);
|
|
}
|
|
|
|
// if (e == current)
|
|
// cpos = length - i + 1;
|
|
h = h->next;
|
|
}
|
|
|
|
XtRealizeWidget (m_submenu);
|
|
XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::update_cb(Widget, XtPointer clientData, XtPointer)
|
|
{
|
|
XFE_HistoryMenu *obj = (XFE_HistoryMenu*)clientData;
|
|
|
|
obj->update();
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::destroy_cb(Widget, XtPointer clientData, XtPointer)
|
|
{
|
|
XFE_HistoryMenu *obj = (XFE_HistoryMenu*)clientData;
|
|
|
|
delete obj;
|
|
}
|
|
|
|
void
|
|
XFE_HistoryMenu::free_cons_cb(Widget, XtPointer clientData, XtPointer)
|
|
{
|
|
XP_FREE(clientData);
|
|
}
|
|
|
|
XFE_CALLBACK_DEFN(XFE_HistoryMenu, historyHasChanged)(XFE_NotificationCenter *,
|
|
void *,
|
|
void *)
|
|
{
|
|
// This may seem stupid, but it keeps us from having more than
|
|
// one reference to this particular callback without having
|
|
// to worry about other cascadingCallbacks.
|
|
|
|
// remove it if it's already there
|
|
XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
|
|
|
|
// and then add it back.
|
|
XtAddCallback(m_cascade, XmNcascadingCallback, update_cb, this);
|
|
}
|