diff org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d @ 120:536e43f63c81

Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661 ===D2=== * added [Try]Immutable/Const/Shared templates to work with differenses in D1/D2 instead of version statements used these templates to work with strict type storage rules of dmd-2.053 * com.ibm.icu now also compilable with D2, but not tested yet * small fixes Snippet288 - shared data is in TLS ===Phobos=== * fixed critical bugs in Phobos implemention completely incorrect segfault prone fromStringz (Linux's port ruthless killer) terrible, incorrect StringBuffer realization (StyledText killer) * fixed small bugs as well Snippet72 - misprint in the snippet * implemented missed functionality for Phobos ByteArrayOutputStream implemented (image loading available) formatting correctly works for all DWT's cases As a result, folowing snippets now works with Phobos (Snippet### - what is fixed): Snippet24, 42, 111, 115, 130, 235, 276 - bad string formatting Snippet48, 282 - crash on image loading Snippet163, 189, 211, 213, 217, 218, 222 - crash on copy/cut in StyledText Snippet244 - hang-up ===Tango=== * few changes for the latest Tango trunc-r5661 * few small performance improvments ===General=== * implMissing-s for only one version changed to implMissingInTango/InPhobos * incorrect calls to Format in toString-s fixed * fixed loading \uXXXX characters in ResourceBundle * added good UTF-8 support for StyledText, TextLayout (Win32) and friends UTF functions revised and tested. It is now in java.nonstandard.*Utf modules StyledText and TextLayout (Win32) modules revised for UTF-8 support * removed small diferences in most identical files in *.swt.* folders *.swt.internal.image, *.swt.events and *.swt.custom are identical in Win32/Linux32 now 179 of 576 (~31%) files in *.swt.* folders are fully identical * Win32: snippets now have right subsystem, pretty icons and native system style controls * small fixes in snippets Snippet44 - it's not Snippet44 Snippet212 - functions work with different images and offsets arrays Win32: Snippet282 - crash on close if the button has an image Snippet293 - setGrayed is commented and others Win32: As a result, folowing snippets now works Snippet68 - color doesn't change Snippet163, 189, 211, 213, 217, 218, 222 - UTF-8 issues (see above) Snippet193 - no tabel headers
author Denis Shelomovskij <verylonglogin.reg@gmail.com>
date Sat, 09 Jul 2011 15:50:20 +0300
parents 9f4c18c268b2
children
line wrap: on
line diff
--- a/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d	Sun Apr 17 17:58:36 2011 +0200
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d	Sat Jul 09 15:50:20 2011 +0300
@@ -81,9 +81,16 @@
 import org.eclipse.swt.custom.StyledTextDropTargetEffect;
 import org.eclipse.swt.custom.StyledTextListener;
 import org.eclipse.swt.custom.ST;
-import java.lang.Runnable;
 
 import java.lang.all;
+import java.nonstandard.UnsafeUtf;
+
+version(Tango){
+    static import tango.io.model.IFile;
+} else { // Phobos
+    static import std.string;
+}
+
 
 /**
  * A StyledText is an editable user interface object that displays lines
@@ -143,9 +150,14 @@
  */
 public class StyledText : Canvas {
     alias Canvas.computeSize computeSize;
+package:
 
     static const char TAB = '\t';
-    static const String PlatformLineDelimiter = "\r\n";
+    version(Tango){
+        static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString;
+    } else { // Phobos
+        static const String PlatformLineDelimiter = std.string.newline;
+    }
     static const int BIDI_CARET_WIDTH = 3;
     static const int DEFAULT_WIDTH  = 64;
     static const int DEFAULT_HEIGHT = 64;
@@ -185,17 +197,18 @@
     int rightMargin;
     int bottomMargin;
     int columnX;                        // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
-    int caretOffset = 0;
+    int/*UTF8index*/ caretOffset = 0;
     int caretAlignment;
     Point selection;                    // x and y are start and end caret offsets of selection
     Point clipboardSelection;           // x and y are start and end caret offsets of previous selection
-    int selectionAnchor;                // position of selection anchor. 0 based offset from beginning of text
+    bool selectedTextValid = true;      // DWT: false if we just changed a text witch was selected
+    int/*UTF8index*/ selectionAnchor;   // position of selection anchor. 0 based offset from beginning of text
     Point doubleClickSelection;         // selection after last mouse double click
     bool editable = true;
     bool wordWrap = false;
-    bool doubleClickEnabled = true;  // see getDoubleClickEnabled
-    bool overwrite = false;          // insert/overwrite edit mode
-    int textLimit = -1;                 // limits the number of characters the user can type in the widget. Unlimited by default.
+    bool doubleClickEnabled = true;     // see getDoubleClickEnabled
+    bool overwrite = false;             // insert/overwrite edit mode
+    int/*UTF8index*/ textLimit = -1;           // limits the number of characters the user can type in the widget. Unlimited by default.
     int[int] keyActionMap;
     Color background = null;            // workaround for bug 4791
     Color foreground = null;            //
@@ -227,12 +240,12 @@
     int lineSpacing;
 
     const static bool IS_CARBON, IS_GTK, IS_MOTIF;
-    static this(){
+mixin(sharedStaticThis!(`{
         String platform = SWT.getPlatform();
         IS_CARBON = ("carbon" == platform);
         IS_GTK    = ("gtk"    == platform);
         IS_MOTIF  = ("motif"  == platform);
-    }
+    }`));
 
     /**
      * The Printing class : printing of a range of text.
@@ -501,6 +514,7 @@
         } else if (data.scope_ is PrinterData.SELECTION) {
             startLine = content.getLineAtOffset(selection.x);
             if (selection.y > 0) {
+                // DWT: index isn't a valid UTF-8 index
                 endLine = content.getLineAtOffset(selection.x + selection.y - 1);
             } else {
                 endLine = startLine - 1;
@@ -825,7 +839,7 @@
      * Determines if Unicode RTF should be written.
      * Don't write Unicode RTF on Windows 95/98/ME or NT.
      */
-    void setUnicode() {
+    void setUnicode() {/*!!!*/
 //         const String Win95 = "windows 95";
 //         const String Win98 = "windows 98";
 //         const String WinME = "windows me";
@@ -862,11 +876,9 @@
      * @param end end offset of segment
      */
     void write(String string, int start, int end) {
-        start = 0;
-        end = string.length;
-        int incr = 1;
-        for (int index = start; index < end; index+=incr) {
-            dchar ch = firstCodePoint( string[index .. $], incr );
+        int incr;
+        for (int index = start; index < end; index += incr) {
+            dchar ch = string.dcharAt(index, incr);
             if (ch > 0xFF && WriteUnicode) {
                 // write the sub string from the last escaped character
                 // to the current one. Fixes bug 21698.
@@ -885,6 +897,7 @@
                 }
                 write('\\');
                 write(cast(char)ch); // ok because one of {}\
+                assert(incr == 1);
                 start = index + 1;
             }
         }
@@ -904,7 +917,7 @@
         // specify code page, necessary for copy to work in bidi
         // systems that don't support Unicode RTF.
         // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase();
-        String cpg = "UTF16";
+        //String cpg = "UTF16";
         /+
         if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
             cpg = cpg.substring(2, cpg.length());
@@ -1218,7 +1231,7 @@
         if (offset < 0 || offset > buffer.length()) {
             return;
         }
-        buffer.insert(offset, string);
+        buffer.insert( offset, string );
     }
     /**
      * Appends the given int to the data.
@@ -1753,13 +1766,14 @@
         // therefore make sure redraw range is valid.
         int redrawStart = Math.min(selectionStart, length);
         int redrawEnd = Math.min(selectionEnd, length);
-        if (redrawEnd - redrawStart > 0) {
+        if (redrawEnd - redrawStart > 0 && selectedTextValid) {
             internalRedrawRange(redrawStart, redrawEnd - redrawStart);
         }
         if (sendEvent) {
             sendSelectionEvent();
         }
     }
+    selectedTextValid = true;
 }
 public override Point computeSize (int wHint, int hHint, bool changed) {
     checkWidget();
@@ -2232,13 +2246,13 @@
         int lineIndex = content.getLineAtOffset(caretOffset);
         int lineOffset = content.getOffsetAtLine(lineIndex);
         if (caretOffset is lineOffset) {
-            // SWT: on line start, delete line break
+            // DWT: on line start, delete line break
             lineOffset = content.getOffsetAtLine(lineIndex - 1);
             event.start = lineOffset + content.getLine(lineIndex - 1).length;
             event.end = caretOffset;
         } else {
             TextLayout layout = renderer.getTextLayout(lineIndex);
-            int start = layout.getPreviousOffset(caretOffset - lineOffset, SWT.MOVEMENT_CLUSTER);
+            int start = layout.getPreviousOffset(caretOffset - lineOffset, SWT.MOVEMENT_CHAR);
             renderer.disposeTextLayout(layout);
             event.start = start + lineOffset;
             event.end = caretOffset;
@@ -2276,7 +2290,7 @@
         // replace character at caret offset if the caret is not at the
         // end of the line
         if (event.end < lineOffset + line.length) {
-            event.end+=dcharToString( key ).length;
+            event.end += line.UTF8strideAt(event.end - lineOffset);
         }
         event.text = dcharToString( key );
     } else {
@@ -2761,7 +2775,7 @@
             if (index is -1 && lineIndex > 0) {
                 bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length;
             } else {
-                bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
+                bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, getPreviousCharOffset(lineIndex, layout.getLineOffsets()[index + 1]));
             }
             renderer.disposeTextLayout(layout);
         } else {
@@ -3957,7 +3971,7 @@
     if (point is null) {
         SWT.error(SWT.ERROR_NULL_ARGUMENT);
     }
-    int[] trailing = new int[1];
+    int[1] trailing;
     int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
     if (offset is -1) {
         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
@@ -3993,7 +4007,8 @@
             String line = content.getLine(lineIndex);
             int level;
             int offset = offsetInLine;
-            while (offset > 0 && Character.isDigit(line.dcharAt(offset))) offset--;
+            while (offset > 0 && Character.isDigit(line.dcharAt(offset)))
+                offset = line.offsetBefore(offset);
             if (offset is 0 && Character.isDigit(line.dcharAt(offset))) {
                 level = isMirrored() ? 1 : 0;
             } else {
@@ -4623,7 +4638,8 @@
     if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
         SWT.error(SWT.ERROR_INVALID_RANGE);
     }
-    return content.getTextRange(start, end - start + 1);
+    auto res = content.getTextRange(start, content.getCharCount() - start);
+    return res[0 .. res.offsetAfter(end - start)];
 }
 /**
  * Returns the smallest bounding rectangle that includes the characters between two offsets.
@@ -4797,9 +4813,12 @@
     int offset = caretOffset - lineOffset;
     int lineLength = line.length;
     if (lineLength is 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT;
-    if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--;
-    if (offset is lineLength && offset > 0) offset--;
-    while (offset > 0 && Character.isDigit(line.dcharAt(offset))) offset--;
+    if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0)
+        offset = line.offsetBefore(offset);
+    if (offset is lineLength && offset > 0)
+        offset = line.offsetBefore(offset);
+    while (offset > 0 && Character.isDigit(line.dcharAt(offset)))
+        offset = line.offsetBefore(offset);
     if (offset is 0 && Character.isDigit(line.dcharAt(offset))) {
         return isMirrored() ? SWT.RIGHT : SWT.LEFT;
     }
@@ -4893,8 +4912,8 @@
     int offsetInLine = offset - lineOffset;
     int lineLength = line.length;
     if (lineIndex < content.getLineCount() - 1) {
-        int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
-        if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
+        int afterEndLineOffset = content.getOffsetAtLine(lineIndex + 1);
+        if (lineLength < offsetInLine && offsetInLine < afterEndLineOffset) {
             offsetInLine = lineLength;
         }
     }
@@ -4902,9 +4921,7 @@
     TextLayout layout = renderer.getTextLayout(lineIndex);
     if (lineLength !is 0  && offsetInLine <= lineLength) {
         if (offsetInLine is lineLength) {
-            // SWT: Instead of go back one byte, go back one codepoint
-            int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
-            point = layout.getLocation(offsetInLine_m1, true);
+            point = layout.getLocation(getPreviousCharOffset(lineIndex, offsetInLine), true);
         } else {
             switch (caretAlignment) {
                 case OFFSET_LEADING:
@@ -4915,9 +4932,7 @@
                     if (offsetInLine is 0) {
                         point = layout.getLocation(offsetInLine, false);
                     } else {
-                        // SWT: Instead of go back one byte, go back one codepoint
-                        int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
-                        point = layout.getLocation(offsetInLine_m1, true);
+                        point = layout.getLocation(getPreviousCharOffset(lineIndex, offsetInLine), true);
                     }
                     break;
             }
@@ -5066,7 +5081,7 @@
         int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length));
         if (startIndex is endIndex) {
             /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
-            Rectangle rect = layout.getBounds(start, end - 1);
+            Rectangle rect = layout.getBounds( start, getPreviousCharOffset(startLine, end) );
             rect.x += lineX;
             rect.y += startLineY;
             super.redraw(rect.x, rect.y, rect.width, rect.height, false);
@@ -5076,7 +5091,7 @@
     }
 
     /* Redraw start line from the start offset to the end of client area */
-    Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
+    Rectangle startRect = layout.getBounds( start, getPreviousCharOffset(startLine, offsets[startIndex + 1]) );
     if (startRect.height is 0) {
         Rectangle bounds = layout.getLineBounds(startIndex);
         startRect.x = bounds.width;
@@ -5095,7 +5110,7 @@
         offsets = layout.getLineOffsets();
     }
     int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length));
-    Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
+    Rectangle endRect = layout.getBounds(offsets[endIndex], getPreviousCharOffset(endLine, end));
     if (endRect.height is 0) {
         Rectangle bounds = layout.getLineBounds(endIndex);
         endRect.y = bounds.y;
@@ -5113,7 +5128,7 @@
     }
 }
 void handleCompositionOffset (Event event) {
-    int[] trailing = new int [1];
+    int[1] trailing;
     event.index = getOffsetAtPoint(event.x, event.y, trailing, true);
     event.count = trailing[0];
 }
@@ -5140,7 +5155,7 @@
             int lineIndex = getCaretLine();
             int lineOffset = content.getOffsetAtLine(lineIndex);
             TextLayout layout = renderer.getTextLayout(lineIndex);
-            caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width;
+            caretWidth = layout.getBounds(start - lineOffset, getPreviousCharOffset(lineIndex, start + length - lineOffset)).width;
             renderer.disposeTextLayout(layout);
         }
     }
@@ -5736,7 +5751,7 @@
     do {
         while (index < length_ && string[index] !is '&') index++;
         if (++index >= length_) return '\0';
-        if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] );
+        if (string[index] !is '&') return Character.toLowerCase (string.dcharAt (index));
         index++;
     } while (index < length_);
     return '\0';
@@ -7816,8 +7831,6 @@
  */
 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;
@@ -8316,7 +8329,7 @@
     setCaretLocation();
     super.redraw();
 }
-// SWT: If necessary, scroll to show the location
+// DWT: If necessary, scroll to show the location
 bool showLocation(Rectangle rect, bool scrollPage) {
     int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin;
     int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
@@ -8433,6 +8446,7 @@
         int redrawStart = startOffset + newLength;
         internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart);
     }
+    selectedTextValid = false;
     if (selection.y > startOffset && selection.x < startOffset + replacedLength) {
         // selection intersects replaced text. set caret behind text change
         setSelection(startOffset + newLength, 0, true);
@@ -8442,4 +8456,14 @@
     }
     setCaretLocation();
 }
-}
+
+// DWT: to use instead of "offsetInLine - 1"
+int getPreviousCharOffset(String F = __FILE__, uint L = __LINE__)(int lineIndex, int offsetInLine) {
+    String line = content.getLine(lineIndex);
+    if(offsetInLine < 0 || offsetInLine > line.length) {
+        getDwtLogger().warn(F, L, Format("Clamped UTF-8 offset:\noffsetInLine = {}, line.length = {}, line = {}", offsetInLine, line.length, line));
+        return offsetInLine - 1;
+    }
+    return line.offsetBefore(offsetInLine);
+}
+}