changeset 182:721afe91f448

Fix: several utf8 awareness problems
author Frank Benoit <benoit@tionex.de>
date Sun, 02 Mar 2008 18:39:35 +0100
parents 2708124a8f6c
children 9b6243da08a5
files dwt/custom/CTabFolder.d dwt/custom/DefaultContent.d dwt/custom/ExtendedModifyEvent.d dwt/custom/StyledText.d dwt/custom/StyledTextContent.d dwt/custom/TextChangingEvent.d dwt/graphics/TextLayout.d
diffstat 7 files changed, 164 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/dwt/custom/CTabFolder.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/CTabFolder.d	Sun Mar 02 18:39:35 2008 +0100
@@ -1304,7 +1304,7 @@
     do {
         while (index < length_ && string[index] !is '&') index++;
         if (++index >= length_) return '\0';
-        if (string[index] !is '&') return CharacterToLower(getFirstCodepoint( string[index..$]));
+        if (string[index] !is '&') return CharacterFirstToLower(string[index..$]);
         index++;
     } while (index < length_);
     return '\0';
--- a/dwt/custom/DefaultContent.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/DefaultContent.d	Sun Mar 02 18:39:35 2008 +0100
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -889,4 +889,33 @@
     lineCount_ -= numOldLines;
     gapLine = getLineAtPhysicalOffset(gapStart);
 }
+
+/++
+ + DWT extension
+ +/
+int utf8AdjustOffset( int offset ){
+    if (textStore is null)
+        return offset;
+    if (offset is 0)
+        return offset;
+    if( offset >= textStore.length ){
+        return offset;
+    }
+    if (!gapExists() || (offset < gapStart)){
+        while( textStore[offset] & 0xC0 is 0x80 ){
+            offset--;
+        }
+        return offset;
+    }
+    int gapLength= gapEnd - gapStart;
+    if( offset+gapLength >= textStore.length ){
+        return offset;
+    }
+    while( textStore[offset+gapLength] & 0xC0 is 0x80 ){
+        offset--;
+    }
+    return offset;
 }
+
+
+}
--- a/dwt/custom/ExtendedModifyEvent.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/ExtendedModifyEvent.d	Sun Mar 02 18:39:35 2008 +0100
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
--- a/dwt/custom/StyledText.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/StyledText.d	Sun Mar 02 18:39:35 2008 +0100
@@ -91,7 +91,6 @@
 alias tango.text.Text.Text!(char) StringBuffer;
 private alias char[] String;
 
-
 /**
  * A StyledText is an editable user interface object that displays lines
  * of text.  The following style attributes can be defined for the text:
@@ -840,26 +839,26 @@
      * @param end end offset of segment
      */
     void write(String string, int start, int end) {
-        wchar[] wstring = tango.text.convert.Utf.toString16( string[ start .. end ] );
         start = 0;
-        end = wstring.length;
-        for (int index = start; index < end; index++) {
-            wchar ch = wstring[index];
+        end = string.length;
+        int incr = 1;
+        for (int index = start; index < end; index+=incr) {
+            dchar ch = firstCodePoint( string[index .. $], incr );
             if (ch > 0xFF && WriteUnicode) {
                 // write the sub string from the last escaped character
                 // to the current one. Fixes bug 21698.
                 if (index > start) {
-                    write(tango.text.convert.Utf.toString(wstring[start .. index ]));
+                    write( string[start .. index ] );
                 }
                 write("\\u");
                 write( to!(char[])( cast(short)ch ));
                 write(' ');                     // control word delimiter
-                start = index + 1;
+                start = index + incr;
             } else if (ch is '}' || ch is '{' || ch is '\\') {
                 // write the sub string from the last escaped character
                 // to the current one. Fixes bug 21698.
                 if (index > start) {
-                    write(tango.text.convert.Utf.toString(wstring[start .. index]));
+                    write(string[start .. index]);
                 }
                 write('\\');
                 write(cast(char)ch); // ok because one of {}\
@@ -869,7 +868,7 @@
         // write from the last escaped character to the end.
         // Fixes bug 21698.
         if (start < end) {
-            write(tango.text.convert.Utf.toString(wstring[ start .. end]));
+            write(string[ start .. end]);
         }
     }
     /**
@@ -2233,7 +2232,7 @@
  *
  * @param key the character typed by the user
  */
-void doContent(char key) {
+void doContent(dchar key) {
     if (textLimit > 0 &&
         content.getCharCount() - (selection.y - selection.x) >= textLimit) {
         return;
@@ -2257,11 +2256,11 @@
         // replace character at caret offset if the caret is not at the
         // end of the line
         if (event.end < lineOffset + line.length) {
-            event.end++;
-        }
-        event.text = [key];
+            event.end+=dcharToString( key ).length;
+        }
+        event.text = dcharToString( key );
     } else {
-        event.text = [key];
+        event.text = dcharToString( key );
     }
     if (event.text !is null) {
         sendKeyEvent(event);
@@ -2975,6 +2974,7 @@
     int lineOffset = content.getOffsetAtLine(caretLine);
     int offsetInLine = caretOffset - lineOffset;
     caretAlignment = OFFSET_LEADING;
+
     if (offsetInLine > 0) {
         caretOffset = getClusterPrevious(caretOffset, caretLine);
         showCaret();
@@ -5623,7 +5623,7 @@
     do {
         while (index < length_ && string[index] !is '&') index++;
         if (++index >= length_) return '\0';
-        if (string[index] !is '&') return CharacterToLower(getFirstCodepoint( string[index .. $ ] ));
+        if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] );
         index++;
     } while (index < length_);
     return '\0';
@@ -7685,6 +7685,8 @@
  */
 void setSelection(int start, int length, bool sendEvent) {
     int end = start + length;
+    start = content.utf8AdjustOffset(start);
+    end = content.utf8AdjustOffset(end);
     if (start > end) {
         int temp = end;
         end = start;
--- a/dwt/custom/StyledTextContent.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/StyledTextContent.d	Sun Mar 02 18:39:35 2008 +0100
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -205,4 +205,10 @@
  * @see TextChangeListener
  */
 public void setText(char[] text);
+
+/++
+ + DWT Extension
+ +/
+int utf8AdjustOffset( int offset );
+
 }
--- a/dwt/custom/TextChangingEvent.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/custom/TextChangingEvent.d	Sun Mar 02 18:39:35 2008 +0100
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
--- a/dwt/graphics/TextLayout.d	Sun Mar 02 18:19:44 2008 +0100
+++ b/dwt/graphics/TextLayout.d	Sun Mar 02 18:39:35 2008 +0100
@@ -71,7 +71,12 @@
     PangoContext* context;
     PangoAttrList* attrList;
     int[] invalidOffsets;
-    static const wchar LTR_MARK = '\u200E', RTL_MARK = '\u200F', ZWS = '\u200B', ZWNBS = '\uFEFF';
+    // LTR_MARK LEFT-TO-RIGHT MARK
+    // RTL_MARK RIGHT-TO-LEFT MARK
+    // ZWS      ZERO WIDTH SPACE
+    // ZWNBS    ZERO WIDTH NO-BREAK SPACE
+    static const dchar LTR_MARK = '\u200E', RTL_MARK = '\u200F', ZWS = '\u200B', ZWNBS = '\uFEFF';
+    static const char[] STR_LTR_MARK = "\u200E", STR_RTL_MARK = "\u200F", STR_ZWS = "\u200B", STR_ZWNBS = "\uFEFF";
 
 /**
  * Constructs a new instance of this class on the given device.
@@ -123,17 +128,16 @@
     auto ptr = OS.pango_layout_get_text(layout);
     attrList = OS.pango_attr_list_new();
     //PangoAttribute* attribute = new PangoAttribute();
-    wchar[] charsW = null;
-    wchar[] segmentsTextW = toString16( segmentsText );
-    int segementsWLength = segmentsTextW.length;
-    if ((ascent !is -1  || descent !is -1) && segementsWLength > 0) {
+    char[] chars = null;
+    int segementsLength = segmentsText.length;
+    if ((ascent !is -1  || descent !is -1) && segementsLength > 0) {
         auto iter = OS.pango_layout_get_iter(layout);
         if (iter is null) DWT.error(DWT.ERROR_NO_HANDLES);
         PangoRectangle rect;
         if (ascent !is -1) rect.y =  -(ascent  * OS.PANGO_SCALE);
         rect.height = (Math.max(0, ascent) + Math.max(0, descent)) * OS.PANGO_SCALE;
         int lineCount = OS.pango_layout_get_line_count(layout);
-        charsW = new wchar[segementsWLength + lineCount * 2];
+        chars = new char[segementsLength + lineCount * 6/*2*/];
         int oldPos = 0, count = 0;
         do {
             int bytePos = OS.pango_layout_iter_get_index(iter);
@@ -147,38 +151,49 @@
             attr.start_index = bytePos + offset + 3;
             attr.end_index = bytePos + offset + 6;
             OS.pango_attr_list_insert(attrList, attr);
-            int pos = OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
-            charsW[pos + count * 2] = ZWS;
-            charsW[pos + count * 2 + 1] = ZWNBS;
-            charsW[ oldPos + count*2 .. oldPos + count*2 + pos - oldPos ] =
-                segmentsTextW[ oldPos .. pos ];
-            //segmentsTextW.getChars(oldPos, pos, chars,  oldPos + count * 2);
+            int pos = bytePos;//OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
+            chars[pos + count * 6 +0 .. pos + count * 6 + 3] = STR_ZWS;
+            chars[pos + count * 6 +3 .. pos + count * 6 + 6] = STR_ZWNBS;
+            chars[ oldPos + count*6 .. oldPos + count*6 + pos - oldPos ] =
+                segmentsText[ oldPos .. pos ];
             oldPos = pos;
             count++;
         } while (OS.pango_layout_iter_next_line(iter));
         OS.pango_layout_iter_free (iter);
-        charsW[ oldPos + count*2 .. oldPos + count*2 + segementsWLength - oldPos ] =
-            segmentsTextW[ oldPos .. segementsWLength ];
-        //segmentsTextW.getChars(oldPos, segementsWLength, chars,  oldPos + count * 2);
-        char[] buffer = .toString( charsW );// Converter.wcsToMbcs(null, chars, false);
+        chars[ oldPos + count*6 .. oldPos + count*6 + segementsLength - oldPos ] =
+            segmentsText[ oldPos .. segementsLength ];
+        char[] buffer = chars;// Converter.wcsToMbcs(null, chars, false);
+
         OS.pango_layout_set_text (layout, buffer.ptr, buffer.length);
         ptr = OS.pango_layout_get_text(layout);
     } else {
-        charsW = segmentsTextW.dup;
+        chars = segmentsText.dup;
     }
     int offsetCount = 0;
-    for (int i = 0; i < charsW.length; i++) {
-        wchar c = charsW[i];
-        if (c is LTR_MARK || c is RTL_MARK || c is ZWNBS || c is ZWS) {
-            offsetCount++;
+    {
+        int i = 0;
+        while( i < chars.length ){
+            int incr;
+            dchar c = firstCodePoint( chars[ i .. $ ], incr );
+            if (c is LTR_MARK || c is RTL_MARK || c is ZWNBS || c is ZWS) {
+                offsetCount+=3;
+            }
+            i += incr;
         }
     }
     invalidOffsets = new int[offsetCount];
     offsetCount = 0;
-    for (int i = 0; i < charsW.length; i++) {
-        wchar c = charsW[i];
-        if (c is LTR_MARK || c is RTL_MARK || c is ZWNBS || c is ZWS) {
-            invalidOffsets[offsetCount++] = i;
+    {
+        int i = 0;
+        while( i < chars.length ){
+            int incr;
+            dchar c = firstCodePoint( chars[ i .. $ ], incr );
+            if (c is LTR_MARK || c is RTL_MARK || c is ZWNBS || c is ZWS) {
+                invalidOffsets[offsetCount++] = i;
+                invalidOffsets[offsetCount++] = i+1;
+                invalidOffsets[offsetCount++] = i+2;
+            }
+            i += incr;
         }
     }
     int slen = strlen(ptr);
@@ -188,8 +203,8 @@
         if (style is null) continue;
         int start = translateOffset(styleItem.start);
         int end = translateOffset(styles[i+1].start - 1);
-        int byteStart = (OS.g_utf8_offset_to_pointer(ptr, start) - ptr);
-        int byteEnd = (OS.g_utf8_offset_to_pointer(ptr, end + 1) - ptr);
+        int byteStart = start;//(OS.g_utf8_offset_to_pointer(ptr, start) - ptr);
+        int byteEnd = end+1;//(OS.g_utf8_offset_to_pointer(ptr, end + 1) - ptr);
         byteStart = Math.min(byteStart, slen);
         byteEnd = Math.min(byteEnd, slen);
         Font font = style.font;
@@ -370,7 +385,7 @@
             OS.pango_layout_iter_get_line_extents(iter, null, &rect);
             if (OS.pango_layout_iter_next_line(iter)) {
                 int bytePos = OS.pango_layout_iter_get_index(iter);
-                lineEnd = OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
+                lineEnd = bytePos;//OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
             } else {
                 lineEnd = OS.g_utf8_strlen(ptr, -1);
             }
@@ -439,8 +454,8 @@
             }
         } else {
             auto ptr = OS.pango_layout_get_text(layout);
-            int byteSelStart = (OS.g_utf8_offset_to_pointer(ptr, selectionStart) - ptr);
-            int byteSelEnd = (OS.g_utf8_offset_to_pointer(ptr, selectionEnd + 1) - ptr);
+            int byteSelStart = selectionStart;//(OS.g_utf8_offset_to_pointer(ptr, selectionStart) - ptr);
+            int byteSelEnd = selectionEnd + 1;//(OS.g_utf8_offset_to_pointer(ptr, selectionEnd + 1) - ptr);
             int slen = strlen(ptr);
             byteSelStart = Math.min(byteSelStart, slen);
             byteSelEnd = Math.min(byteSelEnd, slen);
@@ -582,8 +597,15 @@
     start = translateOffset(start);
     end = translateOffset(end);
     auto ptr = OS.pango_layout_get_text(layout);
-    int byteStart = (OS.g_utf8_offset_to_pointer (ptr, start) - ptr);
-    int byteEnd = (OS.g_utf8_offset_to_pointer (ptr, end + 1) - ptr);
+    auto cont = fromStringz(ptr);
+    start = cont.utf8AdjustOffset( start );
+    end = cont.utf8AdjustOffset( end );
+    int incr = 1;
+    if( end < cont.length ){
+        incr = cont.getRelativeCodePointOffset( end, 1 );
+    }
+    int byteStart = start;//(OS.g_utf8_offset_to_pointer (ptr, start) - ptr);
+    int byteEnd = end + incr;//(OS.g_utf8_offset_to_pointer (ptr, end + 1) - ptr);
     int slen = strlen(ptr);
     byteStart = Math.min(byteStart, slen);
     byteEnd = Math.min(byteEnd, slen);
@@ -718,7 +740,7 @@
     PangoItem* item = new PangoItem();
     PangoLayoutRun* run = new PangoLayoutRun();
     auto ptr = OS.pango_layout_get_text(layout);
-    auto byteOffset = OS.g_utf8_offset_to_pointer(ptr, offset) - ptr;
+    auto byteOffset = offset;//OS.g_utf8_offset_to_pointer(ptr, offset) - ptr;
     int slen = strlen(ptr);
     byteOffset = Math.min(byteOffset, slen);
     do {
@@ -808,7 +830,7 @@
     offset = translateOffset(offset);
     int line = 0;
     auto ptr = OS.pango_layout_get_text(layout);
-    auto byteOffset = OS.g_utf8_offset_to_pointer(ptr,offset) - ptr;
+    auto byteOffset = offset;//OS.g_utf8_offset_to_pointer(ptr,offset) - ptr;
     int slen = strlen(ptr);
     byteOffset = Math.min(byteOffset, slen);
     auto iter = OS.pango_layout_get_iter(layout);
@@ -882,7 +904,7 @@
     int i = 0;
     do {
         int bytePos = OS.pango_layout_iter_get_index(iter);
-        int pos = OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
+        int pos = bytePos;//OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos);
         offsets[i++] = untranslateOffset(pos);
     } while (OS.pango_layout_iter_next_line(iter));
     OS.pango_layout_iter_free(iter);
@@ -913,8 +935,11 @@
     if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE);
     offset = translateOffset(offset);
     auto ptr = OS.pango_layout_get_text(layout);
-    int byteOffset = (OS.g_utf8_offset_to_pointer(ptr, offset) - ptr);
-    int slen = strlen(ptr);
+    auto cont = fromStringz(ptr);
+    offset = cont.utf8AdjustOffset(offset);
+    // leading ZWS+ZWNBS are 2 codepoints in 6 bytes, so we miss 4 bytes here
+    int byteOffset = offset;//(OS.g_utf8_offset_to_pointer(ptr, offset) - ptr);
+    int slen = cont.length;
     byteOffset = Math.min(byteOffset, slen);
     PangoRectangle* pos = new PangoRectangle();
     OS.pango_layout_index_to_pos(layout, byteOffset, pos);
@@ -956,16 +981,26 @@
     } else {
         if (offset is 0) return 0;
     }
+    auto cont = OS.pango_layout_get_text(layout);
+    assert( cont );
+    auto dcont = fromStringz(cont);
     int step = forward ? 1 : -1;
-    if ((movement & DWT.MOVEMENT_CHAR) !is 0) return offset + step;
+    if ((movement & DWT.MOVEMENT_CHAR) !is 0){
+        //PORTING take care of utf8
+        int toffset = translateOffset(offset);
+        toffset = dcont.utf8AdjustOffset( toffset );
+        int incr = dcont.getRelativeCodePointOffset( toffset, step );
+        return offset + incr;
+    }
     PangoLogAttr* attrs;
     int nAttrs;
     OS.pango_layout_get_log_attrs(layout, &attrs, &nAttrs);
     if (attrs is null) return offset + step;
-    length = OS.g_utf8_strlen(OS.pango_layout_get_text(layout), -1);
+    length = OS.g_utf8_strlen(cont, -1);
     offset = translateOffset(offset);
+    offset = dcont.utf8AdjustOffset( offset );
     PangoLogAttr* logAttr = new PangoLogAttr();
-    offset = validateOffset(offset, step);
+    offset = validateOffset( dcont, offset, step);
     while (0 < offset && offset < length) {
         *logAttr = attrs[ offset ];
         if (((movement & DWT.MOVEMENT_CLUSTER) !is 0) && ( logAttr.bitfield0 & (1<<4/*is_cursor_position*/))) break;
@@ -982,7 +1017,7 @@
         if ((movement & DWT.MOVEMENT_WORD_END) !is 0) {
             if (logAttr.bitfield0 & (1<<6/*is_word_end*/)) break;
         }
-        offset = validateOffset(offset, step);
+        offset = validateOffset( dcont, offset, step);
     }
     OS.g_free(attrs);
     return Math.min(Math.max(0, untranslateOffset(offset)), text.length);
@@ -1073,7 +1108,7 @@
     int piTrailing;
     OS.pango_layout_xy_to_index(layout, x * OS.PANGO_SCALE, y * OS.PANGO_SCALE, &index, &piTrailing);
     auto ptr = OS.pango_layout_get_text(layout);
-    int offset = OS.g_utf8_pointer_to_offset(ptr, ptr + index);
+    int offset = index;//OS.g_utf8_pointer_to_offset(ptr, ptr + index);
     if (trailing !is null) trailing[0] = piTrailing;
     return untranslateOffset(offset);
 }
@@ -1172,19 +1207,22 @@
         if (segments[0] is 0 && segments[1] is len) return text;
     }
     char[] oldChars = text[0..len].dup;
-    char[] newChars = new char[len + nSegments];
+    char[] newChars = new char[len + nSegments*3];
     int charCount = 0, segmentCount = 0;
-    wchar separator = getOrientation() is DWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+    char[] separator = getOrientation() is DWT.RIGHT_TO_LEFT ? STR_RTL_MARK : STR_LTR_MARK;
     while (charCount < len) {
         if (segmentCount < nSegments && charCount is segments[segmentCount]) {
-            newChars[charCount + segmentCount++] = separator;
+            newChars[charCount + segmentCount .. charCount + segmentCount + separator.length ] = separator;
+            segmentCount+=separator.length;
         } else {
-            newChars[charCount + segmentCount] = oldChars[charCount++];
+            newChars[charCount + segmentCount] = oldChars[charCount];
+            charCount++;
         }
     }
     if (segmentCount < nSegments) {
         segments[segmentCount] = charCount;
-        newChars[charCount + segmentCount++] = separator;
+        newChars[charCount + segmentCount .. charCount + segmentCount + separator.length ] = separator;
+        segmentCount+=separator.length;
     }
     return newChars[ 0 .. Math.min(charCount + segmentCount, newChars.length) ];
 }
@@ -1424,7 +1462,7 @@
     checkLayout ();
     if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     if (this.font is font) return;
-    if (font !is null && font ==/*eq*/ this.font ) return;
+    if (font !is null && font.opEquals(this.font)) return;
     this.font = font;
     OS.pango_layout_set_font_description(layout, font !is null ? font.handle : null);
 }
@@ -1554,12 +1592,19 @@
  * </ul>
  */
 public void setStyle (TextStyle style, int start, int end) {
+    char[] styleTxt = "<null>";
+    if( style !is null ){
+        styleTxt = style.toString;
+    }
     checkLayout();
     int length = text.length;
     if (length is 0) return;
     if (start > end) return;
     start = Math.min(Math.max(0, start), length - 1);
     end = Math.min(Math.max(0, end), length - 1);
+    start = text.utf8AdjustOffset( start );
+    end = text.utf8AdjustOffset( end );
+
 
     /*
     * Bug in Pango. Pango 1.2.2 will cause a segmentation fault if a style
@@ -1568,11 +1613,12 @@
     *
     * NOTE that fix only LamAlef ligatures.
     */
-    if (start > 0 && isAlef(text[start]) && isLam(text[start - 1])) {
-        start--;
+    int relIndex;
+    if ((start > 0 ) && isAlef(text[ start .. $ ].firstCodePoint()) && isLam(text.getRelativeCodePoint( start, -1, relIndex ))) {
+        start += relIndex;
     }
-    if (end < length - 1 && isLam(text[end]) && isAlef(text[end + 1])) {
-        end++;
+    if ((end < length - 1) && isLam(text[ end .. $ ].firstCodePoint()) && isAlef(text.getRelativeCodePoint(end, 1,relIndex))) {
+        end += relIndex;
     }
 
     int low = -1;
@@ -1591,7 +1637,7 @@
             if (style is null) {
                 if (item.style is null) return;
             } else {
-                if (style ==/*eq*/ item.style) return;
+                if (style.opEquals(item.style)) return;
             }
         }
     }
@@ -1694,7 +1740,7 @@
  */
 public void setText (char[] text) {
     checkLayout ();
-    if (text ==/*eq*/this.text) return;
+    if (text.equals(this.text)) return;
     freeRuns();
     this.text = text;
     styles = new StyleItem[2];
@@ -1792,11 +1838,16 @@
     return offset - invalidOffsets.length;
 }
 
-int validateOffset(int offset, int step) {
+int validateOffset( char[] cont, int offset, int step) {
     if (invalidOffsets is null) return offset + step;
     int i = step > 0 ? 0 : invalidOffsets.length - 1;
     do {
-        offset += step;
+        if( offset is 0 && step < 0 ){
+            offset += step;
+        }
+        else{
+            offset += cont.getRelativeCodePointOffset( offset, step );
+        }
         while (0 <= i && i < invalidOffsets.length) {
             if (invalidOffsets[i] is offset) break;
             i += step;