experimental Japanese support
thanks to Daiki Ueno (dueno@redhat.com) Resolves: #596900
This commit is contained in:
parent
b37670d16e
commit
59e4ee9270
859
groff-japanese-charclass.patch
Normal file
859
groff-japanese-charclass.patch
Normal file
@ -0,0 +1,859 @@
|
|||||||
|
Resolves: #596900
|
||||||
|
|
||||||
|
From 8855b7d5f80f7c7a667abd690da7e65e0a77ab97 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daiki Ueno <ueno@unixuser.org>
|
||||||
|
Date: Thu, 5 Aug 2010 16:00:32 +0900
|
||||||
|
Subject: [PATCH] Import Colin Watson's charclass branch with minor fixes.
|
||||||
|
|
||||||
|
Changes from the branch:
|
||||||
|
- libgroff: make sure to return -1 from glyph_to_unicode() on error.
|
||||||
|
- tmac: add cflags to non-punct Japanese characters to ja.tmac.
|
||||||
|
- troff: skip "-" on parsing character ranges of the class request.
|
||||||
|
- troff: make class request parsing robuster.
|
||||||
|
- troff: suppress debug messages if DEBUGGING is not set.
|
||||||
|
- nroff: supply "-mja" to groff if running under Japanese locales.
|
||||||
|
---
|
||||||
|
src/include/classes.h | 62 ++++++++++++
|
||||||
|
src/include/font.h | 16 +++
|
||||||
|
src/libs/libgroff/Makefile.sub | 2 +
|
||||||
|
src/libs/libgroff/classes.cpp | 48 ++++++++++
|
||||||
|
src/libs/libgroff/font.cpp | 203 ++++++++++++++++++++++++++--------------
|
||||||
|
src/roff/nroff/nroff.sh | 6 +
|
||||||
|
src/roff/troff/charinfo.h | 50 +++++++++--
|
||||||
|
src/roff/troff/input.cpp | 138 +++++++++++++++++++++++++++
|
||||||
|
tmac/Makefile.sub | 3 +-
|
||||||
|
tmac/ja.tmac | 49 ++++++++++
|
||||||
|
10 files changed, 499 insertions(+), 78 deletions(-)
|
||||||
|
create mode 100644 src/include/classes.h
|
||||||
|
create mode 100644 src/libs/libgroff/classes.cpp
|
||||||
|
create mode 100644 tmac/ja.tmac
|
||||||
|
|
||||||
|
diff --git a/src/include/classes.h b/src/include/classes.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..2f0e2bd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/include/classes.h
|
||||||
|
@@ -0,0 +1,62 @@
|
||||||
|
+/* This file is in the public domain. */
|
||||||
|
+
|
||||||
|
+class charinfo;
|
||||||
|
+
|
||||||
|
+class char_class
|
||||||
|
+{
|
||||||
|
+ public:
|
||||||
|
+ virtual bool is_in_class(int c);
|
||||||
|
+ virtual int lookup_char(int c) = 0;
|
||||||
|
+ charinfo *get_charinfo();
|
||||||
|
+ void set_charinfo(charinfo *);
|
||||||
|
+ protected:
|
||||||
|
+ private:
|
||||||
|
+ charinfo *ci;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+class single_char_class : public char_class
|
||||||
|
+{
|
||||||
|
+ public:
|
||||||
|
+ single_char_class(int c);
|
||||||
|
+ int lookup_char(int c);
|
||||||
|
+ protected:
|
||||||
|
+ private:
|
||||||
|
+ int ch;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+class range_char_class : public char_class
|
||||||
|
+{
|
||||||
|
+ public:
|
||||||
|
+ range_char_class(int low, int high);
|
||||||
|
+ int lookup_char(int c);
|
||||||
|
+ protected:
|
||||||
|
+ private:
|
||||||
|
+ int lo, hi;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+class ref_char_class : public char_class
|
||||||
|
+{
|
||||||
|
+ public:
|
||||||
|
+ ref_char_class(char_class *klass);
|
||||||
|
+ int lookup_char(int c);
|
||||||
|
+ char_class *get_class();
|
||||||
|
+ protected:
|
||||||
|
+ private:
|
||||||
|
+ char_class *ref;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+inline bool char_class::is_in_class(int c)
|
||||||
|
+{
|
||||||
|
+ return lookup_char(c) == 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline charinfo *char_class::get_charinfo()
|
||||||
|
+{
|
||||||
|
+ return ci;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline void char_class::set_charinfo(charinfo *cis)
|
||||||
|
+{
|
||||||
|
+ ci = cis;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff --git a/src/include/font.h b/src/include/font.h
|
||||||
|
index 944250b..4e9edc4 100644
|
||||||
|
--- a/src/include/font.h
|
||||||
|
+++ b/src/include/font.h
|
||||||
|
@@ -18,6 +18,12 @@ for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#include <string>
|
||||||
|
+#include <map>
|
||||||
|
+#include <vector>
|
||||||
|
+
|
||||||
|
+class char_class;
|
||||||
|
+
|
||||||
|
// A function of this type can be registered to define the semantics of
|
||||||
|
// arbitrary commands in a font DESC file.
|
||||||
|
typedef void (*FONT_COMMAND_HANDLER)(const char *, // command
|
||||||
|
@@ -73,6 +79,9 @@ inline int glyph_to_number(glyph *); // Convert the given glyph back to
|
||||||
|
// a numbered character.
|
||||||
|
inline int glyph_to_index(glyph *); // Return the unique index that is
|
||||||
|
// associated with the given glyph. It is >= 0.
|
||||||
|
+extern int glyph_to_unicode(glyph *); // Convert the given glyph to its
|
||||||
|
+ // Unicode codepoint. Return -1 if it does not
|
||||||
|
+ // designate a Unicode character.
|
||||||
|
|
||||||
|
inline int glyph_to_number(glyph *g)
|
||||||
|
{
|
||||||
|
@@ -267,6 +276,8 @@ public:
|
||||||
|
// upper1, ... lowerN, upperN, 0 }.
|
||||||
|
|
||||||
|
private:
|
||||||
|
+ std::map<std::string, std::vector<char_class *> > class_map;
|
||||||
|
+ // A map of names to class objects.
|
||||||
|
unsigned ligatures; // Bit mask of available ligatures. Used by
|
||||||
|
// has_ligature().
|
||||||
|
font_kern_list **kern_hash_table; // Hash table of kerning pairs.
|
||||||
|
@@ -308,6 +319,11 @@ private:
|
||||||
|
void extend_ch();
|
||||||
|
void compact();
|
||||||
|
|
||||||
|
+ // These methods add glyphs to character classes.
|
||||||
|
+ void add_class(const char *, glyph *);
|
||||||
|
+ void add_class(const char *, glyph *, glyph *);
|
||||||
|
+ void add_class(const char *, const char *);
|
||||||
|
+
|
||||||
|
void add_kern(glyph *, glyph *, int); // Add to the kerning table a
|
||||||
|
// kerning amount (arg3) between two given glyphs
|
||||||
|
// (arg1 and arg2).
|
||||||
|
diff --git a/src/libs/libgroff/Makefile.sub b/src/libs/libgroff/Makefile.sub
|
||||||
|
index ac83892..cb8c14e 100644
|
||||||
|
--- a/src/libs/libgroff/Makefile.sub
|
||||||
|
+++ b/src/libs/libgroff/Makefile.sub
|
||||||
|
@@ -5,6 +5,7 @@ EXTRA_CFLAGS=-D__GETOPT_PREFIX=groff_ \
|
||||||
|
OBJS=\
|
||||||
|
assert.$(OBJEXT) \
|
||||||
|
change_lf.$(OBJEXT) \
|
||||||
|
+ classes.$(OBJEXT) \
|
||||||
|
cmap.$(OBJEXT) \
|
||||||
|
color.$(OBJEXT) \
|
||||||
|
cset.$(OBJEXT) \
|
||||||
|
@@ -55,6 +56,7 @@ OBJS=\
|
||||||
|
CCSRCS=\
|
||||||
|
$(srcdir)/assert.cpp \
|
||||||
|
$(srcdir)/change_lf.cpp \
|
||||||
|
+ $(srcdir)/classes.cpp \
|
||||||
|
$(srcdir)/cmap.cpp \
|
||||||
|
$(srcdir)/color.cpp \
|
||||||
|
$(srcdir)/cset.cpp \
|
||||||
|
diff --git a/src/libs/libgroff/classes.cpp b/src/libs/libgroff/classes.cpp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..eef1742
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/libs/libgroff/classes.cpp
|
||||||
|
@@ -0,0 +1,48 @@
|
||||||
|
+/* This file is in the public domain. */
|
||||||
|
+
|
||||||
|
+#include "classes.h"
|
||||||
|
+
|
||||||
|
+single_char_class::single_char_class(int c) :
|
||||||
|
+ ch(c)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int single_char_class::lookup_char(int c)
|
||||||
|
+{
|
||||||
|
+ if (c < ch)
|
||||||
|
+ return -1;
|
||||||
|
+ else if (c > ch)
|
||||||
|
+ return 1;
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+range_char_class::range_char_class(int low, int high) :
|
||||||
|
+ lo(low), hi(high)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int range_char_class::lookup_char(int c)
|
||||||
|
+{
|
||||||
|
+ if (c < lo)
|
||||||
|
+ return -1;
|
||||||
|
+ else if (c > hi)
|
||||||
|
+ return 1;
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+ref_char_class::ref_char_class(char_class *klass) :
|
||||||
|
+ ref(klass)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int ref_char_class::lookup_char(int c)
|
||||||
|
+{
|
||||||
|
+ return ref->lookup_char(c);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char_class *ref_char_class::get_class()
|
||||||
|
+{
|
||||||
|
+ return ref;
|
||||||
|
+}
|
||||||
|
diff --git a/src/libs/libgroff/font.cpp b/src/libs/libgroff/font.cpp
|
||||||
|
index d0b4a12..18e0a07 100644
|
||||||
|
--- a/src/libs/libgroff/font.cpp
|
||||||
|
+++ b/src/libs/libgroff/font.cpp
|
||||||
|
@@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
#include "font.h"
|
||||||
|
#include "unicode.h"
|
||||||
|
#include "paper.h"
|
||||||
|
+#include "classes.h"
|
||||||
|
|
||||||
|
const char *const WS = " \t\n\r";
|
||||||
|
|
||||||
|
@@ -148,6 +149,49 @@ void text_file::error(const char *format,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+int glyph_to_unicode(glyph *g)
|
||||||
|
+{
|
||||||
|
+ const char *nm = glyph_to_name(g);
|
||||||
|
+ if (nm != NULL) {
|
||||||
|
+ // ASCII character?
|
||||||
|
+ if (nm[0] == 'c' && nm[1] == 'h' && nm[2] == 'a' && nm[3] == 'r'
|
||||||
|
+ && (nm[4] >= '0' && nm[4] <= '9')) {
|
||||||
|
+ int n = (nm[4] - '0');
|
||||||
|
+ if (nm[5] == '\0')
|
||||||
|
+ return n;
|
||||||
|
+ if (n > 0 && (nm[5] >= '0' && nm[5] <= '9')) {
|
||||||
|
+ n = 10*n + (nm[5] - '0');
|
||||||
|
+ if (nm[6] == '\0')
|
||||||
|
+ return n;
|
||||||
|
+ if (nm[6] >= '0' && nm[6] <= '9') {
|
||||||
|
+ n = 10*n + (nm[6] - '0');
|
||||||
|
+ if (nm[7] == '\0' && n < 128)
|
||||||
|
+ return n;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Unicode character?
|
||||||
|
+ if (check_unicode_name(nm)) {
|
||||||
|
+ char *ignore;
|
||||||
|
+ return (int)strtol(nm + 1, &ignore, 16);
|
||||||
|
+ }
|
||||||
|
+ // If `nm' is a single letter `x', the glyph name is `\x'.
|
||||||
|
+ char buf[] = { '\\', '\0', '\0' };
|
||||||
|
+ if (nm[1] == '\0') {
|
||||||
|
+ buf[1] = nm[0];
|
||||||
|
+ nm = buf;
|
||||||
|
+ }
|
||||||
|
+ // groff glyphs that map to Unicode?
|
||||||
|
+ const char *unicode = glyph_name_to_unicode(nm);
|
||||||
|
+ if (unicode != NULL && strchr(unicode, '_') == NULL) {
|
||||||
|
+ char *ignore;
|
||||||
|
+ return (int)strtol(unicode, &ignore, 16);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/* font functions */
|
||||||
|
|
||||||
|
font::font(const char *s)
|
||||||
|
@@ -269,39 +313,10 @@ int font::contains(glyph *g)
|
||||||
|
return 1;
|
||||||
|
if (is_unicode) {
|
||||||
|
// Unicode font
|
||||||
|
- const char *nm = glyph_to_name(g);
|
||||||
|
- if (nm != NULL) {
|
||||||
|
- // ASCII character?
|
||||||
|
- if (nm[0] == 'c' && nm[1] == 'h' && nm[2] == 'a' && nm[3] == 'r'
|
||||||
|
- && (nm[4] >= '0' && nm[4] <= '9')) {
|
||||||
|
- int n = (nm[4] - '0');
|
||||||
|
- if (nm[5] == '\0')
|
||||||
|
- return 1;
|
||||||
|
- if (n > 0 && (nm[5] >= '0' && nm[5] <= '9')) {
|
||||||
|
- n = 10*n + (nm[5] - '0');
|
||||||
|
- if (nm[6] == '\0')
|
||||||
|
- return 1;
|
||||||
|
- if (nm[6] >= '0' && nm[6] <= '9') {
|
||||||
|
- n = 10*n + (nm[6] - '0');
|
||||||
|
- if (nm[7] == '\0' && n < 128)
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- // Unicode character?
|
||||||
|
- if (check_unicode_name(nm))
|
||||||
|
- return 1;
|
||||||
|
- // If `nm' is a single letter `x', the glyph name is `\x'.
|
||||||
|
- char buf[] = { '\\', '\0', '\0' };
|
||||||
|
- if (nm[1] == '\0') {
|
||||||
|
- buf[1] = nm[0];
|
||||||
|
- nm = buf;
|
||||||
|
- }
|
||||||
|
- // groff glyph name that maps to Unicode?
|
||||||
|
- const char *unicode = glyph_name_to_unicode(nm);
|
||||||
|
- if (unicode != NULL && strchr(unicode, '_') == NULL)
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
+ // ASCII or Unicode character, or groff glyph name that maps to Unicode?
|
||||||
|
+ int uni = glyph_to_unicode(g);
|
||||||
|
+ if (uni >= 0)
|
||||||
|
+ return 1;
|
||||||
|
// Numbered character?
|
||||||
|
int n = glyph_to_number(g);
|
||||||
|
if (n >= 0)
|
||||||
|
@@ -554,43 +569,10 @@ int font::get_code(glyph *g)
|
||||||
|
}
|
||||||
|
if (is_unicode) {
|
||||||
|
// Unicode font
|
||||||
|
- const char *nm = glyph_to_name(g);
|
||||||
|
- if (nm != NULL) {
|
||||||
|
- // ASCII character?
|
||||||
|
- if (nm[0] == 'c' && nm[1] == 'h' && nm[2] == 'a' && nm[3] == 'r'
|
||||||
|
- && (nm[4] >= '0' && nm[4] <= '9')) {
|
||||||
|
- int n = (nm[4] - '0');
|
||||||
|
- if (nm[5] == '\0')
|
||||||
|
- return n;
|
||||||
|
- if (n > 0 && (nm[5] >= '0' && nm[5] <= '9')) {
|
||||||
|
- n = 10*n + (nm[5] - '0');
|
||||||
|
- if (nm[6] == '\0')
|
||||||
|
- return n;
|
||||||
|
- if (nm[6] >= '0' && nm[6] <= '9') {
|
||||||
|
- n = 10*n + (nm[6] - '0');
|
||||||
|
- if (nm[7] == '\0' && n < 128)
|
||||||
|
- return n;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- // Unicode character?
|
||||||
|
- if (check_unicode_name(nm)) {
|
||||||
|
- char *ignore;
|
||||||
|
- return (int)strtol(nm + 1, &ignore, 16);
|
||||||
|
- }
|
||||||
|
- // If `nm' is a single letter `x', the glyph name is `\x'.
|
||||||
|
- char buf[] = { '\\', '\0', '\0' };
|
||||||
|
- if (nm[1] == '\0') {
|
||||||
|
- buf[1] = nm[0];
|
||||||
|
- nm = buf;
|
||||||
|
- }
|
||||||
|
- // groff glyphs that map to Unicode?
|
||||||
|
- const char *unicode = glyph_name_to_unicode(nm);
|
||||||
|
- if (unicode != NULL && strchr(unicode, '_') == NULL) {
|
||||||
|
- char *ignore;
|
||||||
|
- return (int)strtol(unicode, &ignore, 16);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ // ASCII or Unicode character, or groff glyph name that maps to Unicode?
|
||||||
|
+ int uni = glyph_to_unicode(g);
|
||||||
|
+ if (uni >= 0)
|
||||||
|
+ return uni;
|
||||||
|
// Numbered character?
|
||||||
|
int n = glyph_to_number(g);
|
||||||
|
if (n >= 0)
|
||||||
|
@@ -790,6 +772,38 @@ again:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void font::add_class(const char *name, glyph *g)
|
||||||
|
+{
|
||||||
|
+ int num = glyph_to_number(g);
|
||||||
|
+
|
||||||
|
+ if (num == -1)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ single_char_class *ref = new single_char_class(num);
|
||||||
|
+ class_map[name].push_back(ref);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void font::add_class(const char *name, glyph *g1, glyph *g2)
|
||||||
|
+{
|
||||||
|
+ int num1 = glyph_to_number(g1);
|
||||||
|
+ int num2 = glyph_to_number(g2);
|
||||||
|
+
|
||||||
|
+ if ((num1 == -1) || (num2 == -1))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ range_char_class *ref = new range_char_class(num1, num2);
|
||||||
|
+ class_map[name].push_back(ref);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void font::add_class(const char *name, const char *oname)
|
||||||
|
+{
|
||||||
|
+ std::vector<char_class *> *vec = &class_map[oname];
|
||||||
|
+ int nelems = vec->size();
|
||||||
|
+ for (int i = 0; i < nelems; i++) {
|
||||||
|
+ class_map[name].push_back((*vec)[i]);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// If the font can't be found, then if not_found is non-NULL, it will be set
|
||||||
|
// to 1 otherwise a message will be printed.
|
||||||
|
|
||||||
|
@@ -1020,6 +1034,55 @@ int font::load(int *not_found, int head_only)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ else if (strcmp(command, "classes") == 0) {
|
||||||
|
+ if (head_only)
|
||||||
|
+ return 1;
|
||||||
|
+ for (;;) {
|
||||||
|
+ if (!t.next()) {
|
||||||
|
+ command = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ char *cname = strtok(t.buf, WS);
|
||||||
|
+ if (cname == 0)
|
||||||
|
+ continue;
|
||||||
|
+ char *equals = strtok(0, WS);
|
||||||
|
+ if (equals == 0) {
|
||||||
|
+ command = cname;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ p = strtok(0, WS);
|
||||||
|
+ if (p == 0) {
|
||||||
|
+ t.error("empty character classes not allowed");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ glyph *g1 = 0, *g2 = 0;
|
||||||
|
+ while (p != 0) {
|
||||||
|
+ if ((g1 != 0) && (p[0] == '-')) {
|
||||||
|
+ p = strtok(0, WS);
|
||||||
|
+ if (p == 0) {
|
||||||
|
+ t.error("incomplete range in class definition");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ g2 = name_to_glyph(p);
|
||||||
|
+ add_class(cname, g1, g2);
|
||||||
|
+ g1 = g2 = 0;
|
||||||
|
+ }
|
||||||
|
+ else if (g1 != 0) {
|
||||||
|
+ add_class(cname, g1);
|
||||||
|
+ g1 = 0;
|
||||||
|
+ }
|
||||||
|
+ if ((p[0] == '<') && (p[strlen(p)-1] == '>')) {
|
||||||
|
+ add_class(cname, p);
|
||||||
|
+ }
|
||||||
|
+ else if (p[0] != '-') {
|
||||||
|
+ g1 = name_to_glyph(p);
|
||||||
|
+ }
|
||||||
|
+ p = strtok(0, WS);
|
||||||
|
+ }
|
||||||
|
+ if (g1 != 0)
|
||||||
|
+ add_class(cname, g1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
else {
|
||||||
|
t.error("unrecognised command `%1' "
|
||||||
|
"after `kernpairs' or `charset' command",
|
||||||
|
diff --git a/src/roff/nroff/nroff.sh b/src/roff/nroff/nroff.sh
|
||||||
|
index d4bd8a0..22529f8 100644
|
||||||
|
--- a/src/roff/nroff/nroff.sh
|
||||||
|
+++ b/src/roff/nroff/nroff.sh
|
||||||
|
@@ -125,6 +125,12 @@ case $T in
|
||||||
|
T=-T$Tloc ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
+case "${LC_ALL-${LC_CTYPE-${LANG}}}" in
|
||||||
|
+ ja*)
|
||||||
|
+ opts="$opts -mja"
|
||||||
|
+ ;;
|
||||||
|
+esac
|
||||||
|
+
|
||||||
|
# Set up the `GROFF_BIN_PATH' variable
|
||||||
|
# to be exported in the current `GROFF_RUNTIME' environment.
|
||||||
|
|
||||||
|
diff --git a/src/roff/troff/charinfo.h b/src/roff/troff/charinfo.h
|
||||||
|
index 2c2c268..71cd84d 100644
|
||||||
|
--- a/src/roff/troff/charinfo.h
|
||||||
|
+++ b/src/roff/troff/charinfo.h
|
||||||
|
@@ -18,6 +18,9 @@ for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#include <vector>
|
||||||
|
+#include <utility>
|
||||||
|
+
|
||||||
|
class macro;
|
||||||
|
|
||||||
|
class charinfo : glyph {
|
||||||
|
@@ -35,6 +38,9 @@ class charinfo : glyph {
|
||||||
|
char translate_input; // non-zero means that asciify_code is
|
||||||
|
// active for .asciify (set by .trin)
|
||||||
|
char_mode mode;
|
||||||
|
+ // Unicode character classes
|
||||||
|
+ std::vector<std::pair<int, int> > ranges;
|
||||||
|
+ std::vector<charinfo *> nested_classes;
|
||||||
|
public:
|
||||||
|
enum { // Values for the flags bitmask. See groff
|
||||||
|
// manual, description of the `.cflags' request.
|
||||||
|
@@ -66,6 +72,7 @@ public:
|
||||||
|
unsigned char get_hyphenation_code();
|
||||||
|
unsigned char get_ascii_code();
|
||||||
|
unsigned char get_asciify_code();
|
||||||
|
+ int get_unicode_code();
|
||||||
|
void set_hyphenation_code(unsigned char);
|
||||||
|
void set_ascii_code(unsigned char);
|
||||||
|
void set_asciify_code(unsigned char);
|
||||||
|
@@ -73,6 +80,7 @@ public:
|
||||||
|
int get_translation_input();
|
||||||
|
charinfo *get_translation(int = 0);
|
||||||
|
void set_translation(charinfo *, int, int);
|
||||||
|
+ unsigned char get_flags();
|
||||||
|
void set_flags(unsigned char);
|
||||||
|
void set_special_translation(int, int);
|
||||||
|
int get_special_translation(int = 0);
|
||||||
|
@@ -87,6 +95,13 @@ public:
|
||||||
|
int is_fallback();
|
||||||
|
int is_special();
|
||||||
|
symbol *get_symbol();
|
||||||
|
+ void add_to_class(int);
|
||||||
|
+ void add_to_class(int, int);
|
||||||
|
+ void add_to_class(charinfo *);
|
||||||
|
+ bool is_class();
|
||||||
|
+ bool contains(int);
|
||||||
|
+ bool contains(symbol);
|
||||||
|
+ bool contains(charinfo *);
|
||||||
|
};
|
||||||
|
|
||||||
|
charinfo *get_charinfo(symbol);
|
||||||
|
@@ -95,37 +110,37 @@ charinfo *get_charinfo_by_number(int);
|
||||||
|
|
||||||
|
inline int charinfo::overlaps_horizontally()
|
||||||
|
{
|
||||||
|
- return flags & OVERLAPS_HORIZONTALLY;
|
||||||
|
+ return get_flags() & OVERLAPS_HORIZONTALLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::overlaps_vertically()
|
||||||
|
{
|
||||||
|
- return flags & OVERLAPS_VERTICALLY;
|
||||||
|
+ return get_flags() & OVERLAPS_VERTICALLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::can_break_before()
|
||||||
|
{
|
||||||
|
- return flags & BREAK_BEFORE;
|
||||||
|
+ return get_flags() & BREAK_BEFORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::can_break_after()
|
||||||
|
{
|
||||||
|
- return flags & BREAK_AFTER;
|
||||||
|
+ return get_flags() & BREAK_AFTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::ends_sentence()
|
||||||
|
{
|
||||||
|
- return flags & ENDS_SENTENCE;
|
||||||
|
+ return get_flags() & ENDS_SENTENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::transparent()
|
||||||
|
{
|
||||||
|
- return flags & TRANSPARENT;
|
||||||
|
+ return get_flags() & TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::ignore_hcodes()
|
||||||
|
{
|
||||||
|
- return flags & IGNORE_HCODES;
|
||||||
|
+ return get_flags() & IGNORE_HCODES;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int charinfo::numbered()
|
||||||
|
@@ -216,3 +231,24 @@ inline symbol *charinfo::get_symbol()
|
||||||
|
{
|
||||||
|
return( &nm );
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+inline void charinfo::add_to_class(int c)
|
||||||
|
+{
|
||||||
|
+ // TODO ranges cumbersome for single characters?
|
||||||
|
+ ranges.push_back(std::pair<int, int>(c, c));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline void charinfo::add_to_class(int lo, int hi)
|
||||||
|
+{
|
||||||
|
+ ranges.push_back(std::pair<int, int>(lo, hi));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline void charinfo::add_to_class(charinfo *ci)
|
||||||
|
+{
|
||||||
|
+ nested_classes.push_back(ci);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline bool charinfo::is_class()
|
||||||
|
+{
|
||||||
|
+ return (!ranges.empty() || !nested_classes.empty());
|
||||||
|
+}
|
||||||
|
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
|
||||||
|
index 5335c1c..88782b1 100644
|
||||||
|
--- a/src/roff/troff/input.cpp
|
||||||
|
+++ b/src/roff/troff/input.cpp
|
||||||
|
@@ -6740,6 +6740,74 @@ void hyphenation_patterns_file_code()
|
||||||
|
skip_line();
|
||||||
|
}
|
||||||
|
|
||||||
|
+dictionary char_class_dictionary(501);
|
||||||
|
+
|
||||||
|
+void define_class()
|
||||||
|
+{
|
||||||
|
+ tok.skip();
|
||||||
|
+ symbol nm = get_name(1);
|
||||||
|
+ if (nm.is_null()) {
|
||||||
|
+ skip_line();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ charinfo *ci = get_charinfo(nm);
|
||||||
|
+ charinfo *child1 = 0, *child2 = 0;
|
||||||
|
+ while (!tok.newline() && !tok.eof()) {
|
||||||
|
+ tok.skip();
|
||||||
|
+ if (child1 != 0 && tok.ch() == '-') {
|
||||||
|
+ tok.next();
|
||||||
|
+ child2 = tok.get_char(1);
|
||||||
|
+ if (!child2) {
|
||||||
|
+ warning(WARN_MISSING,
|
||||||
|
+ "missing the end of character range in class `%1'",
|
||||||
|
+ nm.contents());
|
||||||
|
+ skip_line();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (child1->is_class() || child2->is_class()) {
|
||||||
|
+ warning(WARN_SYNTAX,
|
||||||
|
+ "nested character class is not allowed in range definition");
|
||||||
|
+ skip_line();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ ci->add_to_class(child1->get_unicode_code(), child2->get_unicode_code());
|
||||||
|
+ child1 = child2 = 0;
|
||||||
|
+ }
|
||||||
|
+ else if (child1 != 0) {
|
||||||
|
+ if (child1->is_class()) {
|
||||||
|
+ ci->add_to_class(child1);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ci->add_to_class(child1->get_unicode_code());
|
||||||
|
+ }
|
||||||
|
+ child1 = 0;
|
||||||
|
+ }
|
||||||
|
+ child1 = tok.get_char(1);
|
||||||
|
+ tok.next();
|
||||||
|
+ if (!child1) {
|
||||||
|
+ if (!tok.newline())
|
||||||
|
+ skip_line();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (child1 != 0) {
|
||||||
|
+ if (child1->is_class()) {
|
||||||
|
+ ci->add_to_class(child1);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ci->add_to_class(child1->get_unicode_code());
|
||||||
|
+ }
|
||||||
|
+ child1 = 0;
|
||||||
|
+ }
|
||||||
|
+ if (!ci->is_class()) {
|
||||||
|
+ warning(WARN_SYNTAX,
|
||||||
|
+ "empty class definition for `%1'",
|
||||||
|
+ nm.contents());
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ (void)char_class_dictionary.lookup(nm, ci);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
charinfo *token::get_char(int required)
|
||||||
|
{
|
||||||
|
if (type == TOKEN_CHAR)
|
||||||
|
@@ -7817,6 +7885,7 @@ void init_input_requests()
|
||||||
|
init_request("cflags", char_flags);
|
||||||
|
init_request("char", define_character);
|
||||||
|
init_request("chop", chop_macro);
|
||||||
|
+ init_request("class", define_class);
|
||||||
|
init_request("close", close_request);
|
||||||
|
init_request("color", activate_color);
|
||||||
|
init_request("composite", composite_request);
|
||||||
|
@@ -8367,6 +8436,13 @@ charinfo::charinfo(symbol s)
|
||||||
|
number = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int charinfo::get_unicode_code()
|
||||||
|
+{
|
||||||
|
+ if (ascii_code != '\0')
|
||||||
|
+ return ascii_code;
|
||||||
|
+ return glyph_to_unicode(this);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void charinfo::set_hyphenation_code(unsigned char c)
|
||||||
|
{
|
||||||
|
hyphenation_code = c;
|
||||||
|
@@ -8388,6 +8464,25 @@ void charinfo::set_translation(charinfo *ci, int tt, int ti)
|
||||||
|
transparent_translate = tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// Get the union of all flags affecting this charinfo.
|
||||||
|
+unsigned char charinfo::get_flags()
|
||||||
|
+{
|
||||||
|
+ unsigned char all_flags = flags;
|
||||||
|
+ dictionary_iterator iter(char_class_dictionary);
|
||||||
|
+ charinfo *cp;
|
||||||
|
+ symbol s;
|
||||||
|
+ while (iter.get(&s, (void **)&cp)) {
|
||||||
|
+ assert(!s.is_null());
|
||||||
|
+ if (cp->contains(get_unicode_code())) {
|
||||||
|
+#if defined(DEBUGGING)
|
||||||
|
+ fprintf(stderr, "charinfo::get_flags %p %s %d\n", cp, cp->nm.contents(), cp->flags);
|
||||||
|
+#endif
|
||||||
|
+ all_flags |= cp->flags;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return all_flags;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void charinfo::set_special_translation(int c, int tt)
|
||||||
|
{
|
||||||
|
special_translation = c;
|
||||||
|
@@ -8432,6 +8527,49 @@ int charinfo::get_number()
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool charinfo::contains(int c)
|
||||||
|
+{
|
||||||
|
+ std::vector<std::pair<int, int> >::const_iterator ranges_iter;
|
||||||
|
+ ranges_iter = ranges.begin();
|
||||||
|
+ while (ranges_iter != ranges.end()) {
|
||||||
|
+ if (c >= ranges_iter->first && c <= ranges_iter->second) {
|
||||||
|
+#if defined(DEBUGGING)
|
||||||
|
+ fprintf(stderr, "charinfo::contains(%d)\n", c);
|
||||||
|
+#endif
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ ++ranges_iter;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ std::vector<charinfo *>::const_iterator nested_iter;
|
||||||
|
+ nested_iter = nested_classes.begin();
|
||||||
|
+ while (nested_iter != nested_classes.end()) {
|
||||||
|
+ if ((*nested_iter)->contains(c))
|
||||||
|
+ return true;
|
||||||
|
+ ++nested_iter;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool charinfo::contains(symbol nm)
|
||||||
|
+{
|
||||||
|
+ const char *unicode = glyph_name_to_unicode(nm.contents());
|
||||||
|
+ if (unicode != NULL && strchr(unicode, '_') == NULL) {
|
||||||
|
+ char *ignore;
|
||||||
|
+ int c = (int)strtol(unicode, &ignore, 16);
|
||||||
|
+ return contains(c);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool charinfo::contains(charinfo *)
|
||||||
|
+{
|
||||||
|
+ // TODO
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
symbol UNNAMED_SYMBOL("---");
|
||||||
|
|
||||||
|
// For numbered characters not between 0 and 255, we make a symbol out
|
||||||
|
diff --git a/tmac/Makefile.sub b/tmac/Makefile.sub
|
||||||
|
index ef4b577..5900010 100644
|
||||||
|
--- a/tmac/Makefile.sub
|
||||||
|
+++ b/tmac/Makefile.sub
|
||||||
|
@@ -55,7 +55,8 @@ NORMALFILES=\
|
||||||
|
fr.tmac hyphen.fr \
|
||||||
|
sv.tmac hyphen.sv \
|
||||||
|
de.tmac den.tmac hyphen.det hyphen.den hyphenex.det \
|
||||||
|
- cs.tmac hyphen.cs hyphenex.cs
|
||||||
|
+ cs.tmac hyphen.cs hyphenex.cs \
|
||||||
|
+ ja.tmac
|
||||||
|
|
||||||
|
# These files are handled specially during installation and deinstallation.
|
||||||
|
SPECIALFILES=an.tmac s.tmac www.tmac
|
||||||
|
diff --git a/tmac/ja.tmac b/tmac/ja.tmac
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..eed664b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tmac/ja.tmac
|
||||||
|
@@ -0,0 +1,49 @@
|
||||||
|
+.\" -*- mode: nroff; coding: utf-8; -*-
|
||||||
|
+.\"
|
||||||
|
+.\" Japanese localization for groff
|
||||||
|
+.\"
|
||||||
|
+.\" Copyright (C) 2009 Free Software Foundation, Inc.
|
||||||
|
+.\" Written by Fumitoshi UKAI <ukai@debian.or.jp> and
|
||||||
|
+.\" Colin Watson <cjwatson@debian.org>
|
||||||
|
+.\"
|
||||||
|
+.\" This file is part of groff.
|
||||||
|
+.\"
|
||||||
|
+.\" groff is free software; you can redistribute it and/or modify it under
|
||||||
|
+.\" the terms of the GNU General Public License as published by the Free
|
||||||
|
+.\" Software Foundation, either version 3 of the License, or
|
||||||
|
+.\" (at your option) any later version.
|
||||||
|
+.\"
|
||||||
|
+.\" groff is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
+.\" WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
+.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
+.\" for more details.
|
||||||
|
+.\"
|
||||||
|
+.\" You should have received a copy of the GNU General Public License
|
||||||
|
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+.\"
|
||||||
|
+.\" Please send comments to groff@gnu.org.
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
+.\" Locale string
|
||||||
|
+.
|
||||||
|
+.ds locale japanese\"
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
+.class [CJKprepunct] \
|
||||||
|
+ , : ; > } \
|
||||||
|
+ \[u3001] \[u3002] \[uFF0C] \[uFF0E] \[u30FB] \[uFF1A] \[uFF1B] \[uFF1F] \
|
||||||
|
+ \[uFF01] \[uFF09] \[u3015] \[uFF3D] \[uFF5D] \[u300D] \[u300F] \[u3011] \
|
||||||
|
+ \[u3041] \[u3043] \[u3045] \[u3047] \[u3049] \[u3063] \[u3083] \[u3085] \
|
||||||
|
+ \[u3087] \[u30FC] \
|
||||||
|
+ \[u30A1] \[u30A3] \[u30A5] \[u30A7] \[u30A9] \[u30C3] \[u30E3] \[u30E5] \
|
||||||
|
+ \[u30E7]
|
||||||
|
+.class [CJKpostpunct] \
|
||||||
|
+ \[uFF08] \[u3014] \[uFF3B] \[uFF5B] \[u300C] \[u300E] \[u3010]
|
||||||
|
+.
|
||||||
|
+.\" Hiragana, Katakana, and Kanji glyphs.
|
||||||
|
+.class [CJKnormal] \
|
||||||
|
+ \[u3041]-\[u3096] \[u30A0]-\[u30FF] \[u4E00]-\[u9FFF]
|
||||||
|
+.
|
||||||
|
+.cflags 2 \C'[CJKprepunct]'
|
||||||
|
+.cflags 4 \C'[CJKpostpunct]'
|
||||||
|
+.cflags 66 \C'[CJKnormal]'
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
23721
groff-japanese-wcwidth.patch
Normal file
23721
groff-japanese-wcwidth.patch
Normal file
File diff suppressed because it is too large
Load Diff
10
groff.spec
10
groff.spec
@ -3,7 +3,7 @@
|
|||||||
Summary: A document formatting system
|
Summary: A document formatting system
|
||||||
Name: groff
|
Name: groff
|
||||||
Version: 1.20.1
|
Version: 1.20.1
|
||||||
Release: 2%{?dist}
|
Release: 3%{?dist}
|
||||||
License: GPLv3+ and GFDL and BSD and MIT
|
License: GPLv3+ and GFDL and BSD and MIT
|
||||||
Group: Applications/Publishing
|
Group: Applications/Publishing
|
||||||
URL: http://groff.ffii.org
|
URL: http://groff.ffii.org
|
||||||
@ -11,6 +11,8 @@ URL: http://groff.ffii.org
|
|||||||
Source0: ftp://ftp.gnu.org/gnu/groff/groff-%{version}.tar.gz
|
Source0: ftp://ftp.gnu.org/gnu/groff/groff-%{version}.tar.gz
|
||||||
|
|
||||||
Patch1: groff-info-missing-x11.patch
|
Patch1: groff-info-missing-x11.patch
|
||||||
|
Patch2: groff-japanese-charclass.patch
|
||||||
|
Patch3: groff-japanese-wcwidth.patch
|
||||||
|
|
||||||
Requires: mktemp
|
Requires: mktemp
|
||||||
Requires: /sbin/install-info
|
Requires: /sbin/install-info
|
||||||
@ -76,6 +78,8 @@ language and documentation for creating PDF files.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%patch1 -p1 -b .info-missing-x11
|
%patch1 -p1 -b .info-missing-x11
|
||||||
|
%patch2 -p1 -b .japanese-charclass
|
||||||
|
%patch3 -p1 -b .japanese-wcwidth
|
||||||
|
|
||||||
for file in NEWS src/devices/grolbp/grolbp.man doc/{groff.info*,webpage.ms} \
|
for file in NEWS src/devices/grolbp/grolbp.man doc/{groff.info*,webpage.ms} \
|
||||||
contrib/mm/*.man contrib/mom/examples/{README.txt,*.mom} ; do
|
contrib/mm/*.man contrib/mom/examples/{README.txt,*.mom} ; do
|
||||||
@ -198,6 +202,10 @@ fi
|
|||||||
%doc %{_docdir}/%{name}-%{version}/pdf/
|
%doc %{_docdir}/%{name}-%{version}/pdf/
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Nov 26 2010 Jan Vcelak <jvcelak@redhat.com> 1.20.1-3
|
||||||
|
- experimental support of Japanese (charclass and wcwidth patches)
|
||||||
|
thanks to Daiki Ueno (dueno@redhat.com)
|
||||||
|
|
||||||
* Fri Jul 30 2010 Jan Vcelak <jvcelak@redhat.com> 1.20.1-2
|
* Fri Jul 30 2010 Jan Vcelak <jvcelak@redhat.com> 1.20.1-2
|
||||||
- Resolves: #477394 - Please convert to new font packaging guidelines
|
- Resolves: #477394 - Please convert to new font packaging guidelines
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user