views:

488

answers:

2

I'm trying to diagnose a problem in UKSyntaxColoredTextDocument 0.4 http://www.zathras.de/angelweb/blog-uksctd-oh-four.htm where text that actually lives in a different font than the one you have specified disappears as you type. (You can download and try out this cool utility to see this problem for yourself...)

Here's the background: This is some syntax coloring code that recolors as you type. It works great, but if you enter some characters that are not a part of the font set for that text view (e.g. Monaco, Helvetica) ... for instance, a symbol character or something in Japanese, which actually uses fonts like ZapfDingbatsITC or HiraKakuProN-W3 to display it, then those characters are not displayed as you type.

Let's say you have some text like this: fdsafd[☀]sfds‡[☀☀☀][日本語]...

If you paste that into the text field, and switch among syntax coloring from the popup, this invokes oldRecolorRange:, with this line:

[[textView textStorage] replaceCharactersInRange: range withAttributedString: vString];

Here, things behave as I would expect. The ASCII text, the symbols, and the Japanese text are all visible. The value of [textView textStorage] starts out, and ends up, something like this: (This is output of gdb; it's not showing the unicode characters, don't worry about that.)

df{
    NSFont = "LucidaGrande 20.00 pt. P [] (0x001a3380) fobj=0x001a4970, spc=6.33";
}?{
    NSFont = "ZapfDingbatsITC 20.00 pt. P [] (0x001ae720) fobj=0x001bb370, spc=5.56";
}fdsafd[{
    NSFont = "LucidaGrande 20.00 pt. P [] (0x001a3380) fobj=0x001a4970, spc=6.33";
}?{
    NSFont = "HiraKakuProN-W3 20.00 pt. P [] (0x001b59e0) fobj=0x001bb600, spc=6.66";
}]sfds[{
...

... even after setting the new value to be

dffdsafd[?]sfds[???][???] Nihddfdfffdfdd{
    NSFont = "LucidaGrande 20.00 pt. P [] (0x001a3380) fobj=0x001a4970, spc=6.33";
}

In other words, the "foreign" fonts needed to display this string are preserved automatically somehow, even though the fonts are not specified in the replacement string.

However, when you type in one character at a time, a different call of replaceCharactersInRange:withAttributedString: in the method recolorRange: results in an attributed string that is only in the base font -- no foreign-character fonts have been added for us, so the characters out of the range of the main font are not visible at all!

dffdsafd[?]sfds[???][???] Nihddfdfffdfddx{
    NSFont = "LucidaGrande 20.00 pt. P [] (0x001a3380) fobj=0x001a4970, spc=6.33";
}

Any idea why this method would be working one way in one circumstance and not in another? Is there some kind of switch that I can pass to give the NSTextStorage/NSAttributedString a hint that we want the text to display foreign characters?

+1  A: 

Have you tried turning it off and on again?

schwa
+2  A: 

Try [[textView textStorage] fixFontAttributeInRange:range]; after the [[textView textStorage] replaceCharactersInRange: range withAttributedString: vString] in recolorRange:

I think the problem is editing the text storage again in response to processEditing, which is already the tail end of an edit. -[NSTextStorage processEditing] uses fixFontAttributeInRange:, but since you're trying to edit again, something is going wrong and the fix behavior is being dropped.

When you do it for the whole document, there is a normal beginEditing/endEditing/processEditing sequence which causes fixFontAttributeInRange: to be called happily.

Christopher Lloyd
That did it!From the docs: "Fixes the font attribute in aRange, assigning default fonts to characters with illegal fonts for their scripts and otherwise correcting font attribute assignments."Thanks!
danwood