pjs/cmd/xfe/src/RDFUtils.cpp

749 строки
20 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.
*/
//////////////////////////////////////////////////////////////////////////
// //
// Name: RDFUtils.cpp //
// //
// Description: Misc RDF XFE specific utilities. //
// //
// Author: Ramiro Estrugo <ramiro@netscape.com> //
// //
//////////////////////////////////////////////////////////////////////////
#include "RDFUtils.h"
#include "IconGroup.h"
#include "BrowserFrame.h" // For fe_reuseBrowser()
#include "xp_str.h"
#include "xpassert.h"
#include "felocale.h" // For fe_ConvertToXmString()
#include "intl_csi.h" // For INTL_ functions
#include "prefapi.h" // For PREF_GetIntPref
#include "xfe.h" // For fe_FormatDocTitle()
#include <Xfe/Xfe.h> // For XfeIsAlive()
#include <Xfe/Label.h> // For XfeIsLabel()
#include <Xm/Label.h> // For XmIsLabel()
#include <Xfe/Button.h> // For XmBUTTON_ defines
#include <Xfe/BmButton.h> // For XfeIsBmButton()
#include <Xfe/BmCascade.h> // For XfeIsBmCascade()
#include "utf8xfe.h"
//////////////////////////////////////////////////////////////////////////
//
// XFE Command utilities
//
// Is the URL a 'special' command url that translates to an FE command ?
//
//////////////////////////////////////////////////////////////////////////
/*static*/ XP_Bool
XFE_RDFUtils::ht_IsFECommand(HT_Resource item)
{
const char* url = HT_GetNodeURL(item);
return (XP_STRNCMP(url, "command:", 8) == 0);
}
//////////////////////////////////////////////////////////////////////////
/*static*/ CommandType
XFE_RDFUtils::ht_GetFECommand(HT_Resource item)
{
const char* url = HT_GetNodeURL(item);
if (url && XP_STRNCMP(url, "command:", 8) == 0)
{
return Command::convertOldRemote(url + 8);
}
else
{
return NULL;
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// RDF folder and item utilities
//
//////////////////////////////////////////////////////////////////////////
/* static */ HT_Resource
XFE_RDFUtils::ht_FindFolderByName(HT_Resource root,
char * folder_name)
{
if (!root || !folder_name)
{
return NULL;
}
HT_Resource header;
char * header_name = HT_GetNodeName(root);
if(XP_STRCMP(header_name,folder_name) == 0)
{
return root;
}
HT_SetOpenState(root, PR_TRUE);
HT_Cursor child_cursor = HT_NewCursor(root);
HT_Resource child;
while ( (child = HT_GetNextItem(child_cursor)) )
{
if (HT_IsContainer(child))
{
header = ht_FindFolderByName(child, folder_name);
if(header != NULL)
{
HT_DeleteCursor(child_cursor);
return header;
}
}
}
HT_DeleteCursor(child_cursor);
return NULL;
}
//////////////////////////////////////////////////////////////////////////
/* static */ HT_Resource
XFE_RDFUtils::ht_FindItemByAddress(HT_Resource root,
const char * target_address)
{
if (!root || !target_address)
{
return NULL;
}
char * entry_address = HT_GetNodeURL(root);
if (entry_address && (XP_STRCMP(target_address,entry_address) == 0))
{
return root;
}
if (HT_IsContainer(root))
{
HT_Resource entry;
HT_SetOpenState(entry, PR_TRUE);
HT_Cursor child_cursor = HT_NewCursor(entry);
HT_Resource child;
while ( (child = HT_GetNextItem(child_cursor)) )
{
HT_Resource test_entry;
test_entry = ht_FindItemByAddress(entry,target_address);
if (test_entry)
{
HT_DeleteCursor(child_cursor);
return test_entry;
}
}
HT_DeleteCursor(child_cursor);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
/* static */ HT_Resource
XFE_RDFUtils::ht_FindNextItem(HT_Resource current)
{
if (current)
{
HT_View ht_view = HT_GetView(current);
uint32 index = HT_GetNodeIndex(ht_view, current);
return HT_GetNthItem(ht_view, index + 1);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
/* static */ HT_Resource
XFE_RDFUtils::ht_FindPreviousItem(HT_Resource current)
{
if (current)
{
HT_View ht_view = HT_GetView(current);
uint32 index = HT_GetNodeIndex(ht_view, current);
if (index > 0)
return HT_GetNthItem(ht_view, index - 1);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
/* static */ XP_Bool
XFE_RDFUtils::ht_FolderHasChildren(HT_Resource header)
{
XP_ASSERT( header != NULL );
XP_ASSERT( HT_IsContainer(header) );
return (HT_GetCountDirectChildren(header) > 0);
}
//////////////////////////////////////////////////////////////////////////
/* static */ XP_Bool
XFE_RDFUtils::ht_FolderHasFolderChildren(HT_Resource header)
{
XP_ASSERT( header != NULL );
XP_ASSERT( HT_IsContainer(header) );
HT_SetOpenState(header, PR_TRUE);
HT_Cursor child_cursor = HT_NewCursor(header);
HT_Resource child;
// Traverse until we find a header entry
while ( (child = HT_GetNextItem(child_cursor)) )
{
if (HT_IsContainer(child))
{
HT_DeleteCursor(child_cursor);
return True;
}
}
HT_DeleteCursor(child_cursor);
return False;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Guess the title for a url address
//
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::guessTitle(MWContext * context,
const char * address,
XP_Bool sameShell,
char ** guessedTitleOut,
time_t * guessedLastDateOut)
{
XP_ASSERT( context != NULL );
XP_ASSERT( address != NULL );
XP_ASSERT( guessedTitleOut != NULL );
XP_ASSERT( guessedLastDateOut != NULL );
// Initialize the results to begin with
*guessedLastDateOut = 0;
*guessedTitleOut = NULL;
// If the operation occurs in the same shell, look in the history.
if (sameShell)
{
// Obtain the current history entry
History_entry * hist_entry = SHIST_GetCurrent(&context->hist);
// Make sure the history entry matches the given address, or else
// the caller used a the same shell with a link that is not the
// the proxy icon (ie, in the html area).
if (hist_entry && (XP_STRCMP(hist_entry->address,address) == 0))
{
*guessedTitleOut = hist_entry->title;
*guessedLastDateOut = hist_entry->last_access;
}
}
#if 0
/* Currently don't for a static way to get the bookmarks */
// Look in the bookmarks for a dup
if (!*guessedTitleOut)
{
HT_Resource test_entry = NULL;
HT_Resource root_entry = getRootFolder();
if (root_entry)
{
test_entry = ht_FindItemByAddress(root_entry, address);
}
if (test_entry)
{
*guessedTitleOut = HT_GetNodeName(test_entry);
}
}
#endif
// As a last resort use the address itself as a title
if (!*guessedTitleOut)
{
*guessedTitleOut = (char *) address;
}
// Strip the leading http:// from the title
if (XP_STRLEN(*guessedTitleOut) > 7)
{
if ((XP_STRNCMP(*guessedTitleOut,"http://",7) == 0) ||
(XP_STRNCMP(*guessedTitleOut,"file://",7) == 0))
{
(*guessedTitleOut) += 7;
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// XmString hackery
//
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::entryToXmStringAndFontList(HT_Resource entry,
Display* dpy,
XmString* pStr,
XmFontList* pFontList)
{
XP_ASSERT( entry != NULL );
char *name = HT_GetNodeName(entry);
XFE_RDFUtils::utf8ToXmStringAndFontList(name, dpy, pStr, pFontList);
}
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::utf8ToXmStringAndFontList(char* utf8str,
Display* dpy,
XmString* pXmStr,
XmFontList* pFontList)
{
fe_Font uFont;
XmFontList dontFreeFontList;
// need to perform mid truncation here
// need to replace with UTF8 to XmString conversion and get FontList here
uFont = UnicodeFontSingleton::Instance(dpy, "helvetica", 120);
*pXmStr = fe_ConvertToXmString((unsigned char*) utf8str, CS_UTF8, uFont,
XmFONT_IS_FONT, &dontFreeFontList);
*pFontList = XmFontListCopy(dontFreeFontList);
}
//////////////////////////////////////////////////////////////////////////
/* static */ XmString
XFE_RDFUtils::formatItem(HT_Resource entry)
{
XmString xmstring;
char *data;
if (HT_IsSeparator(entry))
data = "-------------------------";
else
data = HT_GetNodeName(entry);
// need to replace with UTF8 to XmString conversion and get FontList here
xmstring = XmStringCreateLtoR(data ,XmSTRING_DEFAULT_CHARSET);
return (xmstring);
}
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::setItemLabelString(Widget item,
HT_Resource entry)
{
XP_ASSERT( entry != NULL );
char *name = HT_GetNodeName(entry);
setLabelString(item, name);
}
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::setLabelString(Widget item,
char* utf8text
)
{
XP_ASSERT( XfeIsAlive(item) );
XP_ASSERT( XmIsLabel(item) ||
XmIsLabelGadget(item) ||
XfeIsLabel(item) );
// Create am XmString from the entry
XmString xmname;
XmFontList fontlist = NULL;
XFE_RDFUtils::utf8ToXmStringAndFontList(utf8text, XtDisplay(item), &xmname, &fontlist);
if (xmname != NULL)
{
XtVaSetValues(item,XmNlabelString,xmname,XmNfontList, fontlist, NULL);
XmStringFree(xmname);
XmFontListFree(fontlist);
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Pixmap hackery
//
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::getPixmapsForEntry(Widget item,
HT_Resource entry,
Pixmap * pixmapOut,
Pixmap * maskOut,
Pixmap * armedPixmapOut,
Pixmap * armedMaskOut)
{
XP_ASSERT( entry != NULL );
XP_ASSERT( XfeIsAlive(item) );
IconGroup * ig = NULL;
// Right now the only way an entry can be NULL is for the
// bookmarkMoreButton which kinda looks and acts like a folder so
// we use folder pixmaps for it
if (!entry)
{
ig = &BM_Folder_group;
}
else
{
#ifdef NOT_YET
if (hasCustomIcon(entry)) {} /*else {*/
#endif /*NOT_YET*/
if (XFE_RDFUtils::ht_IsFECommand(entry))
{
const char* url = HT_GetNodeURL(entry);
ig = IconGroup_findGroupForName(url + 8);
}
else
{
if (HT_IsContainer(entry))
{
XP_Bool is_menu = False;//(entry == getMenuFolder());
XP_Bool is_add = False;//(entry == getAddFolder());
if (is_add && is_menu) ig = &BM_NewAndMenuFolder_group;
else if (is_add) ig = &BM_NewFolder_group;
else if (is_menu) ig = &BM_MenuFolder_group;
else ig = &BM_Folder_group;
}
else
{
int url_type = NET_URL_Type(HT_GetNodeURL(entry));
if (url_type == IMAP_TYPE_URL || url_type == MAILBOX_TYPE_URL)
ig = &BM_MailBookmark_group;
else if (url_type == NEWS_TYPE_URL)
ig = &BM_NewsBookmark_group;
else
ig = &BM_Bookmark_group;
}
}
}
Pixmap pixmap = XmUNSPECIFIED_PIXMAP;
Pixmap mask = XmUNSPECIFIED_PIXMAP;
Pixmap armedPixmap = XmUNSPECIFIED_PIXMAP;
Pixmap armedMask = XmUNSPECIFIED_PIXMAP;
if (ig)
{
Widget shell_for_colormap =
XfeAncestorFindByClass(item,shellWidgetClass,XfeFIND_ANY);
XP_ASSERT( XfeIsAlive(shell_for_colormap) );
IconGroup_createAllIcons(ig,
shell_for_colormap,
XfeForeground(item),
XfeBackground(item));
pixmap = ig->pixmap_icon.pixmap;
mask = ig->pixmap_icon.mask;
armedPixmap = ig->pixmap_mo_icon.pixmap;
armedMask = ig->pixmap_mo_icon.mask;
}
if (pixmapOut)
{
*pixmapOut = pixmap;
}
if (maskOut)
{
*maskOut = mask;
}
if (armedPixmapOut)
{
*armedPixmapOut = armedPixmap;
}
if (armedMaskOut)
{
*armedMaskOut = armedMask;
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Style and layout
//
//////////////////////////////////////////////////////////////////////////
/* static */ int32
XFE_RDFUtils::getStyleForEntry(HT_Resource entry)
{
XP_ASSERT( entry != NULL );
int32 style = BROWSER_TOOLBAR_TEXT_ONLY;
void * data = NULL;
// Get the Toolbar displaymode from HT
HT_GetTemplateData(HT_TopNode(HT_GetView(entry)),
gNavCenter->toolbarDisplayMode,
HT_COLUMN_STRING,
&data);
// No value provided initially. So get it from prefs and set in HT
if (!data)
{
/* int result = */ PREF_GetIntPref("browser.chrome.toolbar_style",
&style);
if (style == BROWSER_TOOLBAR_TEXT_ONLY)
{
HT_SetNodeData(HT_TopNode(HT_GetView(entry)),
gNavCenter->toolbarDisplayMode,
HT_COLUMN_STRING,
"text");
}
else if (style == BROWSER_TOOLBAR_ICONS_ONLY)
{
HT_SetNodeData(HT_TopNode(HT_GetView(entry)),
gNavCenter->toolbarDisplayMode,
HT_COLUMN_STRING,
"pictures");
}
else
{
HT_SetNodeData(HT_TopNode(HT_GetView(entry)),
gNavCenter->toolbarDisplayMode,
HT_COLUMN_STRING,
"PicturesAndText");
}
}
// Value is found in HT
else
{
char * answer = (char *) data;
if ((!XP_STRCASECMP(answer, "text")))
{
style = BROWSER_TOOLBAR_TEXT_ONLY;
}
else if ((!XP_STRCASECMP(answer, "icons")))
{
style = BROWSER_TOOLBAR_ICONS_ONLY;
}
else
{
style = BROWSER_TOOLBAR_ICONS_AND_TEXT;
}
}
return style;
}
//////////////////////////////////////////////////////////////////////////
/* static */ unsigned char
XFE_RDFUtils::getButtonLayoutForEntry(HT_Resource entry,int32 style)
{
XP_ASSERT( entry != NULL ) ;
unsigned char layout = XmBUTTON_LABEL_ONLY;
void * data = NULL;
if (style == BROWSER_TOOLBAR_ICONS_AND_TEXT)
{
// Get the Toolbar bitmap position from HT */
HT_GetTemplateData(HT_TopNode(HT_GetView(entry)),
gNavCenter->toolbarBitmapPosition,
HT_COLUMN_STRING,
&data);
if (data)
{
char * answer = (char *) data;
if ((!XP_STRCASECMP(answer, "top")))
{
layout = XmBUTTON_LABEL_ON_BOTTOM;
}
else if ((!XP_STRCASECMP(answer, "side")))
{
layout = XmBUTTON_LABEL_ON_RIGHT;
}
}
// Value not provided. It is top for command buttons and side
// for personal
else
{
if (XFE_RDFUtils::ht_IsFECommand(entry))
{
layout = XmBUTTON_LABEL_ON_BOTTOM;
}
else
{
layout = XmBUTTON_LABEL_ON_RIGHT;
}
}
}
else if (style == BROWSER_TOOLBAR_ICONS_ONLY)
{
layout = XmBUTTON_PIXMAP_ONLY;
}
else if (style == BROWSER_TOOLBAR_TEXT_ONLY)
{
layout = XmBUTTON_LABEL_ONLY;
}
return layout;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Menu items
//
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::configureMenuPushButton(Widget item,HT_Resource entry)
{
XP_ASSERT( XfeIsAlive(item) );
XP_ASSERT( entry != NULL );
// Pixmaps can only be set for XfeBmButton widgets
if (XfeIsBmButton(item))
{
int32 style;
PREF_GetIntPref("browser.chrome.style", &style);
if (style == BROWSER_TOOLBAR_TEXT_ONLY)
{
XtVaSetValues(item,
XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
XmNlabelPixmapMask, XmUNSPECIFIED_PIXMAP,
NULL);
}
else
{
Pixmap pixmap;
Pixmap mask;
XFE_RDFUtils::getPixmapsForEntry(item,
entry,
&pixmap,
&mask,
NULL,
NULL);
XtVaSetValues(item,
XmNlabelPixmap, pixmap,
XmNlabelPixmapMask, mask,
NULL);
}
}
}
//////////////////////////////////////////////////////////////////////////
/* static */ void
XFE_RDFUtils::configureMenuCascadeButton(Widget item,HT_Resource entry)
{
XP_ASSERT( XfeIsAlive(item) );
XP_ASSERT( entry != NULL );
// Pixmaps can only be set for XfeBmCascade widgets
if (XfeIsBmCascade(item))
{
int32 style;
PREF_GetIntPref("browser.chrome.style", &style);
if (style == BROWSER_TOOLBAR_TEXT_ONLY)
{
XtVaSetValues(item,
XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
XmNlabelPixmapMask, XmUNSPECIFIED_PIXMAP,
XmNarmPixmap, XmUNSPECIFIED_PIXMAP,
XmNarmPixmapMask, XmUNSPECIFIED_PIXMAP,
NULL);
}
else
{
Pixmap pixmap;
Pixmap mask;
Pixmap armedPixmap;
Pixmap armedMask;
XFE_RDFUtils::getPixmapsForEntry(item,
entry,
&pixmap,
&mask,
&armedPixmap,
&armedMask);
Arg av[4];
Cardinal ac = 0;
XtSetArg(av[ac],XmNlabelPixmap, pixmap); ac++;
XtSetArg(av[ac],XmNlabelPixmapMask, mask); ac++;
// Only show the armed pixmap/mask if this entry has children
if (XfeIsAlive(XfeCascadeGetSubMenu(item)))
{
XtSetArg(av[ac],XmNarmPixmap, armedPixmap); ac++;
XtSetArg(av[ac],XmNarmPixmapMask, armedMask); ac++;
}
XtSetValues(item,av,ac);
}
}
}
//////////////////////////////////////////////////////////////////////////
/*static*/
void
XFE_RDFUtils::launchEntry(MWContext * context,
HT_Resource entry)
{
if (!entry) return;
if (!HT_IsContainer(entry) && !HT_IsSeparator(entry))
{
// Let HT handle the launch first
if (!HT_Launch(entry, context))
{
char * address = HT_GetNodeURL(entry);
URL_Struct * url = NET_CreateURLStruct(address,NET_DONT_RELOAD);
XP_ASSERT( context != NULL );
fe_reuseBrowser (context, url);
}
}
}
//////////////////////////////////////////////////////////////////////////