エンコーディング/ロカール判定をまともにしてみた。[2007-11-06改訂]

Index: NSStringITerm.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/NSStringITerm.m,v
retrieving revision 1.8
diff -u -r1.8 NSStringITerm.m
--- NSStringITerm.m	13 Nov 2006 08:01:04 -0000	1.8
+++ NSStringITerm.m	6 Nov 2007 09:24:28 -0000
@@ -294,9 +294,92 @@
return [NSString stringWithFormat:@"%d", num];
}
++ (BOOL)isCJKEncoding:(NSStringEncoding)encoding
+{
+    static NSMutableDictionary *isEncodingCJK = nil; // cache for encoding to isCJK mapping
+    static NSStringEncoding previousEncoding = 1; // ASCII
+    static BOOL isCJK = NO;
+    NSNumber *key, *val;
+    const char *lang;
+
+    if (encoding == previousEncoding) {
+        //NSLog(@"encoding[0x%08lx] is %s, again", encoding, isCJK ? "CJK" : "not CJK");
+        return isCJK;
+    }
+
+    previousEncoding = encoding;
+
+    key = [NSNumber numberWithUnsignedInt:encoding];
+
+    if (isEncodingCJK == nil) {
+        isEncodingCJK = [[NSMutableDictionary alloc] init];
+    }
+    else {
+        val = [isEncodingCJK objectForKey:key];
+
+        if (val != nil) {
+            isCJK = [val boolValue];
+            //NSLog(@"encoding[0x%08lx] is %s, IIRC", encoding, isCJK ? "CJK" : "not CJK");
+            return isCJK;
+        }
+    }
+
+    switch (encoding) {
+      // Simplified Chinese
+      case 0x80000019: // Mac
+      case 0x80000421: // Windows
+      case 0x80000631: // GBK
+      case 0x80000632: // GB 18030
+      case 0x80000930: // EUC
+      // Traditional Chinese
+      case 0x80000002: // Mac
+      case 0x80000423: // Windows
+      case 0x80000931: // EUC
+      case 0x80000A03: // Big5
+      case 0x80000A06: // Big5 HKSCS
+      // Japanese
+      case 0x00000003: // EUC
+      case 0x00000008: // Windows
+      case 0x00000015: // ISO-2022-JP
+      case 0x80000001: // Mac
+      case 0x80000628: // Shift JIS X0213
+      case 0x80000A01: // Shift JIS
+      // Korean
+      case 0x80000003: // Mac
+      case 0x80000422: // Windows
+      case 0x80000840: // ISO-2022-KR
+      case 0x80000940: // EUC
+        isCJK = YES;
+        //NSLog(@"0x%08lx is known to be %s", encoding, isCJK ? "CJK" : "not CJK");
+        break;
+
+      case 0x00000004: // UTF-8
+        isCJK = ((lang = getenv("LC_ALL")) != NULL ||
+                 (lang = getenv("LC_CTYPE")) != NULL ||
+                 (lang = getenv("LANG")) != NULL) &&
+            strlen(lang) >= 3 &&
+            (!strncmp(lang, "ja_", 3) ||
+             !strncmp(lang, "kr_", 3) ||
+             !strncmp(lang, "zh_", 3));
+        //NSLog(@"locale[%s] looks %s", lang, isCJK ? "CJK" : "not CJK");
+        break;
+
+      default:
+        isCJK = NO;
+        //NSLog(@"encoding[0x%08lx] is not known to be CJK", encoding);
+        break;
+    }
+
+    // Store in cache
+    val = [NSNumber numberWithBool:isCJK];
+    [isEncodingCJK setObject:val forKey:key];
+
+    return isCJK;
+}
+
+ (BOOL)isDoubleWidthCharacter:(unichar)unicode encoding:(NSStringEncoding) e
{
-	if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x200f))
+	if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x1100))
return NO;
/*
unicode character width check
@@ -325,11 +408,7 @@
/* Ambiguous ones */
-	if ((e)==0x80000019||(e)==0x80000421||(e)==0x80000631||(e)==0x80000632||(e)==0x80000930 || //GB
-		(e)==0x80000002||(e)==0x80000423||(e)==0x80000931||(e)==0x80000a03||(e)==0x80000a06 || //BIG5
-		(e)==0x80000001||(e)==0x8||(e)==0x15 || //JP
-		(e)==0x80000628||(e)==0x80000a01 || //SJIS
-		(e)==0x80000422||(e)==0x80000003||(e)==0x80000840||(e)==0x80000940) //KR
+	if ([self isCJKEncoding:e])
{
if ((unicode >=0xfe00 && unicode <=0xfe0f) ||
(unicode >=0x2776 && unicode <=0x277f) ||

これならsubmit可能か。ただ、描画部分でASCII/non-ASCIIフォントの選択を誤るのでまだ不完全。また時間が取れたら見ます。

あと、下線が倍幅に対応していない。

Index: PTYTextView.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/PTYTextView.m,v
retrieving revision 1.307
diff -u -r1.307 PTYTextView.m
--- PTYTextView.m	17 Jun 2007 01:56:31 -0000	1.307
+++ PTYTextView.m	6 Nov 2007 02:07:04 -0000
@@ -963,7 +963,7 @@
 					//draw underline
 					if (theLine[j].fg_color & UNDER_MASK && theLine[j].ch) {
 						[[self colorForCode:(fgcode & 0x1ff)] set];
-						NSRectFill(NSMakeRect(curX,curY-2,charWidth,1));
+						NSRectFill(NSMakeRect(curX,curY-2,double_width?charWidth*2:charWidth,1));
 					}
 				}
 			}

ほかにも、あんまり致命的ではないが特定のケースでカーソル移動によって文字の右半分が欠けたりする。まあ、ソースがあるからいつか捕まえて直せるだろう。Terminal.appもソースを公開してほしいね。


Categories : Tech