diff options
-rw-r--r-- | examples/gui/widgettest/widgettest.pas | 1 | ||||
-rw-r--r-- | gfx/fputf8utils.pas | 126 | ||||
-rw-r--r-- | gfx/gdi/fpgfxpackage.lpk | 6 | ||||
-rw-r--r-- | gfx/gdi/fpgfxpackage.pas | 2 | ||||
-rw-r--r-- | gfx/x11/fpgfxpackage.lpk | 6 | ||||
-rw-r--r-- | gfx/x11/fpgfxpackage.pas | 2 | ||||
-rw-r--r-- | gfx/x11/gfx_x11.pas | 5 | ||||
-rw-r--r-- | gui/fpgui.pas | 1 | ||||
-rw-r--r-- | gui/fpguiedit.inc | 45 |
9 files changed, 176 insertions, 18 deletions
diff --git a/examples/gui/widgettest/widgettest.pas b/examples/gui/widgettest/widgettest.pas index fcfe3b99..704e1619 100644 --- a/examples/gui/widgettest/widgettest.pas +++ b/examples/gui/widgettest/widgettest.pas @@ -694,6 +694,7 @@ constructor TEditForm.Create(AOwner: TComponent); begin inherited Create(AOwner); LoadForm(self); + Edit1.Text := 'Gráficas Magnificacion! Teste'; Edit2.PasswordChar := '*'; end; diff --git a/gfx/fputf8utils.pas b/gfx/fputf8utils.pas new file mode 100644 index 00000000..0bad5380 --- /dev/null +++ b/gfx/fputf8utils.pas @@ -0,0 +1,126 @@ +{ + Some handly UTF8 function copied from the Lazarus LCL. Surely we can move + this into FPC? +} +unit fpUTF8Utils; + +{$ifdef FPC} + {$mode objfpc}{$H+} +{$endif} + +interface + +uses + Classes, SysUtils; + + +function UTF8Pos(const SearchForText, SearchInText: string): integer; +function UTF8Copy(const s: string; StartCharIndex, CharCount: integer): string; +function UTF8Length(p: PChar; ByteCount: integer): integer; +function UTF8CharStart(UTF8Str: PChar; Len, Index: integer): PChar; +function UTF8CharacterLength(p: PChar): integer; + + +implementation + +function UTF8Pos(const SearchForText, SearchInText: string): integer; +// returns the character index, where the SearchForText starts in SearchInText +var + p: LongInt; +begin + p:=System.Pos(SearchForText,SearchInText); + if p>0 then + Result:=UTF8Length(PChar(SearchInText),p-1)+1 + else + Result:=0; +end; + +function UTF8Copy(const s: string; StartCharIndex, CharCount: integer): string; +// returns substring +var + StartBytePos: PChar; + EndBytePos: PChar; + MaxBytes: PtrInt; +begin + StartBytePos:=UTF8CharStart(PChar(s),length(s),StartCharIndex-1); + if StartBytePos=nil then + Result:='' + else begin + MaxBytes:=PtrInt(PChar(s)+length(s)-StartBytePos); + EndBytePos:=UTF8CharStart(StartBytePos,MaxBytes,CharCount); + if EndBytePos=nil then + Result:=copy(s,StartBytePos-PChar(s)+1,MaxBytes) + else + Result:=copy(s,StartBytePos-PChar(s)+1,EndBytePos-StartBytePos); + end; +end; + +function UTF8Length(p: PChar; ByteCount: integer): integer; +var + CharLen: LongInt; +begin + Result:=0; + while (ByteCount>0) do begin + inc(Result); + CharLen:=UTF8CharacterLength(p); + inc(p,CharLen); + dec(ByteCount,CharLen); + end; +end; + +function UTF8CharStart(UTF8Str: PChar; Len, Index: integer): PChar; +var + CharLen: LongInt; +begin + Result:=UTF8Str; + if Result<>nil then begin + while (Index>0) and (Len>0) do begin + CharLen:=UTF8CharacterLength(Result); + dec(Len,CharLen); + dec(Index); + inc(Result,CharLen); + end; + if (Index>0) or (Len<0) then + Result:=nil; + end; +end; + +function UTF8CharacterLength(p: PChar): integer; +begin + if p<>nil then begin + if ord(p^)<%11000000 then begin + // regular single byte character (#0 is a character, this is pascal ;) + Result:=1; + end + else if ((ord(p^) and %11100000) = %11000000) then begin + // could be 2 byte character + if (ord(p[1]) and %11000000) = %10000000 then + Result:=2 + else + Result:=1; + end + else if ((ord(p^) and %11110000) = %11100000) then begin + // could be 3 byte character + if ((ord(p[1]) and %11000000) = %10000000) + and ((ord(p[2]) and %11000000) = %10000000) then + Result:=3 + else + Result:=1; + end + else if ((ord(p^) and %11111000) = %11110000) then begin + // could be 4 byte character + if ((ord(p[1]) and %11000000) = %10000000) + and ((ord(p[2]) and %11000000) = %10000000) + and ((ord(p[3]) and %11000000) = %10000000) then + Result:=4 + else + Result:=1; + end + else + Result:=1 + end else + Result:=0; +end; + +end. + diff --git a/gfx/gdi/fpgfxpackage.lpk b/gfx/gdi/fpgfxpackage.lpk index 84d2ab5b..06dbd483 100644 --- a/gfx/gdi/fpgfxpackage.lpk +++ b/gfx/gdi/fpgfxpackage.lpk @@ -24,7 +24,7 @@ <License Value="Modified LGPL "/> <Version Minor="4"/> - <Files Count="6"> + <Files Count="7"> <Item1> <Filename Value="..\gfxbase.pas"/> <UnitName Value="GfxBase"/> @@ -49,6 +49,10 @@ <Filename Value="..\gelimage.pas"/> <UnitName Value="GELImage"/> </Item6> + <Item7> + <Filename Value="..\fputf8utils.pas"/> + <UnitName Value="fpUTF8Utils"/> + </Item7> </Files> <RequiredPkgs Count="1"> <Item1> diff --git a/gfx/gdi/fpgfxpackage.pas b/gfx/gdi/fpgfxpackage.pas index 61ffe20c..0669f181 100644 --- a/gfx/gdi/fpgfxpackage.pas +++ b/gfx/gdi/fpgfxpackage.pas @@ -7,7 +7,7 @@ unit fpGFXPackage; interface uses - GfxBase, GFXInterface, GFX_GDI, fpgfx, GELDirty, GELImage; + GfxBase, GFXInterface, GFX_GDI, fpgfx, GELDirty, GELImage, fpUTF8Utils; implementation diff --git a/gfx/x11/fpgfxpackage.lpk b/gfx/x11/fpgfxpackage.lpk index c58916a3..5c02e39b 100644 --- a/gfx/x11/fpgfxpackage.lpk +++ b/gfx/x11/fpgfxpackage.lpk @@ -21,7 +21,7 @@ <License Value="Modified LGPL "/> <Version Minor="4"/> - <Files Count="9"> + <Files Count="10"> <Item1> <Filename Value="../gfxbase.pas"/> <UnitName Value="GfxBase"/> @@ -58,6 +58,10 @@ <Filename Value="../commandlineparams.pas"/> <UnitName Value="CommandLineParams"/> </Item9> + <Item10> + <Filename Value="../fputf8utils.pas"/> + <UnitName Value="fpUTF8Utils"/> + </Item10> </Files> <LazDoc Paths="../../docs/xml/gfx/"/> <RequiredPkgs Count="1"> diff --git a/gfx/x11/fpgfxpackage.pas b/gfx/x11/fpgfxpackage.pas index 84c4bda2..f6e51e3b 100644 --- a/gfx/x11/fpgfxpackage.pas +++ b/gfx/x11/fpgfxpackage.pas @@ -8,7 +8,7 @@ interface uses GfxBase, GFX_X11, gfxinterface, schar16, unitkeys, fpgfx, GELDirty, GELImage, - CommandLineParams; + CommandLineParams, fpUTF8Utils; implementation diff --git a/gfx/x11/gfx_x11.pas b/gfx/x11/gfx_x11.pas index 7128c4bf..1deba25a 100644 --- a/gfx/x11/gfx_x11.pas +++ b/gfx/x11/gfx_x11.pas @@ -621,6 +621,7 @@ function TX11Canvas.TextExtent(const AText: String): TSize; var {$IFDEF XftSupport} extents : TXGlyphInfo; + WideText: WideString; {$ELSE} Direction, FontAscent, FontDescent: LongInt; CharStruct: TXCharStruct; @@ -634,7 +635,9 @@ begin else begin {$IFDEF XftSupport} - XftTextExtents8(GFApplication.Handle, FFontStruct.FontData, PChar(AText), Length(AText), extents); + WideText := Utf8Decode(AText); +// XftTextExtents8(GFApplication.Handle, FFontStruct.FontData, PChar(AText), Length(AText), extents); + XftTextExtents16(GFApplication.Handle, FFontStruct.FontData, PChar(WideText), Length(WideText), extents); Result.cx := extents.xOff; Result.cy := extents.yOff; {$ELSE} diff --git a/gui/fpgui.pas b/gui/fpgui.pas index 285c4c3b..ac69f788 100644 --- a/gui/fpgui.pas +++ b/gui/fpgui.pas @@ -159,6 +159,7 @@ implementation uses Math ,StyleManager + ,fpUTF8Utils ; diff --git a/gui/fpguiedit.inc b/gui/fpguiedit.inc index 8cd3268c..6ad17cb7 100644 --- a/gui/fpguiedit.inc +++ b/gui/fpguiedit.inc @@ -142,11 +142,13 @@ begin BoundsSize.cx - Borders.Right - 1, BoundsSize.cy - Borders.Bottom - 1)) then exit; + // setup the correct font color if wsEnabled in WidgetState then Canvas.SetColor(Style.GetUIColor(FFontColor)) else Canvas.SetColor(Style.GetUIColor(clGrayText)); + // paint the text s := GetDrawText; Canvas.TextOut(Point(-FDrawOffset + Borders.Left+2, 3), s); @@ -176,7 +178,7 @@ begin // drawing cursor Canvas.SetColor(Style.GetUIColor(clWindowText)); // Style.SetUIColor(Canvas, clWindowText); - tw := Canvas.TextWidth(Copy(s, 1, FCursorPos)); + tw := Canvas.TextWidth(UTF8Copy(s, 1, FCursorPos)); // 2 pixel cursor line // ItemRect.Top := Borders.Top; @@ -202,21 +204,24 @@ begin end; procedure TFCustomEdit.EvKeyPressed(Key: Word; Shift: TShiftState); +var + WideText: WideString; begin if Shift * [ssShift, ssAlt, ssCtrl, ssMeta, ssSuper, ssHyper, ssAltGr] = [] then begin + WideText := UTF8Decode(Text); // Normal typing - no selections case Key of keyLeft, keyUp: if CursorPos > 0 then CursorPos := CursorPos - 1; keyRight, keyDown: - if CursorPos < Length(Text) then + if CursorPos < Length(WideText) then CursorPos := CursorPos + 1; keyHome: CursorPos := 0; keyEnd: - CursorPos := Length(Text); + CursorPos := Length(WideText); else inherited EvKeyPressed(Key, Shift); end; @@ -250,23 +255,27 @@ end; procedure TFCustomEdit.EvKeyChar(KeyChar: Char); +var + WideText: WideString; begin + WideText := UTF8Decode(FText); + case KeyChar of #8: { Backspace } if FCursorPos > 0 then begin - FText := Copy(FText, 1, FCursorPos - 1) + Copy(FText, FCursorPos + 1, Length(FText)); + FText := UTF8Copy(FText, 1, FCursorPos - 1) + UTF8Copy(FText, FCursorPos + 1, Length(WideText)); FCursorPos := FCursorPos - 1; end; #127: { Del } - if FCursorPos < Length(FText) then + if FCursorPos < Length(WideText) then begin - FText := Copy(FText, 1, FCursorPos) + Copy(FText, FCursorPos + 2, Length(FText)); + FText := UTF8Copy(FText, 1, FCursorPos) + UTF8Copy(FText, FCursorPos + 2, Length(WideText)); Redraw; end; #32..#126, #128..#255: begin - FText := Copy(FText, 1, FCursorPos) + KeyChar + Copy(FText, CursorPos + 1, Length(FText)); + FText := UTF8Copy(FText, 1, FCursorPos) + KeyChar + UTF8Copy(FText, CursorPos + 1, Length(WideText)); FCursorPos := FCursorPos + 1; end; else @@ -292,10 +301,13 @@ begin end; procedure TFCustomEdit.SetText(const AText: String); +var + WideText: WideString; begin inherited SetText(AText); + WideText := Utf8Decode(FText); FSelOffset := 0; - FCursorPos := Length(FText); + FCursorPos := Length(WideText); FSelStart := FCursorPos; FDrawOffset := 0; AdjustCursor; @@ -334,6 +346,7 @@ var n: integer; cx: integer; lText: string; + WideText: WideString; begin if (pEvent.Button = mbLeft) then begin @@ -343,13 +356,14 @@ begin // Make sure we work with the correct displayed text lText := GetDrawText; + WideText := UTF8Decode(lText); cp := FCursorPos; - cpx := FindForm.Wnd.Canvas.TextWidth(Copy(lText, 1, FCursorPos)) - FDrawOffset + lSideMargin; + cpx := FindForm.Wnd.Canvas.TextWidth(UTF8Copy(lText, 1, FCursorPos)) - FDrawOffset + lSideMargin; - for n := 0 to Length(lText) do + for n := 0 to Length(WideText) do begin - cx := FindForm.Wnd.Canvas.TextWidth(Copy(lText, 1, n)) - FDrawOffset + lSideMargin; + cx := FindForm.Wnd.Canvas.TextWidth(UTF8Copy(lText, 1, n)) - FDrawOffset + lSideMargin; if abs(cx - pEvent.Position.x) < abs(cpx - pEvent.Position.x) then begin cpx := cx; @@ -396,7 +410,7 @@ begin Exit; //==> Canvas := FindForm.Wnd.Canvas; - tw := Canvas.TextWidth(Copy(GetDrawText, 1, FCursorPos)); + tw := Canvas.TextWidth(UTF8Copy(GetDrawText, 1, FCursorPos)); lBorders := Style.GetEditBoxBorders; lSideMargins := lBorders.Left + lBorders.Right; @@ -416,11 +430,16 @@ end; // Return the correct text to be displayed function TFCustomEdit.GetDrawText: string; +var + WideText: WideString; begin if FPasswordChar = #0 then Result := FText else - Result := StringOfChar(FPasswordChar, Length(FText)); + begin + WideText := Utf8Decode(FText); + Result := StringOfChar(FPasswordChar, Length(WideText)); + end; end; {$ENDIF read_implementation} |