# HG changeset patch # User sheepluva # Date 1430432258 -7200 # Node ID 05e6f3b02612e45f570d27e6ddbf69db35c9e030 # Parent 11a28d22985f2053f367a9fed4b95d2dfe5bee20 chat: further tweaks and cleanups diff -r 11a28d22985f -r 05e6f3b02612 hedgewars/uChat.pas --- a/hedgewars/uChat.pas Thu Apr 30 21:53:41 2015 +0200 +++ b/hedgewars/uChat.pas Fri May 01 00:17:38 2015 +0200 @@ -36,7 +36,7 @@ uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; const MaxStrIndex = 27; - MaxInputStrLen = 240; + MaxInputStrLen = 200; type TChatLine = record Tex: PTexture; @@ -68,8 +68,6 @@ const - InputStrLNoPred: byte = 255; - colors: array[#0..#6] of TSDL_Color = ( (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] @@ -95,10 +93,10 @@ ClHeight = 2 * Padding + 16; // font height // relevant for UTF-8 handling -function IsFirstCharByte(b: byte): boolean; inline; +function IsFirstCharByte(c: char): boolean; inline; begin // based on https://en.wikipedia.org/wiki/UTF-8#Description - IsFirstCharByte:= (b and $C0) <> $80; + IsFirstCharByte:= (byte(c) and $C0) <> $80; end; function charIsForHogSpeech(c: char): boolean; @@ -597,7 +595,7 @@ begin if cursorPos > 0 then begin - while (not IsFirstCharByte(byte(InputStr.s[cursorPos]))) do + while (not IsFirstCharByte(InputStr.s[cursorPos])) do begin dec(cursorPos); end; @@ -610,7 +608,7 @@ if cursorPos < Length(InputStr.s) then begin inc(cursorPos, 2); - while (cursorPos < Length(InputStr.s)) and (not IsFirstCharByte(byte(InputStr.s[cursorPos]))) do + while (cursorPos < Length(InputStr.s)) and (not IsFirstCharByte(InputStr.s[cursorPos])) do begin inc(cursorPos); end; @@ -618,6 +616,22 @@ end; end; +procedure DeleteLastUTF8CharFromStr(var s: shortstring); +var l: byte; +begin + l:= Length(s); + + while (l > 1) and (not IsFirstCharByte(s[l])) do + begin + dec(l); + end; + + if l > 0 then + dec(l); + + s[0]:= char(l); +end; + procedure DeleteSelected(); begin if (selectedPos >= 0) and (cursorPos <> selectedPos) then @@ -732,25 +746,43 @@ end; procedure InsertIntoInputStr(s: shortstring); -var l, lastc: integer; +var limit: integer; begin - // safe length for string - l:= min(MaxInputStrLen-cursorPos, Length(s)); - // SetLength(s, l); - s[0]:= char(l); + // we check limit for trailing stuff before insertion limit for a reason + // (possible remaining space after too long UTF8-insertion has been shortened) + + // length limit for stuff to that will trail the insertion + limit:= max(cursorPos, MaxInputStrLen-Length(s)); + + while Length(InputStr.s) > limit do + begin + DeleteLastUTF8CharFromStr(InputStr.s); + end; + + // length limit for stuff to insert + limit:= max(0, MaxInputStrLen-cursorPos); - // insert string truncated to safe length - Insert(s, InputStr.s, cursorPos + 1); - // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit - if Length(InputStr.s) > MaxInputStrLen then - InputStr.s[0]:= char(MaxInputStrLen); + if limit = 0 then + s:= '' + else while Length(s) > limit do + begin + DeleteLastUTF8CharFromStr(s); + end; - SetLine(InputStr, InputStr.s, true); + if Length(s) > 0 then + begin + // insert string truncated to safe length + Insert(s, InputStr.s, cursorPos + 1); - // move cursor to end of inserted string - lastc:= MaxInputStrLen; - cursorPos:= min(lastc, cursorPos + l); - UpdateCursorCoords(); + if Length(InputStr.s) > MaxInputStrLen then + InputStr.s[0]:= char(MaxInputStrLen); + + SetLine(InputStr, InputStr.s, true); + + // move cursor to end of inserted string + inc(cursorPos, Length(s)); + UpdateCursorCoords(); + end; end; procedure PasteFromClipboard(); @@ -963,7 +995,10 @@ begin // paste if ctrl then - PasteFromClipboard() + begin + DeleteSelected(); + PasteFromClipboard(); + end else action:= false; end;