about summary refs log tree commit diff stats
path: root/src/UCdomap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/UCdomap.c')
-rw-r--r--src/UCdomap.c711
1 files changed, 472 insertions, 239 deletions
diff --git a/src/UCdomap.c b/src/UCdomap.c
index 61bdfd70..344f3057 100644
--- a/src/UCdomap.c
+++ b/src/UCdomap.c
@@ -4,7 +4,7 @@
  *
  * Derived from code in the Linux kernel console driver.
  * The GNU Public Licence therefore applies, see 
- * the file COPYING in the about_lynx directory 
+ * the file COPYING in the top-level directory 
  * which should come with every Lynx distribution.
  *
  *  [ original comment: - KW ]
@@ -282,12 +282,16 @@ PRIVATE void UC_con_set_trans PARAMS((
 	int		update_flag));
 PRIVATE int con_insert_unipair PARAMS((
 	u16 		unicode,
-	u16		fontpos));
+	u16		fontpos,
+	int		fordefault));
 PRIVATE int con_insert_unipair_str PARAMS((
 	u16		unicode,
-	char *		replace_str));
-PRIVATE void con_clear_unimap NOPARAMS;
-PRIVATE void con_clear_unimap_str NOPARAMS;
+	char *		replace_str,
+	int		fordefault));
+PRIVATE void con_clear_unimap PARAMS((
+        int		fordefault));
+PRIVATE void con_clear_unimap_str PARAMS((
+        int		fordefault));
 #ifdef NOTDEFINED
 PRIVATE int con_set_unimap PARAMS((
 	u16			ct,
@@ -299,7 +303,8 @@ PRIVATE int UC_con_set_unimap PARAMS((
 	int		update_flag));
 PRIVATE int UC_con_set_unimap_str PARAMS((
 	u16			ct,
-	struct unipair_str *	list));
+	struct unipair_str *	list,
+	int			fordefault));
 #ifdef NOTDEFINED
 PRIVATE int con_get_unimap PARAMS((
 	u16			ct,
@@ -307,11 +312,13 @@ PRIVATE int con_get_unimap PARAMS((
 	struct unipair *	list));
 #endif /* NOTDEFINED */
 PRIVATE int conv_uni_to_pc PARAMS((
-	long			ucs));
+	long			ucs,
+	int			usedefault));
 PRIVATE int conv_uni_to_str PARAMS((
 	char*		outbuf,
 	int		buflen,
-	long		ucs));
+	long		ucs,
+	int		usedefault));
 PRIVATE void UCconsole_map_init NOPARAMS;
 PRIVATE int UC_MapGN PARAMS((
 	int		UChndl,
@@ -330,6 +337,7 @@ PRIVATE int UC_Register_with_LYCharSets PARAMS((
 	int		lowest_eightbit));
 PRIVATE void UCcleanup_mem NOPARAMS;
 
+PRIVATE int default_UChndl = -1;
 
 PRIVATE void set_inverse_transl ARGS1(
 	int,		i)
@@ -350,7 +358,7 @@ PRIVATE void set_inverse_transl ARGS1(
 		q[j] = 0;
 
 	for (j=0; j<E_TABSZ; j++) {
-		glyph = conv_uni_to_pc(p[j]);
+		glyph = conv_uni_to_pc(p[j], 0);
 		if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
 			/* prefer '-' above SHY etc. */
 		  	q[glyph] = j;
@@ -480,13 +488,13 @@ PRIVATE void UC_con_set_trans ARGS3(
   u16 *ptrans;
 
     if (!UC_valid_UC_charset(UC_charset_in_hndl)) {
-      if (TRACE)
-	fprintf(stderr,"UC_con_set_trans: Invalid charset handle %i.\n",
-		UC_charset_in_hndl);
-      return;
+	if (TRACE)
+	    fprintf(stderr,"UC_con_set_trans: Invalid charset handle %i.\n",
+		    UC_charset_in_hndl);
+	return;
     }
-  ptrans = translations[Gn];
-  p = UCInfo[UC_charset_in_hndl].unitable;
+    ptrans = translations[Gn];
+    p = UCInfo[UC_charset_in_hndl].unitable;
 #if(0)
   if (p == UC_current_unitable) {    /* test whether pointers are equal */
     return;			/* nothing to be done */
@@ -497,18 +505,18 @@ PRIVATE void UC_con_set_trans ARGS3(
   con_clear_unimap();
 #endif
     for (i = 0; i < 256; i++) {
-      if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
-	ptrans[i] = *p;
+	if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
+	    ptrans[i] = *p;
 	    for (; j; j--) {
-	  p++;
-      }
+		p++;
+	    }
 	} else {
-	ptrans[i] = 0xfffd;
-    }
+	    ptrans[i] = 0xfffd;
+	}
     }
     if (update_flag) {
-    set_inverse_transl(Gn);    /* Update inverse translation for this one */
-}
+	set_inverse_transl(Gn);	/* Update inverse translation for this one */
+    }
 }
 
 /*
@@ -521,8 +529,8 @@ PRIVATE void UC_con_set_trans ARGS3(
  * this 3-level paged table scheme to be comparable to a hash table.
  */
 
-int hashtable_contents_valid = 0; /* Use ASCII-only mode for bootup*/
-int hashtable_str_contents_valid = 0; 
+PRIVATE int unitable_contents_valid = 0; /* Use ASCII-only mode for bootup*/
+PRIVATE int unitable_str_contents_valid = 0; 
 
 static u16 **uni_pagedir[32] =
 {
@@ -542,16 +550,50 @@ static char* **uni_pagedir_str[32] =
 PRIVATE u16 * UC_current_unitable = NULL;
 PRIVATE struct unimapdesc_str *UC_current_unitable_str = NULL;
 
-PRIVATE int con_insert_unipair ARGS2(
+/*
+ *  Keep a second set of structures for the translation designated
+ *  as "default" - kw
+ */
+PRIVATE int unidefault_contents_valid = 0; /* Use ASCII-only mode for bootup*/
+PRIVATE int unidefault_str_contents_valid = 0; 
+
+static u16 **unidefault_pagedir[32] =
+{
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+static char* **unidefault_pagedir_str[32] =
+{
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+PRIVATE u16 * UC_default_unitable = NULL;
+PRIVATE struct unimapdesc_str *UC_default_unitable_str = NULL;
+
+PRIVATE int con_insert_unipair ARGS3(
 	u16, 		unicode,
-	u16,		fontpos)
+	u16,		fontpos,
+	int,		fordefault)
 {
   int i, n;
   u16 **p1, *p2;
 
-  if ( !(p1 = uni_pagedir[n = unicode >> 11]) )
+  if(fordefault)
+      p1 = unidefault_pagedir[n = unicode >> 11];
+  else
+      p1 = uni_pagedir[n = unicode >> 11];
+  if (!p1)
     {
-      p1 = uni_pagedir[n] = (u16* *) malloc(32*sizeof(u16 *));
+      p1 = (u16* *) malloc(32*sizeof(u16 *));
+      if (fordefault)
+	  unidefault_pagedir[n] = p1;
+      else
+	  uni_pagedir[n] = p1;
       if ( !p1 )
 	return -ENOMEM;
 
@@ -574,16 +616,25 @@ PRIVATE int con_insert_unipair ARGS2(
   return 0;
 }
  
-PRIVATE int con_insert_unipair_str ARGS2(
+PRIVATE int con_insert_unipair_str ARGS3(
 	u16,		unicode,
-	char *,		replace_str)
+	char *,		replace_str,
+	int,		fordefault)
 {
   int i, n;
   char ***p1, **p2;
 
-  if ( !(p1 = uni_pagedir_str[n = unicode >> 11]) )
+  if(fordefault)
+      p1 = unidefault_pagedir_str[n = unicode >> 11];
+  else
+      p1 = uni_pagedir_str[n = unicode >> 11];
+  if (!p1)
     {
-      p1 = uni_pagedir_str[n] = (char** *) malloc(32*sizeof(char **));
+      p1 = (char** *) malloc(32*sizeof(char **));
+      if (fordefault)
+	  unidefault_pagedir_str[n] = p1;
+      else
+	  uni_pagedir_str[n] = p1;
       if ( !p1 )
 	return -ENOMEM;
 
@@ -608,11 +659,24 @@ PRIVATE int con_insert_unipair_str ARGS2(
  
 /* ui arg was a leftover, deleted -kw */
 PRIVATE void
-con_clear_unimap NOARGS
+con_clear_unimap ARGS1(int, fordefault)
 {
   int i, j;
   u16 **p1;
-  
+
+  if (fordefault) {
+    for (i = 0; i < 32; i++) {
+	if ((p1 = unidefault_pagedir[i]) != NULL) {
+	    for (j = 0; j < 32; j++) {
+		FREE(p1[j]);
+	    }
+	    FREE(p1);
+	}
+      unidefault_pagedir[i] = NULL;
+    }
+
+    unidefault_contents_valid = 1;
+  } else {
     for (i = 0; i < 32; i++) {
 	if ((p1 = uni_pagedir[i]) != NULL) {
 	    for (j = 0; j < 32; j++) {
@@ -623,15 +687,29 @@ con_clear_unimap NOARGS
       uni_pagedir[i] = NULL;
     }
 
-  hashtable_contents_valid = 1;
+    unitable_contents_valid = 1;
+  }
 }
 
 PRIVATE void
-con_clear_unimap_str NOARGS
+con_clear_unimap_str ARGS1(int, fordefault)
 {
   int i, j;
   char ***p1;
-  
+
+  if (fordefault) {
+    for (i = 0; i < 32; i++) {
+	if ((p1 = unidefault_pagedir_str[i]) != NULL) {
+	    for (j = 0; j < 32; j++) {
+		FREE(p1[j]);
+	    }
+	    FREE(p1);
+	}
+      unidefault_pagedir_str[i] = NULL;
+    }
+
+    unidefault_str_contents_valid = 1;  /* ??? probably no use... */
+  } else {
     for (i = 0; i < 32; i++) {
 	if ((p1 = uni_pagedir_str[i]) != NULL) {
 	    for (j = 0; j < 32; j++) {
@@ -642,7 +720,8 @@ con_clear_unimap_str NOARGS
       uni_pagedir_str[i] = NULL;
     }
 
-  hashtable_str_contents_valid = 1;  /* ??? probably no use... */
+    unitable_str_contents_valid = 1;  /* ??? probably no use... */
+  }
 }
 
 #ifdef NOTDEFINED
@@ -679,17 +758,23 @@ con_set_default_unimap NOARGS
 
   /* The default font is always 256 characters */
 
-  con_clear_unimap();
+  con_clear_unimap(1);
 
   p = dfont_unitable;
   for ( i = 0 ; i < 256 ; i++ )
     for ( j = dfont_unicount[i] ; j ; j-- )
-      con_insert_unipair(*(p++), i);
+      con_insert_unipair(*(p++), i, 1);
 
+#if 0
   for ( i = 0 ; i <= 3 ; i++ )
     set_inverse_transl(i);	/* Update all inverse translations */
+#endif
+
+  UC_default_unitable = dfont_unitable;
 
-  UC_current_unitable = dfont_unitable;
+  con_clear_unimap_str(1);
+  UC_con_set_unimap_str(dfont_replacedesc.entry_ct, repl_map, 1);
+  UC_default_unitable_str = &dfont_replacedesc;
 }
 
 PUBLIC int UCNumCharsets = 0;
@@ -721,11 +806,11 @@ PRIVATE int UC_con_set_unimap ARGS2(
 
   /* The font is always 256 characters - so far. */
 
-  con_clear_unimap();
+  con_clear_unimap(0);
 
     for (i = 0; i < 256; i++) {
  	for (j = UCInfo[UC_charset_out_hndl].unicount[i]; j; j--) {
-      con_insert_unipair(*(p++), i);
+	    con_insert_unipair(*(p++), i, 0);
 	}
     }
 
@@ -735,15 +820,18 @@ PRIVATE int UC_con_set_unimap ARGS2(
   return 0;
 }
 
-PRIVATE int
-UC_con_set_unimap_str ARGS2(u16, ct, struct unipair_str *, list)
+PRIVATE int UC_con_set_unimap_str ARGS3(
+    u16,		ct,
+    struct unipair_str *, list,
+    int,		fordefault)
 {
   int err = 0, err1;
 
   while( ct-- )
     {
       if ( (err1 = con_insert_unipair_str(list->unicode,
-				      list->replace_str)) != 0 )
+					  list->replace_str,
+					  fordefault)) != 0 )
 	err = err1;
       list++;
     }
@@ -752,7 +840,10 @@ UC_con_set_unimap_str ARGS2(u16, ct, struct unipair_str *, list)
      *  No inverse translations for replacement strings!
      */
     if (!err) {
-	hashtable_str_contents_valid = 1;  
+	if (fordefault)
+	    unidefault_str_contents_valid = 1;
+	else
+	    unitable_str_contents_valid = 1;  
     }
 
   return err;
@@ -788,8 +879,9 @@ con_get_unimap ARGS3(u16, ct, u16 *, uct, struct unipair *, list)
 }
 #endif
 
-PRIVATE int conv_uni_to_pc ARGS1(
-	long,		ucs) 
+PRIVATE int conv_uni_to_pc ARGS2(
+	long,		ucs,
+	int,		usedefault)
 {
   int h;
   u16 **p1, *p2;
@@ -809,10 +901,17 @@ PRIVATE int conv_uni_to_pc ARGS1(
   else if ( (ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE )
     return ucs & UNI_DIRECT_MASK;
   
-  if (!hashtable_contents_valid)
-    return -3;
-  
-  if ( (p1 = uni_pagedir[ucs >> 11]) &&
+  if (usedefault) {
+      if (!unidefault_contents_valid)
+	  return -3;
+      p1 = unidefault_pagedir[ucs >> 11];
+  } else {
+      if (!unitable_contents_valid)
+	  return -3;
+      p1 = uni_pagedir[ucs >> 11];
+  }
+
+  if (p1 &&
       (p2 = p1[(ucs >> 6) & 0x1f]) &&
       (h = p2[ucs & 0x3f]) < MAX_GLYPH )
     return h;
@@ -823,10 +922,11 @@ PRIVATE int conv_uni_to_pc ARGS1(
 /*
  *  Note: contents of outbuf is not changes for negative return value!
  */
-PRIVATE int conv_uni_to_str ARGS3(
+PRIVATE int conv_uni_to_str ARGS4(
 	char*,		outbuf,
 	int,		buflen,
-	long,		ucs) 
+	long,		ucs,
+	int,		usedefault)
 {
   char *h;
   char ***p1, **p2;
@@ -849,10 +949,18 @@ PRIVATE int conv_uni_to_str ARGS3(
   else if ( (ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE )
     return ucs & UNI_DIRECT_MASK;
 #endif
-  if (!hashtable_str_contents_valid)
-    return -3;
-  
-  if ( (p1 = uni_pagedir_str[ucs >> 11]) &&
+
+  if (usedefault) {
+      if (!unidefault_str_contents_valid)
+	  return -3;
+      p1 = unidefault_pagedir_str[ucs >> 11];
+  } else {
+      if (!unitable_str_contents_valid)
+	  return -3;
+      p1 = uni_pagedir_str[ucs >> 11];
+  }
+
+  if (p1 &&
       (p2 = p1[(ucs >> 6) & 0x1f]) &&
       (h = p2[ucs & 0x3f]) ) {
     strncpy (outbuf,h,(size_t) (buflen-1));
@@ -875,8 +983,8 @@ PUBLIC int UCInitialized = 0;
 PRIVATE void
 UCconsole_map_init NOARGS
 {
-  con_set_default_unimap();
-  UCInitialized = 1;
+    con_set_default_unimap();
+    UCInitialized = 1;
 }
 
 /*
@@ -891,24 +999,44 @@ PUBLIC int UCTransUniChar ARGS2(
 	long,		unicode,
 	int,		charset_out)
 {
-  int rc;
-  int UChndl_out;
-  u16 * ut;
+    int rc;
+    int UChndl_out;
+    int isdefault, trydefault;
+    u16 * ut;
 
-  if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0)
-    return -12;
+    if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+	if ((UChndl_out = default_UChndl) < 0)
+	    return -12;
+	isdefault = 1;
+    } else {
+	isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+	trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+    }
 
-  ut = UCInfo[UChndl_out].unitable;
-  if (ut != UC_current_unitable) {
-    rc = UC_con_set_unimap(UChndl_out, 1);
-	if (rc < 0) {
-      return rc;
-  }
+    if (!isdefault) {
+	ut = UCInfo[UChndl_out].unitable;
+	if (ut != UC_current_unitable) {
+	    rc = UC_con_set_unimap(UChndl_out, 1);
+	    if (rc < 0) {
+		return rc;
+	    }
+	}
+	rc = conv_uni_to_pc(unicode, 0);
+	if (rc >= 0)
+	    return rc;
+    }
+    if (isdefault || trydefault) {
+	rc = conv_uni_to_pc(unicode, 1);
+	if (rc >= 0)
+	    return rc;
+    }
+    if (!isdefault && (rc == -4)) {
+	rc = conv_uni_to_pc(0xfffd, 0);
+    }
+    if ((isdefault || trydefault) && (rc == -4)) {
+	rc = conv_uni_to_pc(0xfffd, 1);
     }
-  rc = conv_uni_to_pc(unicode);
-  if (rc == -4)
-    rc = conv_uni_to_pc(0xfffd);
-  return rc;
+    return rc;
 }
   
 /*
@@ -923,49 +1051,79 @@ PUBLIC int UCTransUniCharStr ARGS5(
 {
   int rc, src = 0, ignore_err;
   int UChndl_out;
+  int isdefault, trydefault;
   struct unimapdesc_str * repl;
   u16 * ut;
 
-if (buflen<2)
-  return -13;
+  if (buflen<2)
+      return -13;
 
-  if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0)
-    return -12;
+  if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+      if ((UChndl_out = default_UChndl) < 0)
+	  return -12;
+      isdefault = 1;
+  } else {
+      isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+      trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+  }
 
   if (chk_single_flag) {
-    ut = UCInfo[UChndl_out].unitable;
-    if (ut != UC_current_unitable) {
-      src = UC_con_set_unimap(UChndl_out, 1);
-	    if (src < 0) {
-	return src;
-    }
-	}
-    src = conv_uni_to_pc(unicode);
-    if (src >= 32) {
-      outbuf[0] = src; outbuf[1] = '\0';
-	    return 1;
-	}
+      if (!isdefault) {
+	  ut = UCInfo[UChndl_out].unitable;
+	  if (ut != UC_current_unitable) {
+	      src = UC_con_set_unimap(UChndl_out, 1);
+	      if (src < 0) {
+		  return src;
+	      }
+	  }
+      }
+      src = conv_uni_to_pc(unicode, isdefault);
+      if (src >= 32) {
+	  outbuf[0] = src; outbuf[1] = '\0';
+	  return 1;
+      }
   }
-
   repl = &(UCInfo[UChndl_out].replacedesc);
-  if (repl != UC_current_unitable_str)  {
-    con_clear_unimap_str();
-    ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries);
-    UC_current_unitable_str = repl;
+  if (!isdefault) {
+      if (repl != UC_current_unitable_str)  {
+	  con_clear_unimap_str(0);
+	  ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
+	  UC_current_unitable_str = repl;
+      }
+      rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
+      if (rc >= 0)
+	  return (strlen(outbuf));
+  }
+  if (trydefault && chk_single_flag) {
+      src = conv_uni_to_pc(unicode, 1);
+      if (src >= 32) {
+	  outbuf[0] = src; outbuf[1] = '\0';
+	  return 1;
+      }
+  }
+  if (isdefault || trydefault) {
+      rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
+      if (rc >= 0)
+	  return (strlen(outbuf));
+  }
+  if (rc == -4) {
+    if (!isdefault)
+	rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
+    if ((rc == -4) && (isdefault || trydefault))
+	rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
+    if (rc >= 0)
+	return (strlen(outbuf));
   }
-  rc = conv_uni_to_str(outbuf, buflen, unicode);
-  if (rc == -4)
-    rc = conv_uni_to_str(outbuf, buflen, 0xfffd);
-  if (rc >= 0)
-    return (strlen(outbuf));
-
   if (chk_single_flag && src == -4) {
-    rc = conv_uni_to_pc(0xfffd);
-    if (rc >= 32) {
-      outbuf[0] = rc; outbuf[1] = '\0';
-	    return 1; 
-	}
-	return rc;
+      if (!isdefault)
+	  rc = conv_uni_to_pc(0xfffd, 0);
+      if ((rc == -4) && (isdefault || trydefault))
+	  rc = conv_uni_to_pc(0xfffd, 1);
+      if (rc >= 32) {
+	  outbuf[0] = rc; outbuf[1] = '\0';
+	  return 1; 
+      }
+      return rc;
   }
   return -4;
 }
@@ -976,39 +1134,39 @@ PRIVATE int UC_MapGN ARGS2(
 	int,		UChndl,
 	int,		update_flag)
 {
-  int i,Gn,found,lasthndl;
-  found = 0;
-  Gn = -1;
-  for (i=0; i<4 && Gn<0; i++) { 
+    int i,Gn,found,lasthndl;
+    found = 0;
+    Gn = -1;
+    for (i=0; i<4 && Gn<0; i++) { 
 	if (UC_GNhandles[i] < 0) {
 	    Gn = i;
 	} else if (UC_GNhandles[i] == UChndl) {
-      Gn = i;
+	    Gn = i;
 	    found = 1;
-  }
+	}
     }
     if (found) 
 	return Gn;
-  if (Gn >= 0) {
-    UCInfo[UChndl].GN = Gn;
-    UC_GNhandles[Gn] = UChndl;
+    if (Gn >= 0) {
+	UCInfo[UChndl].GN = Gn;
+	UC_GNhandles[Gn] = UChndl;
     } else {
 	if (UC_lastautoGN == GRAF_MAP) {
-      Gn = IBMPC_MAP;
+	    Gn = IBMPC_MAP;
 	} else {
 	    Gn = GRAF_MAP;
 	}
-    UC_lastautoGN = Gn;
-    lasthndl = UC_GNhandles[Gn];
-    UCInfo[lasthndl].GN = -1;
-    UCInfo[UChndl].GN = Gn;
-    UC_GNhandles[Gn] = UChndl;
-  }
-  if (TRACE)
-      fprintf(stderr,"UC_Map...... Using %i <- %i (%s)\n",
+	UC_lastautoGN = Gn;
+	lasthndl = UC_GNhandles[Gn];
+	UCInfo[lasthndl].GN = -1;
+	UCInfo[UChndl].GN = Gn;
+	UC_GNhandles[Gn] = UChndl;
+    }
+    if (TRACE)
+	fprintf(stderr,"UC_Map...... Using %i <- %i (%s)\n",
 		Gn, UChndl, UCInfo[UChndl].MIMEname);
-  UC_con_set_trans(UChndl,Gn,update_flag);
-  return Gn;
+    UC_con_set_trans(UChndl,Gn,update_flag);
+    return Gn;
 }
   
 PUBLIC int UCTransChar ARGS3(
@@ -1016,48 +1174,69 @@ PUBLIC int UCTransChar ARGS3(
 	int,		charset_in,
 	int,		charset_out)
 {
-  int unicode, Gn;
-  int rc;
-  int UChndl_in, UChndl_out;
-  u16 * ut;
-  int upd = 0;
+    int unicode, Gn;
+    int rc = -4;
+    int UChndl_in, UChndl_out;
+    int isdefault, trydefault;
+    u16 * ut;
+    int upd = 0;
 
 #ifndef UC_NO_SHORTCUTS
-  if (charset_in == charset_out)
-    return (unsigned char)ch_in;
+    if (charset_in == charset_out)
+	return (unsigned char)ch_in;
 #endif /* UC_NO_SHORTCUTS */
     if (charset_in < 0)
 	return -11;
-  if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
-    return -11;
-  if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0)
-    return -12;
-  if (!UCInfo[UChndl_in].num_uni)
-    return -11;
+    if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+	return -11;
+    if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+	if ((UChndl_out = default_UChndl) < 0)
+	    return -12;
+	isdefault = 1;
+    } else {
+	isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+	trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+    }
+    if (!UCInfo[UChndl_in].num_uni)
+	return -11;
     if ((Gn = UCInfo[UChndl_in].GN) < 0) {
 	Gn = UC_MapGN(UChndl_in,0);
 	upd = 1;
+
     }
 
-  ut = UCInfo[UChndl_out].unitable;
-    if (ut == UC_current_unitable) {
-	if (upd) {
-	    set_inverse_transl(Gn);
+    ut = UCInfo[UChndl_out].unitable;
+    if (!isdefault) {
+	if (ut == UC_current_unitable) {
+	    if (upd) {
+		set_inverse_transl(Gn);
+	    }
+	} else {
+	    rc = UC_con_set_unimap(UChndl_out, 1);
+	    if (rc > 0) {
+		set_inverse_transl(Gn);
+	    } else if (rc < 0) {
+		return rc;
+	    }
 	}
-    } else {
-    rc = UC_con_set_unimap(UChndl_out, 1);
-	if (rc > 0) {
-      set_inverse_transl(Gn);
-	} else if (rc < 0) {
-      return rc;
-  }
     }
-  UC_translate = set_translate(Gn);
-  unicode = UC_translate[(unsigned char)ch_in];
-  rc = conv_uni_to_pc(unicode);
-  if (rc == -4)
-    rc = conv_uni_to_pc(0xfffd);
-  return rc;
+    UC_translate = set_translate(Gn);
+    unicode = UC_translate[(unsigned char)ch_in];
+    if (!isdefault) {
+	rc = conv_uni_to_pc(unicode, 0);
+	if (rc >= 0)
+	    return rc;
+    }
+    if ((rc == -4) && (isdefault || trydefault)) {
+	rc = conv_uni_to_pc(unicode, 1);
+    }
+    if ((rc == -4) && !isdefault) {
+	rc = conv_uni_to_pc(0xfffd, 0);
+    }
+    if ((rc == -4) && (isdefault || trydefault)) {
+	rc = conv_uni_to_pc(0xfffd, 1);
+    }
+    return rc;
 }
 
 PUBLIC long int UCTransToUni ARGS2(
@@ -1102,6 +1281,7 @@ PUBLIC int UCReverseTransChar ARGS3(char, ch_out, int, charset_in, int, charset_
     int Gn;
     int rc;
     int UChndl_in, UChndl_out;
+    int isdefault;
     int i_ch = (unsigned char)ch_out;
     u16 * ut;
 
@@ -1113,27 +1293,40 @@ PUBLIC int UCReverseTransChar ARGS3(char, ch_out, int, charset_in, int, charset_
 	return -11;
     if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
 	return -11;
-    if (charset_out < 0)
-	return -12;
-    if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0)
-	return -12;
     if (!UCInfo[UChndl_in].num_uni)
 	return -11;
+    if (charset_out < 0)
+	return -12;
+    if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+	if ((UChndl_out = default_UChndl) < 0)
+	    return -12;
+	isdefault = 1;
+    } else {
+	isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+    }
 
-    ut = UCInfo[UChndl_out].unitable;
-    if (ut == UC_current_unitable) {
-	if ((Gn = UCInfo[UChndl_in].GN) >= 0) {
-	    UC_translate = set_translate(Gn);
-	    rc = inv_translate[i_ch];
-	    if (rc >= 32) {
-		return rc;
-	    }
-	} else {
-	    Gn = UC_MapGN(UChndl_in,1);
-	    UC_translate = set_translate(Gn);
-	    rc = inv_translate[i_ch];
-	    if (rc >= 32) {
-		return rc;
+    if (!isdefault) {
+	/*
+	 *  Try to use the inverse table if charset_out is not equivalent
+	 *  to using just the default table.  If it is, it should have
+	 *  just ASCII chars and trying to back-translate those should
+	 *  not give anything but themselves. - kw
+	 */
+	ut = UCInfo[UChndl_out].unitable;
+	if (ut == UC_current_unitable) {
+	    if ((Gn = UCInfo[UChndl_in].GN) >= 0) {
+		UC_translate = set_translate(Gn);
+		rc = inv_translate[i_ch];
+		if (rc >= 32) {
+		    return rc;
+		}
+	    } else {
+		Gn = UC_MapGN(UChndl_in,1);
+		UC_translate = set_translate(Gn);
+		rc = inv_translate[i_ch];
+		if (rc >= 32) {
+		    return rc;
+		}
 	    }
 	}
     }
@@ -1151,17 +1344,18 @@ PUBLIC int UCTransCharStr ARGS6(
 	int,		charset_out,
 	int,		chk_single_flag)
 {
-  int unicode, Gn;
-  int rc, src = 0, ignore_err;
-  int UChndl_in, UChndl_out;
-  struct unimapdesc_str * repl;
-  u16 * ut;
-  int upd = 0;
+    int unicode, Gn;
+    int rc, src = 0, ignore_err;
+    int UChndl_in, UChndl_out;
+    int isdefault, trydefault;
+    struct unimapdesc_str * repl;
+    u16 * ut;
+    int upd = 0;
 
-if (buflen<2)
-  return -13;
+    if (buflen<2)
+	return -13;
 #ifndef UC_NO_SHORTCUTS
-  if (chk_single_flag && charset_in == charset_out) {
+    if (chk_single_flag && charset_in == charset_out) {
 	outbuf[0] = ch_in;
 	outbuf[1] = '\0';
 	return 1;
@@ -1169,60 +1363,91 @@ if (buflen<2)
 #endif /* UC_NO_SHORTCUTS */
     if (charset_in < 0)
 	return -11;
-  if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
-    return -11;
-  if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0)
-    return -12;
-  if (!UCInfo[UChndl_in].num_uni)
-    return -11;
-  if ((Gn = UCInfo[UChndl_in].GN) < 0)
+    if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+	return -11;
+    if (!UCInfo[UChndl_in].num_uni)
+	return -11;
+    if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+	if ((UChndl_out = default_UChndl) < 0)
+	    return -12;
+	isdefault = 1;
+    } else {
+	isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+	trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+    }
+    if ((Gn = UCInfo[UChndl_in].GN) < 0)
     {Gn = UC_MapGN(UChndl_in,!chk_single_flag); upd=chk_single_flag;}
 
-  UC_translate = set_translate(Gn);
-  unicode = UC_translate[(unsigned char)ch_in];
-
-  if (chk_single_flag) {
-    ut = UCInfo[UChndl_out].unitable;
-	if (ut == UC_current_unitable) {
-	    if (upd) set_inverse_transl(Gn);
-	} else {
-      src = UC_con_set_unimap(UChndl_out, 1);
-	    if (src > 0) {
-	set_inverse_transl(Gn);
-	    } else if (src < 0) {
-	return src;
-    }
+    UC_translate = set_translate(Gn);
+    unicode = UC_translate[(unsigned char)ch_in];
+
+    if (chk_single_flag) {
+	if (!isdefault) {
+	    ut = UCInfo[UChndl_out].unitable;
+	    if (ut == UC_current_unitable) {
+		if (upd) set_inverse_transl(Gn);
+	    } else {
+		src = UC_con_set_unimap(UChndl_out, 1);
+		if (src > 0) {
+		    set_inverse_transl(Gn);
+		} else if (src < 0) {
+		    return src;
+		}
+	    }
 	}
-    src = conv_uni_to_pc(unicode);
-    if (src >= 32) {
-      outbuf[0] = src; outbuf[1] = '\0';
+	src = conv_uni_to_pc(unicode, isdefault);
+	if (src >= 32) {
+	    outbuf[0] = src; outbuf[1] = '\0';
 	    return 1;
 	}
-  }
-
-  repl = &(UCInfo[UChndl_out].replacedesc);
-  if (repl != UC_current_unitable_str)  {
-    con_clear_unimap_str();
-    ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries);
-    UC_current_unitable_str = repl;
-  }
-  rc = conv_uni_to_str(outbuf, buflen, unicode);
-  if (rc == -4)
-    rc = conv_uni_to_str(outbuf, buflen, 0xfffd);
-  if (rc >= 0)
-    return (strlen(outbuf));
+    }
 
-  if (chk_single_flag && src == -4) {
-    rc = conv_uni_to_pc(0xfffd);
-    if (rc >= 32) {
-      outbuf[0] = rc; outbuf[1] = '\0';
+    repl = &(UCInfo[UChndl_out].replacedesc);
+    if (!isdefault) {
+	if (repl != UC_current_unitable_str) {
+	    con_clear_unimap_str(0);
+	    ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
+	    UC_current_unitable_str = repl;
+	}
+	rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
+	if (rc >= 0)
+	    return (strlen(outbuf));
+    }
+    if (trydefault && chk_single_flag) {
+	src = conv_uni_to_pc(unicode, 1);
+	if (src >= 32) {
+	    outbuf[0] = src; outbuf[1] = '\0';
 	    return 1;
+	}
+    }
+    if (isdefault || trydefault) {
+	rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
+	if (rc >= 0)
+	    return (strlen(outbuf));
+    }
+    if (rc == -4) {
+	if (!isdefault)
+	    rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
+	if ((rc == -4) && (isdefault || trydefault))
+	    rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
+	if (rc >= 0)
+	    return (strlen(outbuf));
+    }
+    if (chk_single_flag && src == -4) {
+	if (!isdefault)
+	    rc = conv_uni_to_pc(0xfffd, 0);
+	if ((rc == -4) && (isdefault || trydefault))
+	    rc = conv_uni_to_pc(0xfffd, 1);
+	if (rc >= 32) {
+	    outbuf[0] = rc; outbuf[1] = '\0';
+	    return 1; 
 	} else if (rc <= 0) {
 	    outbuf[0] = '\0';
 	    return rc;
 	}
-  }
-  return -4;
+	return rc;
+    }
+    return -4;
 }
 
 PRIVATE int UC_FindGN_byMIME ARGS1(
@@ -1262,10 +1487,10 @@ PUBLIC int UCGetLYhndl_byMIME ARGS1(
     for (i = 0;
 	 (i < MAXCHARSETS && i < LYNumCharsets &&
           LYchar_set_names[i] && LYhndl < 0); i++) {
-    if (LYCharSet_UC[i].MIMEname &&
-	!strcmp(UC_MIMEcharset,LYCharSet_UC[i].MIMEname)) {
-      LYhndl = i;
-    }
+	if (LYCharSet_UC[i].MIMEname &&
+	    !strcmp(UC_MIMEcharset,LYCharSet_UC[i].MIMEname)) {
+	    LYhndl = i;
+	}
     }
     if (LYhndl < 0) {
 	/*
@@ -1282,10 +1507,13 @@ PUBLIC int UCGetLYhndl_byMIME ARGS1(
 	  return UCGetLYhndl_byMIME("euc-jp");
 	} else if (!strcmp(UC_MIMEcharset, "iso-2022-kr")) {
 	  return UCGetLYhndl_byMIME("euc-kr");
-	} else if (!strcmp(UC_MIMEcharset, "gb2312")) {
+	} else if (!strcmp(UC_MIMEcharset, "gb2312") ||
+		   !strncmp(UC_MIMEcharset, "cn-gb", 5)) {
 	  return UCGetLYhndl_byMIME("euc-cn");
 	} else if (!strcmp(UC_MIMEcharset, "iso-2022-cn")) {
 	    return UCGetLYhndl_byMIME("euc-cn");
+	} else if (!strcmp(UC_MIMEcharset, "cn-big5")) {
+	    return UCGetLYhndl_byMIME("big5");
 	} else if (!strcmp(UC_MIMEcharset, "windows-1252")) {
 	    /*
 	     *  It's not my fault that Microsoft hasn't registered
@@ -1423,7 +1651,7 @@ PRIVATE char ** UC_setup_LYCharSets_repl ARGS2(
   }
     /*
      *  Now allocate a new table compatible with LYCharSets[] 
-     *  and with the HTMLDTD for entitied.
+     *  and with the HTMLDTD for entities.
      *  We don't know yet whether we'll keep it around. */
   p = prepl = (char **) malloc(HTML_dtd.number_of_entities * sizeof(char *));
   if (!p) {
@@ -1528,7 +1756,7 @@ PRIVATE int UC_Register_with_LYCharSets ARGS4(
 
     /*
      *  Do different kinds of searches...
-     *  after all, this is experimental...
+     *  Normally the first should find the match if there is one!
      */
     for (i = 0; i < MAXCHARSETS && LYchar_set_names[i] && LYhndl < 0; i++) {
 	if (!strcmp(UC_LYNXcharset, LYchar_set_names[i])) {
@@ -1643,6 +1871,9 @@ PUBLIC void UC_Charset_Setup ARGS8(
   UCInfo[s].unitable = unitable;
   UCInfo[s].num_uni = nnuni;
   UCInfo[s].replacedesc = replacedesc;
+  if (replacedesc.isdefault) {
+      default_UChndl = s;
+  }
   Gn = UC_FindGN_byMIME(UC_MIMEcharset);
   if (Gn >= 0)
     UC_GNhandles[Gn] = s;
@@ -1664,8 +1895,10 @@ PRIVATE void UCcleanup_mem NOARGS
 {
     int i;
     UCfree_allocated_LYCharSets();
-    con_clear_unimap_str();
-    con_clear_unimap();
+    con_clear_unimap_str(0);
+    con_clear_unimap_str(1);
+    con_clear_unimap(0);
+    con_clear_unimap(1);
     for (i = 1; i < 4; i++) {	/* first one is static! */
 	FREE(inverse_translations[i]);
 }