/* -*- 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; }