Browse Source

* Various fixes in position calculation

Michaël Van Canneyt 5 months ago
parent
commit
787e031f3a
1 changed files with 39 additions and 24 deletions
  1. 39 24
      src/base/fresnel.edit.pp

+ 39 - 24
src/base/fresnel.edit.pp

@@ -173,9 +173,17 @@ end;
 
 procedure TEdit.DoDeleteSelection;
 
+var
+  lDeletePos,lDeleteEndPos,lStart : PAnsiChar;
+
 begin
+  if (FValue='') or (FSelectionStart=FSelectionEnd) then
+    exit;
   NormalizeSelection;
-  Delete(FValue,1 + FSelectionStart,FSelectionStart-FSelectionEnd);
+  lStart:=PAnsiChar(FValue);
+  lDeletePos:=UTF8CodepointStart(lStart,Length(FValue),FSelectionStart);
+  lDeleteEndPos:=UTF8CodepointStart(lStart,Length(FValue),FSelectionEnd);
+  Delete(FValue,1 + (lDeletePos-lStart),lDeleteEndPos-lDeletePos);
   EditParamsChanged;
 end;
 
@@ -225,6 +233,7 @@ var
   lKeyLen : Integer;
   lChanged : Boolean;
   lOffset : Integer;
+  pInsert,pStart : PAnsiChar;
 
 begin
   lChanged:=False;
@@ -235,13 +244,14 @@ begin
       exit;
     DoDeleteSelection;
     lKeyUTF8:=UnicodeToUTF8(aEvent.NumKey);
-    Insert(lKeyUTF8,FValue,FCursorPos+1);
-    lKeyLen:=Length(lKeyUTF8);
+    pStart:=PAnsiChar(FValue);
+    pInsert:=UTF8CodepointStart(pStart,Length(FValue),FCursorPos);
+    Insert(lKeyUTF8,FValue,PtrInt(PInsert-PStart)+1);
     if FCursorPos<=FSelectionEnd then
-      Inc(FSelectionEnd,lKeyLen);
+      Inc(FSelectionEnd,1);
     if FCursorPos<=FSelectionStart then
-      Inc(FSelectionStart,lKeyLen);
-    Inc(FCursorPos,lKeyLen);
+      Inc(FSelectionStart,1);
+    Inc(FCursorPos,1);
     EventDispatcher.DispatchEvent(evtChange);
     lChanged:=True;
     end
@@ -253,16 +263,18 @@ begin
         begin
         if FSelectionStart=FSelectionEnd then
           begin
-          lOffset:=UTF8FindNearestCharStart(PChar(FValue),Length(FValue),FCursorPos);
-          lKeyLen:=UTF8CodepointSize(@FValue[lOffset+1]);
-          Delete(FValue,lOffSet+1,lKeyLen);
-          FCursorPos:=lOffSet;
-          FSelectionStart:=FCursorPos;
-          FSelectionEnd:=FCursorPos;
+          if FCursorPos>0 then
+            begin
+            lOffset:=UTF8FindNearestCharStart(PChar(FValue),Length(FValue),FCursorPos-1);
+            lKeyLen:=UTF8CodepointSize(@FValue[lOffset+1]);
+            Delete(FValue,lOffSet+1,lKeyLen);
+            FCursorPos:=lOffSet;
+            FSelectionStart:=FCursorPos;
+            FSelectionEnd:=FCursorPos;
+            end
           end
         else
           begin
-          lKeyLen:=Abs(FSelectionStart-FSelectionEnd);
           DoDeleteSelection;
           FSelectionEnd:=FSelectionStart;
           FCursorPos:=FSelectionStart;
@@ -334,6 +346,7 @@ begin
     end;
   if lChanged then
     EditParamsChanged;
+  Writeln('Text now: "',FValue,'", Selection now: "',GetSelectionText,'"');
 end;
 
 procedure TEdit.HandleMouseMove(aEvent : TFresnelMouseEvent);
@@ -507,8 +520,8 @@ begin
     lpos := UTF8CharAtBytePos(lText, lpos, lUnicodeChar);
     lPreviousWidth := lTotalWidth;
     // Writeln(lPos,': "',lUnicodeChar,'" -> ',CalcCharSize(lFont, lUnicodeChar),' width');
-    lTotalWidth  := lTotalWidth + CalcCharSize(lFont, lUnicodeChar);
-    // lTotalWidth  := CalcCharSize(lFont, copy(lText,1,lPos-1));
+    // lTotalWidth  := lTotalWidth + CalcCharSize(lFont, lUnicodeChar);
+    lTotalWidth  := CalcCharSize(lFont, copy(lText,1,lPrevPos));
     // Character position relative to edit origin. Text offset was calculated using cursor position.
     lCharX := lLeftSideMargin + lTotalWidth - FTextOffset;
     AdjustSelection;
@@ -529,6 +542,7 @@ begin
       end
     else
       begin
+      Writeln('Prem brak');
       break; // we can safely break after last visible character is found
       end;
     Inc(lCharNum);
@@ -548,6 +562,7 @@ begin
 
   FVisibleText := Copy(lText, lFirstVisibleIndex, lLastVisibleIndex - lFirstVisibleIndex);
   FDrawOffset := FTextOffset - FDrawOffset;
+  Writeln('Calc cursor at: ',FCursorX,' text width : ',Font.TextSize(lText).x,' offset : ', FTextOffset);
 
   // Write('Value: "',FValue,'", Visible: "',FVisibleText,'"');
   // Write(', Sel: [Char:',FSelectionStart:2,' -',FSelectionEnd:5,', Pos:',FSelectionStartX:5:2,' -',FSelectionEndX:5:2,']');
@@ -562,10 +577,10 @@ var
   lCharNum : Integer;         // Character index (in codepoints)
   lClosestX: TFresnelLength;  // X position closest to cursor X)
   lCurrWidth: TFresnelLength; // Running total character width
-  lPos: integer;  // Character loop pos
+  lPos,lPrevPos: integer;  // Character loop pos
   lFont : IFresnelFont;
   lLeftSideMargin : TFresnelLength;
-  lCharWidth : TFresnelLength;
+
 begin
   lLeftSideMargin:=GetComputedLength(fcaPaddingLeft);
   lFont:=GetFont;
@@ -582,10 +597,9 @@ begin
   aXOffset:=aXOffset + FTextOffset - lLeftSideMargin;
   while (lPos <= Length(lText)) do
     begin
+    lPrevPos:=lPos;
     lPos:=UTF8CharAtBytePos(lText,lPos,lChar);
-    lCharWidth:=CalcCharSize(lFont,lChar);
-    lCurrWidth  := lCurrWidth + lCharWidth;
-    // lCurrWidth  := CalcCharSize(lFont,Copy(lText,1,lPos));
+    lCurrWidth  := CalcCharSize(lFont,Copy(lText,1,lPrevPos));
     if abs(lCurrWidth - aXOffset) < abs(lClosestX - aXOffset) then
       begin
       // We're getting closer to the actual char.
@@ -597,6 +611,7 @@ begin
       break;
     Inc(lCharNum);
     end;
+  Writeln('CalcCharOffset : ',Result);
 end;
 
 Function TEdit.CalcXOffset(aCharPos: Integer; aUseOffset: Boolean = true; aUseDrawText : Boolean = False) : TFresnelLength;
@@ -605,9 +620,8 @@ var
   lText: string;
   lChar: string;      // current character (UTF8)
   lCharNum : Integer; // Character index (in codepoints)
-  lPos: integer;      // Character loop pos
+  lPrevPos,lPos: integer;      // Character loop pos
   lFont : IFresnelFont;
-  lCharWidth : TFresnelLength;
 
 begin
   lFont := GetFont;
@@ -624,9 +638,9 @@ begin
     Result:=0;
   While (lCharNum<=aCharPos) and (lPos<=Length(lText)) do
     begin
+    lPrevPos:=lPos;
     lPos := UTF8CharAtBytePos(lText,lPos,lChar);
-    lCharWidth:=CalcCharSize(lFont,lChar);
-    Result:=Result+lCharWidth;
+    Result := CalcCharSize(lFont,Copy(lText,1,lPrevPos));
     Inc(lCharNum);
     end;
 end;
@@ -833,6 +847,7 @@ begin
   else
     begin
     aRenderer.TextOut(R.Left+lLeftSideMargin,R.Top+lTopSideMargin,Font,lColorFP,lCaption);
+    Writeln('Cursor at: ',FCursorX,' text width : ',Font.TextSize(lCaption).x);
     end;
 
   if FCursorVisible then