hedgewars/uChat.pas
changeset 10919 8aed2bfc43c5
parent 10868 acb03a9712c3
child 10920 11a28d22985f
equal deleted inserted replaced
10918:1b878d1d32ce 10919:8aed2bfc43c5
    50 type TInputStrL = array[0..260] of byte;
    50 type TInputStrL = array[0..260] of byte;
    51 
    51 
    52 var Strs: array[0 .. MaxStrIndex] of TChatLine;
    52 var Strs: array[0 .. MaxStrIndex] of TChatLine;
    53     MStrs: array[0 .. MaxStrIndex] of shortstring;
    53     MStrs: array[0 .. MaxStrIndex] of shortstring;
    54     LocalStrs: array[0 .. MaxStrIndex] of shortstring;
    54     LocalStrs: array[0 .. MaxStrIndex] of shortstring;
    55     LocalStrsL: array[0 .. MaxStrIndex] of TInputStrL;
       
    56     missedCount: LongWord;
    55     missedCount: LongWord;
    57     lastStr: LongWord;
    56     lastStr: LongWord;
    58     localLastStr: LongInt;
    57     localLastStr: LongInt;
    59     history: LongInt;
    58     history: LongInt;
    60     visibleCount: LongWord;
    59     visibleCount: LongWord;
   425 if s <> LocalStrs[localLastStr] then
   424 if s <> LocalStrs[localLastStr] then
   426     begin
   425     begin
   427     // put in input history
   426     // put in input history
   428     localLastStr:= (localLastStr + 1) mod MaxStrIndex;
   427     localLastStr:= (localLastStr + 1) mod MaxStrIndex;
   429     LocalStrs[localLastStr]:= s;
   428     LocalStrs[localLastStr]:= s;
   430     LocalStrsL[localLastStr]:= InputStrL;
       
   431     end;
   429     end;
   432 
   430 
   433 t:= LocalTeam;
   431 t:= LocalTeam;
   434 x:= 0;
   432 x:= 0;
   435 if (s[1] = '"') and (s[Length(s)] = '"')
   433 if (s[1] = '"') and (s[Length(s)] = '"')
   746         selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos));
   744         selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos));
   747         CopyToClipboard(selection);
   745         CopyToClipboard(selection);
   748         end;
   746         end;
   749 end;
   747 end;
   750 
   748 
   751 // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit
   749 // regenerate UTF-8 info for current input string
       
   750 procedure RegenInputStrL();
       
   751 var i, n, lastL: integer;
       
   752     b: byte;
       
   753 begin
       
   754     lastL:= InputStrLNoPred;
       
   755     i:= 0;
       
   756     n:= Length(InputStr.s);
       
   757     while i <= n do
       
   758         begin
       
   759 
       
   760         // also save lastL if we reached the end
       
   761         if i = n then
       
   762             b:= 0
       
   763         else
       
   764             b:= byte(InputStr.s[i+1]);
       
   765 
       
   766         // start of char, based on https://en.wikipedia.org/wiki/UTF-8#Description
       
   767         if (b and $C0) <> $80 then
       
   768             begin
       
   769             InputStrL[i]:= lastL;
       
   770             lastL:= i;
       
   771             end
       
   772         else
       
   773             InputStrL[i]:= InputStrLNoPred;
       
   774 
       
   775         inc(i);
       
   776         end;
       
   777 end;
       
   778 
   752 procedure InsertIntoInputStr(s: shortstring);
   779 procedure InsertIntoInputStr(s: shortstring);
   753 var i, l, il, lastc: integer;
   780 var i, l, il, lastc: integer;
   754 begin
   781 begin
   755     // safe length for string
   782     // safe length for string
   756     l:= min(MaxInputStrLen-cursorPos, Length(s));
   783     l:= min(MaxInputStrLen-cursorPos, Length(s));
   757     s:= copy(s,1,l);
   784     s:= copy(s,1,l);
   758 
   785 
   759     // if we insert rather than append, shift info in InputStrL accordingly
       
   760     if cursorPos < Length(InputStr.s) then
       
   761         begin
       
   762         for i:= Length(InputStr.s) downto cursorPos + 1 do
       
   763             begin
       
   764             if InputStrL[i] <> InputStrLNoPred then
       
   765                 begin
       
   766                 il:= i + l;
       
   767                 // only shift if not overflowing
       
   768                 if il <= MaxInputStrLen then
       
   769                     InputStrL[il]:= InputStrL[i] + l;
       
   770                 InputStrL[i]:= InputStrLNoPred;
       
   771                 end;
       
   772             end;
       
   773         end;
       
   774 
       
   775     InputStrL[cursorPos + l]:= cursorPos;
       
   776     // insert string truncated to safe length
   786     // insert string truncated to safe length
       
   787     // TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit
   777     Insert(s, InputStr.s, cursorPos + 1);
   788     Insert(s, InputStr.s, cursorPos + 1);
   778     if Length(InputStr.s) > MaxInputStrLen then
   789     if Length(InputStr.s) > MaxInputStrLen then
   779         InputStr.s[0]:= char(MaxInputStrLen);
   790         InputStr.s[0]:= char(MaxInputStrLen);
   780 
   791 
   781     SetLine(InputStr, InputStr.s, true);
   792     SetLine(InputStr, InputStr.s, true);
       
   793 
       
   794     // update InputStrL to also reflect whatever was inserted
       
   795     RegenInputStrL();
   782 
   796 
   783     // move cursor to end of inserted string
   797     // move cursor to end of inserted string
   784     lastc:= MaxInputStrLen;
   798     lastc:= MaxInputStrLen;
   785     cursorPos:= min(lastc, cursorPos + l);
   799     cursorPos:= min(lastc, cursorPos + l);
   786     UpdateCursorCoords();
   800     UpdateCursorCoords();
   901                 FillChar(InputStrL, sizeof(InputStrL), InputStrLNoPred);
   915                 FillChar(InputStrL, sizeof(InputStrL), InputStrLNoPred);
   902                 end
   916                 end
   903             else
   917             else
   904                 begin
   918                 begin
   905                 SetLine(InputStr, LocalStrs[index], true);
   919                 SetLine(InputStr, LocalStrs[index], true);
   906                 InputStrL:= LocalStrsL[index];
   920                 RegenInputStrL();
   907                 end;
   921                 end;
   908             cursorPos:= Length(InputStr.s);
   922             cursorPos:= Length(InputStr.s);
   909             ResetSelection();
   923             ResetSelection();
   910             UpdateCursorCoords();
   924             UpdateCursorCoords();
   911             end;
   925             end;
  1060         utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8;
  1074         utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8;
  1061 
  1075 
  1062         if Length(InputStr.s) + btw > MaxInputStrLen then
  1076         if Length(InputStr.s) + btw > MaxInputStrLen then
  1063             exit;
  1077             exit;
  1064 
  1078 
       
  1079         // if speech bubble quotes are used as first input, add the closing quote and place cursor inbetween
  1065         if (Length(InputStr.s) = 0) and (Length(utf8) = 1) and (charIsForHogSpeech(utf8[1])) then
  1080         if (Length(InputStr.s) = 0) and (Length(utf8) = 1) and (charIsForHogSpeech(utf8[1])) then
  1066             begin
  1081             begin
  1067             InsertIntoInputStr(utf8);
  1082             InsertIntoInputStr(utf8);
  1068             InsertIntoInputStr(utf8);
  1083             InsertIntoInputStr(utf8);
  1069             cursorPos:= 1;
  1084             cursorPos:= 1;