gecko-dev/lib/libi18n/intl_csi.c
1998-03-28 02:44:41 +00:00

400 lines
9.1 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.
*/
/* intl_csi.c International Character Set Information
*
* This file contains the INTL_CSI accessor functions
*
* This allows the i18n character set data to be
* changed without (hopefully) changing all the
* code that accesses it.
*
* UNFORTUNATELY, as of this date Oct. 28, 1996
* there is not document context so we are still
* using the old MWContext.
* When this is fix all that is needed should
* be change the USE_REAL_DOCUMENT_CONTEXT flag
* and recompile (and test of course).
*/
#include "intlpriv.h"
#include "xp.h"
#include "libi18n.h"
#include "intl_csi.h"
struct OpaqueINTL_CharSetInfo {
uint16 doc_csid;
uint16 http_doc_csid;
uint16 meta_doc_csid;
uint16 override_doc_csid;
uint16 win_csid;
unsigned char *mime_charset;
int relayout;
};
typedef enum
{
OVERRIDE_CSID_TYPE,
HTTP_CSID_TYPE,
META_CSID_TYPE,
DOC_CSID_TYPE
} CsidType;
PRIVATE uint16 get_charset_tag(char *charset_tag);
/*
*
* Setup the character set info
*
*/
void
INTL_CSIInitialize(INTL_CharSetInfo c, XP_Bool is_metacharset_reload,
char *http_charset, int doc_type, uint16 default_doc_csid)
{
uint16 http_doc_csid = get_charset_tag(http_charset);
uint16 win_csid;
XP_ASSERT(NULL != c);
/*
* Initiliaze the Character-Set-Info (CSI)
* (unless if we are doing a meta_charset_reload)
*/
if (!is_metacharset_reload)
INTL_CSIReset(c);
/*
* Setup the CSI with the information we currently know
*/
/* first check if this is a metacharset reload */
if (is_metacharset_reload)
{
INTL_SetCSIRelayoutFlag(c, METACHARSET_RELAYOUTDONE);
}
/* Check for a doc csid override */
else if (DOC_CSID_KNOWN(INTL_GetCSIOverrideDocCSID(c)))
{
INTL_SetCSIDocCSID(c, INTL_GetCSIOverrideDocCSID(c));
}
/* if we have a HTTP charset tag then use it */
else if (DOC_CSID_KNOWN(http_doc_csid))
{
INTL_SetCSIHTTPDocCSID(c, http_doc_csid);
}
else /* normal case */
{
uint16 init_doc_csid = default_doc_csid;
/*
* mail/news sometimes has the wrong meta charset
* so for mail/news we always ignore the meta charset tag
* which causes us to use the encoding the user set in the
* encoding menu
*/
if (!(MAIL_NEWS_TYPE(doc_type)))
init_doc_csid = CS_DEFAULT;
#ifdef XP_UNIX
/*
* The PostScript and Text FEs inherit the doc_csid from
* the parent context in order to pick up the per-window
* default. Apparently, this already works for some
* reason on Windows. Don't know about Mac. -- erik
*/
if ((doc_type != MWContextPostScript) &&
(doc_type != MWContextText))
#endif /* XP_UNIX */
INTL_SetCSIDocCSID(c, init_doc_csid /*CS_DEFAULT*/ );
}
/*
* alot of code (parsing/layout/FE) wants to know
* the encoding so we must set something
*/
if (DOC_CSID_KNOWN(INTL_GetCSIDocCSID(c)))
win_csid = INTL_DocToWinCharSetID(INTL_GetCSIDocCSID(c));
else
win_csid = INTL_DocToWinCharSetID(default_doc_csid);
INTL_SetCSIWinCSID(c, win_csid); /* true until we know otherwise */
}
PRIVATE void
set_csid(INTL_CharSetInfo c, uint16 csid, CsidType type)
{
XP_ASSERT(NULL != c);
if (OVERRIDE_CSID_TYPE == type)
{
c->override_doc_csid = csid;
c->doc_csid = csid;
}
else if (HTTP_CSID_TYPE == type)
{
c->http_doc_csid = csid;
if (CS_DEFAULT == c->override_doc_csid)
c->doc_csid = csid;
}
else if (META_CSID_TYPE == type)
{
c->meta_doc_csid = csid;
if ( (CS_DEFAULT == c->override_doc_csid)
&& (CS_DEFAULT == c->http_doc_csid))
c->doc_csid = csid;
}
else if (DOC_CSID_TYPE == type)
{
if ( (CS_DEFAULT == c->override_doc_csid)
&& (CS_DEFAULT == c->http_doc_csid)
&& (CS_DEFAULT == c->meta_doc_csid))
c->doc_csid = csid;
}
else
{
XP_ASSERT(0);
}
}
void
INTL_CSIReportMetaCharsetTag(INTL_CharSetInfo c, char *charset_tag, int type)
{
int16 doc_csid;
XP_ASSERT(charset_tag);
doc_csid = INTL_CharSetNameToID(charset_tag);
/* ignore invalid tags */
if (doc_csid == CS_UNKNOWN)
return;
/* mail and news ignores meta charset tags since some are wrong */
if (MAIL_NEWS_TYPE(type))
return;
/* only honor the first (meta or http) charset tag */
if (INTL_GetCSIRelayoutFlag(c) == METACHARSET_NONE)
{
uint16 old_doc_csid = INTL_GetCSIDocCSID(c);
INTL_SetCSIMetaDocCSID(c, doc_csid);
/* ignore subsequent meta charset tags */
INTL_SetCSIRelayoutFlag(c, METACHARSET_HASCHARSET);
/*
* if we already set up the converter wrong we have to reload
*/
if (DOC_CSID_KNOWN(old_doc_csid)
&& ((old_doc_csid & ~CS_AUTO) != doc_csid))
INTL_SetCSIRelayoutFlag(c, METACHARSET_REQUESTRELAYOUT);
/*
* if we told the FE the wrong win_csid we have to reload
* (we had to tell the FE something so it could do layout
* while we were looking for the metacharset tag)
*/
else if (INTL_DocToWinCharSetID(doc_csid) != INTL_GetCSIWinCSID(c))
INTL_SetCSIRelayoutFlag(c, METACHARSET_REQUESTRELAYOUT);
}
}
PRIVATE uint16 get_charset_tag(char *charset_tag)
{
uint16 csid;
/* validate the http_charset */
if ((NULL == charset_tag) || ('\0' == *charset_tag))
return CS_UNKNOWN;
csid = INTL_CharSetNameToID(charset_tag);
if (CS_DEFAULT == csid)
csid = CS_UNKNOWN;
return csid;
}
INTL_CharSetInfo
LO_GetDocumentCharacterSetInfo(MWContext *context)
{
XP_ASSERT(context);
XP_ASSERT(INTL_TAG == context->INTL_tag);
XP_ASSERT(NULL != context->INTL_CSIInfo);
return(context->INTL_CSIInfo);
}
INTL_CharSetInfo
INTL_CSICreate(void)
{
INTL_CharSetInfo c;
#if (defined(DEBUG_bstell) || defined(DEBUG_nhotta) || defined(DEBUG_ftang))
#define BSTELLS_FREE_TRICK_OFFSET 64
/* I use (abuse) the malloc system to find improper frees */
{
char *p;
p = (char *)XP_CALLOC(1,
BSTELLS_FREE_TRICK_OFFSET+sizeof(struct OpaqueINTL_CharSetInfo));
c = (INTL_CharSetInfo)(p + BSTELLS_FREE_TRICK_OFFSET);
}
#else
c = (INTL_CharSetInfo)XP_CALLOC(1, sizeof(struct OpaqueINTL_CharSetInfo));
#endif
return c;
}
void
INTL_CSIDestroy(INTL_CharSetInfo c)
{
XP_ASSERT(c);
#if (defined(DEBUG_bstell) || defined(DEBUG_nhotta) || defined(DEBUG_ftang))
{
char *p = (char *)c;
XP_FREE(p - BSTELLS_FREE_TRICK_OFFSET);
}
#else
XP_FREE(c);
#endif
}
void
INTL_CSIReset(INTL_CharSetInfo c)
{
INTL_SetCSIOverrideDocCSID (c, CS_DEFAULT);
INTL_SetCSIHTTPDocCSID (c, CS_DEFAULT);
INTL_SetCSIMetaDocCSID (c, CS_DEFAULT);
INTL_SetCSIDocCSID (c, CS_DEFAULT);
INTL_SetCSIWinCSID (c, CS_DEFAULT);
INTL_SetCSIMimeCharset(c, NULL);
INTL_SetCSIRelayoutFlag(c, METACHARSET_NONE);
}
/* ----------- CSI CSID ----------- */
/* Override is strongest. Must set doc_csid */
void
INTL_SetCSIOverrideDocCSID (INTL_CharSetInfo c, int16 doc_csid)
{
set_csid(c, doc_csid, OVERRIDE_CSID_TYPE);
}
/* Next strongest. Set doc_csid if no override */
void
INTL_SetCSIHTTPDocCSID (INTL_CharSetInfo c, int16 doc_csid)
{
set_csid(c, doc_csid, HTTP_CSID_TYPE);
}
/* Next strongest. Set doc_csid if no override */
void
INTL_SetCSIMetaDocCSID (INTL_CharSetInfo c, int16 doc_csid)
{
set_csid(c, doc_csid, META_CSID_TYPE);
}
/* Meta charset is weakest. Only set doc_csid if no http or override */
void
INTL_SetCSIDocCSID (INTL_CharSetInfo c, int16 doc_csid)
{
set_csid(c, doc_csid, DOC_CSID_TYPE);
}
int16
INTL_GetCSIDocCSID(INTL_CharSetInfo c)
{
XP_ASSERT(c);
return c->doc_csid;
}
int16
INTL_GetCSIMetaDocCSID(INTL_CharSetInfo c)
{
XP_ASSERT(c);
return c->meta_doc_csid;
}
int16
INTL_GetCSIOverrideDocCSID(INTL_CharSetInfo c)
{
XP_ASSERT(c);
return c->override_doc_csid;
}
/* ----------- Window CSID ----------- */
void
INTL_SetCSIWinCSID(INTL_CharSetInfo c, int16 win_csid)
{
XP_ASSERT(c);
c->win_csid = win_csid;
}
int16
INTL_GetCSIWinCSID(INTL_CharSetInfo c)
{
XP_ASSERT(c);
return c->win_csid;
}
/* ----------- Mime CSID ----------- */
char *
INTL_GetCSIMimeCharset (INTL_CharSetInfo c)
{
XP_ASSERT(c);
return (char *)c->mime_charset;
}
void
INTL_SetCSIMimeCharset(INTL_CharSetInfo c, char *mime_charset)
{
unsigned char *p;
XP_ASSERT(c);
if (c->mime_charset)
{
XP_FREE(c->mime_charset);
c->mime_charset = NULL;
}
if (NULL == mime_charset)
return;
c->mime_charset = (unsigned char *)XP_STRDUP(mime_charset);
if (NULL == c->mime_charset)
return;
/* Legitimate charset names must be in ASCII and case insensitive */
/* convert to lower case */
for (p=c->mime_charset; *p; p++)
*p = tolower(*p);
return;
}
/* ----------- Relayout Flag ----------- */
int16
INTL_GetCSIRelayoutFlag(INTL_CharSetInfo c)
{
XP_ASSERT(c);
return c->relayout;
}
void
INTL_SetCSIRelayoutFlag(INTL_CharSetInfo c, int16 relayout)
{
XP_ASSERT(c);
c->relayout = relayout;
}