groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff] unicode support, part 6 X: public glyph to name/number API


From: Bruno Haible
Subject: [Groff] unicode support, part 6 X: public glyph to name/number API
Date: Wed, 15 Feb 2006 13:21:44 +0100
User-agent: KMail/1.5

Hi,

The logical consequence of the last patch that added glyph::glyph_name(),
needed for unicode fonts, is the reverse mapping from glyph to index or
number.

Please don't apply this patch! It is too ugly to have to convert a string
from decimal to binary in order to find the number to which a glyph is
defined. This patch shows that some more simplification of the two 'glyph'
implementations are needed first.

diff -r -u groff-20060213.orig/src/include/font.h 
groff-20060213/src/include/font.h
--- groff-20060213.orig/src/include/font.h      2006-02-13 13:00:19.000000000 
+0100
+++ groff-20060213/src/include/font.h   2006-02-14 02:36:22.000000000 +0100
@@ -227,7 +227,7 @@
                        // device) and initialize some static variables with
                        // info from there.
 
-  // The next two functions exist in two versions: one in
+  // The next four functions exist in two versions: one in
   // roff/troff/input.cpp for troff, and one for
   // libs/libgroff/nametoindex.cpp for the preprocessors and the
   // postprocessors.
@@ -241,6 +241,12 @@
                        // object.  This has the same semantics as the groff
                        // escape sequence \N'number'.  If such a `glyph'
                        // object does not yet exist, a new one is allocated.
+  static const char *index_to_name(glyph);     // Convert the given glyph
+                       // back to its name.  Return NULL if the glyph
+                       // doesn't have a name.
+  static int index_to_number(glyph);   // Convert the given glyph back to
+                       // its number.  Return -1 if it does not designate
+                       // a numbered character.
 
   static FONT_COMMAND_HANDLER
     set_unknown_desc_command_handler(FONT_COMMAND_HANDLER);    // Register
diff -r -u groff-20060213.orig/src/libs/libgroff/nametoindex.cpp 
groff-20060213/src/libs/libgroff/nametoindex.cpp
--- groff-20060213.orig/src/libs/libgroff/nametoindex.cpp       2006-02-13 
13:00:19.000000000 +0100
+++ groff-20060213/src/libs/libgroff/nametoindex.cpp    2006-02-14 
02:40:28.000000000 +0100
@@ -36,15 +36,26 @@
 public:
   character_indexer();
   ~character_indexer();
+  // --------------------- Lookup or creation of a glyph.
   glyph ascii_char_index(unsigned char);
   glyph named_char_index(const char *);
   glyph numbered_char_index(int);
+  // --------------------- Retrieve information about a glyph.
+  int index_as_ascii_char(glyph);      // Return the 'unsigned char' value,
+                       // or -1 if not a single-char glyph.
+  int index_as_numbered_char(glyph);   // Return the numbered glyph value,
+                       // or -1 if not a numbered glyph.
+  const char *index_to_name(glyph);    // Return the glyph name, or NULL
+                       // if not a named glyph.
 private:
+  int next_index;      // Number of glyphs already allocated.
+  PTABLE(int) table;   // Table mapping name to glyph.  For numbered glyphs,
+                       // " NNNN" is used as a name in the table.
+  glyph ascii_index[256];      // Shorthand table for looking up "charNNN"
+                       // glyphs.
   enum { NSMALL = 256 };
-  int next_index;
-  glyph ascii_index[256];
-  glyph small_number_index[NSMALL];
-  PTABLE(int) table;
+  glyph small_number_index[NSMALL];    // Shorthand table for looking up
+                       // numbered glyphs.
 };
 
 character_indexer::character_indexer()
@@ -75,21 +86,26 @@
 glyph character_indexer::numbered_char_index(int n)
 {
   if (n >= 0 && n < NSMALL) {
-    if (small_number_index[n].index < 0)
-      small_number_index[n] = glyph(next_index++, NULL);
+    if (small_number_index[n].index < 0) {
+      char buf[1 + 1 + INT_DIGITS + 1];
+      buf[0] = ' ';
+      strcpy(buf + 1, i_to_a(n));
+      small_number_index[n] = glyph(next_index++, strsave(buf));
+    }
     return small_number_index[n];
   }
   // Not the most efficient possible implementation.
   char buf[1 + 1 + INT_DIGITS + 1];
   buf[0] = ' ';
   strcpy(buf + 1, i_to_a(n));
-  int *np = table.lookup(buf);
+  const char *s = buf;
+  int *np = table.lookupassoc(&s);
   if (!np) {
     np = new int[1];
     *np = next_index++;
-    table.define(buf, np);
+    s = table.define(s, np);
   }
-  return glyph(*np, NULL);
+  return glyph(*np, s);
 }
 
 glyph character_indexer::named_char_index(const char *s)
@@ -103,6 +119,56 @@
   return glyph(*np, s);
 }
 
+int character_indexer::index_as_ascii_char(glyph g)
+{
+  if (g.index >= 0 && g.index < next_index) {
+    const char *name = g.name;
+    if (name != NULL)
+      if (name[0] == 'c' && name[1] == 'h' && name[2] == 'a' && name[3] == 'r'
+         && (name[4] >= '0' && name[4] <= '9')) {
+       int n = (name[4] - '0');
+       if (name[5] == '\0')
+         return n;
+       if (n > 0 && (name[5] >= '0' && name[5] <= '9')) {
+         n = 10*n + (name[5] - '0');
+         if (name[6] == '\0')
+           return n;
+         if (name[6] >= '0' && name[6] <= '9') {
+           n = 10*n + (name[6] - '0');
+           if (name[7] == '\0' && n < 256)
+             return n;
+         }
+       }
+      }
+  }
+  return -1;
+}
+
+int character_indexer::index_as_numbered_char(glyph g)
+{
+  if (g.index >= 0 && g.index < next_index) {
+    const char *name = g.name;
+    if (name != NULL)
+      if (name[0] == ' ' && (name[1] >= '0' && name[1] <= '9')) {
+       char *end;
+       long n = strtol(name + 1, &end, 10);
+       if (end > name + 1 && *end == '\0' && n == (int)n)
+         return (int)n;
+      }
+  }
+  return -1;
+}
+
+const char *character_indexer::index_to_name(glyph g)
+{
+  if (g.index >= 0 && g.index < next_index) {
+    const char *name = g.name;
+    if (name != NULL && name[0] != ' ')
+      return name;
+  }
+  return NULL;
+}
+
 static character_indexer indexer;
 
 glyph font::number_to_index(int n)
@@ -124,3 +190,13 @@
   }
   return glyph(indexer.named_char_index(s));
 }
+
+const char *font::index_to_name(glyph g)
+{
+  return indexer.index_to_name(g);
+}
+
+int font::index_to_number(glyph g)
+{
+  return indexer.index_as_numbered_char(g);
+}
diff -r -u groff-20060213.orig/src/roff/troff/input.cpp 
groff-20060213/src/roff/troff/input.cpp
--- groff-20060213.orig/src/roff/troff/input.cpp        2006-02-13 
13:00:20.000000000 +0100
+++ groff-20060213/src/roff/troff/input.cpp     2006-02-14 02:41:59.000000000 
+0100
@@ -8162,8 +8162,6 @@
   return number;
 }
 
-symbol UNNAMED_SYMBOL("---");
-
 // For numbered characters not between 0 and 255, we make a symbol out
 // of the number and store them in this dictionary.
 
@@ -8176,7 +8174,10 @@
   if (n >= 0 && n < 256) {
     charinfo *ci = number_table[n];
     if (!ci) {
-      ci = new charinfo(UNNAMED_SYMBOL);
+      char buf[1 + 1 + INT_DIGITS + 1];
+      buf[0] = ' ';
+      strcpy(buf + 1, i_to_a(n));
+      ci = new charinfo(symbol(buf));
       ci->set_number(n);
       number_table[n] = ci;
     }
@@ -8186,7 +8187,10 @@
     symbol ns(i_to_a(n));
     charinfo *ci = (charinfo *)numbered_charinfo_dictionary.lookup(ns);
     if (!ci) {
-      ci = new charinfo(UNNAMED_SYMBOL);
+      char buf[1 + 1 + INT_DIGITS + 1];
+      buf[0] = ' ';
+      strcpy(buf + 1, i_to_a(n));
+      ci = new charinfo(symbol(buf));
       ci->set_number(n);
       (void)numbered_charinfo_dictionary.lookup(ns, ci);
     }
@@ -8213,3 +8217,23 @@
 {
   return get_charinfo_by_number(n)->get_index();
 }
+
+const char *font::index_to_name(glyph g)
+{
+  const char *name = g.name;
+  if (name[0] != ' ')
+    return name;
+  return NULL;
+}
+
+int font::index_to_number(glyph g)
+{
+  const char *name = g.name;
+  if (name[0] == ' ' && (name[1] >= '0' && name[1] <= '9')) {
+    char *end;
+    long n = strtol(name + 1, &end, 10);
+    if (end > name + 1 && *end == '\0' && n == (int)n)
+      return (int)n;
+  }
+  return -1;
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]