CVSTAG = r$(subst .,-,$(VERSION))
SONAME = @SONAME@
-PROGS = test whiptail whiptcl.so testgrid testtree
+PROGS = test test-j whiptail whiptcl.so testgrid testgrid-j testtree testtree-j
TESTOBJS = test.o
+TESTJOBJS = test-j.o
NDIALOGOBJS = whiptail.o dialogboxes.o
WHIPTCLOBJS = whiptcl.o dialogboxes.o
LIBNEWT = libnewt.a
LIBNEWTSONAME = libnewt.so.$(SONAME)
LIBOBJS = newt.o button.o form.o checkbox.o entry.o label.o listbox.o \
scrollbar.o textbox.o scale.o grid.o windows.o buttonbar.o \
- checkboxtree.o
+ checkboxtree.o eawidth.o
SHCFLAGS = -fPIC
#--------------------------------------
-SOURCES = $(subst .o,.c,$(TESTOBJS) $(NDIALOGOBJS) $(LIBOBJS))
+SOURCES = $(subst .o,.c,$(TESTOBJS) $(TESTJOBJS) $(NDIALOGOBJS) $(LIBOBJS))
SHAREDDIR = shared
SHAREDOBJS = $(patsubst %,$(SHAREDDIR)/%, $(LIBOBJS))
test: $(TESTOBJS) $(LIBNEWT)
gcc -g -o test $(TESTOBJS) $(LIBNEWT) $(LIBS) -static
+test-j: $(TESTJOBJS) $(LIBNEWT)
+ gcc -g -o test-j $(TESTJOBJS) $(LIBNEWT) $(LIBS) -static
+
testgrid: testgrid.o $(LIBNEWT)
gcc -g -o testgrid testgrid.o $(LIBNEWT) $(LIBS)
+testgrid-j: testgrid-j.o $(LIBNEWT)
+ gcc -g -o testgrid-j testgrid-j.o $(LIBNEWT) $(LIBS)
+
testtree: testtree.o $(LIBNEWT)
gcc -g -o testtree testtree.o $(LIBNEWT) $(LIBS)
+testtree-j: testtree-j.o $(LIBNEWT)
+ gcc -g -o testtree-j testtree-j.o $(LIBNEWT) $(LIBS)
+
_snackmodule.so: snackmodule.o $(LIBNEWTSH)
gcc --shared $(SHCFLAGS) -o _snackmodule.so snackmodule.o -L . $(LIBNEWTSH)
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct button {
char * text;
static newtComponent createButton(int left, int row, const char * text, int compact) {
newtComponent co;
struct button * bu;
+ int width = get_east_asia_str_width (NULL, text, 0);
co = malloc(sizeof(*co));
bu = malloc(sizeof(struct button));
if (bu->compact) {
co->height = 1;
- co->width = strlen(text) + 3;
+ co->width = width + 3;
} else {
co->height = 4;
- co->width = strlen(text) + 5;
+ co->width = width + 5;
}
co->top = row;
co->left = left;
co->takesFocus = 1;
co->isMapped = 0;
+ co->isLabel = 0;
newtGotorc(co->top, co->left);
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
enum type { CHECK, RADIO };
co->callback = NULL;
co->height = 1;
- co->width = strlen(text) + 4;
+ co->width = get_east_asia_str_width (NULL, text, 0) + 4;
co->top = top;
co->left = left;
co->takesFocus = 1;
+ co->isLabel = 0;
return co;
}
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct items {
char * text;
int flags, int * indexes) {
struct items * curList, * newNode, * item;
struct items ** listPtr = NULL;
- int i, index, numIndexes;
+ int i, index, numIndexes, width;
struct CheckboxTree * ct = co->data;
numIndexes = 0;
item->depth = numIndexes - 1;
i = 4 + (3 * item->depth);
+ width = get_east_asia_str_width (NULL, text, 0);
- if ((strlen(text) + i + ct->pad) > co->width) {
- co->width = strlen(text) + i + ct->pad;
+ if ((width + i + ct->pad) > co->width) {
+ co->width = width + i + ct->pad;
}
return 0;
co->height = height;
co->width = 0;
co->isMapped = 0;
+ co->isLabel = 0;
ct->itemlist = NULL;
ct->firstItem = NULL;
ct->currItem = NULL;
{
struct CheckboxTree * ct;
struct items * item;
- int i;
+ int i, width;
if (!co) return;
ct = co->data;
item->text = strdup(text);
i = 4 + (3 * item->depth);
+ width = get_east_asia_str_width (NULL, text, 0);
- if ((strlen(text) + i + ct->pad) > co->width) {
- co->width = strlen(text) + i + ct->pad;
+ if ((width + i + ct->pad) > co->width) {
+ co->width = width + i + ct->pad;
}
ctDraw(co);
#include "dialogboxes.h"
#include "newt.h"
#include "popt.h"
+#include "eawidth.h"
/* globals -- ick */
static int buttonHeight = 1;
int maxTagWidth = 0;
int maxTextWidth = 0;
int scrollFlag;
+ int w;
struct {
const char * text;
const char * tag;
} else
itemInfo[numItems].text = "";
- if (strlen(itemInfo[numItems].text) > (unsigned int)maxTextWidth)
- maxTextWidth = strlen(itemInfo[numItems].text);
- if (strlen(itemInfo[numItems].tag) > (unsigned int)maxTagWidth)
- maxTagWidth = strlen(itemInfo[numItems].tag);
+ if ((w = get_east_asia_str_width (NULL, itemInfo[numItems].text, 0)) > (unsigned int)maxTextWidth)
+ maxTextWidth = w;
+ if ((w = get_east_asia_str_width (NULL, itemInfo[numItems].tag, 0)) > (unsigned int)maxTagWidth)
+ maxTagWidth = w;
numItems++;
}
char buf[80], format[20];
int maxWidth = 0;
int top;
+ int w;
struct {
const char * text;
const char * tag;
else
cbStates[numBoxes] = ' ';
- if (strlen(cbInfo[numBoxes].tag) > (unsigned int)maxWidth)
- maxWidth = strlen(cbInfo[numBoxes].tag);
+ if ((w = get_east_asia_str_width (NULL, cbInfo[numBoxes].tag, 0)) > (unsigned int)maxWidth)
+ maxWidth = w;
numBoxes++;
}
--- /dev/null
+/* #define TEST_GET_EAST_ASIA_STR_WIDTH 1 */
+
+#include <assert.h>
+#include <locale.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eawidth.h"
+
+/*
+ * If the amount of columns the cursor advances on a TAB character depends
+ * on the current position, set this to a negative number (i.e. -8 for tab
+ * stops every eight columns. If static, set to a positive number. Zero if
+ * tabs are ignored.
+ */
+static const int tab_width = -8;
+
+typedef struct {
+ unsigned short start, end;
+ east_asia_type type;
+} eaw_db_type;
+
+static const eaw_db_type eaw_db[] = {
+ { 0x0020,0x007E,narrow },
+ { 0x00A1,0x00A1,ambiguous }, /*INVERTED EXCLAMATION MARK*/
+ { 0x00A2,0x00A3,narrow },
+ { 0x00A4,0x00A4,ambiguous }, /*CURRENCY SIGN*/
+ { 0x00A5,0x00A6,narrow },
+ { 0x00A7,0x00A8,ambiguous },
+ { 0x00AA,0x00AA,ambiguous }, /*FEMININE ORDINAL INDICATOR*/
+ { 0x00AC,0x00AC,narrow }, /*NOT SIGN*/
+ { 0x00AD,0x00AD,ambiguous }, /*SOFT HYPHEN*/
+ { 0x00AF,0x00AF,narrow }, /*MACRON*/
+ { 0x00B0,0x00B4,ambiguous },
+ { 0x00B6,0x00BA,ambiguous },
+ { 0x00BC,0x00BF,ambiguous },
+ { 0x00C6,0x00C6,ambiguous }, /*LATIN CAPITAL LETTER AE*/
+ { 0x00D0,0x00D0,ambiguous }, /*LATIN CAPITAL LETTER ETH*/
+ { 0x00D7,0x00D8,ambiguous },
+ { 0x00DE,0x00E1,ambiguous },
+ { 0x00E6,0x00E6,ambiguous }, /*LATIN SMALL LETTER AE*/
+ { 0x00E8,0x00EA,ambiguous },
+ { 0x00EC,0x00ED,ambiguous },
+ { 0x00F0,0x00F0,ambiguous }, /*LATIN SMALL LETTER ETH*/
+ { 0x00F2,0x00F3,ambiguous },
+ { 0x00F7,0x00FA,ambiguous },
+ { 0x00FC,0x00FC,ambiguous }, /*LATIN SMALL LETTER U WITH DIAERESIS*/
+ { 0x00FE,0x00FE,ambiguous }, /*LATIN SMALL LETTER THORN*/
+ { 0x0101,0x0101,ambiguous }, /*LATIN SMALL LETTER A WITH MACRON*/
+ { 0x0111,0x0111,ambiguous }, /*LATIN SMALL LETTER D WITH STROKE*/
+ { 0x0113,0x0113,ambiguous }, /*LATIN SMALL LETTER E WITH MACRON*/
+ { 0x011B,0x011B,ambiguous }, /*LATIN SMALL LETTER E WITH CARON*/
+ { 0x0126,0x0127,ambiguous },
+ { 0x012B,0x012B,ambiguous }, /*LATIN SMALL LETTER I WITH MACRON*/
+ { 0x0131,0x0133,ambiguous },
+ { 0x0138,0x0138,ambiguous }, /*LATIN SMALL LETTER KRA*/
+ { 0x013F,0x0142,ambiguous },
+ { 0x0144,0x0144,ambiguous }, /*LATIN SMALL LETTER N WITH ACUTE*/
+ { 0x0148,0x014A,ambiguous },
+ { 0x014D,0x014D,ambiguous }, /*LATIN SMALL LETTER O WITH MACRON*/
+ { 0x0152,0x0153,ambiguous },
+ { 0x0166,0x0167,ambiguous },
+ { 0x016B,0x016B,ambiguous }, /*LATIN SMALL LETTER U WITH MACRON*/
+ { 0x01CE,0x01CE,ambiguous }, /*LATIN SMALL LETTER A WITH CARON*/
+ { 0x01D0,0x01D0,ambiguous }, /*LATIN SMALL LETTER I WITH CARON*/
+ { 0x01D2,0x01D2,ambiguous }, /*LATIN SMALL LETTER O WITH CARON*/
+ { 0x01D4,0x01D4,ambiguous }, /*LATIN SMALL LETTER U WITH CARON*/
+ { 0x01D6,0x01D6,ambiguous }, /*LATIN SMALL LETTER U W/DIAERESIS+MACRON*/
+ { 0x01D8,0x01D8,ambiguous }, /*LATIN SMALL LETTER U W/DIAERESIS+ACUTE*/
+ { 0x01DA,0x01DA,ambiguous }, /*LATIN SMALL LETTER U W/DIAERESIS+CARON*/
+ { 0x01DC,0x01DC,ambiguous }, /*LATIN SMALL LETTER U W/DIAERESIS+GRAVE*/
+ { 0x0251,0x0251,ambiguous }, /*LATIN SMALL LETTER ALPHA*/
+ { 0x0261,0x0261,ambiguous }, /*LATIN SMALL LETTER SCRIPT G*/
+ { 0x02C7,0x02C7,ambiguous }, /*CARON*/
+ { 0x02C9,0x02CB,ambiguous },
+ { 0x02CD,0x02CD,ambiguous }, /*MODIFIER LETTER LOW MACRON*/
+ { 0x02D0,0x02D0,ambiguous }, /*MODIFIER LETTER TRIANGULAR COLON*/
+ { 0x02D8,0x02DB,ambiguous },
+ { 0x02DD,0x02DD,ambiguous }, /*DOUBLE ACUTE ACCENT*/
+ { 0x0300,0x0362,ambiguous },
+ { 0x0391,0x03A9,ambiguous },
+ { 0x03B1,0x03C1,ambiguous },
+ { 0x03C3,0x03C9,ambiguous },
+ { 0x0401,0x0401,ambiguous }, /*CYRILLIC CAPITAL LETTER IO*/
+ { 0x0410,0x044F,ambiguous },
+ { 0x0451,0x0451,ambiguous }, /*CYRILLIC SMALL LETTER IO*/
+ { 0x1100,0x115F,wide },
+ { 0x2010,0x2010,ambiguous }, /*HYPHEN*/
+ { 0x2013,0x2016,ambiguous },
+ { 0x2018,0x2019,ambiguous },
+ { 0x201C,0x201D,ambiguous },
+ { 0x2020,0x2021,ambiguous },
+ { 0x2025,0x2027,ambiguous },
+ { 0x2030,0x2030,ambiguous }, /*PER MILLE SIGN*/
+ { 0x2032,0x2033,ambiguous },
+ { 0x2035,0x2035,ambiguous }, /*REVERSED PRIME*/
+ { 0x203B,0x203B,ambiguous }, /*REFERENCE MARK*/
+ { 0x2074,0x2074,ambiguous }, /*SUPERSCRIPT FOUR*/
+ { 0x207F,0x207F,ambiguous }, /*SUPERSCRIPT LATIN SMALL LETTER N*/
+ { 0x2081,0x2084,ambiguous },
+ { 0x20A9,0x20A9,half_width }, /*WON SIGN*/
+ { 0x20AC,0x20AC,ambiguous }, /*EURO SIGN*/
+ { 0x2103,0x2103,ambiguous }, /*DEGREE CELSIUS*/
+ { 0x2105,0x2105,ambiguous }, /*CARE OF*/
+ { 0x2109,0x2109,ambiguous }, /*DEGREE FAHRENHEIT*/
+ { 0x2113,0x2113,ambiguous }, /*SCRIPT SMALL L*/
+ { 0x2121,0x2122,ambiguous },
+ { 0x2126,0x2126,ambiguous }, /*OHM SIGN*/
+ { 0x212B,0x212B,ambiguous }, /*ANGSTROM SIGN*/
+ { 0x2154,0x2155,ambiguous },
+ { 0x215B,0x215B,ambiguous }, /*VULGAR FRACTION ONE EIGHTH*/
+ { 0x215E,0x215E,ambiguous }, /*VULGAR FRACTION SEVEN EIGHTHS*/
+ { 0x2160,0x216B,ambiguous },
+ { 0x2170,0x2179,ambiguous },
+ { 0x2190,0x2199,ambiguous },
+ { 0x21D2,0x21D2,ambiguous }, /*RIGHTWARDS DOUBLE ARROW*/
+ { 0x21D4,0x21D4,ambiguous }, /*LEFT RIGHT DOUBLE ARROW*/
+ { 0x2200,0x2200,ambiguous }, /*FOR ALL*/
+ { 0x2202,0x2203,ambiguous },
+ { 0x2207,0x2208,ambiguous },
+ { 0x220B,0x220B,ambiguous }, /*CONTAINS AS MEMBER*/
+ { 0x220F,0x220F,ambiguous }, /*N-ARY PRODUCT*/
+ { 0x2211,0x2211,ambiguous }, /*N-ARY SUMMATION*/
+ { 0x2215,0x2215,ambiguous }, /*DIVISION SLASH*/
+ { 0x221A,0x221A,ambiguous }, /*SQUARE ROOT*/
+ { 0x221D,0x2220,ambiguous },
+ { 0x2223,0x2223,ambiguous }, /*DIVIDES*/
+ { 0x2225,0x2225,ambiguous }, /*PARALLEL TO*/
+ { 0x2227,0x222C,ambiguous },
+ { 0x222E,0x222E,ambiguous }, /*CONTOUR INTEGRAL*/
+ { 0x2234,0x2237,ambiguous },
+ { 0x223C,0x223D,ambiguous },
+ { 0x2248,0x2248,ambiguous }, /*ALMOST EQUAL TO*/
+ { 0x224C,0x224C,ambiguous }, /*ALL EQUAL TO*/
+ { 0x2252,0x2252,ambiguous }, /*APPROXIMATELY EQUAL TO OR THE IMAGE OF*/
+ { 0x2260,0x2261,ambiguous },
+ { 0x2264,0x2267,ambiguous },
+ { 0x226A,0x226B,ambiguous },
+ { 0x226E,0x226F,ambiguous },
+ { 0x2282,0x2283,ambiguous },
+ { 0x2286,0x2287,ambiguous },
+ { 0x2295,0x2295,ambiguous }, /*CIRCLED PLUS*/
+ { 0x2299,0x2299,ambiguous }, /*CIRCLED DOT OPERATOR*/
+ { 0x22A5,0x22A5,ambiguous }, /*UP TACK*/
+ { 0x22BF,0x22BF,ambiguous }, /*RIGHT TRIANGLE*/
+ { 0x2312,0x2312,ambiguous }, /*ARC*/
+ { 0x2460,0x24BF,ambiguous },
+ { 0x24D0,0x24E9,ambiguous },
+ { 0x2500,0x254B,ambiguous },
+ { 0x2550,0x2574,ambiguous },
+ { 0x2580,0x258F,ambiguous },
+ { 0x2592,0x25A1,ambiguous },
+ { 0x25A3,0x25A9,ambiguous },
+ { 0x25B2,0x25B3,ambiguous },
+ { 0x25B6,0x25B7,ambiguous },
+ { 0x25BC,0x25BD,ambiguous },
+ { 0x25C0,0x25C1,ambiguous },
+ { 0x25C6,0x25C8,ambiguous },
+ { 0x25CB,0x25CB,ambiguous }, /*WHITE CIRCLE*/
+ { 0x25CE,0x25D1,ambiguous },
+ { 0x25E2,0x25E5,ambiguous },
+ { 0x25EF,0x25EF,ambiguous }, /*LARGE CIRCLE*/
+ { 0x2605,0x2606,ambiguous },
+ { 0x2609,0x2609,ambiguous }, /*SUN*/
+ { 0x260E,0x260F,ambiguous },
+ { 0x261C,0x261C,ambiguous }, /*WHITE LEFT POINTING INDEX*/
+ { 0x261E,0x261E,ambiguous }, /*WHITE RIGHT POINTING INDEX*/
+ { 0x2640,0x2640,ambiguous }, /*FEMALE SIGN*/
+ { 0x2642,0x2642,ambiguous }, /*MALE SIGN*/
+ { 0x2660,0x2661,ambiguous },
+ { 0x2663,0x2665,ambiguous },
+ { 0x2667,0x266A,ambiguous },
+ { 0x266C,0x266D,ambiguous },
+ { 0x266F,0x266F,ambiguous }, /*MUSIC SHARP SIGN*/
+ { 0x2E80,0x3009,wide },
+ { 0x300A,0x300B,ambiguous },
+ { 0x300C,0x3019,wide },
+ { 0x301A,0x301B,ambiguous },
+ { 0x301C,0x303E,wide },
+ { 0x3041,0xD7A3,wide },
+ { 0xE000,0xF8FF,ambiguous },
+ { 0xF900,0xFA2D,wide },
+ { 0xFE30,0xFE6B,wide },
+ { 0xFF01,0xFF5E,full_width },
+ { 0xFF61,0xFFDC,half_width },
+ { 0xFFE0,0xFFE6,full_width },
+ { 0xFFE8,0xFFEE,half_width },
+};
+
+static int
+eaw_db_cmp (const void *ck, const void *ce) {
+ const eaw_db_type *key = ck, *element = ce;
+
+ assert(key != NULL);
+ assert(element != NULL);
+ if (key->start < element->start) return -1;
+ else if (key->end > element->end) return 1;
+ return 0;
+}
+
+static int
+is_cjk_locale (const char *locale_name) {
+ static const char c[] = "zh"; /* Chinese */
+ static const char j[] = "ja"; /* Japanese */
+ static const char k[] = "ko"; /* Korean */
+
+ if (NULL == locale_name) return 0;
+ if (strncmp(locale_name, c, sizeof(c)) == 0) return 1;
+ if (strncmp(locale_name, j, sizeof(j)) == 0) return 1;
+ if (strncmp(locale_name, k, sizeof(k)) == 0) return 1;
+ return 0;
+}
+
+east_asia_type
+get_east_asia_type (wchar_t unicode) {
+ assert(0xFFFF != unicode && 0xFFFE != unicode);
+
+ if (unicode > 0xFFFF) {
+
+ /*
+ * Plane 2 is intended for CJK ideographs
+ */
+ if (unicode >= 0x20000 && unicode <= 0x2FFFD) return wide;
+ return ambiguous;
+ }
+ else {
+ eaw_db_type *pos, key;
+ size_t n;
+
+ n = sizeof(eaw_db) / sizeof(eaw_db_type);
+ key.start = key.end = (unsigned short) unicode;
+ pos = bsearch(&key, eaw_db, n, sizeof(eaw_db_type), eaw_db_cmp);
+ if (NULL != pos) return pos->type;
+ }
+ return neutral;
+}
+
+int
+east_asia_mblen (const char *locale_name, const char *s, size_t n, int x)
+{
+ wchar_t *wcs, *p;
+ int width = 0;
+
+ if (NULL == s) s = "";
+
+ /*
+ * Getting the locale name via setlocale() is expensive, so we prefer
+ * to have it passed to us.
+ */
+ if (NULL == locale_name) {
+ locale_name = setlocale(LC_CTYPE, NULL);
+ if (NULL == locale_name) return INT_MAX;
+ }
+
+ wcs = (wchar_t *) calloc(n, sizeof(wchar_t));
+ if (NULL == wcs) return INT_MAX;
+
+#if defined __GLIBC__ && !__GLIBC_PREREQ(2,2)
+#warning wide character support is broken. Glibc 2.2 or better needed.
+#endif
+
+ if ((size_t) -1 == mbstowcs(wcs, s, n)) return INT_MAX;
+
+ switch (get_east_asia_type(*wcs)) {
+ case neutral:
+
+ /*
+ * Put characters that print nothing here.
+ *
+ * XXX: Yes, I know there are a lot more than this in ISO-10646, but
+ * this function is intended to calculate the width of strings for
+ * fixed width terminals displaying legacy CJK character sets.
+ * State-of-the-art Unicode handling terminals probably won't need
+ * this function anyway.
+ */
+ if (0x0000 == *wcs) break; /* NULL */
+ if (0x0007 == *wcs) break; /* BELL */
+
+ /* FIXME: there will probably be ASCII chars after the escape
+ * code, which will be counted as part of the width even though they
+ * aren't displayed.
+ */
+ if (0x001B == *wcs) break; /* ESC */
+ if (0xFEFF == *wcs) break; /* ZWNBSP aka BOM (magic, signature) */
+
+ /*
+ * Special characters go here
+ */
+ if (0x0008 == *wcs) { /* BACKSPACE */
+ width = -1;
+ break;
+ }
+ if (0x0009 == *wcs) { /* TAB */
+ if (tab_width < 0) width = x % abs(tab_width);
+ else width = tab_width;
+ break;
+ }
+
+ /*FALLTHRU*/
+ case narrow:
+ case half_width:
+ width = 1;
+ break;
+ case wide:
+ case full_width:
+ width = 2;
+ break;
+ case ambiguous:
+ width = is_cjk_locale(locale_name) ? 2 : 1;
+ break;
+ default:
+ width = INT_MAX;
+ }
+ free(wcs);
+ return width;
+}
+
+int
+get_east_asia_str_n_width (const char *locale_name, const char *s, size_t n, int x)
+{
+ int total_width = 0;
+ wchar_t *wcs, *p;
+
+ if (NULL == s) s = "";
+
+ /*
+ * Getting the locale name via setlocale() is expensive, so we prefer
+ * to have it passed to us.
+ */
+ if (NULL == locale_name) {
+ locale_name = setlocale(LC_CTYPE, NULL);
+ if (NULL == locale_name) return INT_MAX;
+ }
+
+ wcs = (wchar_t *) calloc(n, sizeof(wchar_t));
+ if (NULL == wcs) return INT_MAX;
+
+#if defined __GLIBC__ && !__GLIBC_PREREQ(2,2)
+#warning wide character support is broken. Glibc 2.2 or better needed.
+#endif
+
+ if ((size_t) -1 == mbstowcs(wcs, s, n)) return INT_MAX;
+
+ for (p = wcs; L'\0' != *p; p++) {
+ int width = 0;
+
+ switch (get_east_asia_type(*p)) {
+ case neutral:
+
+ /*
+ * Put characters that print nothing here.
+ *
+ * XXX: Yes, I know there are a lot more than this in ISO-10646, but
+ * this function is intended to calculate the width of strings for
+ * fixed width terminals displaying legacy CJK character sets.
+ * State-of-the-art Unicode handling terminals probably won't need
+ * this function anyway.
+ */
+ if (0x0000 == *p) break; /* NULL */
+ if (0x0007 == *p) break; /* BELL */
+
+ /* FIXME: there will probably be ASCII chars after the escape
+ * code, which will be counted as part of the width even though they
+ * aren't displayed.
+ */
+ if (0x001B == *p) break; /* ESC */
+ if (0xFEFF == *p) break; /* ZWNBSP aka BOM (magic, signature) */
+
+ /*
+ * Special characters go here
+ */
+ if (0x0008 == *p) { /* BACKSPACE */
+ width = -1;
+ break;
+ }
+ if (0x0009 == *p) { /* TAB */
+ if (tab_width < 0) width = x % abs(tab_width);
+ else width = tab_width;
+ break;
+ }
+
+ /*FALLTHRU*/
+ case narrow:
+ case half_width:
+ width = 1;
+ break;
+ case wide:
+ case full_width:
+ width = 2;
+ break;
+ case ambiguous:
+ width = is_cjk_locale(locale_name) ? 2 : 1;
+ break;
+ default: abort(); /* Doh! */
+ }
+ x += width;
+ total_width += width;
+ }
+ free(wcs);
+ return total_width;
+}
+
+int
+get_east_asia_str_width (const char *locale_name, const char *s, int x) {
+ size_t n;
+
+ n = strlen(s) + 1;
+ return get_east_asia_str_n_width (locale_name, s, n, x);
+}
+
+#if TEST_GET_EAST_ASIA_STR_WIDTH
+
+#include <stdio.h>
+
+int
+main (int argc, char *argv[]) {
+ int i;
+ char *lc;
+ const char *fmt = "word #%d ('%s') length is %zu, width is %u\n";
+
+ lc = setlocale(LC_CTYPE, "");
+ if (NULL == lc) {
+ fputs("couldn't set the default locale for LC_CTYPE\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ if (printf("character type locale is '%s'\n", lc) < 0) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 1; argc < 2 || i < argc; i++) {
+ char *s;
+ size_t length;
+ unsigned width;
+
+ if (argc < 2) {
+ if (scanf("%as", &s) < 1 && ferror(stdin)) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ else if (feof(stdin)) break;
+ }
+ else s = strdup(argv[(size_t) i]);
+ if (NULL == s) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ length = strlen(s);
+ width = get_east_asia_str_width(lc, s, 0);
+ if (printf(fmt, i, s, length, width) < 0) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ free(s);
+ }
+ return 0;
+}
+
+#endif
--- /dev/null
+#include <stddef.h>
+
+typedef enum {
+ ambiguous, neutral, narrow, half_width, wide, full_width
+} east_asia_type;
+
+/**
+ * get_east_asia_type returns the character classification of a given
+ * Unicode character according to Unicode Technical
+ * Report 11.
+ *
+ * @param unicode the Unicode/ISO-10646 character to get the type of
+ * @return the classification of the character, according to
+ * UAX#11 data.
+ */
+east_asia_type get_east_asia_type(wchar_t unicode);
+
+/**
+ * get_east_asia_width measures the amount of space a multibyte string
+ * takes an a traditional fixed width terminal such
+ * as xterm in character cells.
+ *
+ * @param locale_name used to determine the if character width should
+ * be interpreted as CJK or Asian in the case of
+ * Greek and Cyrillic characters. If NULL, it will
+ * use setlocale() to determine the LC_CTYPE setting.
+ * @param s the multibyte string to measure the width of.
+ * @param x the current cursor position, used to handle the
+ * calculation of tab widths. 0 is the first column.
+ * @return the number of fixed width character cells the string
+ * takes up. If the string is an illegal multibyte
+ * string, or a memory error or other occurs, INT_MAX
+ * is returned and errno is set.
+ */
+int get_east_asia_str_width(const char *locale_name, const char *s, int x);
+int get_east_asia_str_n_width (const char *locale_name, const char *s, size_t n, int x);
+int east_asia_mblen (const char *locale_name, const char *s, size_t n, int x);
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct entry {
int flags;
char ** resultPtr, int flags) {
newtComponent co;
struct entry * en;
+ int w;
co = malloc(sizeof(*co));
en = malloc(sizeof(struct entry));
co->width = width;
co->isMapped = 0;
co->callback = NULL;
+ co->isLabel = 0;
co->ops = &entryOps;
else
co->takesFocus = 0;
- if (initialValue && strlen(initialValue) > (unsigned int)width) {
- en->bufAlloced = strlen(initialValue) + 1;
+ if (initialValue && (w = get_east_asia_str_width (NULL, initialValue, 0)) > (unsigned int)width) {
+ en->bufAlloced = w + 1;
}
en->buf = malloc(en->bufAlloced);
en->resultPtr = resultPtr;
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
+#include <string.h>
#ifdef USE_GPM
#include <ctype.h>
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
+
+struct label {
+ char *text;
+ int length;
+};
#ifdef USE_GPM
/*....................................... The connection data structure */
co->top = -1;
co->left = -1;
co->isMapped = 0;
+ co->isLabel = 0;
co->takesFocus = 0; /* we may have 0 components */
co->ops = &formOps;
void newtFormAddComponent(newtComponent co, newtComponent newco) {
struct form * form = co->data;
+ int i, j, k, l, xmap, ymap, x, y;
+ char *map, *s = NULL;
co->takesFocus = 1;
form->currComp = form->numComps;
form->numComps++;
+
+ /* check multibyte char broken */
+ /* create text map */
+ xmap = 0;
+ ymap = 0;
+ for ( i = 0; i < form->numComps; i++ ) {
+ if ((form->elements[i].co->top + form->elements[i].co->height) > ymap )
+ ymap = form->elements[i].co->top + form->elements[i].co->height;
+ if ((form->elements[i].co->left + form->elements[i].co->width) > xmap )
+ xmap = form->elements[i].co->left + form->elements[i].co->width;
+ }
+ map = (char *)calloc ((xmap+1) * (ymap+1), sizeof (char));
+
+#define MAP(x,y) *(map + ((x)*ymap + (y)))
+
+ /* create non-label components map */
+ for ( i = 0; i < form->numComps; i++ ) {
+ if ( form->elements[i].co->isLabel == 0 && form->elements[i].co->left >= 0 && form->elements[i].co->top >= 0 ) {
+ for ( x = 0; x < form->elements[i].co->width; x++ ) {
+ for ( y = 0; y < form->elements[i].co->height; y++ )
+ MAP (form->elements[i].co->left+x, form->elements[i].co->top+y) = 1;
+ }
+ }
+ }
+
+ /* check label overlap */
+ for ( i = 0; i < form->numComps; i++ ) {
+ if ( form->elements[i].co->isLabel != 0 ) {
+ y = form->elements[i].co->top;
+ l = form->elements[i].co->left;
+ if ( y >= 0 && l >= 0 ) {
+ for ( j = 0; j < form->elements[i].co->width; j++ ) {
+ if ( MAP (j+l, y) != 0 ) {
+ if ( MAP (j+l, y) != 1 ) {
+ /* if label is here, move label */
+ while ( MAP (form->elements[i].co->left, y) != 0 )
+ form->elements[i].co->left++;
+ } else {
+ /* if label is overlapping, cut label */
+ if ((j+l) == form->elements[i].co->left ) {
+ free (((struct label *)form->elements[i].co->data)->text);
+ ((struct label *)form->elements[i].co->data)->text = malloc (1);
+ ((struct label *)form->elements[i].co->data)->text[0] = 0;
+ ((struct label *)form->elements[i].co->data)->length = 0;
+ form->elements[i].co->width = 0;
+ } else {
+ x = 0;
+ while (x < j) {
+ s = &((struct label *)form->elements[i].co->data)->text[x];
+ k = east_asia_mblen (NULL, s, strlen (s), 0);
+ if ( k <= 0 ) break;
+ else {
+ if ((x+k) < j ) x += k;
+ else break;
+ }
+ }
+ s = ((struct label *)form->elements[i].co->data)->text;
+ ((struct label *)form->elements[i].co->data)->text = realloc(s, x+1);
+ ((struct label *)form->elements[i].co->data)->text[x] = 0;
+ ((struct label *)form->elements[i].co->data)->length = strlen (s);
+ form->elements[i].co->width = get_east_asia_str_width (NULL, s, 0);
+ }
+ }
+ } else
+ MAP (j+l, y) = 2;
+ }
+ }
+ }
+ }
+ free (map);
}
void newtFormAddComponents(newtComponent co, ...) {
free(form->elements);
free(form);
free(co);
+ newtResizeScreen(1);
}
newtComponent newtRunForm(newtComponent co) {
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct gridField {
enum newtGridElement type;
}
void newtGridWrappedWindow(newtGrid grid, char * title) {
- int width, height, offset = 0;
+ int width, height, offset = 0, w;
newtGridGetSize(grid, &width, &height);
- if (width < strlen(title) + 2) {
- offset = ((strlen(title) + 2) - width) / 2;
- width = strlen(title) + 2;
+ w = get_east_asia_str_width (NULL, title, 0);
+ if (width < (w + 2)) {
+ offset = ((w + 2) - width) / 2;
+ width = w + 2;
}
newtCenteredWindow(width + 2, height + 2, title);
newtGridPlace(grid, 1 + offset, 1);
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct label {
char * text;
co->ops = &labelOps;
co->height = 1;
- co->width = strlen(text);
+ co->width = get_east_asia_str_width (NULL, text, 0);
co->top = top;
co->left = left;
co->takesFocus = 0;
+ co->isLabel = 1;
la->length = strlen(text);
la->text = strdup(text);
int newLength;
struct label * la = co->data;
- newLength = strlen(text);
+ newLength = get_east_asia_str_width (NULL, text, 0);
if (newLength <= la->length) {
memset(la->text, ' ', la->length);
memcpy(la->text, text, newLength);
#include "newt.h"
#include "newt_pr.h"
-
+#include "eawidth.h"
/* Linked list of items in the listbox */
struct items {
co->ops = &listboxOps;
co->takesFocus = 1;
co->callback = NULL;
+ co->isLabel = 0;
updateWidth(co, li, 5);
void newtListboxSetEntry(newtComponent co, int num, const char * text) {
struct listbox * li = co->data;
- int i;
+ int i, w;
struct items *item;
for(i = 0, item = li->boxItems; item != NULL && i < num;
free(item->text);
item->text = strdup(text);
}
- if (li->userHasSetWidth == 0 && strlen(text) > li->curWidth) {
- updateWidth(co, li, strlen(text));
+ w = get_east_asia_str_width (NULL, text, 0);
+ if (li->userHasSetWidth == 0 && w > li->curWidth) {
+ updateWidth(co, li, w);
}
if (num >= li->startShowItem && num <= li->startShowItem + co->height)
const void * data) {
struct listbox * li = co->data;
struct items *item;
+ int w;
if(li->boxItems) {
for (item = li->boxItems; item->next != NULL; item = item->next);
item = li->boxItems = malloc(sizeof(struct items));
}
- if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth))
- updateWidth(co, li, strlen(text));
+ w = get_east_asia_str_width (NULL, text, 0);
+ if (!li->userHasSetWidth && text && (w > li->curWidth))
+ updateWidth(co, li, w);
item->text = strdup(text); item->data = data; item->next = NULL;
item->isSelected = 0;
const void * data, void * key) {
struct listbox * li = co->data;
struct items *item, *t;
+ int w;
if (li->boxItems) {
if (key) {
item->next = NULL;
}
- if (!li->userHasSetWidth && text && (strlen(text) > li->curWidth))
- updateWidth(co, li, strlen(text));
+ w = get_east_asia_str_width (NULL, text, 0);
+ if (!li->userHasSetWidth && text && (w > li->curWidth))
+ updateWidth(co, li, w);
item->text = strdup(text?text:"(null)"); item->data = data;
item->isSelected = 0;
if (!li->userHasSetWidth) {
widest = 0;
for (item = li->boxItems; item != NULL; item = item->next)
- if ((t = strlen(item->text)) > widest) widest = t;
+ if ((t = get_east_asia_str_width (NULL, item->text, 0)) > widest) widest = t;
}
if (li->currItem >= num)
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
+#include <locale.h>
#include "newt.h"
#include "newt_pr.h"
int newtInit(void) {
char * MonoValue, * MonoEnv = "NEWT_MONO";
+ /* initialize locale */
+ setlocale (LC_ALL, "");
+
/* use the version variable just to be sure it gets included */
strlen(version);
int top, left;
int takesFocus;
int isMapped;
+ int isLabel;
struct componentOps * ops;
co->top = top;
co->left = left;
co->takesFocus = 0;
+ co->isLabel = 0;
sc->fullValue = fullValue;
sc->charsSet = 0;
co->height = height;
co->width = 1;
co->takesFocus = 0;
+ co->isLabel = 0;
return co;
}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "newt.h"
+
+struct callbackInfo {
+ newtComponent en;
+ char * state;
+};
+
+void disableCallback(newtComponent co, void * data) {
+ struct callbackInfo * cbi = data;
+
+ if (*cbi->state == ' ') {
+ newtEntrySetFlags(cbi->en, NEWT_FLAG_DISABLED, NEWT_FLAGS_RESET);
+ } else {
+ newtEntrySetFlags(cbi->en, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
+ }
+
+ newtRefresh();
+}
+
+void suspend(void * d) {
+ newtSuspend();
+ raise(SIGTSTP);
+ newtResume();
+}
+
+int main(void) {
+ newtComponent b1, b2, r1, r2, r3, e2, e3, l1, l2, l3, scale;
+ newtComponent lb, t, rsf, answer;
+ newtComponent cs[10];
+ newtComponent f, chklist, e1;
+ struct callbackInfo cbis[3];
+ char results[10];
+ char * enr2, * enr3, * scaleVal;
+ void ** selectedList;
+ int i, numsel;
+ char buf[20];
+
+ newtInit();
+ newtCls();
+
+ newtSetSuspendCallback(suspend, NULL);
+
+ newtDrawRootText(0, 0, "Newt ¥Æ¥¹¥È¥×¥í¥°¥é¥à");
+ newtPushHelpLine(NULL);
+ newtDrawRootText(-50, 0, "¥ë¡¼¥È¥Æ¥¥¹¥È");
+
+ newtOpenWindow(2, 2, 30, 10, "£±ÈÖÌܤΥ¦¥£¥ó¥É¥¦");
+ newtOpenWindow(10, 5, 65, 16, "¥¦¥£¥ó¥É¥¦£²");
+
+ f = newtForm(NULL, NULL, 0);
+ chklist = newtForm(NULL, NULL, 0);
+
+ b1 = newtButton(3, 1, "½ªÎ»");
+ b2 = newtButton(18, 1, "¹¹¿·");
+ r1 = newtRadiobutton(20, 10, "ÁªÂò»è£±", 0, NULL);
+ r2 = newtRadiobutton(20, 11, "ÁªÂò»è£²", 1, r1);
+ r3 = newtRadiobutton(20, 12, "ÁªÂò»è£³", 0, r2);
+ rsf = newtForm(NULL, NULL, 0);
+ newtFormAddComponents(rsf, r1, r2, r3, NULL);
+ newtFormSetBackground(rsf, NEWT_COLORSET_CHECKBOX);
+
+ for (i = 0; i < 10; i++) {
+ sprintf(buf, "¥Á¥§¥Ã¥¯ %d", i);
+ cs[i] = newtCheckbox(3, 10 + i, buf, ' ', NULL, &results[i]);
+ newtFormAddComponent(chklist, cs[i]);
+ }
+
+ l1 = newtLabel(3, 6, "¥¹¥±¡¼¥ë:");
+ l2 = newtLabel(3, 7, "¥¹¥¯¥í¡¼¥ë:");
+ l3 = newtLabel(3, 8, "¥Ò¥É¥¥¥ó:");
+ e1 = newtEntry(12, 6, "", 20, &scaleVal, 0);
+ e2 = newtEntry(12, 7, "ɸ½à", 20, &enr2, NEWT_FLAG_SCROLL);
+ e3 = newtEntry(12, 8, NULL, 20, &enr3, NEWT_FLAG_HIDDEN);
+
+ cbis[0].state = &results[0];
+ cbis[0].en = e1;
+ newtComponentAddCallback(cs[0], disableCallback, &cbis[0]);
+
+ scale = newtScale(3, 14, 32, 100);
+
+ newtFormSetHeight(chklist, 3);
+
+ newtFormAddComponents(f, b1, b2, l1, l2, l3, e1, e2, e3, chklist, NULL);
+ newtFormAddComponents(f, rsf, scale, NULL);
+
+ lb = newtListbox(45, 1, 6, NEWT_FLAG_MULTIPLE | NEWT_FLAG_BORDER |
+ NEWT_FLAG_SCROLL);
+ newtListboxAppendEntry(lb, "£±ÈÖÌÜ", (void *) 1);
+ newtListboxAppendEntry(lb, "£²ÈÖÌÜ", (void *) 2);
+ newtListboxAppendEntry(lb, "£³ÈÖÌÜ", (void *) 3);
+ newtListboxAppendEntry(lb, "£´ÈÖÌÜ", (void *) 4);
+ newtListboxAppendEntry(lb, "£¶ÈÖÌÜ", (void *) 6);
+ newtListboxAppendEntry(lb, "£·ÈÖÌÜ", (void *) 7);
+ newtListboxAppendEntry(lb, "£¸ÈÖÌÜ", (void *) 8);
+ newtListboxAppendEntry(lb, "£¹ÈÖÌÜ", (void *) 9);
+ newtListboxAppendEntry(lb, "£±£°ÈÖÌÜ", (void *) 10);
+
+ newtListboxInsertEntry(lb, "£µÈÖÌÜ", (void *) 5, (void *) 4);
+ newtListboxInsertEntry(lb, "£±£±ÈÖÌÜ", (void *) 11, (void *) 10);
+ newtListboxDeleteEntry(lb, (void *) 11);
+
+ t = newtTextbox(45, 10, 17, 5, NEWT_FLAG_WRAP);
+ newtTextboxSetText(t, "¤³¤ì¤Ï¥Æ¥¥¹¥È¤Î¥µ¥ó¥×¥ë¤Ç¤¹¡£\nÀµ¾ï¤Ëɽ¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¤«¡©\n¤³¤ì¤ÏñÆÈ¹Ô¤Ç¤¹¡£\n¤³¤ì¤Ïɽ¼¨¤µ¤ì¤Æ¤Ï¤¤¤±¤Þ¤»¤ó");
+
+ newtFormAddComponents(f, lb, t, NULL);
+ newtRefresh();
+
+ do {
+ answer = newtRunForm(f);
+
+ if (answer == b2) {
+ newtScaleSet(scale, atoi(scaleVal));
+ newtRefresh();
+ answer = NULL;
+ }
+ } while (!answer);
+
+ scaleVal = strdup(scaleVal);
+ enr2 = strdup(enr2);
+ enr3 = strdup(enr3);
+
+ selectedList = newtListboxGetSelection(lb, &numsel);
+
+ newtFormDestroy(f);
+
+ newtPopWindow();
+ newtPopWindow();
+ newtFinished();
+
+ printf("got string 1: %s\n", scaleVal);
+ printf("got string 2: %s\n", enr2);
+ printf("got string 3: %s\n", enr3);
+
+ if(selectedList) {
+ printf("\nSelected listbox items:\n");
+ for(i = 0; i < numsel; i++)
+ puts(selectedList[i]);
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "newt.h"
+
+int main(void) {
+ newtComponent b1, b2, b3, b4;
+ newtComponent answer, f, t;
+ newtGrid grid, subgrid;
+ char * flowedText;
+ int textWidth, textHeight, rc;
+ char * menuContents[] = { "°ì", "Æó", "»°", "»Í", "¸Þ", NULL };
+ char * entries[10];
+ struct newtWinEntry autoEntries[] = {
+ { "¥¨¥ó¥È¥ê", entries + 0, 0 },
+ { "Ê̤Υ¨¥ó¥È¥ê", entries + 1, 0 },
+ { "»°ÈÖÌܤΥ¨¥ó¥È¥ê", entries + 2, 0 },
+ { "»ÍÈÖÌܤΥ¨¥ó¥È¥ê", entries + 3, 0 },
+ { NULL, NULL, 0 } };
+
+ memset(entries, 0, sizeof(entries));
+
+ newtInit();
+ newtCls();
+
+ b1 = newtCheckbox(-1, -1, "¥Æ¥¹¥È¤Î¤¿¤á¤Î¤«¤Ê¤êŤ¤¥Á¥§¥Ã¥¯¥Ü¥Ã¥¯¥¹", ' ', NULL, NULL);
+ b2 = newtButton(-1, -1, "Ê̤Υܥ¿¥ó");
+ b3 = newtButton(-1, -1, "¤·¤«¤·¡¢¤·¤«¤·");
+ b4 = newtButton(-1, -1, "¤·¤«¤·²¿¤À¤í¤¦¡©");
+
+ f = newtForm(NULL, NULL, 0);
+
+ grid = newtCreateGrid(2, 2);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, b1, 0, 0, 0, 0,
+ NEWT_ANCHOR_RIGHT, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0);
+ newtGridSetField(grid, 1, 0, NEWT_GRID_COMPONENT, b3, 0, 0, 0, 0, 0, 0);
+ newtGridSetField(grid, 1, 1, NEWT_GRID_COMPONENT, b4, 0, 0, 0, 0, 0, 0);
+
+
+ newtFormAddComponents(f, b1, b2, b3, b4, NULL);
+
+ newtGridWrappedWindow(grid, "°ìÈÖÌܤΥ¦¥£¥ó¥É¥¦");
+ newtGridFree(grid, 1);
+
+ answer = newtRunForm(f);
+
+ newtFormDestroy(f);
+ newtPopWindow();
+
+ flowedText = newtReflowText("¤³¤ì¤Ï¤«¤Ê¤ê¥Æ¥¥¹¥È¤é¤·¤¤¤â¤Î¤Ç¤¹¡£40¥«¥é¥à"
+ "¤ÎŤµ¤Ç¡¢¥é¥Ã¥Ô¥ó¥°¤¬¹Ô¤ï¤ì¤Þ¤¹¡£"
+ "ÁÇÁᤤ¡¢Ãã¿§¤Î¸Ñ¤¬¤Î¤í¤Þ¤Ê¸¤¤òÈô¤Ó"
+ "±Û¤¨¤¿¤Î¤òÃΤäƤ뤫¤¤?\n\n"
+ "¾¤Ë¤ªÃΤ餻¤¹¤ë¤³¤È¤È¤·¤Æ¡¢Å¬Åö¤Ë²þ¹Ô¤ò¤¹¤ë"
+ "¤³¤È¤¬½ÅÍפǤ¹¡£",
+ 40, 5, 5, &textWidth, &textHeight);
+ t = newtTextbox(-1, -1, textWidth, textHeight, NEWT_FLAG_WRAP);
+ newtTextboxSetText(t, flowedText);
+ free(flowedText);
+
+
+ b1 = newtButton(-1, -1, "λ²ò");
+ b2 = newtButton(-1, -1, "¥¥ã¥ó¥»¥ë");
+
+ grid = newtCreateGrid(1, 2);
+ subgrid = newtCreateGrid(2, 1);
+
+ newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, b1, 0, 0, 0, 0, 0, 0);
+ newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0);
+
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, t, 0, 0, 0, 1, 0, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, subgrid, 0, 0, 0, 0, 0,
+ NEWT_GRID_FLAG_GROWX);
+ newtGridWrappedWindow(grid, "Ê̤ÎÎã");
+ newtGridDestroy(grid, 1);
+
+ f = newtForm(NULL, NULL, 0);
+ newtFormAddComponents(f, b1, t, b2, NULL);
+ answer = newtRunForm(f);
+
+ newtPopWindow();
+ newtFormDestroy(f);
+
+ newtWinMessage("¥·¥ó¥×¥ë", "λ²ò", "¤³¤ì¤Ï¥·¥ó¥×¥ë¤Ê¥á¥Ã¥»¡¼¥¸¥¦¥£¥ó¥É¥¦¤Ç¤¹");
+ newtWinChoice("¥·¥ó¥×¥ë", "λ²ò", "¥¥ã¥ó¥»¥ë", "¤³¤ì¤Ï¥·¥ó¥×¥ë¤ÊÁªÂò¥¦¥£¥ó¥É¥¦¤Ç¤¹");
+
+ textWidth = 0;
+ rc = newtWinMenu("¥Æ¥¹¥È¥á¥Ë¥å¡¼", "¤³¤ì¤Ï newtWinMenu() ¥³¡¼¥ë¤Î¥µ¥ó¥×¥ë"
+ "¤Ç¤¹¡£ ¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ÏɬÍפ˱þ¤¸¤Æ¤Ä¤¤¤¿¤ê¡¢ "
+ "¤Ä¤«¤Ê¤«¤Ã¤¿¤ê¤·¤Þ¤¹¡£", 50, 5, 5, 3,
+ menuContents, &textWidth, "λ²ò", "¥¥ã¥ó¥»¥ë", NULL);
+
+ rc = newtWinEntries("¥Æ¥¥¹¥È newtWinEntries()", "¤³¤ì¤Ï newtWinEntries()"
+ "¥³¡¼¥ë¤Î¥µ¥ó¥×¥ë¤Ç¤¹¡£¤¿¤¤¤Ø¤ó´Êñ¤Ë¤¿¤¯¤µ¤ó¤ÎÆþÎϤò"
+ "°·¤¦¤³¤È¤¬¤Ç¤¤Þ¤¹¡£", 50, 5, 5, 20, autoEntries, "λ²ò",
+ "¥¥ã¥ó¥»¥ë", NULL);
+
+ newtFinished();
+
+ printf("rc = 0x%x item = %d\n", rc, textWidth);
+
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "newt.h"
+
+int main(void) {
+ newtGrid grid;
+ newtComponent checktree;
+ newtComponent button;
+ newtComponent form;
+ newtComponent answer;
+ void ** result, **ptr;
+ int numselected, i, j;
+ int * list;
+
+ newtInit();
+ newtCls();
+
+ checktree = newtCheckboxTreeMulti(-1, -1, 10, " ab", NEWT_FLAG_SCROLL);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼", (void *) 2, 0,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "ËÜÅö¤ËËÜÅö¤ËŤ¤¥â¥Î",
+ (void *) 3, 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£µ", (void *) 5,
+ NEWT_FLAG_SELECTED,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£¶", (void *) 6, 0,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£·", (void *) 7,
+ NEWT_FLAG_SELECTED,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£¸", (void *) 8, 0,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£¹", (void *) 9, 0,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£±£°", (void *) 10,
+ NEWT_FLAG_SELECTED,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£±£±", (void *) 11, 0,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£±£²", (void *) 12,
+ NEWT_FLAG_SELECTED,
+ NEWT_ARG_APPEND, NEWT_ARG_LAST);
+
+ newtCheckboxTreeAddItem(checktree, "¥«¥é¡¼", (void *) 1, 0,
+ 0, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "ÀÖ¿§", (void *) 100, 0,
+ 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "Çò¿§", (void *) 101, 0,
+ 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "ÀÄ¿§", (void *) 102, 0,
+ 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+
+ newtCheckboxTreeAddItem(checktree, "¥Ê¥ó¥Ð¡¼£´", (void *) 4, 0,
+ 3, NEWT_ARG_LAST);
+
+ newtCheckboxTreeAddItem(checktree, "°ì·å¤Î¿ô»ú", (void *) 200, 0,
+ 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "°ì", (void *) 201, 0,
+ 1, 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "Æó", (void *) 202, 0,
+ 1, 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "»°", (void *) 203, 0,
+ 1, 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "»Í", (void *) 204, 0,
+ 1, 0, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+
+ newtCheckboxTreeAddItem(checktree, "Æó·å¤Î¿ô»ú", (void *) 300, 0,
+ 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "½½", (void *) 210, 0,
+ 1, 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "½½°ì", (void *) 211, 0,
+ 1, 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "½½Æó", (void *) 212, 0,
+ 1, 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+ newtCheckboxTreeAddItem(checktree, "½½»°", (void *) 213, 0,
+ 1, 1, NEWT_ARG_APPEND, NEWT_ARG_LAST);
+
+ button = newtButton(-1, -1, "½ªÎ»");
+
+ grid = newtCreateGrid(1, 2);
+ newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, checktree, 0, 0, 0, 1,
+ NEWT_ANCHOR_RIGHT, 0);
+ newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, button, 0, 0, 0, 0,
+ 0, 0);
+
+ newtGridWrappedWindow(grid, "¥Á¥§¥Ã¥¯¥Ü¥Ã¥¯¥¹¥Ä¥ê¡¼¥Æ¥¹¥È");
+ newtGridFree(grid, 1);
+
+ form = newtForm(NULL, NULL, 0);
+ newtFormAddComponents(form, checktree, button, NULL);
+
+ answer = newtRunForm(form);
+
+ newtFinished();
+
+ result = newtCheckboxTreeGetSelection(checktree, &numselected);
+ ptr = result;
+ if (!result || !numselected)
+ printf("none selected\n");
+ else
+ printf("Current selection (all) (%d):\n", numselected);
+ for (i = 0; i < numselected; i++) {
+ j = (int) *ptr++;
+ printf("%d\n", j);
+ }
+ result = newtCheckboxTreeGetMultiSelection(checktree, &numselected, 'b');
+ ptr = result;
+ if (!result || !numselected)
+ printf("none selected\n");
+ else
+ printf("Current selection (b) (%d):\n",numselected);
+ for (i = 0; i < numselected; i++) {
+ j = (int) *ptr++;
+ printf("%d\n", j);
+ }
+
+ if (result)
+ free(result);
+
+ list = newtCheckboxTreeFindItem(checktree, (void *) 213);
+ printf("path:");
+ for (i = 0; list && list[i] != NEWT_ARG_LAST; i++)
+ printf(" %d", list[i]);
+ printf("\n");
+
+ newtFormDestroy(form);
+
+ return 0;
+}
#include <ctype.h>
#include <slang.h>
+#include <slkanji.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "newt.h"
#include "newt_pr.h"
+#include "eawidth.h"
struct textbox {
char ** lines;
co->left = left;
co->takesFocus = 0;
co->width = width;
+ co->isLabel = 0;
tb->doWrap = flags & NEWT_FLAG_WRAP;
tb->numLines = 0;
int howbad = 0;
int height = 0;
int kanji = 0;
+ int w, w2;
+ w = get_east_asia_str_width (NULL, text, 0);
if (resultPtr) {
- /* XXX I think this will work */
- result = malloc(strlen(text) + (strlen(text) / width) + 2);
- *result = '\0';
+ /* XXX I think this will work */
+ result = malloc(w * 2 + 2);
+ *result = '\0';
}
while (*text) {
kanji = 0;
- end = strchr(text, '\n');
- if (!end)
- end = text + strlen(text);
-
- while (*text && text <= end) {
- if (end - text < width) {
- if (result) {
- strncat(result, text, end - text);
- strcat(result, "\n");
- height++;
+ end = strchr(text, '\n');
+ if (!end)
+ end = text + strlen(text);
+
+ while (*text && text <= end) {
+ char *ptr;
+
+ ptr = (char *)malloc (sizeof (char)*((end-text)+1));
+ strncpy (ptr, text, end - text);
+ *(ptr + (end-text)) = 0;
+ w2 = get_east_asia_str_width (NULL, ptr, 0);
+ free (ptr);
+ if (w2 < width) {
+ if (result) {
+ strncat(result, text, end - text);
+ strcat(result, "\n");
+ }
+ height++;
+
+ if (w2 < (width / 2))
+ howbad += ((width / 2) - w2) / 2;
+ text = end;
+ if (*text) text++;
+ } else {
+ int is_space = 0, into_kanji = 0;
+ char *spcptr = NULL;
+
+ chptr = text;
+ i = 0;
+ while ( i < (width - 1)) {
+ kanji = east_asia_mblen (NULL, chptr, end - chptr, 0);
+ if ( kanji == INT_MAX || kanji <= 0 ) kanji = 1;
+ else {
+ if ( kanji == 1 ) {
+ if ( is_space == 0 ) {
+ if (isspace(*chptr)) {
+ is_space = 1;
+ }
+ else if ( into_kanji == 1 ) {
+ if (!spcptr) spcptr = chptr;
+ is_space = 1;
+ }
+ } else {
+ if (!spcptr) spcptr = chptr;
+ else if (isspace(*chptr)) {
+ spcptr = NULL;
+ is_space = 1;
+ }
+ }
+ } else {
+ into_kanji = 1;
+ is_space = 0;
+ spcptr = NULL;
+ }
+ if ((i+kanji) < (width - 1)) i += kanji;
+ else break;
+ }
+ chptr = chptr + kanji;
+ }
+ if ( is_space != 0 && spcptr-text > 1 ) chptr = spcptr;
+ howbad += width - (chptr - text) + 1;
+ if ( result ) {
+ strncat (result, text, chptr - text);
+ strcat (result, "\n");
+ }
+ height++;
+ text = chptr;
+ while (east_asia_mblen (NULL, text, end - text, 0) == 1 && isspace(*text)) text++;
+ }
}
-
- if (end - text < (width / 2))
- howbad += ((width / 2) - (end - text)) / 2;
- text = end;
- if (*text) text++;
- } else {
- chptr = text;
- kanji = 0;
- for ( i = 0; i < width - 1; i++ ) {
- if ( !iseuckanji(*chptr)) {
- kanji = 0;
- } else if ( kanji == 1 ) {
- kanji = 2;
- } else {
- kanji = 1;
- }
- chptr++;
- }
- if (kanji == 0) {
- while (chptr > text && !isspace(*chptr)) chptr--;
- while (chptr > text && isspace(*chptr)) chptr--;
- chptr++;
- }
-
- if (chptr-text == 1 && !isspace(*chptr))
- chptr = text + width - 1;
-
- if (chptr > text)
- howbad += width - (chptr - text) + 1;
- if (result) {
- if (kanji == 1) {
- strncat(result, text, chptr - text + 1 );
- chptr++;
- kanji = 0;
- } else {
- strncat(result, text, chptr - text );
- }
- strcat(result, "\n");
- height++;
- }
-
- if (isspace(*chptr))
- text = chptr + 1;
- else
- text = chptr;
- while (isspace(*text)) text++;
- }
}
- }
-
if (badness) *badness = howbad;
if (resultPtr) *resultPtr = result;
if (heightPtr) *heightPtr = height;
newtFormDestroy(f);
newtPopWindow();
+ newtResizeScreen(1);
if (answer == f)
return NULL;
va_start(args, message);
rc = newtvwindow(title, button1, button2, NULL, message, args);
+ newtResizeScreen(1);
va_end(args);
if (rc == button1)
void newtWinMessagev(char * title, char * buttonText, char * text,
va_list argv) {
newtvwindow(title, buttonText, NULL, NULL, text, argv);
+ newtResizeScreen(1);
}
int newtWinTernary(char * title, char * button1, char * button2,
va_start(args, message);
rc = newtvwindow(title, button1, button2, button3, message, args);
+ newtResizeScreen(1);
va_end(args);
if (rc == button1)
buttonName = va_arg(args, char *);
}
+ newtResizeScreen(1);
va_end(button1);
buttonBar = newtCreateGrid(numButtons, 1);
newtFormDestroy(form);
newtPopWindow();
+ newtResizeScreen(1);
+
return rc;
}
newtFormDestroy(form);
newtPopWindow();
+ newtResizeScreen(1);
return rc;
}