Mercurial > projects > dwt-linux
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;