mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 12:15:51 +00:00
400 lines
9.1 KiB
C
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;
|
||
|
}
|
||
|
|
||
|
|