fix for bug 29569, truncating mac menus better. Also pushes around and refactors a lot of our ugly i18n font code. r=sfraser.

This commit is contained in:
pinkerton%netscape.com 2000-07-28 23:12:43 +00:00
Родитель 90a621288c
Коммит 94bf195712
5 изменённых файлов: 168 добавлений и 283 удалений

Просмотреть файл

@ -246,7 +246,6 @@ NS_METHOD nsMenu::SetLabel(const nsString &aText)
SysBeep(30);
#endif
//mMacMenuHandle = NSStringNewChildMenu(mMacMenuID, mLabel);
mMacMenuHandle = ::GetMenuHandle(mMacMenuID);
} else {
#if !TARGET_CARBON
@ -347,7 +346,7 @@ NS_METHOD nsMenu::AddMenuItem(nsIMenuItem * aMenuItem)
//printf("%s \n", label.ToNewCString());
//printf("%d = mMacMenuID\n", mMacMenuID);
::InsertMenuItem(mMacMenuHandle, "\p(Blank menu item", currItemIndex);
NSStringSetMenuItemText(mMacMenuHandle, currItemIndex, label);
MenuHelpers::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter);
// I want to be internationalized too!
nsAutoString keyEquivalent; keyEquivalent.AssignWithConversion(" ");
@ -416,7 +415,7 @@ NS_METHOD nsMenu::AddMenu(nsIMenu * aMenu)
//printf("AddMenu %s \n", label.ToNewCString());
::InsertMenuItem(mMacMenuHandle, "\p(Blank Menu", currItemIndex);
NSStringSetMenuItemText(mMacMenuHandle, currItemIndex, label);
MenuHelpers::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter);
PRBool isEnabled;
aMenu->GetEnabled(&isEnabled);
@ -1025,191 +1024,30 @@ NS_METHOD nsMenu::GetDOMNode(nsIDOMNode ** aMenuNode)
}
//-------------------------------------------------------------------------
void nsMenu::NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString)
{
OSErr err;
const PRUnichar* unicodeText;
char* scriptRunText;
size_t unicodeTextLengthInBytes, unicdeTextReadInBytes,
scriptRunTextSizeInBytes, scriptRunTextLengthInBytes,
scriptCodeRunListLength;
ScriptCodeRun convertedTextScript;
short themeFontID;
Str255 themeFontName;
SInt16 themeFontSize;
Style themeFontStyle;
//
// extract the Unicode text from the nsString and convert it into a single script run
//
unicodeText = menuString.GetUnicode();
unicodeTextLengthInBytes = menuString.Length() * sizeof(PRUnichar);
scriptRunTextSizeInBytes = unicodeTextLengthInBytes * 2;
scriptRunText = new char[scriptRunTextSizeInBytes + 1];
err = ::ConvertFromUnicodeToScriptCodeRun(mUnicodeTextRunConverter,
unicodeTextLengthInBytes,NS_REINTERPRET_CAST(const PRUint16*, unicodeText),
0, /* no flags*/
0,NULL,NULL,NULL, /* no offset arrays */
scriptRunTextSizeInBytes,&unicdeTextReadInBytes,&scriptRunTextLengthInBytes,
scriptRunText,
1 /* count of script runs*/,&scriptCodeRunListLength,&convertedTextScript);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: ConvertFromUnicodeToScriptCodeRun failed.");
if (err!=noErr) { delete [] scriptRunText; return; }
scriptRunText[scriptRunTextLengthInBytes] = 0; // null terminate
//
// get a font from the script code
//
err = ::GetThemeFont(kThemeSystemFont,convertedTextScript.script,themeFontName,&themeFontSize,&themeFontStyle);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: GetThemeFont failed.");
if (err!=noErr) { delete [] scriptRunText; return; }
::GetFNum(themeFontName,&themeFontID);
Str255 menuTitle;
// Copy C to P string
if (scriptRunTextLengthInBytes > 255)
scriptRunTextLengthInBytes = 255;
BlockMoveData(scriptRunText, &menuTitle[1], scriptRunTextLengthInBytes);
menuTitle[0] = scriptRunTextLengthInBytes;
if (menuItem == 0) // setting the menu title
{
#if TARGET_CARBON
SetMenuTitle(macMenuHandle, menuTitle);
#else
BlockMoveData(menuTitle, (**macMenuHandle).menuData, menuTitle[0] + 1);
#endif
}
else
{
::SetMenuItemText(macMenuHandle, menuItem, menuTitle);
err = ::SetMenuItemFontID(macMenuHandle, menuItem, themeFontID);
}
//
// clean up and exit
//
delete [] scriptRunText;
}
//-------------------------------------------------------------------------
MenuHandle nsMenu::NSStringNewMenu(short menuID, nsString& menuTitle)
{
OSErr err;
const PRUnichar* unicodeText;
char* scriptRunText;
size_t unicodeTextLengthInBytes, unicdeTextReadInBytes,
scriptRunTextSizeInBytes, scriptRunTextLengthInBytes,
scriptCodeRunListLength;
ScriptCodeRun convertedTextScript;
short themeFontID;
Str255 themeFontName;
SInt16 themeFontSize;
Style themeFontStyle;
MenuHandle newMenuHandle;
//
// extract the Unicode text from the nsString and convert it into a single script run
//
unicodeText = menuTitle.GetUnicode();
unicodeTextLengthInBytes = menuTitle.Length() * sizeof(PRUnichar);
scriptRunTextSizeInBytes = unicodeTextLengthInBytes * 2;
scriptRunText = new char[scriptRunTextSizeInBytes + 1]; // +1 for the null terminator.
err = ::ConvertFromUnicodeToScriptCodeRun(mUnicodeTextRunConverter,
unicodeTextLengthInBytes,NS_REINTERPRET_CAST(const PRUint16*, unicodeText),
0, /* no flags*/
0,NULL,NULL,NULL, /* no offset arrays */
scriptRunTextSizeInBytes,&unicdeTextReadInBytes,&scriptRunTextLengthInBytes,
scriptRunText,
1 /* count of script runs*/,&scriptCodeRunListLength,&convertedTextScript);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: ConvertFromUnicodeToScriptCodeRun failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
scriptRunText[scriptRunTextLengthInBytes] = 0; // null terminate
//
// get a font from the script code
//
err = ::GetThemeFont(kThemeSystemFont,convertedTextScript.script,themeFontName,&themeFontSize,&themeFontStyle);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: GetThemeFont failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
::GetFNum(themeFontName,&themeFontID);
newMenuHandle = ::NewMenu(menuID,c2pstr(scriptRunText));
NS_ASSERTION(newMenuHandle!=NULL,"nsMenu::NSStringNewMenu: NewMenu failed.");
if (newMenuHandle==NULL) { delete [] scriptRunText; return NULL; }
err = SetMenuFont(newMenuHandle,themeFontID,themeFontSize);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: SetMenuFont failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
MenuHandle newMenuHandle = nsnull;
short themeFontID;
SInt16 themeFontSize;
Style themeFontStyle;
char* scriptRunText = MenuHelpers::ConvertToScriptRun ( menuTitle, mUnicodeTextRunConverter, &themeFontID,
&themeFontSize, &themeFontStyle );
if ( scriptRunText ) {
newMenuHandle = ::NewMenu(menuID,c2pstr(scriptRunText));
NS_ASSERTION(newMenuHandle!=NULL,"nsMenu::NSStringNewMenu: NewMenu failed.");
if (newMenuHandle==NULL) { nsMemory::Free(scriptRunText); return NULL; }
OSErr err = ::SetMenuFont(newMenuHandle,themeFontID,themeFontSize);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: SetMenuFont failed.");
if (err!=noErr) { nsMemory::Free(scriptRunText); return NULL; }
//
// clean up and exit
//
delete [] scriptRunText;
return newMenuHandle;
nsMemory::Free(scriptRunText);
}
return newMenuHandle;
}
//-------------------------------------------------------------------------
MenuHandle nsMenu::NSStringNewChildMenu(short menuID, nsString& menuTitle)
{
OSErr err;
const PRUnichar* unicodeText;
char* scriptRunText;
size_t unicodeTextLengthInBytes, unicdeTextReadInBytes,
scriptRunTextSizeInBytes, scriptRunTextLengthInBytes,
scriptCodeRunListLength;
ScriptCodeRun convertedTextScript;
short themeFontID;
Str255 themeFontName;
SInt16 themeFontSize;
Style themeFontStyle;
MenuHandle newMenuHandle;
//
// extract the Unicode text from the nsString and convert it into a single script run
//
unicodeText = menuTitle.GetUnicode();
unicodeTextLengthInBytes = menuTitle.Length() * sizeof(PRUnichar);
scriptRunTextSizeInBytes = unicodeTextLengthInBytes * 2;
scriptRunText = new char[scriptRunTextSizeInBytes];
err = ::ConvertFromUnicodeToScriptCodeRun(mUnicodeTextRunConverter,
unicodeTextLengthInBytes,NS_REINTERPRET_CAST(const PRUint16*, unicodeText),
0, /* no flags*/
0,NULL,NULL,NULL, /* no offset arrays */
scriptRunTextSizeInBytes,&unicdeTextReadInBytes,&scriptRunTextLengthInBytes,
scriptRunText,
1 /* count of script runs*/,&scriptCodeRunListLength,&convertedTextScript);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: ConvertFromUnicodeToScriptCodeRun failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
scriptRunText[scriptRunTextLengthInBytes] = 0; // null terminate
//
// get a font from the script code
//
err = ::GetThemeFont(kThemeSystemFont,convertedTextScript.script,themeFontName,&themeFontSize,&themeFontStyle);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: GetThemeFont failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
::GetFNum(themeFontName,&themeFontID);
//newMenuHandle = ::NewMenu(menuID,c2pstr(scriptRunText));
newMenuHandle = ::GetMenuHandle(menuID);
NS_ASSERTION(newMenuHandle!=NULL,"nsMenu::NSStringNewMenu: NewMenu failed.");
if (newMenuHandle==NULL) { delete [] scriptRunText; return NULL; }
err = SetMenuFont(newMenuHandle,themeFontID,themeFontSize);
NS_ASSERTION(err==noErr,"nsMenu::NSStringNewMenu: SetMenuFont failed.");
if (err!=noErr) { delete [] scriptRunText; return NULL; }
//
// clean up and exit
//
delete [] scriptRunText;
return newMenuHandle;
}
//----------------------------------------
void nsMenu::LoadMenuItem(
@ -1713,39 +1551,3 @@ nsMenu :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIn
} // ContentRemoved
#pragma mark -
//
// WebShellToPresContext
//
// Helper to dig out a pres context from a webshell. A common thing to do before
// sending an event into the dom.
//
nsresult
MenuHelpers :: WebShellToPresContext (nsIWebShell* inWebShell, nsIPresContext** outContext )
{
NS_ENSURE_ARG_POINTER(outContext);
*outContext = nsnull;
if (!inWebShell)
return NS_ERROR_INVALID_ARG;
nsresult retval = NS_OK;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(inWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
docShell->GetContentViewer(getter_AddRefs(contentViewer));
if ( contentViewer ) {
nsCOMPtr<nsIDocumentViewer> docViewer ( do_QueryInterface(contentViewer) );
if ( docViewer )
docViewer->GetPresContext(*outContext); // AddRefs for us
else
retval = NS_ERROR_FAILURE;
}
else
retval = NS_ERROR_FAILURE;
return retval;
} // WebShellToPresContext

Просмотреть файл

@ -50,13 +50,6 @@ extern const PRInt16 kAppleMenuID;
extern PRInt16 mMacMenuIDCount;// = kMacMenuID;
namespace MenuHelpers
{
// utility routine for getting a PresContext out of a webShell
nsresult WebShellToPresContext ( nsIWebShell* inWebShell, nsIPresContext** outContext ) ;
}
class nsMenu : public nsIMenu,
public nsIMenuListener,
public nsIChangeObserver,
@ -153,9 +146,7 @@ protected:
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void* menuNode, void* aWebShell);
void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& nsString);
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);
MenuHandle NSStringNewChildMenu(short menuID, nsString& menuTitle);
private:

Просмотреть файл

@ -485,7 +485,7 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
nsCRT::free(ptrv);
::AppendMenu(appleMenu, "\pa");
NSStringSetMenuItemText(appleMenu, 1, label);
MenuHelpers::SetMenuItemText(appleMenu, 1, label, mUnicodeTextRunConverter);
::AppendMenu(appleMenu, "\p-");
::AppendResMenu(appleMenu, 'DRVR');
::InsertMenu(appleMenu, 0);
@ -512,60 +512,7 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
return NS_OK;
}
void
nsMenuBar::NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString)
{
OSErr err;
const PRUnichar* unicodeText;
char* scriptRunText;
size_t unicodeTextLengthInBytes, unicdeTextReadInBytes,
scriptRunTextSizeInBytes, scriptRunTextLengthInBytes,
scriptCodeRunListLength;
ScriptCodeRun convertedTextScript;
short themeFontID;
Str255 themeFontName;
SInt16 themeFontSize;
Style themeFontStyle;
//
// extract the Unicode text from the nsString and convert it into a single script run
//
unicodeText = menuString.GetUnicode();
unicodeTextLengthInBytes = menuString.Length() * sizeof(PRUnichar);
scriptRunTextSizeInBytes = unicodeTextLengthInBytes * 2;
scriptRunText = new char[scriptRunTextSizeInBytes + 1];
err = ::ConvertFromUnicodeToScriptCodeRun(mUnicodeTextRunConverter,
unicodeTextLengthInBytes,NS_REINTERPRET_CAST(const PRUint16*, unicodeText),
0, /* no flags*/
0,NULL,NULL,NULL, /* no offset arrays */
scriptRunTextSizeInBytes,&unicdeTextReadInBytes,&scriptRunTextLengthInBytes,
scriptRunText,
1 /* count of script runs*/,&scriptCodeRunListLength,&convertedTextScript);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: ConvertFromUnicodeToScriptCodeRun failed.");
if (err!=noErr) { delete [] scriptRunText; return; }
scriptRunText[scriptRunTextLengthInBytes] = 0; // null terminate
//
// get a font from the script code
//
err = ::GetThemeFont(kThemeSystemFont,convertedTextScript.script,themeFontName,&themeFontSize,&themeFontStyle);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: GetThemeFont failed.");
if (err!=noErr) { delete [] scriptRunText; return; }
::GetFNum(themeFontName,&themeFontID);
::SetMenuItemText(macMenuHandle,menuItem,c2pstr(scriptRunText));
err = ::SetMenuItemFontID(macMenuHandle,menuItem,themeFontID);
//
// clean up and exit
//
delete [] scriptRunText;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
{
@ -893,4 +840,131 @@ nsMenuBar :: Lookup ( nsIContent *aContent, nsIChangeObserver **_retval )
}
#pragma mark -
//
// SetMenuItemText
//
// A utility routine for handling unicode->OS text conversions for setting the item
// text in a menu.
//
void
MenuHelpers :: SetMenuItemText ( MenuHandle inMacMenuHandle, short inMenuItem, const nsString& inMenuString,
const UnicodeToTextRunInfo inConverter )
{
// ::TruncString() doesn't take the number of characters to truncate to, it takes a pixel with
// to fit the string in. Ugh. I talked it over with sfraser and we couldn't come up with an
// easy way to compute what this should be given the system font, etc, so we're just going
// to hard code it to something reasonable and bigger fonts will just have to deal.
const short kMaxItemPixelWidth = 300;
short themeFontID;
SInt16 themeFontSize;
Style themeFontStyle;
char* scriptRunText = ConvertToScriptRun ( inMenuString, inConverter, &themeFontID,
&themeFontSize, &themeFontStyle );
if ( scriptRunText ) {
// convert it to a pascal string
Str255 menuTitle;
short scriptRunTextLength = strlen(scriptRunText);
if (scriptRunTextLength > 255)
scriptRunTextLength = 255;
BlockMoveData(scriptRunText, &menuTitle[1], scriptRunTextLength);
menuTitle[0] = scriptRunTextLength;
// if the item text is too long, truncate it.
::TruncString ( kMaxItemPixelWidth, menuTitle, truncMiddle );
::SetMenuItemText(inMacMenuHandle, inMenuItem, menuTitle);
OSErr err = ::SetMenuItemFontID(inMacMenuHandle, inMenuItem, themeFontID);
nsMemory::Free(scriptRunText);
}
} // SetMenuItemText
//
// ConvertToScriptRun
//
// Converts unicode to a single script run and extract the relevant font information. The
// caller is responsible for deleting the memory allocated by this call with |nsMemory::Free()|.
// Returns |nsnull| if an error occurred.
//
char*
MenuHelpers :: ConvertToScriptRun ( const nsString & inStr, const UnicodeToTextRunInfo inConverter,
short* outFontID, SInt16* outFontSize, Style* outFontStyle )
{
//
// extract the Unicode text from the nsString and convert it into a single script run
//
const PRUnichar* unicodeText = inStr.GetUnicode();
size_t unicodeTextLengthInBytes = inStr.Length() * sizeof(PRUnichar);
size_t scriptRunTextSizeInBytes = unicodeTextLengthInBytes * 2;
char* scriptRunText = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(scriptRunTextSizeInBytes + sizeof(char)));
if ( !scriptRunText )
return nsnull;
ScriptCodeRun convertedTextScript;
size_t unicdeTextReadInBytes, scriptRunTextLengthInBytes, scriptCodeRunListLength;
OSErr err = ::ConvertFromUnicodeToScriptCodeRun(inConverter, unicodeTextLengthInBytes,
NS_REINTERPRET_CAST(const PRUint16*, unicodeText),
0, /* no flags*/
0,NULL,NULL,NULL, /* no offset arrays */
scriptRunTextSizeInBytes,&unicdeTextReadInBytes,&scriptRunTextLengthInBytes,
scriptRunText,
1 /* count of script runs*/,&scriptCodeRunListLength,&convertedTextScript);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: ConvertFromUnicodeToScriptCodeRun failed.");
if ( err ) { nsMemory::Free(scriptRunText); return nsnull; }
scriptRunText[scriptRunTextLengthInBytes] = '\0'; // null terminate
//
// get a font from the script code
//
Str255 themeFontName;
err = ::GetThemeFont(kThemeSystemFont, convertedTextScript.script, themeFontName, outFontSize, outFontStyle);
NS_ASSERTION(err==noErr,"nsMenu::NSStringSetMenuItemText: GetThemeFont failed.");
if ( err ) { nsMemory::Free(scriptRunText); return nsnull; }
::GetFNum(themeFontName, outFontID);
return scriptRunText;
} // ConvertToScriptRun
//
// WebShellToPresContext
//
// Helper to dig out a pres context from a webshell. A common thing to do before
// sending an event into the dom.
//
nsresult
MenuHelpers :: WebShellToPresContext (nsIWebShell* inWebShell, nsIPresContext** outContext )
{
NS_ENSURE_ARG_POINTER(outContext);
*outContext = nsnull;
if (!inWebShell)
return NS_ERROR_INVALID_ARG;
nsresult retval = NS_OK;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(inWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
docShell->GetContentViewer(getter_AddRefs(contentViewer));
if ( contentViewer ) {
nsCOMPtr<nsIDocumentViewer> docViewer ( do_QueryInterface(contentViewer) );
if ( docViewer )
docViewer->GetPresContext(*outContext); // AddRefs for us
else
retval = NS_ERROR_FAILURE;
}
else
retval = NS_ERROR_FAILURE;
return retval;
} // WebShellToPresContext

Просмотреть файл

@ -39,6 +39,25 @@ extern nsWeakPtr gMacMenubar;
class nsIWidget;
namespace MenuHelpers
{
// utility routine for getting a PresContext out of a webShell
nsresult WebShellToPresContext ( nsIWebShell* inWebShell, nsIPresContext** outContext ) ;
// utility routine for handling unicode->OS text conversions for setting the item
// text in a menu.
void SetMenuItemText ( MenuHandle macMenuHandle, short menuItem, const nsString& text,
const UnicodeToTextRunInfo converter ) ;
// Converts unicode to a single script run and extract the relevant font information. The
// caller is responsible for deleting the memory allocated by this call with |nsMemory::Free()|.
// Returns |nsnull| if an error occurred.
char* ConvertToScriptRun ( const nsString & inStr, const UnicodeToTextRunInfo inConverter,
short* outFontID, SInt16* outFontSize, Style* outFontStyle ) ;
}
/**
* Native Mac MenuBar wrapper
*/
@ -153,7 +172,6 @@ protected:
Handle mMacMBarHandle;
Handle mOriginalMacMBarHandle;
UnicodeToTextRunInfo mUnicodeTextRunConverter;
void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString);
};

Просмотреть файл

@ -25,7 +25,7 @@
#include "nsIContent.h"
#include "nsIPresContext.h"
#include "nsMenu.h" // for MenuHelpers namespace
#include "nsMenuBar.h" // for MenuHelpers namespace
#include "nsMenuItem.h"
#include "nsIMenu.h"
#include "nsIMenuBar.h"