Thanks for your reply.<div><br></div><div>Yes, a 
"view->word boundaries"  mode would be very helpful (or even incorporating the current "view->field shading" to include viewing 'gray marks' at the automatic ICU breaking so that users can see what is being done). Would this be hard to implement?</div>
<div><br></div><div>Also, we are making some changes to the ICU break iterator dictionary for Khmer - and I've heard there will be some changes in ICU 50 which should improve results for Khmer.</div><div><br></div><div>
If anyone has any ideas - it would be appreciated.</div><div><br></div><div>Thanks!</div><div>Nathan</div><div><br><br><div class="gmail_quote">On Wed, Jul 25, 2012 at 8:41 PM, Caolán McNamara <span dir="ltr"><<a href="mailto:caolanm@redhat.com" target="_blank">caolanm@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I'll cc this to the list if you don't mind, in order to archive it. I<br>
have no immediate great ideas. But I wonder if a "view->word boundaries"<br>
mode would be helpful, i.e. something that indicates the boundaries of<br>
the words that the software thinks exist.<br>
<div><div class="h5"><br>
On Sun, 2012-07-15 at 21:40 +0700, Nathan Wells wrote:<br>
><br>
> I hope you don't mind if I write and ask some more questions and ask<br>
> for additional help in making the break iterator more functional in<br>
> LibreOffice. Thank you again for your help implementing ICU for Khmer<br>
> in LibreOffice. I downloaded a recent beta build with your code<br>
> implemented and did some testing – it is great! But it also brought to<br>
> my attention some issues that hamper the useability of the automatic<br>
> breaking for Khmer (and I also believe for Thai – see this discussion<br>
> -<br>
> <a href="http://www.thaivisa.com/forum/topic/444360-thai-in-openoffice-on-ubuntu-lucid-lynx/#entry5160455" target="_blank">http://www.thaivisa.com/forum/topic/444360-thai-in-openoffice-on-ubuntu-lucid-lynx/#entry5160455</a>).<br>

><br>
><br>
> An automatic word and line breaker is very necessary for Khmer and<br>
> Thai because traditionally they have no spaces between words, and so<br>
> line-breaking and spell checking require the use of a zero-width space<br>
> between words which is counterintuitive for most native speakers, and<br>
> so spell checking goes widely unused.<br>
> But now with the ICU code you implemented, Thai and Khmer can be<br>
> automatically broken, and the results are quite good. But with its<br>
> implementation in the real world, I have found some issues that I<br>
> wanted to raise and also suggest possible solutions. I write this as<br>
> an end-user, not so much as a programmer, nor do I claim to fully<br>
> understand the inner-workings of ICU and LibreOffice (because I don't!<br>
> ).<br>
><br>
> First, I will do my best to explain the current results of the ICU<br>
> break iterator with Khmer:<br>
><br>
> Input sentence: មានប្រាជ្ញាឈ្លាសវៃឈ្មោះសិវកឥវលិយៈ<br>
><br>
> Current ICU line-breaking: មាន|ប្រាជ្ញាឈ្លាស|វៃ|ឈ្មោះ|សិវ|កឥ|វលិ|យៈ<br>
><br>
> Compared with the sentence manually broken: មាន|ប្រាជ្ញា|ឈ្លាសវៃ|<br>
> ឈ្មោះ|សិវកឥវលិយៈ<br>
><br>
> The differences should be clear – the ICU break iterator does not<br>
> break the words with 100% accuracy.<br>
><br>
> But, obviously with a dictionary approach, no automatic word breaker<br>
> will ever break correctly 100% of the time. There is no solution that<br>
> will currently automatically break Thai or Khmer 100% correctly (I<br>
> have used, Hidden Markov Model breakers, dictionary probability<br>
> breakers, and plain dictionary breakers – none work 100% of a time)<br>
> because, especially for names and places, words in Khmer can just defy<br>
> all rules and patterns. Perhaps in the future, a solution will arise<br>
> that can break Khmer words with 100% accuracy, but at this time, we<br>
> are far from any such solution.<br>
><br>
> And this is an important reality to remember, because it<br>
> differentiates Thai and Khmer (and possibly other languages that do<br>
> not use spaces between words) from Western languages such as English,<br>
> where a line-breaker and word-breaker can be correct 100% of the time.<br>
><br>
> As an end user, this inability of the ICU break iterator to break<br>
> Khmer words with 100% causes usability issues when it comes to<br>
> correcting the automatic breaks that are broken in error.<br>
><br>
> Here are some reasons why:<br>
><br>
</div></div>>      1. In LibreOffice a user cannot see where the words have been<br>
>         broken, they are invisible.<br>
><br>
>      2. Therefore, trying to use a U+2060 (No Width Word Joiner) to<br>
<div class="im">>         correct an error in order to correctly spell check is very<br>
>         difficult, because the user cannot see where to place the<br>
>         joiner in order to join the word (as in the example case above<br>
>         the word សិវ|កឥ|វលិ|យៈ actually needs three U+2060 characters<br>
>         to join it to be treated as one word, but the end user does<br>
>         not know this because the breaks are invisible.<br>
<br>
</div>FWIW with view->field shading on you should see a little gray mark where<br>
the word joiner exists. At least I do anyway.<br>
<br>
>      1. Even if LibreOffice were able to change their code so that the<br>
<div class="im">>         end user could see the word-breaks, adding three U+2060<br>
>         characters is quite laborious just to fix one word so that it<br>
>         can be spell checked correctly (as one word, rather than spell<br>
>         checked as four individual words).<br>
><br>
><br>
><br>
> One possible solution to this issue is by how the ICU Break Iterator<br>
> interacts with zero-width spaces (U+200B) in LibreOffice. Before ICU<br>
> code was enabled to automatically break Khmer, if an end-user wanted<br>
> to spell check Khmer, they had to manually place U+200B characters to<br>
> separate words. This solution worked quite well, but was<br>
> counterintuitive to most native speakers, because Khmer has no spaces<br>
> (as stated before). But with this solution, an end-user could be sure<br>
> that their document was broken with 100% accuracy, if there was no<br>
> human error (something automatic solutions cannot do – it is more<br>
> along the lines of 80% accurate). What I propose, is that the break<br>
> iterator code in LibreOffice looks for U+200B characters in a given<br>
> string and considers them as a sign to NOT automatically break, but to<br>
> allow the end-user full control to manually break words. Let me<br>
> explain:<br>
><br>
</div>>      1. The code starts processing the text and automatically breaking<br>
<div class="im">>         it until it comes across a U+200B character. If one is found,<br>
>         it searches to see if there are any additional U+200B or U<br>
>         +0020 characters in the following 20 characters (or so), and<br>
>         if there are, the break iterator skips over those characters<br>
>         and starts again from the second U+200B character (or U+0020,<br>
>         but a U+0020 character would only signify the “close” of the<br>
>         manual break because sometimes a phrase will end and there<br>
>         will be an actual space – so if the word that the user wants<br>
>         to manually break has a “real” U+0020 space at the end of it,<br>
>         then the user does not need to put an additional U+200B<br>
>         character to close it) which then repeats, looking for U+200B<br>
>         characters etc.<br>
><br>
</div>>      2. This would allow end-users to choose to manually break their<br>
<div class="im">>         whole document so they can have precise control, as well as<br>
>         allow end-users to place U+200B characters around names of<br>
>         people, places or transliterations in order to tell the break<br>
>         iterator to not try to break those words.<br>
><br>
><br>
><br>
> An example of what it would like (since I am not a programmer, I am<br>
> not sure if this would be the best way to add this feature, you<br>
> probably can come up with a better solution, but I thought by giving<br>
> this example it would explain what I mean better); <zw> is the<br>
> zero-width space U+200B character and <sp> is a normal space U+0020:<br>
><br>
</div>>      1. I type:<br>
<div class="im">>         មានប្រាជ្ញាឈ្លាសវៃឈ្មោះសិវកឥវលិយៈ<sp>អ្នកប្រាជ្ញម្នាក់ទៀតដែលល្បីល្បាញជាងគេ and since there are no zero-width spaces, the break iterator works breaks the words automatically.<br>
><br>
</div>>      2. After typing I know that the last word is the name of a<br>
<div class="im">>         person, so I manually add a zero-width space before the word<br>
>         (but not after since there is already a “real” space there):<br>
>         មានប្រាជ្ញាឈ្លាសវៃឈ្មោះ<zw>សិវកឥវលិយៈ<sp>អ្នកប្រាជ្ញម្នាក់ទៀតដែលល្បីល្បាញជាងគេ<br>
><br>
</div>>      3. As the break iterator processes this string, it breaks the<br>
<div class="im">>         words automatically until it comes to the zero-width space,<br>
>         and then stops automatically breaking, looking for a “closing”<br>
>         zero-width space or “real” space. Finding a “closing” real, it<br>
>         then does not break the characters between the zero width<br>
>         space and the “real” space.<br>
><br>
</div>>      4. I then notice that "ម្នាក់ទៀត" line breaks together (since the<br>
<div class="im">>         automatic line-breaking breaks them as one word. And I decide<br>
>         I would rather line-break after “ម្នាក់” rather than have both<br>
>         words break connected to each other, so I place a zero-width<br>
>         space between the words:<br>
>         មាន​ប្រាជ្ញាឈ្លាស​វៃ​ឈ្មោះ<zw>សិវ​កឥ​វលិ​យៈ<sp>​អ្នកប្រាជ្ញ​<br>
>         ម្នាក់<zw>ទៀត​ដែល​ល្បីល្បាញ​ជាងគេ<br>
>         the automatic break iterator comes to the zero width space and<br>
>         then stops automatically breaking and look ahead to see if<br>
>         there is a zero-width space or a “real” space within 20<br>
>         characters (this number might need refining, but I think 20<br>
>         characters would be enough). As there are no zero-width or<br>
>         “real” spaces within 20 characters, the break iterator then<br>
>         goes back to the previous zero-width and starts breaking<br>
>         starting from the zero-width character.<br>
><br>
</div>>      5. Then I notice that "ជាងគេ" line-break together, and I want<br>
>         them to break seperately. So I add a zero-with space of either<br>
>         side of the word "ជាង": មាន​ប្រាជ្ញាឈ្លាស​វៃ​ឈ្មោះ<zw>សិវ​កឥ​<br>
>         វលិ​យៈ<sp>​អ្នកប្រាជ្ញ​ម្នាក់<zw>ទៀត​ដែល​<br>
>         ល្បីល្បាញ​<zw>ជាង<zw>គេ<br>
>         The automatic breaker then comes to the zero-width space<br>
>         before "ជាង" and looks for a “closing” zero-width space or<br>
>         normal space, finding one, it does not break anything between<br>
>         the two zero-width spaces, and begins breaking again after the<br>
>         “closing” zero-width space.<br>
><br>
><br>
> I hope that isn't too much information, but I wanted to try and cover<br>
> every possibility to make sure the concept was clear.<br>
><br>
> I noticed some code in the LibreOffice source that gave me the idea<br>
> that it might be possible to do what I just described – I found it<br>
> online here:<br>
> <a href="http://c-cpp.r3dcode.com/files/LibreOffice/3/4.5.2/libs-gui/i18npool/source/breakiterator/breakiterator_unicode.cxx" target="_blank">http://c-cpp.r3dcode.com/files/LibreOffice/3/4.5.2/libs-gui/i18npool/source/breakiterator/breakiterator_unicode.cxx</a><br>

><br>
><br>
> 403 #define WJ 0x2060   // Word Joiner<br>
> 404             GlueSpace=sal_False;<br>
> 405             if (lbr.breakType == BreakType::WORDBOUNDARY) {<br>
> 406                 nStartPos = lbr.breakIndex;<br>
> 407                 if (Text[nStartPos--] == WJ)<br>
> 408                     GlueSpace=sal_True;<br>
> 409                 while (nStartPos >= 0 &&<br>
> 410                     (u_isWhitespace(Text.iterateCodePoints(&nStartPos, 0)) || Text[nStartPos] == WJ)) {<br>
> 411                     if (Text[nStartPos--] == WJ)<br>
> 412                         GlueSpace=sal_True;<br>
> 413                 }<br>
> 414                 if (GlueSpace && nStartPos < 0)  {<br>
> 415                     lbr.breakIndex = 0;<br>
> 416                     break;<br>
> 417                 }<br>
> 418             }<br>
> 419         }<br>
> 420<br>
> 421         return lbr;<br>
> 422 }<br>
><br>
> Again, I am very grateful for your time and help in making LibreOffice<br>
> work better with Khmer, and I know your time is valuable, but I<br>
> thought I would try to see if you could provide additional help and<br>
> solutions for Khmer. If you don't have time to consider this, no<br>
> worries, we are already grateful for what you have already done.<br>
><br>
><br>
> Thanks,<br>
><br>
> Nathan<br>
><br>
><br>
> On Fri, Jul 13, 2012 at 3:23 PM, Caolán McNamara <<a href="mailto:caolanm@redhat.com">caolanm@redhat.com</a>><br>
> wrote:<br>
>         On Thu, 2012-07-12 at 23:49 +0700, Nathan Wells wrote:<br>
>         ><br>
>         > > There was something similar done in the past IIRC to<br>
>         > > pass around soft-page-break information so that export<br>
>         filters<br>
>         >> could know where the layout last put the page breaks. I<br>
>         forget<br>
>         >> the details of that though.<br>
>         ><br>
>         > This would be a very useful feature for Cambodians (and I<br>
>         would assume<br>
>         > Thai as well, although Thai tends to have more programs that<br>
>         currently<br>
>         > support wordbreaking already) - would it be best to seek to<br>
>         do this<br>
>         > with an extension rather than LibreOffice core?<br>
><br>
><br>
>         Here's the spec for soft-page-breaks, which seems similar to<br>
>         my mind<br>
>         <a href="http://www.openoffice.org/specs/writer/SoftPageBreak/SoftPageBreak.odt" target="_blank">http://www.openoffice.org/specs/writer/SoftPageBreak/SoftPageBreak.odt</a><br>
>         This sort of thing would have to be basically implemented in<br>
>         the core I<br>
>         reckon.<br>
><br>
>         C.<br>
><br>
><br>
><br>
><br>
<br>
<br>
</blockquote></div><br></div>