home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / UCAux.c < prev    next >
C/C++ Source or Header  |  1998-03-25  |  13KB  |  452 lines

  1. #include <HTUtils.h>
  2. #include <tcp.h>
  3.  
  4. #include <HTCJK.h>
  5. #include <UCDefs.h>
  6. #include <HTStream.h>
  7. #include <UCAux.h>
  8.  
  9. extern HTCJKlang HTCJK;
  10. extern LYUCcharset LYCharSet_UC[];
  11.  
  12. PUBLIC BOOL UCCanUniTranslateFrom ARGS1(
  13.     int,        from)
  14. {
  15.     if (from < 0)
  16.     return NO;
  17.     if (LYCharSet_UC[from].enc == UCT_ENC_7BIT ||
  18.     LYCharSet_UC[from].enc == UCT_ENC_UTF8)
  19.     return YES;
  20.     if (LYCharSet_UC[from].codepoints & (UCT_CP_SUBSETOF_LAT1))
  21.     return YES;
  22.     return (LYCharSet_UC[from].UChndl >= 0);
  23. }
  24.  
  25. PUBLIC BOOL UCCanTranslateUniTo ARGS1(
  26.     int,        to)
  27. {
  28.     if (to < 0)
  29.     return NO;
  30.     return YES;            /* well at least some characters... */
  31. }
  32.  
  33. PUBLIC BOOL UCCanTranslateFromTo ARGS2(
  34.     int,        from,
  35.     int,        to)
  36. {
  37.     if (from == to)
  38.     return YES;
  39.     if (from < 0 || to < 0)
  40.     return NO;
  41.     if (from == 0)
  42.     return UCCanTranslateUniTo(to);
  43.     if (to == 0 || LYCharSet_UC[to].enc == UCT_ENC_UTF8)
  44.     return UCCanUniTranslateFrom(from);
  45.     {
  46.     CONST char * fromname = LYCharSet_UC[from].MIMEname;
  47.     CONST char * toname = LYCharSet_UC[to].MIMEname;
  48.     if (!strcmp(fromname, "x-transparent") ||
  49.         !strcmp(toname, "x-transparent")) {
  50.         return YES;
  51.     } else if (!strcmp(fromname, "us-ascii")) {
  52.         return YES;
  53.     }
  54.     if (LYCharSet_UC[from].enc == UCT_ENC_CJK) {
  55.         /*
  56.         **  CJK mode may be off (i.e., HTCJK == NOCJK) because
  57.         **  the current document is not CJK, but the check may
  58.         **  be for capability in relation to another document,
  59.         **  for which CJK mode might be turned on when retrieved.
  60.         **  Thus, when the from charset is CJK, check if the to
  61.         **  charset is CJK, and return NO or YES in relation to
  62.         **  that. - FM
  63.         */
  64.         if (LYCharSet_UC[to].enc != UCT_ENC_CJK)
  65.         return NO;
  66.         if ((!strcmp(toname, "euc-jp") ||
  67.          !strcmp(toname, "shift_jis")) &&
  68.         (!strcmp(fromname, "euc-jp") ||
  69.          !strcmp(fromname, "shift_jis")))
  70.         return YES;
  71.         /*
  72.         **  The euc-cn and euc-kr charsets were handled
  73.         **  by the (from == to) above, so we need not
  74.         **  check those. - FM
  75.         **/
  76.         return NO;
  77.     }
  78.     }
  79.     return (LYCharSet_UC[from].UChndl >= 0);
  80. }
  81.  
  82. /*
  83. **  Returns YES if no translation necessary (because
  84. **  charsets are equal, are equivalent, etc.).
  85. */
  86. PUBLIC BOOL UCNeedNotTranslate ARGS2(
  87.     int,        from,
  88.     int,        to)
  89. {
  90.     CONST char *fromname;
  91.     CONST char *toname;
  92.     if (from == to)
  93.     return YES;
  94.     if (from < 0)
  95.     return NO;        /* ??? */
  96.     if (LYCharSet_UC[from].enc == UCT_ENC_7BIT) {
  97.     return YES;        /* Only 7bit chars. */
  98.     }
  99.     fromname = LYCharSet_UC[from].MIMEname;
  100.     if (!strcmp(fromname, "x-transparent") ||
  101.     !strcmp(fromname, "us-ascii")) {
  102.         return YES;
  103.     }
  104.     if (to < 0)
  105.     return NO;        /* ??? */
  106.     if (to == 0) {
  107.     if (LYCharSet_UC[from].codepoints & (UCT_CP_SUBSETOF_LAT1))
  108.         return YES;
  109.     }
  110.     toname = LYCharSet_UC[to].MIMEname;
  111.     if (!strcmp(toname, "x-transparent")) {
  112.     return YES;
  113.     }
  114.     if (LYCharSet_UC[to].enc == UCT_ENC_UTF8) {
  115.     return NO;
  116.     }
  117.     if (from == 0) {
  118.     if (LYCharSet_UC[from].codepoints & (UCT_CP_SUPERSETOF_LAT1))
  119.         return YES;
  120.     }
  121.     if (LYCharSet_UC[from].enc == UCT_ENC_CJK) {
  122.     if (HTCJK == NOCJK)    /* Use that global flag, for now. */
  123.         return NO;
  124.     if (HTCJK == JAPANESE &&
  125.         /*
  126.         **  Always strip the "x-" from "x-euc-jp",
  127.         **  or convert "x-shift-jis" to "shift_jis",
  128.         **  before calling this function, and so
  129.         **  don't check for them here. - FM
  130.         */
  131.         (!strcmp(fromname, "euc-jp") ||
  132.          !strncmp(fromname, "iso-2022-jp",11) ||
  133.          !strcmp(fromname, "shift_jis")))
  134.         return YES;    /* ??? */
  135.     return NO;    /* If not handled by (from == to) above. */
  136.     }
  137.     return NO;
  138. }
  139.  
  140. /*
  141. **  The idea here is that any stage of the stream pipe which is interested
  142. **  in some charset dependent processing will call this function.
  143. **  Given input and output charsets, this function will set various flags
  144. **  in a UCTransParams structure that _suggest_ to the caller what to do.
  145. **
  146. **  Should be called once when a stage starts processing text (and the
  147. **  input and output charsets are known), or whenever one of input or
  148. **  output charsets has changed (e.g. by SGML.c stage after HTML.c stage
  149. **  has processed a META tag).
  150. **  The global flags (LYRawMode, HTPassEightBitRaw etc.) are currently
  151. **  not taken into account here (except for HTCJK, somewhat), it's still
  152. **  up to the caller to do something about them. - KW
  153. */
  154. PUBLIC void UCSetTransParams ARGS5(
  155.     UCTransParams *,     pT,
  156.     int,        cs_in,
  157.     CONST LYUCcharset*,    p_in,
  158.     int,        cs_out,
  159.     CONST LYUCcharset*,    p_out)
  160. {
  161.     /*
  162.     **  Initialize this element to FALSE, and set it TRUE
  163.     **  below if we're dealing with VISCII. - FM
  164.     */
  165.     pT->trans_C0_to_uni = FALSE;
  166.  
  167.     /*
  168.     **  The "transparent" display character set is a
  169.     **  "super raw mode". - FM
  170.     */
  171.     pT->transp = (!strcmp(p_in->MIMEname, "x-transparent") ||
  172.           !strcmp(p_out->MIMEname, "x-transparent"));
  173.  
  174.     if (pT->transp) {
  175.     /*
  176.     **  Set up the structure for "transparent". - FM
  177.     */
  178.     pT->do_cjk = FALSE;
  179.     pT->decode_utf8 = FALSE;
  180.     pT->output_utf8 = FALSE;  /* We may, but won't know about it. - KW */
  181.     pT->do_8bitraw = TRUE;
  182.     pT->use_raw_char_in = TRUE;
  183.     pT->strip_raw_char_in = FALSE;
  184.     pT->pass_160_173_raw = TRUE;
  185.     pT->repl_translated_C0 = (p_out->enc == UCT_ENC_8BIT_C0);
  186.     pT->trans_C0_to_uni = (p_in->enc == UCT_ENC_8BIT_C0 ||
  187.                    p_out->enc == UCT_ENC_8BIT_C0);
  188.     } else {
  189.         /*
  190.     **  Initialize local flags. - FM
  191.     */
  192.     BOOL intm_ucs = FALSE;
  193.     BOOL use_ucs = FALSE;
  194.     /*
  195.     **  Set this element if we want to treat
  196.     **  the input as CJK. - FM
  197.     */
  198.     pT->do_cjk = ((p_in->enc == UCT_ENC_CJK) && (HTCJK != NOCJK));
  199.     /*
  200.     **  Set these elements based on whether
  201.     **  we are dealing with UTF-8. - FM
  202.     */
  203.     pT->decode_utf8 = (p_in->enc == UCT_ENC_UTF8);
  204.     pT->output_utf8 = (p_out->enc == UCT_ENC_UTF8);
  205.     if (pT->do_cjk) {
  206.         /*
  207.         **  Set up the structure for a CJK input with
  208.         **  a CJK output (HTCJK != NOCJK). - FM
  209.         */
  210.         intm_ucs = FALSE;
  211.         pT->trans_to_uni = FALSE;
  212.         use_ucs = FALSE;
  213.         pT->do_8bitraw = FALSE;
  214.         pT->pass_160_173_raw = TRUE;
  215.         pT->use_raw_char_in = FALSE; /* Not used for CJK. - KW */
  216.         pT->repl_translated_C0 = FALSE;
  217.         pT->trans_from_uni = FALSE;     /* Not used for CJK. - KW */
  218.     } else {
  219.         /*
  220.         **  Set up for all other charset combinations.
  221.         **  The intm_ucs flag is set TRUE if the input
  222.         **  charset is iso-8859-1 or UTF-8, or largely
  223.         **  equivalent to them, i.e. if we have UCS without
  224.         **  having to do a table translation.
  225.         */
  226.         intm_ucs = (cs_in == 0 || pT->decode_utf8 ||
  227.             (p_in->codepoints &
  228.              (UCT_CP_SUBSETOF_LAT1|UCT_CP_SUBSETOF_UCS2)));
  229.         /*
  230.         **  pT->trans_to_uni is set TRUE if we do not have that as
  231.         **  input already, and we can translate to Unicode.  Note
  232.         **  that UTF-8 always is converted to Unicode in functions
  233.         **  that use the transformation structure, so it is
  234.         **  treated as already Unicode here.
  235.         */
  236.         pT->trans_to_uni = (!intm_ucs &&
  237.                 UCCanUniTranslateFrom(cs_in));
  238.         /*
  239.         **  We set this if we are translating to Unicode and
  240.         **  what normally are low value control characters in
  241.         **  fact are encoding octets for the input charset
  242.         **  (presently, this applies to VISCII). - FM
  243.         */
  244.         pT->trans_C0_to_uni = (pT->trans_to_uni &&
  245.                    p_in->enc == UCT_ENC_8BIT_C0);
  246.         /*
  247.         **  We set this, presently, for VISCII. - FM
  248.         */
  249.         pT->repl_translated_C0 = (p_out->enc == UCT_ENC_8BIT_C0);
  250.         /*
  251.         **  Currently unused for any charset combination.
  252.         **  Should always be FALSE
  253.         */
  254.         pT->strip_raw_char_in = FALSE;
  255.         /*
  256.         **  use_ucs should be set TRUE if we have or will create
  257.         **  Unicode values for input octets or UTF multibytes. - FM
  258.         */
  259.         use_ucs = (intm_ucs || pT->trans_to_uni);
  260.         /*
  261.         **  This is set TRUE if use_ucs was set FALSE.  It is
  262.         **  complementary to the HTPassEightBitRaw flag, which
  263.         **  is set TRUE or FALSE elsewhere based on the raw mode
  264.         **  setting in relation to the current Display Character
  265.         **  Set. - FM
  266.         */
  267.         pT->do_8bitraw = (!use_ucs);
  268.         /*
  269.         **  This is set TRUE when 160 and 173 should not be
  270.         **  treated as nbsp and shy, respectively. - FM
  271.         */
  272.         pT->pass_160_173_raw = (!use_ucs &&
  273.                     !(p_in->like8859 & UCT_R_8859SPECL));
  274.         /*
  275.         **  This is set when the input and output charsets match,
  276.         **  and they are not ones which should go through a Unicode
  277.         **  translation process anyway. - FM
  278.         */
  279.         pT->use_raw_char_in = (!pT->output_utf8 &&
  280.                    cs_in == cs_out &&
  281.                            !pT->trans_C0_to_uni);
  282.         /*
  283.         **  This should be set TRUE when we expect to have
  284.         **  done translation to Unicode or had the equivalent
  285.         **  as input, can translate it to our output charset,
  286.         **  and normally want to do so.  The latter depends on
  287.         **  the pT->do_8bitraw and pT->use_raw_char_in values set
  288.         **  above, but also on HTPassEightBitRaw in any functions
  289.         **  which use the transformation structure.. - FM
  290.         */
  291.         pT->trans_from_uni = (use_ucs && !pT->do_8bitraw &&
  292.                   !pT->use_raw_char_in &&
  293.                   UCCanTranslateUniTo(cs_out));
  294.     }
  295.     }
  296. }
  297.  
  298. /*
  299. **  This function initializes the transformation
  300. **  structure by setting all its elements to
  301. **  FALSE. - KW
  302. */
  303. PUBLIC void UCTransParams_clear ARGS1(
  304.     UCTransParams *,    pT)
  305. {
  306.     pT->transp = FALSE;
  307.     pT->do_cjk = FALSE;
  308.     pT->decode_utf8 = FALSE;
  309.     pT->output_utf8 = FALSE;
  310.     pT->do_8bitraw = FALSE;
  311.     pT->use_raw_char_in = FALSE;
  312.     pT->strip_raw_char_in = FALSE;
  313.     pT->pass_160_173_raw = FALSE;
  314.     pT->trans_to_uni = FALSE;
  315.     pT->trans_C0_to_uni = FALSE;
  316.     pT->repl_translated_C0 = FALSE;
  317.     pT->trans_from_uni = FALSE;
  318. }
  319.  
  320. /*
  321. **  If terminal is in UTF-8 mode, it probably cannot understand
  322. **  box drawing chars as (n)curses handles them.  (This may also
  323. **  be true for other display character sets, but isn't currently
  324. **  checked.)  In that case set the chars for hori and vert drawing
  325. **  chars to displayable ASCII chars if '0' was requested.  They'll
  326. **  stay as they are otherwise. - kw
  327. */
  328. PUBLIC void UCSetBoxChars ARGS5(
  329.     int,    cset,
  330.     int *,    pvert_out,
  331.     int *,    phori_out,
  332.     int,    vert_in,
  333.     int,    hori_in)
  334. {
  335.     if (cset >= -1 && LYCharSet_UC[cset].enc == UCT_ENC_UTF8) {
  336.     *pvert_out = (vert_in ? vert_in : '|');
  337.     *phori_out = (hori_in ? hori_in : '-');
  338.     } else {
  339.     *pvert_out = vert_in;
  340.     *phori_out = hori_in;
  341.     }
  342. }
  343.  
  344. /*
  345. **  Given an output target HTStream* (can also be a HTStructured* via
  346. **  typecast), the target stream's put_character method, and a Unicode
  347. **  character,  CPutUtf8_charstring() will either output the UTF8
  348. **  encoding of the Unicode and return YES, or do nothing and return
  349. **  NO (if conversion would be unnecessary or the Unicode character is
  350. **  considered invalid).
  351. **
  352. **  [Could be used more generally, but is currently only used for &#nnnnn
  353. **  stuff - generation of UTF8 from 8-bit encoded charsets not yet done
  354. **  by SGML.c etc.]
  355. */
  356. #define PUTC(ch) ((*myPutc)(target, (char)(ch)))
  357. #define PUTC2(ch) ((*myPutc)(target,(char)(0x80|(0x3f &(ch)))))
  358.  
  359. PUBLIC BOOL UCPutUtf8_charstring ARGS3(
  360.     HTStream *,    target,
  361.     putc_func_t *,    myPutc,
  362.     long,        code)
  363. {
  364.     if (code < 128)
  365.     return NO;        /* indicate to caller we didn't handle it */
  366.     else if   (code < 0x800L) {
  367.     PUTC(0xc0 | (code>>6));
  368.     PUTC2(code);
  369.     } else if (code < 0x10000L) {
  370.     PUTC(0xe0 | (code>>12));
  371.     PUTC2(code>>6);
  372.     PUTC2(code);
  373.     } else if (code < 0x200000L) {
  374.     PUTC(0xf0 | (code>>18));
  375.     PUTC2(code>>12);
  376.     PUTC2(code>>6);
  377.     PUTC2(code);
  378.     } else if (code < 0x4000000L) {
  379.     PUTC(0xf8 | (code>>24));
  380.     PUTC2(code>>18);
  381.     PUTC2(code>>12);
  382.     PUTC2(code>>6);
  383.     PUTC2(code);
  384.     } else if (code <= 0x7fffffffL) {
  385.     PUTC(0xfc | (code>>30));
  386.     PUTC2(code>>24);
  387.     PUTC2(code>>18);
  388.     PUTC2(code>>12);
  389.     PUTC2(code>>6);
  390.     PUTC2(code);
  391.     } else
  392.     return NO;
  393.     return YES;
  394. }
  395.  
  396. /*
  397. **  This function converts a Unicode (UCode_t) value
  398. **  to a multibyte UTF-8 character, which is loaded
  399. **  into the buffer received as an argument.  The
  400. **  buffer should be large enough to hold at least
  401. **  seven characters (but should be declared as 8
  402. **  to minimize byte alignment problems with some
  403. **  compilers). - FM
  404. */
  405. PUBLIC BOOL UCConvertUniToUtf8 ARGS2(
  406.     UCode_t,    code,
  407.     char *,        buffer)
  408. {
  409.     char *ch = buffer;
  410.  
  411.     if (!ch)
  412.     return NO;
  413.  
  414.     if (code <= 0 || code > 0x7fffffffL) {
  415.     *ch = '\0';
  416.         return NO;
  417.     }
  418.  
  419.     if (code < 0x800L) {
  420.     *ch++ = (char)(0xc0 | (code>>6));
  421.     *ch++ = (char)(0x80 | (0x3f & (code)));
  422.     *ch = '\0';
  423.     } else if (code < 0x10000L) {
  424.     *ch++ = (char)(0xe0 | (code>>12));
  425.     *ch++ = (char)(0x80 | (0x3f & (code>>6)));
  426.     *ch++ = (char)(0x80 | (0x3f & (code)));
  427.     *ch = '\0';
  428.     } else if (code < 0x200000L) {
  429.     *ch++ = (char)(0xf0 | (code>>18));
  430.     *ch++ = (char)(0x80 | (0x3f & (code>>12)));
  431.     *ch++ = (char)(0x80 | (0x3f & (code>>6)));
  432.     *ch++ = (char)(0x80 | (0x3f & (code)));
  433.     *ch = '\0';
  434.     } else if (code < 0x4000000L) {
  435.     *ch++ = (char)(0xf8 | (code>>24));
  436.     *ch++ = (char)(0x80 | (0x3f & (code>>18)));
  437.     *ch++ = (char)(0x80 | (0x3f & (code>>12)));
  438.     *ch++ = (char)(0x80 | (0x3f & (code>>6)));
  439.     *ch++ = (char)(0x80 | (0x3f & (code)));
  440.     *ch = '\0';
  441.     } else {
  442.     *ch++ = (char)(0xfc | (code>>30));
  443.     *ch++ = (char)(0x80 | (0x3f & (code>>24)));
  444.     *ch++ = (char)(0x80 | (0x3f & (code>>18)));
  445.     *ch++ = (char)(0x80 | (0x3f & (code>>12)));
  446.     *ch++ = (char)(0x80 | (0x3f & (code>>6)));
  447.     *ch++ = (char)(0x80 | (0x3f & (code)));
  448.     *ch = '\0';
  449.     }
  450.     return YES;
  451. }
  452.