gerv%gerv.net 8b69962ee3 Bug 236613: change to MPL/LGPL/GPL tri-license.
git-svn-id: svn://10.0.0.236/trunk@155500 18797224-902f-48f8-a5cc-f745e15eee43
2004-04-25 21:07:34 +00:00

1020 lines
20 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* wffppeer.cpp (FontDisplayerPeerObject.cpp)
*
* This object is local to the FontDisplayer. One of these objects
* exist for every FontDisplayer that exists. All calls to the FontDisplayer
* are routed through this peer object. This takes care of loading and
* unloading the FontDisplayers as neccessary.
*
* dp Suresh <dp@netscape.com>
*/
#include "wffpPeer.h"
#include "fe_proto.h"
#define WF_ONE_MILLESEC 1
#define WF_ONE_MINUTE (60 * 1000 * WF_ONE_MILLESEC)
/* Getting intl string ids */
#define WANT_ENUM_STRING_IDS
#include "allxpstr.h"
#undef WANT_ENUM_STRING_IDS
FontDisplayerPeerObject::
FontDisplayerPeerObject(struct nffp *fp)
: dlm(NULL), deleted(0), disabled(0), native(-1),
streamCount(0), fhList(NULL), unloadTimerId(NULL)
{
XP_ASSERT(fp);
fpType = FontDisplayerPeerObject::WF_FP_STATIC;
fontDisplayer = fp;
// Although there we aren't expected to free the returned
// Name and Description, we could unload this dynamic modules
// and the name and decription could be in their data space.
// So to prevent losing these, we take a copy.
displayerName = CopyString(nffp_Name(fontDisplayer, NULL));
displayerDescription = CopyString(nffp_Description(fontDisplayer, NULL));
#if defined(XP_WIN) && !defined(WIN32)
// Win16 It seems the const char * assignment doesn't work.
char mimeString[256];
*mimeString = '\0';
strcpy(mimeString, nffp_EnumerateMimeTypes(fontDisplayer, NULL));
#else
const char *mimeString = nffp_EnumerateMimeTypes(fontDisplayer, NULL);
#endif
if (mimeString && *mimeString )
{
mimeList.reconstruct(mimeString);
registerConverters();
}
}
FontDisplayerPeerObject::
FontDisplayerPeerObject(const char *dlmName)
: dlm(dlmName), mimeList(NULL), deleted(0), disabled(0), native(-1),
streamCount(0), fhList(NULL), unloadTimerId(NULL)
{
fpType = FontDisplayerPeerObject::WF_FP_DYNAMIC;
fontDisplayer = NULL;
displayerName = NULL;
displayerDescription = NULL;
if (dlm.status() < 0)
{
deleted = 1;
return;
}
#ifdef DEBUG
// Don't load in purified versions of libraries.
if(XP_STRSTR(dlmName, "_pure_")) {
XP_ASSERT(0);
deleted = 1;
return;
}
#endif
if (load() < 0)
{
deleted = 1;
return;
}
displayerName = CopyString(nffp_Name(fontDisplayer, NULL));
displayerDescription = CopyString(nffp_Description(fontDisplayer,NULL));
#if defined(XP_WIN) && !defined(WIN32)
// Win16 It seems the const char * assignment doesn't work.
char mimeString[256];
*mimeString = '\0';
strcpy(mimeString, nffp_EnumerateMimeTypes(fontDisplayer, NULL));
#else
const char *mimeString = nffp_EnumerateMimeTypes(fontDisplayer, NULL);
#endif
if (mimeString && *mimeString )
{
mimeList.reconstruct(mimeString);
registerConverters();
}
}
FontDisplayerPeerObject::
FontDisplayerPeerObject(FontCatalogFile &fc)
: dlm(NULL), deleted(0), disabled(0), native(-1),
streamCount(0), fhList(NULL), unloadTimerId(NULL)
{
fpType = FontDisplayerPeerObject::WF_FP_DYNAMIC;
fontDisplayer = NULL;
displayerName = NULL;
displayerDescription = NULL;
reconstruct(fc);
}
FontDisplayerPeerObject::
~FontDisplayerPeerObject()
{
finalize();
}
jint FontDisplayerPeerObject::
describe(FontCatalogFile &fc)
{
char *s;
// Print out the displayer information
if (fpType != WF_FP_DYNAMIC)
{
return (0);
}
fc.output("displayer = {");
fc.indentIn();
s = "dynamic";
fc.output("type", s);
s = dlm.describe();
fc.output("dlm", s);
if (s)
{
XP_FREE(s);
}
fc.output("name", displayerName);
fc.output("description", displayerDescription);
s = mimeList.describe();
fc.output("mimeString", s);
if (s)
{
XP_FREE(s);
}
fc.output("deleted", deleted);
fc.output("disabled", disabled);
fc.output("catalog = {");
fc.indentIn();
catalog.describe(fc);
fc.indentOut();
fc.output("} // End of catalog");
fc.indentOut();
fc.output("} // End of displayer");
return (0);
}
jint FontDisplayerPeerObject::
reconstruct(FontCatalogFile &fc)
{
char buf[1024];
int buflen;
int over = 0;
char *variable = NULL;
char *value = NULL;
char *ret;
finalize();
while (!over)
{
ret = fc.readline(buf, sizeof(buf));
if (!ret)
{
over = 1;
continue;
}
buflen = strlen((const char *)buf);
if (buf[buflen-1] == '\n')
{
buf[buflen-1] = '\0';
buflen--;
}
if (!strncmp(buf, "#", 1))
{
// Ignore comments
continue;
}
wf_scanVariableAndValue(buf, buflen, variable, value);
if (!wf_strcasecmp(variable, "displayer"))
{
continue;
}
else if (!wf_strcasecmp(variable, "type"))
{
if (!wf_strcasecmp(value, "dynamic"))
{
fpType = WF_FP_DYNAMIC;
}
else
{
deleted = 1;
over = 1;
continue;
}
}
else if (!wf_strcasecmp(variable, "dlm"))
{
fontDisplayer = NULL;
dlm.reconstruct(value);
if (dlm.status() < 0)
{
deleted = 1;
over = 1;
continue;
}
}
else if (!wf_strcasecmp(variable, "disabled"))
{
disabled = atoi(value);
}
else if (!wf_strcasecmp(variable, "name"))
{
if (displayerName) delete displayerName;
displayerName = CopyString(value);
}
else if (!wf_strcasecmp(variable, "description"))
{
if (displayerDescription) delete displayerDescription;
displayerDescription = CopyString(value);
}
else if (!wf_strcasecmp(variable, "mimeString"))
{
mimeList.reconstruct(value);
registerConverters();
}
else if (!wf_strcasecmp(variable, "deleted"))
{
deleted = atoi(value);
}
else if (!wf_strcasecmp(variable, "catalog"))
{
catalog.reconstruct(fc);
}
else if (!strncmp(variable, "}", 1))
{
over = 1;
continue;
}
}
// sanity check the fpp
if (dlm.filename() == NULL || dlm.status() <= 0 || fpType != WF_FP_DYNAMIC)
deleted = 1;
return (0);
}
jdouble *
FontDisplayerPeerObject::EnumerateSizes(struct nfrc *rc, void *fh)
{
// Check for generic preconditions
if (deleted || disabled)
{
return NULL;
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return((jdouble *)nffp_EnumerateSizes(fontDisplayer, rc, fh, NULL));
}
struct nffmi *
FontDisplayerPeerObject::GetMatchInfo(void *fh)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return(nffp_GetMatchInfo(fontDisplayer, fh, NULL));
}
struct nfrf *
FontDisplayerPeerObject::
CreateRenderableFont(struct nfrc *rc, void *fh, jdouble pointsize)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return(nffp_GetRenderableFont(fontDisplayer, rc, fh, pointsize, NULL));
}
void *
FontDisplayerPeerObject::LookupFont(struct nfrc *rc, struct nffmi *fmi, const char *accessor)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return(nffp_LookupFont(fontDisplayer, rc, fmi, accessor, NULL));
}
void *
FontDisplayerPeerObject::CreateFontFromFile(struct nfrc *rc, const char *mimetype,
const char *filename, const char *urlOfPage)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return(nffp_CreateFontFromFile(fontDisplayer, rc, mimetype, filename, urlOfPage,
NULL));
}
struct nfstrm *
FontDisplayerPeerObject::CreateFontStreamHandler(struct nfrc *rc, const char *urlOfPage)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return((struct nfstrm *)
nffp_CreateFontStreamHandler(fontDisplayer, rc, urlOfPage, NULL));
}
jint
FontDisplayerPeerObject::ReleaseFontHandle(void *fh)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (-1);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (-1);
}
return(nffp_ReleaseFontHandle(fontDisplayer, fh, NULL));
}
//
// Catalogue routines
//
struct nffmi **
FontDisplayerPeerObject::ListFonts(struct nfrc *rc, struct nffmi *fmi)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return((struct nffmi **)
nffp_ListFonts(fontDisplayer, rc, fmi, NULL));
}
jdouble *
FontDisplayerPeerObject::ListSizes(struct nfrc *rc, struct nffmi *fmi)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
// Check for call specific preconditions
if (load() < 0)
{
deleted = 1;
return (NULL);
}
return((jdouble *)
nffp_ListSizes(fontDisplayer, rc, fmi, NULL));
}
int
FontDisplayerPeerObject::queryCatalog(struct nfrc *rc, struct nffmi *fmi)
{
int ret = catalog.supportsFmi(rc, fmi);
if (ret < 0)
{
// Catalog may not have been initialized.
if (!catalog.isInitialized(rc))
{
// Now we need to load the dll to initialize the catalog.
struct nffmi **fmis = ListFonts(rc, NULL);
catalog.update(rc, fmis);
if (fmis)
{
// XXX We need to free the fmis. We may get away
// XXX doing that if we make catalog.update() not
// XXX take a copy of the fmi.
wf_releaseFmis(fmis);
WF_FREE(fmis);
}
ret = catalog.supportsFmi(rc, fmi);
}
}
return (ret);
}
//
// Displayer loading/unloading management routines
//
int
FontDisplayerPeerObject::dlmChanged(const char *dlm_name)
{
int ret = -1;
// if this is the dlm that we are associcated with
if (!strcmp(dlm.filename(), dlm_name))
{
if (dlm.isChanged() == 0)
{
// Unchanged
ret = 0;
}
else
{
// This mean the dlm has either changed or may have been deleted.
ret = 1;
}
}
return (ret);
}
void
FontDisplayerPeerObject::resync(void)
{
native = -1;
finalizeExceptDlmAndDisabled();
// This might cause a core dump as usually a resync() is done only
// when we know that the dlm has changed. And if it was loaded in
// memory and the disk copy was changed whew!
// Some platforms wont let the copy on disk to change. So we are kind of
// safe.
//
// XXX A better solution would be to not unload it at all but just clear our
// internal state. Let us see.
dlm.unload(/*force*/ 1);
dlm.sync();
if (dlm.status() < 0)
{
deleted = 1;
return;
}
if (load() < 0)
{
deleted = 1;
return;
}
displayerName = CopyString(nffp_Name(fontDisplayer, NULL));
displayerDescription = CopyString(nffp_Description(fontDisplayer,NULL));
#if defined(XP_WIN) && !defined(WIN32)
// Win16 It seems the const char * assignment doesn't work.
char mimeString[256];
*mimeString = '\0';
strcpy(mimeString, nffp_EnumerateMimeTypes(fontDisplayer, NULL));
#else
const char *mimeString = nffp_EnumerateMimeTypes(fontDisplayer, NULL);
#endif
if (mimeString && *mimeString )
{
mimeList.reconstruct(mimeString);
registerConverters();
}
}
//
// mime handling routines
//
int
FontDisplayerPeerObject::countMimetypes()
{
// Check for generic preconditions
if (deleted || disabled)
{
return (-1);
}
return (mimeList.count());
}
int
FontDisplayerPeerObject::isMimetypeEnabled(const char *mimetype)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (0);
}
return (mimeList.isEnabled(mimetype));
}
const char *
FontDisplayerPeerObject::getMimetypeFromExtension(const char *ext)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (0);
}
return (mimeList.getMimetypeFromExtension(ext));
}
int
FontDisplayerPeerObject::disableMimetype(const char *mimetype)
{
// Check for generic preconditions
if (deleted)
{
return (-1);
}
return (mimeList.setEnabledStatus(mimetype, 0));
}
int
FontDisplayerPeerObject::enableMimetype(const char *mimetype)
{
// Check for generic preconditions
if (deleted)
{
return (-1);
}
return (mimeList.setEnabledStatus(mimetype, 1));
}
//
// Additional routines
//
const char *
FontDisplayerPeerObject::name(void)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (NULL);
}
return (displayerName);
}
int
FontDisplayerPeerObject::isNative(void)
{
if (native < 0)
{
native = 0; // not native
if (displayerName)
{
native = (strcmp(displayerName, NF_NATIVE_FONT_DISPLAYER) == 0);
}
}
// Check if this is the native font displayer
return (native);
}
int
FontDisplayerPeerObject::isDeleted(void)
{
return (deleted);
}
int
FontDisplayerPeerObject::isLoaded(void)
{
int ret = 0;
// Check for generic preconditions
if (deleted || disabled)
{
return (ret);
}
if (fontDisplayer || fpType == FontDisplayerPeerObject::WF_FP_STATIC)
{
ret = 1;
}
return (ret);
}
void
FontDisplayerPeerObject::StreamCreated(struct nfstrm *strm)
{
streamCount++;
}
void
FontDisplayerPeerObject::StreamDone(struct nfstrm *strm)
{
streamCount--;
decideToUnload();
}
void
FontDisplayerPeerObject::FontHandleCreated(void *fh)
{
fhList.add(fh);
}
void
FontDisplayerPeerObject::FontHandleDone(void *fh)
{
if (fhList.remove(fh) == wfList::SUCCESS)
{
// If there was no other copy of the fh in our fhlist
// then this was the last fh and can be released.
if (fhList.isExist(fh) != wfList::SUCCESS)
{
ReleaseFontHandle(fh);
if (fpType == FontDisplayerPeerObject::WF_FP_DYNAMIC)
{
// Static displayers need not be unloaded.
decideToUnload();
}
}
}
}
int
FontDisplayerPeerObject::disableDisplayer(void)
{
if (deleted)
{
return (-1);
}
disabled = 1;
return (0);
}
int
FontDisplayerPeerObject::enableDisplayer(void)
{
if (deleted)
{
return (-1);
}
disabled = 0;
return (0);
}
int
FontDisplayerPeerObject::isDisplayerEnabled(void)
{
if (deleted)
{
return (0);
}
return ((disabled ? 0 : 1));
}
int
FontDisplayerPeerObject::registerConverters(void)
{
if (deleted)
{
return (-1);
}
if (!mimeList.isEmpty())
{
// Foreach mime
struct wfListElement *tmp = mimeList.head;
for (; tmp; tmp = tmp->next)
{
struct mime_store *ele = (struct mime_store *) tmp->item;
NET_cdataCommit(ele->mimetype, ele->extensions);
}
}
return (0);
}
char *
FontDisplayerPeerObject::aboutData(void)
{
char *aboutData = NULL;
int aboutDataLen = 0;
int aboutDataMaxLen = 0;
#ifndef NO_HTML_DIALOGS_CHANGE
#define WF_ABOUT_DATA_ALLOCATION_STEP 64
#define WF_ACCUMULATE(str) wf_addToString(&aboutData, &aboutDataLen, &aboutDataMaxLen, str);
// Dont show deleted font displayers.
if (isDeleted())
{
return (NULL);
}
// Displayer data
char *fmtstring = NULL;
char *buf;
if (fpType == FontDisplayerPeerObject::WF_FP_STATIC)
{
fmtstring = XP_GetString(WF_MSG_ABOUT_DISPLAYER_STATIC);
buf = PR_smprintf(fmtstring,
(displayerName ? displayerName : ""),
(displayerDescription ? displayerDescription : ""));
}
else
{
fmtstring = XP_GetString(WF_MSG_ABOUT_DISPLAYER_DYNAMIC);
buf = PR_smprintf(fmtstring,
(displayerName ? displayerName : ""),
(displayerDescription ? displayerDescription : ""),
dlm.filename());
}
if (buf)
{
WF_ACCUMULATE(buf);
XP_FREE(buf);
buf = NULL;
}
if (!mimeList.isEmpty())
{
// Foreach mime
struct wfListElement *tmp = mimeList.head;
for (; tmp; tmp = tmp->next)
{
struct mime_store *ele = (struct mime_store *) tmp->item;
buf = PR_smprintf(XP_GetString(WF_MSG_ABOUT_DISPLAYER_MIME),
ele->mimetype,
(displayerName ? displayerName : ""),
(ele->isEnabled ? "checked" : ""), /* NO I18N */
ele->mimetype, ele->description,
ele->extensions);
if (buf)
{
WF_ACCUMULATE(buf);
XP_FREE(buf);
buf = NULL;
}
}
}
WF_ACCUMULATE(XP_GetString(WF_MSG_ABOUT_DISPLAYER_END));
#endif /* NO_HTML_DIALOGS_CHANGE */
return (aboutData);
}
//
// Private method implementations
//
int
FontDisplayerPeerObject::load(void)
{
// Check for generic preconditions
if (deleted || disabled)
{
return (0);
}
if (fontDisplayer || fpType == FontDisplayerPeerObject::WF_FP_STATIC)
{
return (0);
}
dlm.load();
if (dlm.status() < 0)
{
return (-1);
}
fontDisplayer = dlm.createDisplayerObject(WF_fbp);
if (!fontDisplayer)
{
WF_TRACEMSG(("NF: dlm (%s) Couldn't create fontdisplayer object. Skipping dlm.",
dlm.filename()));
dlm.unload();
return (-1);
}
return (0);
}
extern "C" void wf_unloadTimer(void *closure)
{
FontDisplayerPeerObject *fpp = (FontDisplayerPeerObject *)closure;
if (fpp->unloadTimerId)
{
// One last sanity check
if (fpp->streamCount == 0 && fpp->fhList.isEmpty())
{
fpp->unload();
}
fpp->unloadTimerId = 0;
}
}
void
FontDisplayerPeerObject::decideToUnload(void)
{
if (streamCount == 0 && fhList.isEmpty())
{
// This displayer can be unloaded.
// I really want to do something like unloading the displayer
// after say 1 min. because say the navigator moves from one page
// to another and both had use for this displayer, then this displayer
// will get loaded twice and unloaded once causing thrashing.
//
// The problem in implementing this is how to we ensure we get
// back control after this many seconds. We should use the
// FE Timer callback.
// Clear any previous timers
if (unloadTimerId)
{
FE_ClearTimeout(unloadTimerId);
}
// Set the new timer
unloadTimerId = FE_SetTimeout(wf_unloadTimer, this, WF_ONE_MINUTE);
}
else
{
// Unload should not happen
if (unloadTimerId)
{
FE_ClearTimeout(unloadTimerId);
}
}
}
int
FontDisplayerPeerObject::unload(void)
{
if (fpType == FontDisplayerPeerObject::WF_FP_STATIC)
{
// Static displayer need not be unloaded.
return (0);
}
if (!fontDisplayer)
{
// We were never loaded.
return (-1);
}
nffp_release(fontDisplayer, NULL);
fontDisplayer = NULL;
return (dlm.unload());
}
int FontDisplayerPeerObject::
finalizeExceptDlmAndDisabled()
{
// Release memory
if (displayerName)
{
delete displayerName;
displayerName = NULL;
}
if (displayerDescription)
{
delete displayerDescription;
displayerDescription = NULL;
}
// Clear native flag
native = -1;
// Clear deleted flag
deleted = 0;
// Clean mimelist
mimeList.finalize();
// Clean catalog
catalog.finalize();
return (0);
}
int FontDisplayerPeerObject::
finalize()
{
finalizeExceptDlmAndDisabled();
// Clean dlm
unload();
dlm.finalize();
// Clear disabled flag
disabled = 0;
return (0);
}