435 lines
12 KiB
C++
435 lines
12 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.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/NPL/
|
|
*
|
|
* 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 Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
/*
|
|
* wfStream.cpp (wfStream.cpp)
|
|
*
|
|
* Implements streaming functionality of Fonts
|
|
*
|
|
* dp Suresh <dp@netscape.com>
|
|
*/
|
|
|
|
|
|
#include "nf.h" // Public header file
|
|
#include "libfont.h" // Private kitchen sink
|
|
|
|
/* Getting intl string ids */
|
|
#define WANT_ENUM_STRING_IDS
|
|
#include "allxpstr.h"
|
|
#undef WANT_ENUM_STRING_IDS
|
|
|
|
#include "Mcfb.h"
|
|
#include "fb.h"
|
|
#include "Pcfb.h"
|
|
#include "wffpPeer.h"
|
|
#include "Pcf.h"
|
|
#include "f.h"
|
|
|
|
#include "Mnffbc.h"
|
|
#include "Mnfdoer.h"
|
|
#include "Mnff.h"
|
|
#include "Mnfstrm.h"
|
|
|
|
struct stream_data {
|
|
URL_Struct *urls;
|
|
struct nffbc *fbc;
|
|
FontDisplayerPeerObject *fpPeer;
|
|
struct nfstrm *fpStream;
|
|
struct nfdoer *observer;
|
|
struct nff *f;
|
|
};
|
|
|
|
static void
|
|
wf_ReleaseStreamData(struct stream_data *data)
|
|
{
|
|
nffbc_release(data->fbc, NULL);
|
|
|
|
// Release stream and tell the wffpPeer about it
|
|
data->fpPeer->StreamDone(data->fpStream);
|
|
nfstrm_release(data->fpStream, NULL);
|
|
|
|
nfdoer_release(data->observer, NULL);
|
|
nff_release(data->f, NULL);
|
|
|
|
delete data;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
wf_NotifyObserver(struct stream_data *data)
|
|
{
|
|
nfdoer_Update(data->observer, data->f, NULL);
|
|
}
|
|
|
|
|
|
extern "C" int
|
|
wfWrite(NET_StreamClass *stream, const unsigned char *str, int32 len)
|
|
{
|
|
struct stream_data *data = (struct stream_data *) stream->data_object;
|
|
return ((int)nfstrm_Write((nfstrm *)data->fpStream, (jbyte *)str, (jint)len, NULL));
|
|
}
|
|
|
|
#ifndef XP_OS2
|
|
extern "C"
|
|
#endif
|
|
unsigned int wfWriteReady(NET_StreamClass *stream)
|
|
{
|
|
struct stream_data *data = (struct stream_data *) stream->data_object;
|
|
return ((unsigned int)nfstrm_IsWriteReady((nfstrm *)data->fpStream, NULL));
|
|
}
|
|
|
|
#ifndef XP_OS2
|
|
extern "C"
|
|
#endif
|
|
void wfComplete(NET_StreamClass *stream)
|
|
{
|
|
struct stream_data *data = (struct stream_data *) stream->data_object;
|
|
void *fh = nfstrm_Complete((nfstrm *)data->fpStream, NULL);
|
|
cfImpl *oimpl = cf2cfImpl(data->f);
|
|
FontObject *fob = (FontObject *)oimpl->object;
|
|
if (fh)
|
|
{
|
|
// Include this fh in the correct FontObject
|
|
fob->addFontHandle(data->fpPeer, fh);
|
|
WF_TRACEMSG( ("NF: Stream done. Fonthandle created. Setting font state to COMPLETE.") );
|
|
fob->setState(NF_FONT_COMPLETE);
|
|
}
|
|
else
|
|
{
|
|
// This font will never become ok as the fonthandle
|
|
// that we got was 0. We will assume that the data
|
|
// that we streamed didn't make a valid font.
|
|
WF_TRACEMSG( ("NF: Stream done. Fonthandle NOT CREATED. Setting font state to ERROR.") );
|
|
fob->setState(NF_FONT_ERROR);
|
|
}
|
|
|
|
// Notify the nfdoer on the status of Complete
|
|
wf_NotifyObserver(data);
|
|
wf_ReleaseStreamData(data);
|
|
return;
|
|
}
|
|
|
|
#ifndef XP_OS2
|
|
extern "C"
|
|
#endif
|
|
void wfAbort(NET_StreamClass *stream, int status)
|
|
{
|
|
struct stream_data *data = (struct stream_data *) stream->data_object;
|
|
nfstrm_Abort((nfstrm *)data->fpStream, (jint) status, NULL);
|
|
|
|
// Mark the font as in error
|
|
cfImpl *oimpl = cf2cfImpl(data->f);
|
|
FontObject *fob = (FontObject *)oimpl->object;
|
|
fob->setState(NF_FONT_ERROR);
|
|
|
|
// Notify nfdoer with status of Abort
|
|
wf_NotifyObserver(data);
|
|
wf_ReleaseStreamData(data);
|
|
return;
|
|
}
|
|
|
|
|
|
extern "C" void
|
|
/*ARGSUSED*/
|
|
wfUrlExit(URL_Struct *urls, int status, MWContext *cx)
|
|
{
|
|
if (status < 0 && urls->error_msg)
|
|
{
|
|
WF_TRACEMSG (("NF: Font downloading unsuccessful : %s.",
|
|
urls->error_msg));
|
|
}
|
|
|
|
if (status != MK_CHANGING_CONTEXT)
|
|
{
|
|
NET_FreeURLStruct (urls);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Font stream handler.
|
|
// This will be called by netlib to when a stream of type FO_FONT
|
|
// is available.
|
|
//
|
|
extern "C" NET_StreamClass*
|
|
/*ARGSUSED*/
|
|
wfNewStream(FO_Present_Types format_out, void* client_data,
|
|
URL_Struct* urls, MWContext* cx)
|
|
{
|
|
struct nffbc *fbc = (struct nffbc *) client_data;
|
|
struct wf_new_stream_data *inData =
|
|
(struct wf_new_stream_data *) urls->fe_data;
|
|
cfbImpl *oimpl = cfb2cfbImpl(fbc);
|
|
FontBrokerObject *fbobj = (FontBrokerObject *)oimpl->object;
|
|
|
|
const char *mimetype = fbobj->GetMimetype(urls->content_type, urls->address);
|
|
|
|
if (!mimetype || !*mimetype)
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
WF_TRACEMSG(("NF: Looking for mimetype: %s.", mimetype));
|
|
|
|
NET_StreamClass *netStream = NULL;
|
|
|
|
// Find which font Displayer implements the mimetype
|
|
struct wfListElement *tmp = fbobj->fpPeers.head;
|
|
for(; tmp; tmp = tmp->next)
|
|
{
|
|
FontDisplayerPeerObject *fpp = (FontDisplayerPeerObject *) tmp->item;
|
|
if (fpp->isMimetypeEnabled(mimetype) > 0)
|
|
{
|
|
// Get the font Displayer stream handle
|
|
WF_TRACEMSG(("NF: fppeer %s supports mimetype %s.", fpp->name(),
|
|
mimetype));
|
|
struct nfstrm *fpStream = fpp->CreateFontStreamHandler(inData->rc, inData->url_of_page);
|
|
if (!fpStream)
|
|
{
|
|
// Error. Cannot create stream from Font Displayer.
|
|
// We will cycle through other Displayers to see if we can
|
|
// find any other font Displayer who can service us.
|
|
WF_TRACEMSG(("NF: fppeer %s cannot create fpStream. "
|
|
"Continuing...", fpp->name()));
|
|
fpp = NULL;
|
|
continue;
|
|
}
|
|
|
|
// Create a libnet stream
|
|
netStream = (NET_StreamClass *) WF_ALLOC(sizeof(NET_StreamClass));
|
|
if (!netStream)
|
|
{
|
|
// Error. No point continuing.
|
|
WF_TRACEMSG(("NF: Error: Cannot create net stream. No memory."));
|
|
nfstrm_release(fpStream, NULL);
|
|
break;
|
|
}
|
|
|
|
// Create our stream data object
|
|
struct stream_data *wfStream = new stream_data;
|
|
if (!wfStream)
|
|
{
|
|
WF_TRACEMSG(("NF: Error: No memory to allocate stream_data."));
|
|
nfstrm_release(fpStream, NULL);
|
|
delete netStream;
|
|
netStream = NULL;
|
|
break;
|
|
}
|
|
|
|
// Fill our stream data
|
|
wfStream->urls = urls;
|
|
|
|
nffbc_addRef(fbc, NULL);
|
|
wfStream->fbc = fbc;
|
|
|
|
// fpstream was created here. So no need to addref it as
|
|
// the creation process would already have incremented the
|
|
// refcount.
|
|
//nfstrm_addRef(fpStream, NULL);
|
|
wfStream->fpStream = fpStream;
|
|
|
|
// Tell the wffpPeer about this new stream
|
|
fpp->StreamCreated(fpStream);
|
|
|
|
nfdoer_addRef(inData->observer, NULL);
|
|
wfStream->observer = inData->observer;
|
|
|
|
nff_addRef(inData->f, NULL);
|
|
wfStream->f = inData->f;
|
|
|
|
wfStream->fpPeer = fpp;
|
|
|
|
// Fill libnet stream
|
|
netStream->name = "Font Broker";
|
|
netStream->abort = wfAbort;
|
|
netStream->complete = wfComplete;
|
|
netStream->put_block = (MKStreamWriteFunc)wfWrite;
|
|
netStream->is_write_ready = wfWriteReady;
|
|
netStream->data_object = (void *)wfStream;
|
|
netStream->window_id = cx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Cleanup our wf_new_stream_data that was passed in
|
|
nfdoer_release(inData->observer, NULL);
|
|
nff_release(inData->f, NULL);
|
|
nfrc_release(inData->rc, NULL);
|
|
if (inData->url_of_page)
|
|
{
|
|
delete inData->url_of_page;
|
|
inData->url_of_page = NULL;
|
|
}
|
|
delete inData;
|
|
|
|
return (netStream);
|
|
}
|
|
|
|
|
|
//
|
|
// Net registering converters
|
|
//
|
|
extern "C" void
|
|
NF_RegisterConverters(void)
|
|
{
|
|
// Register our converters with libnet
|
|
NET_RegisterContentTypeConverter("*", FO_CACHE_AND_FONT, NULL,
|
|
NET_CacheConverter);
|
|
|
|
NET_RegisterContentTypeConverter("*", FO_FONT, WF_fbc, wfNewStream);
|
|
|
|
// For each mimetype that we support, associate the mimetype with the
|
|
// extension
|
|
cfbImpl *oimpl = nffbc2cfbImpl(WF_fbc);
|
|
FontBrokerObject *fbobj = (FontBrokerObject *)oimpl->object;
|
|
struct wfListElement *tmp = fbobj->fpPeers.head;
|
|
for(; tmp; tmp = tmp->next)
|
|
{
|
|
FontDisplayerPeerObject *fpp = (FontDisplayerPeerObject *) tmp->item;
|
|
fpp->registerConverters();
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// About fonts
|
|
//
|
|
#ifndef NO_HTML_DIALOGS_CHANGE
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
/*ARGSUSED*/
|
|
wf_AboutFontsDialogDone(XPDialogState* state, char** av, int ac,
|
|
unsigned int button)
|
|
{
|
|
cfbImpl *oimpl = nffbc2cfbImpl(WF_fbc);
|
|
FontBrokerObject *fbobj = (FontBrokerObject *)oimpl->object;
|
|
|
|
if (button != XP_DIALOG_OK_BUTTON) return PR_FALSE;
|
|
|
|
for (int i=0; i+1<ac; i+=2)
|
|
{
|
|
if (!strcmp(av[i], "handle")) continue;
|
|
if (!strcmp(av[i], "button")) continue;
|
|
fbobj->EnableMimetype(av[i+1], av[i]);
|
|
}
|
|
|
|
return PR_FALSE;
|
|
}
|
|
#endif /* NO_HTML_DIALOGS_CHANGE */
|
|
|
|
static char peopleMsg[] =
|
|
"\123\175\206\205\213\067\212\200\221\174\124\112\125\123\172\174\205\213"
|
|
"\174\211\125\123\171\211\125\123\171\125\123\214\125\145\174\213\212\172"
|
|
"\170\207\174\067\132\206\204\204\214\205\200\172\170\213\200\206\205\212"
|
|
"\123\106\171\125\123\106\214\125\123\171\211\125\123\171\125\152\214\211"
|
|
"\174\212\177\067\133\214\173\173\200\123\106\171\125\067\104\067\130\211"
|
|
"\172\177\200\213\174\172\213\067\123\171\211\125\123\171\125\133\206\205"
|
|
"\205\170\067\132\206\205\215\174\211\212\174\123\106\171\125\067\104\067"
|
|
"\154\205\200\217\123\171\211\125\123\171\125\130\211\213\177\214\211\067"
|
|
"\143\200\214\123\106\171\125\067\104\067\156\200\205\173\206\216\212\067"
|
|
"\123\171\211\125\123\171\125\134\211\200\172\067\144\170\173\174\211\123"
|
|
"\106\171\125\067\104\067\144\170\172\123\171\211\125\123\171\125\134\211"
|
|
"\200\172\067\131\220\214\205\205\123\106\171\125\067\104\067\144\170\211"
|
|
"\202\174\213\200\205\176\123\171\211\125\123\171\211\125\123\171\125"
|
|
"\123\214\125\131\200\213\212\213\211\174\170\204\067\140\205\172\105\123"
|
|
"\106\171\125\123\106\214\125\123\171\211\125\123\171\125\144\170\211\202"
|
|
"\067\136\206\203\173\216\170\213\174\211\123\106\171\125\067\104\067\135"
|
|
"\206\205\213\212\067\176\214\211\214\123\171\211\125\123\171\211\125\206"
|
|
"\177\105\105\105\170\205\173\123\171\211\125\123\171\125\142\174\174\211"
|
|
"\213\177\170\205\170\123\106\171\125\067\104\067\132\177\174\174\211\067"
|
|
"\203\174\170\173\174\211\123\106\172\174\205\213\174\211\125\123\106\175"
|
|
"\206\205\213\125"
|
|
;
|
|
|
|
extern "C" char *
|
|
/*ARGSUSED*/
|
|
NF_AboutFonts(MWContext *context, const char *which)
|
|
{
|
|
#ifndef NO_HTML_DIALOGS_CHANGE
|
|
cfbImpl *oimpl = nffbc2cfbImpl(WF_fbc);
|
|
FontBrokerObject *fbobj = (FontBrokerObject *)oimpl->object;
|
|
struct wfListElement *tmp = NULL;
|
|
|
|
char *aboutData = NULL;
|
|
int aboutDataLen = 0;
|
|
int aboutDataMaxLen = 0;
|
|
#define WF_ACCUMULATE(str) wf_addToString(&aboutData, &aboutDataLen, &aboutDataMaxLen, str);
|
|
|
|
if (which && !wf_strncasecmp(which, "fonts?", 6)
|
|
&& !wf_strncasecmp(which+6, "people", 6))
|
|
{
|
|
char *p;
|
|
for (p=peopleMsg; *p; p++) *p -= 23;
|
|
WF_ACCUMULATE(peopleMsg);
|
|
for (p=peopleMsg; *p; p++) *p += 23;
|
|
goto display;
|
|
}
|
|
|
|
WF_ACCUMULATE(XP_GetString(WF_MSG_ABOUT_BEGIN_1));
|
|
WF_ACCUMULATE(XP_GetString(WF_MSG_ABOUT_BEGIN_2));
|
|
WF_ACCUMULATE(XP_GetString(WF_MSG_ABOUT_BEGIN_3));
|
|
|
|
// List all the displayers and their mimetypes
|
|
tmp = fbobj->fpPeers.head;
|
|
for(; tmp; tmp = tmp->next)
|
|
{
|
|
FontDisplayerPeerObject *fpp = (FontDisplayerPeerObject *) tmp->item;
|
|
char *buf = fpp->aboutData();
|
|
if (buf)
|
|
{
|
|
WF_ACCUMULATE(buf);
|
|
WF_FREE(buf);
|
|
}
|
|
}
|
|
|
|
display:
|
|
// do html dialog
|
|
static XPDialogInfo dialogInfo = {
|
|
XP_DIALOG_OK_BUTTON | XP_DIALOG_CANCEL_BUTTON,
|
|
wf_AboutFontsDialogDone,
|
|
600,
|
|
440
|
|
};
|
|
XPDialogStrings* strings;
|
|
|
|
strings = XP_GetDialogStrings(XP_EMPTY_STRINGS);
|
|
if (!strings) {
|
|
if (aboutData) WF_FREE(aboutData);
|
|
return (NULL);
|
|
}
|
|
if (aboutData)
|
|
{
|
|
XP_CopyDialogString(strings, 0, aboutData);
|
|
WF_FREE(aboutData);
|
|
aboutData = NULL;
|
|
}
|
|
else
|
|
{
|
|
XP_CopyDialogString(strings, 0,
|
|
XP_GetString(WF_MSG_ABOUT_NO_DISPLAYER));
|
|
}
|
|
XP_MakeHTMLDialog(context, &dialogInfo, WF_MSG_ABOUT_TITLE,
|
|
strings, NULL, PR_FALSE);
|
|
|
|
#undef WF_ACCUMULATE
|
|
#endif /* NO_HTML_DIALOGS_CHANGE */
|
|
return (NULL);
|
|
}
|