usr/src/cmd/localedef/ctype.c
changeset 14265 8ae0bbd9e7cc
parent 13908 90142813f484
--- a/usr/src/cmd/localedef/ctype.c	Tue Aug 27 13:00:09 2013 -0700
+++ b/usr/src/cmd/localedef/ctype.c	Tue Aug 27 18:16:23 2013 -0700
@@ -11,7 +11,8 @@
 
 /*
  * Copyright 2010,2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright 2012 Garrett D'Amore <[email protected]>  All rights reserved.
+ * Copyright 2012 Garrett D'Amore <[email protected]>
+ * Copyright 2013 DEY Storage Systems, Inc.
  */
 
 /*
@@ -27,6 +28,7 @@
 #include <ctype.h>
 #include <wctype.h>
 #include <unistd.h>
+#include "_ctype.h"
 #include "localedef.h"
 #include "parser.tab.h"
 #include "runefile.h"
@@ -43,6 +45,13 @@
 	avl_node_t avl;
 } ctype_node_t;
 
+typedef struct width_node {
+	wchar_t start;
+	wchar_t end;
+	int8_t width;
+	avl_node_t avl;
+} width_node_t;
+
 static int
 ctype_compare(const void *n1, const void *n2)
 {
@@ -178,6 +187,48 @@
 
 }
 
+/*
+ * A word about widths: if the width mask is specified, then libc
+ * unconditionally honors it.  Otherwise, it assumes printable
+ * characters have width 1, and non-printable characters have width
+ * -1 (except for NULL which is special with with 0).  Hence, we have
+ * no need to inject defaults here -- the "default" unset value of 0
+ * indicates that libc should use its own logic in wcwidth as described.
+ */
+void
+add_width(int wc, int width)
+{
+	ctype_node_t	*ctn;
+
+	if ((ctn = get_ctype(wc)) == NULL) {
+		INTERR;
+		return;
+	}
+	ctn->ctype &= ~(_CTYPE_SWM);
+	switch (width) {
+	case 0:
+		ctn->ctype |= _CTYPE_SW0;
+		break;
+	case 1:
+		ctn->ctype |= _CTYPE_SW1;
+		break;
+	case 2:
+		ctn->ctype |= _CTYPE_SW2;
+		break;
+	case 3:
+		ctn->ctype |= _CTYPE_SW3;
+		break;
+	}
+}
+
+void
+add_width_range(int start, int end, int width)
+{
+	for (; start <= end; start++) {
+		add_width(start, width);
+	}
+}
+
 void
 add_caseconv(int val, int wc)
 {
@@ -235,6 +286,7 @@
 	for (ctn = avl_first(&ctypes); ctn; ctn = AVL_NEXT(&ctypes, ctn)) {
 		int conflict = 0;
 
+
 		wc = ctn->wc;
 
 		/*