/* -*- Mode: C++; tab-width: 8; 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. */ /* cvchcode.c */ #include "intlpriv.h" #include "xp.h" #include "intl_csi.h" #include "libi18n.h" #include "katakana.h" int16 PeekMetaCharsetTag (char *, uint32); /* * DocumentContext access to creating a * Character Code Converter * * This should be split into two layers: * 1) a non-DocumentContext access to creating a Character Code Converter * 2) a DocumentContext interface to above */ PUBLIC CCCDataObject INTL_CreateDocumentCCC(INTL_CharSetInfo c, uint16 default_doc_csid) { CCCDataObject obj; /* * create the CCC object */ obj = INTL_CreateCharCodeConverter();; if (obj == NULL) return(NULL); INTL_SetCCCDefaultCSID(obj, default_doc_csid); /* * if we know the doc_csid then get the converter */ if (DOC_CSID_KNOWN(INTL_GetCSIDocCSID(c))) { (void) INTL_GetCharCodeConverter(INTL_GetCSIDocCSID(c), 0, obj); XP_ASSERT(INTL_GetCSIWinCSID(c) == INTL_GetCCCToCSID(obj)); } else { /* we know what the default converter is but do not install * it yet. Wait until the first block and see if we determine * what the charset is from that block. */ } return obj; } PUBLIC void INTL_CCCReportMetaCharsetTag(MWContext *context, char *charset_tag) { INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); INTL_CSIReportMetaCharsetTag(c, charset_tag, context->type); } #ifdef MOZ_MAIL_NEWS #if 0 /* INTL_ConvWinToMailCharCode Converts 8bit encoding to 7bit mail encoding. It decides which 7bit and 8bit encoding to use based on current default language. input: char *pSrc; // Source display buffer output: char *pDest; // Destination buffer // pDest == NULL means either conversion fail // or does OneToOne conversion */ PUBLIC unsigned char *INTL_ConvWinToMailCharCode(iDocumentContext context, unsigned char *pSrc, uint32 block_size) { CCCDataObject obj; unsigned char *pDest; int16 wincsid; CCCFunc cvtfunc; obj = INTL_CreateCharCodeConverter(); if (obj == NULL) return NULL; wincsid = INTL_DefaultWinCharSetID(context); /* Converts 8bit Window codeset to 7bit Mail Codeset. */ (void) INTL_GetCharCodeConverter(wincsid, INTL_DefaultMailCharSetID(wincsid), obj); cvtfunc = INTL_GetCCCCvtfunc(obj); if (cvtfunc) pDest = (unsigned char *)cvtfunc(obj, pSrc, block_size); else pDest = NULL ; XP_FREE(obj); if (pDest == pSrc) /* converted to input buffer */ { /* no additional memory been allocated */ return NULL; } return pDest ; } #endif /* if 0 */ PRIVATE void mail_report_autodetect(void *closure, CCCDataObject obj, uint16 doc_csid) { iDocumentContext doc_context = (iDocumentContext)closure; INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(doc_context); INTL_SetCSIDocCSID(c, doc_csid); INTL_SetCSIWinCSID(c, INTL_GetCCCToCSID(obj)); } #endif /* MOZ_MAIL_NEWS */ #ifndef XP_WIN #ifndef XP_MAC /* * FE_DefaultDocCharSetID - get the UI charset encoding setting * * gets the currently selected charset encoding for this document * (not the global default, not the detected document encoding) * */ uint16 FE_DefaultDocCharSetID(iDocumentContext context) { uint16 csid; /* need to implement a FE_DefaultDocCharSetID() which only returns the FE default, ignoring the doc_csid in the the context. The Current INTL_DefaultDocCharSetID tries to be smart and return the doc_csid if it is known, which causes a problem in HERE !! */ #ifdef REAL_FIX_AFTER_B3 /* ftang, bstell: Need to change to this code in early 4.0 B4 cycle */ csid = FE_DefaultDocCharSetID(context); /* Need to implement FE_DefaultDocCharSetID before active this */ if((CS_JIS == csid) || (CS_EUCJP == csid) || (CS_SJIS == csid) || (CS_KSC_8BIT == csid) || (CS_2022_KR == csid)) { csid |= CS_AUTO; } #else /* 4.0 B3 temp fix */ INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); csid = INTL_GetCSIDocCSID(c); if (csid == 0) { csid = INTL_DefaultDocCharSetID(context); } #ifdef MOZ_MAIL_NEWS else { csid = INTL_DefaultMailCharSetID(csid); /* Turn on the auto converter in case people do receive SJIS mail */ if((CS_JIS == csid) || (CS_EUCJP == csid) || (CS_SJIS == csid) || (CS_KSC_8BIT == csid) || (CS_2022_KR == csid)) { csid |= CS_AUTO; } } #endif /* MOZ_MAIL_NEWS */ #endif return csid; } #endif /*XP_MAC*/ #endif #ifdef MOZ_MAIL_NEWS /* INTL_ConvMailToWinCharCode Converts mail encoding to display charset which is used by current window. It decides which Display charset to use based on current default language. input: iDocumentContext context; the context (window ID) char *pSrc; // Source buffer uint32 block_size; the length of the source buffer output: char *pDest; // Destination buffer // pDest == NULL means either conversion fail // or does OneToOne conversion */ PUBLIC unsigned char *INTL_ConvMailToWinCharCode(iDocumentContext context, unsigned char *pSrc, uint32 block_size) { CCCDataObject obj; unsigned char *pDest; Stream stream; CCCFunc cvtfunc; int16 csid; obj = INTL_CreateCharCodeConverter(); if (obj == NULL) return 0; (void) memset(&stream, 0, sizeof(stream)); stream.window_id = context; csid = FE_DefaultDocCharSetID(context); /* Converts 7bit news codeset to 8bit windows Codeset. */ (void) INTL_GetCharCodeConverter(csid, 0, obj); INTL_SetCCCReportAutoDetect(obj, mail_report_autodetect, context ); cvtfunc = INTL_GetCCCCvtfunc(obj); if (cvtfunc) pDest = (unsigned char *)cvtfunc(obj, pSrc, block_size); else pDest = NULL ; XP_FREE(obj); if (pSrc == pDest) return NULL ; return pDest ; } #endif /* MOZ_MAIL_NEWS */ #if defined(MOZ_MAIL_COMPOSE) || defined(MOZ_MAIL_NEWS) /* This is the ugly hack for Korean News and Mail Our libmsg code assume mail and news use the same code. Unfortunately, Korean use different encoding in news and mail We have to tell the DocToMailCoverter convert to different encoding according to the reciver. Problem 1: It is easy to decide which encoding we should send if the receipt is only Newsgroup or only email. But what should we do if the receipt include both newsgroup and personal address ? Currently we always send News encoding if the recipt include Newsgroup. Problem 2: There are no way I can pass such information to the code between msgsendp.cpp and msgsend.cpp. So I create such a hack here. */ static XP_Bool intl_message_to_newsgroup = FALSE; PUBLIC void INTL_MessageSendToNews(XP_Bool toNews) { intl_message_to_newsgroup = toNews; } PUBLIC CCCDataObject INTL_CreateDocToMailConverter(iDocumentContext context, XP_Bool isHTML, unsigned char *buffer, uint32 buffer_size) { CCCDataObject selfObj; int16 p_doc_csid = CS_DEFAULT; #if defined(MOZ_MAIL_NEWS) int16 mail_news_csid; #endif CCCFunc cvtfunc; INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); /* Ok!! let's create the object here We need the conversion obj to keep the state information */ selfObj = INTL_CreateCharCodeConverter(); if(selfObj == NULL) return NULL; /* First, let's determine the from_csid and to_csid */ /* It is a TEXT_HTML !!! Let's use our PeekMetaCharsetTag to get a csid */ if(isHTML) p_doc_csid = PeekMetaCharsetTag((char*) buffer, buffer_size); if(p_doc_csid == CS_DEFAULT) { /* got default, try to get the doc_csid from context */ if((context == 0 ) || (INTL_GetCSIDocCSID(c) == CS_DEFAULT)) p_doc_csid = INTL_DefaultDocCharSetID(context); else p_doc_csid = INTL_GetCSIDocCSID(c); #ifdef XP_MAC /* To Make Macintosh happe when there is a HTML Mail composer send out plain text file. It put the MacRoman text into the temp file and then let this function load it. Because I change the mac version of INTL_DefaultDocCharSetID() so now it listen to the front window to tell me which doc csid it is. It is Latin1 in the case email. But the data is really MacRoman. So we add this hack here. Which only change the doccsid if it is not HTML */ if(! isHTML) { switch(p_doc_csid) { case CS_LATIN1: p_doc_csid = CS_MAC_ROMAN; break; case CS_LATIN2: p_doc_csid = CS_MAC_CE; break; case CS_8859_5: case CS_KOI8_R: p_doc_csid = CS_MAC_CYRILLIC; break; case CS_8859_7: p_doc_csid = CS_MAC_GREEK; break; case CS_8859_9: p_doc_csid = CS_MAC_TURKISH; break; default: break; } } #endif /* The doc_csid from the context (or default) has CS_AUTO bit. */ /* So let's try to call the auto detection function */ /* ftang add this: The CS_AUTO is still buggy, */ if( (CS_JIS == p_doc_csid) || (CS_SJIS == p_doc_csid) || (CS_EUCJP == p_doc_csid) || (CS_KSC_8BIT == p_doc_csid) || (CS_2022_KR == p_doc_csid) || (CS_JIS_AUTO == p_doc_csid) || (CS_SJIS_AUTO == p_doc_csid) || (CS_EUCJP_AUTO == p_doc_csid) || (CS_KSC_8BIT_AUTO == p_doc_csid) /* || (CS_2022_KR_AUTO == p_doc_csid) */ ) { uint16 default_csid = INTL_DefaultDocCharSetID(context); switch(p_doc_csid & ~CS_AUTO) { case CS_JIS: case CS_SJIS: case CS_EUCJP: p_doc_csid = intl_detect_JCSID((uint16)(default_csid&~CS_AUTO), buffer, buffer_size); break; case CS_KSC_8BIT: case CS_2022_KR: p_doc_csid = intl_detect_KCSID((uint16)(default_csid&~CS_AUTO), buffer, buffer_size); break; /* Probably need to take care UCS2 / UTF8 and UTF7 here */ case CS_BIG5: case CS_CNS_8BIT: case CS_UTF8: case CS_UTF7: case CS_UCS2: case CS_UCS2_SWAP: default: XP_ASSERT(FALSE); } } } #if defined(MOZ_MAIL_NEWS) mail_news_csid = (intl_message_to_newsgroup ? INTL_DefaultNewsCharSetID(p_doc_csid) : INTL_DefaultMailCharSetID(p_doc_csid)); #endif /* Now, we get the converter */ (void) INTL_GetCharCodeConverter(p_doc_csid, #ifdef MOZ_MAIL_NEWS (intl_message_to_newsgroup ? INTL_DefaultNewsCharSetID(p_doc_csid) : INTL_DefaultMailCharSetID(p_doc_csid)), #else /* must be MOZ_MAIL_COMPOSE */ INTL_DefaultMailCharSetID(p_doc_csid), #endif /* MOZ_MAIL_NEWS */ selfObj); #if defined(MOZ_MAIL_NEWS) /* If we sending JIS then listen the pref setting and decide if we convert * hankaku (1byte) to zenkaku (2byte) kana. The flag to be checked in * euc2jis and sjis2jis. */ if (CS_JIS == mail_news_csid && INTL_GetSendHankakuKana()) { INTL_SetCCCCvtflag_SendHankakuKana(selfObj, TRUE); } #endif /* If the cvtfunc == NULL, we don't need to do conversion */ cvtfunc = INTL_GetCCCCvtfunc(selfObj); if(! (cvtfunc) ) { XP_FREE(selfObj); return NULL; } else return selfObj; } #endif /* MOZ_MAIL_COMPOSE */