hedgewars/uChat.pas
changeset 10836 0b415bc2e0eb
parent 10835 8ac09cd322b7
child 10837 1b7a4d3111ea
equal deleted inserted replaced
10835:8ac09cd322b7 10836:0b415bc2e0eb
    26 procedure freeModule;
    26 procedure freeModule;
    27 procedure ReloadLines;
    27 procedure ReloadLines;
    28 procedure CleanupInput;
    28 procedure CleanupInput;
    29 procedure AddChatString(s: shortstring);
    29 procedure AddChatString(s: shortstring);
    30 procedure DrawChat;
    30 procedure DrawChat;
    31 procedure KeyPressChat(Key, Sym: Longword);
    31 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word);
    32 procedure SendHogSpeech(s: shortstring);
    32 procedure SendHogSpeech(s: shortstring);
    33 
    33 
    34 implementation
    34 implementation
    35 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils;
    35 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils;
    36 
    36 
    62     showAll: boolean;
    62     showAll: boolean;
    63     liveLua: boolean;
    63     liveLua: boolean;
    64     ChatHidden: boolean;
    64     ChatHidden: boolean;
    65     InputLinePrefix: shortstring;
    65     InputLinePrefix: shortstring;
    66     // cursor
    66     // cursor
    67     cursorPos, cursorX: LongInt;
    67     cursorPos, cursorX, selectedPos, selectionDx: LongInt;
    68     LastKeyPressTick: LongWord;
    68     LastKeyPressTick: LongWord;
    69 
    69 
    70 const
    70 const
    71     InputStrLNoPred: byte = 255;
    71     InputStrLNoPred: byte = 255;
    72 
    72 
    92 
    92 
    93 
    93 
    94 const Padding  = 2;
    94 const Padding  = 2;
    95       ClHeight = 2 * Padding + 16; // font height
    95       ClHeight = 2 * Padding + 16; // font height
    96 
    96 
       
    97 procedure ResetSelection();
       
    98 begin
       
    99     selectedPos:= -1;
       
   100 end;
       
   101 
    97 procedure UpdateCursorCoords();
   102 procedure UpdateCursorCoords();
    98 var font: THWFont;
   103 var font: THWFont;
    99     str : shortstring;
   104     str : shortstring;
   100     coff: LongInt;
   105     coff, soff: LongInt;
   101 begin
   106 begin
       
   107     if cursorPos = selectedPos then
       
   108         ResetSelection();
       
   109 
   102     // calculate cursor offset
   110     // calculate cursor offset
   103 
   111 
   104     str:= InputLinePrefix + InputStr.s;
   112     str:= InputLinePrefix + InputStr.s;
   105     font:= CheckCJKFont(ansistring(str), fnt16);
   113     font:= CheckCJKFont(ansistring(str), fnt16);
   106 
   114 
   107     // get only substring before cursor to determine length
   115     // get only substring before cursor to determine length
   108     SetLength(str, Length(InputLinePrefix) + cursorPos);
   116     SetLength(str, Length(InputLinePrefix) + cursorPos);
   109     // get render size of text
   117     // get render size of text
   110     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil);
   118     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil);
   111 
   119 
   112 
       
   113     cursorX:= 7 - cScreenWidth div 2 + coff;
   120     cursorX:= 7 - cScreenWidth div 2 + coff;
   114 end;
   121 
       
   122     // calculate selection width on screen
       
   123     if selectedPos >= 0 then
       
   124         begin
       
   125         if selectedPos > cursorPos then
       
   126             str:= InputLinePrefix + InputStr.s;
       
   127         SetLength(str, Length(InputLinePrefix) + selectedPos);
       
   128         TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil);
       
   129         selectionDx:= soff - coff;
       
   130         end
       
   131     else
       
   132         selectionDx:= 0;
       
   133 end;
       
   134 
   115 
   135 
   116 procedure ResetCursor();
   136 procedure ResetCursor();
   117 begin
   137 begin
       
   138     ResetSelection();
   118     cursorPos:= 0;
   139     cursorPos:= 0;
   119     UpdateCursorCoords();
   140     UpdateCursorCoords();
   120 end;
   141 end;
   121 
   142 
   122 procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring);
   143 procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring);
   224 inc(visibleCount)
   245 inc(visibleCount)
   225 end;
   246 end;
   226 
   247 
   227 procedure DrawChat;
   248 procedure DrawChat;
   228 var i, t, left, top, cnt: LongInt;
   249 var i, t, left, top, cnt: LongInt;
       
   250     selRect: TSDL_Rect;
   229 begin
   251 begin
   230 ChatReady:= true; // maybe move to somewhere else?
   252 ChatReady:= true; // maybe move to somewhere else?
   231 
   253 
   232 if ChatHidden and (not showAll) then
   254 if ChatHidden and (not showAll) then
   233     visibleCount:= 0;
   255     visibleCount:= 0;
   238 
   260 
   239 // draw chat input line first and under all other lines
   261 // draw chat input line first and under all other lines
   240 if (GameState = gsChat) and (InputStr.Tex <> nil) then
   262 if (GameState = gsChat) and (InputStr.Tex <> nil) then
   241     begin
   263     begin
   242     DrawTexture(left, top, InputStr.Tex);
   264     DrawTexture(left, top, InputStr.Tex);
   243     // draw cursor
   265     if selectedPos < 0 then
   244     if ((RealTicks - LastKeyPressTick) and 512) < 256 then
   266         begin
   245         DrawLineOnScreen(cursorX, top + 2, cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF);
   267         // draw cursor
       
   268         if ((RealTicks - LastKeyPressTick) and 512) < 256 then
       
   269             DrawLineOnScreen(cursorX, top + 2, cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF);
       
   270         end
       
   271     else // draw selection
       
   272         begin
       
   273         selRect.y:= top + 2;
       
   274         selRect.h:= clHeight - 4;
       
   275         if selectionDx < 0 then
       
   276             begin
       
   277             selRect.x:= cursorX + selectionDx;
       
   278             selRect.w:= -selectionDx;
       
   279             end
       
   280         else
       
   281             begin
       
   282             selRect.x:= cursorX;
       
   283             selRect.w:= selectionDx;
       
   284             end;
       
   285 
       
   286         DrawRect(selRect, $FF, $FF, $FF, $40, true);
       
   287         end;
   246     end;
   288     end;
   247 
   289 
   248 
   290 
   249 // draw chat lines
   291 // draw chat lines
   250 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then
   292 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then
   450 {$ENDIF}
   492 {$ENDIF}
   451     GameState:= gsGame;
   493     GameState:= gsGame;
   452     ResetKbd;
   494     ResetKbd;
   453 end;
   495 end;
   454 
   496 
   455 procedure DelBytesFromInputStr(endIdx: integer; count: byte);
   497 procedure DelBytesFromInputStrBack(endIdx: integer; count: byte);
   456 var i, startIdx: integer;
   498 var i, startIdx: integer;
   457 begin
   499 begin
   458     // nothing to do if count is 0
   500     // nothing to do if count is 0
   459     if count = 0 then
   501     if count = 0 then
   460         exit;
   502         exit;
   492 
   534 
   493     btw:= byte(idx) - InputStrL[idx];
   535     btw:= byte(idx) - InputStrL[idx];
   494 
   536 
   495     DelCharFromInputStr:= btw;
   537     DelCharFromInputStr:= btw;
   496 
   538 
   497     DelBytesFromInputStr(idx, btw);
   539     DelBytesFromInputStrBack(idx, btw);
   498 end;
   540 end;
   499 
   541 
       
   542 // unchecked
   500 procedure DoCursorStepForward();
   543 procedure DoCursorStepForward();
   501 begin
   544 begin
   502     if cursorPos < Length(InputStr.s) then
   545     // go to end of next utf8-char
   503         begin
   546     repeat
   504         // go to end of next utf8-char
   547         inc(cursorPos);
   505         repeat
   548     until InputStrL[cursorPos] <> InputStrLNoPred;
   506             inc(cursorPos);
   549 end;
   507         until InputStrL[cursorPos] <> InputStrLNoPred;
   550 
   508         end;
   551 procedure DeleteSelected();
   509 end;
   552 begin
   510 
   553     if (selectedPos >= 0) and (cursorPos <> selectedPos) then
   511 procedure KeyPressChat(Key, Sym: Longword);
   554         begin
       
   555         DelBytesFromInputStrBack(max(cursorPos, selectedPos), abs(selectedPos-cursorPos));
       
   556         cursorPos:= min(cursorPos, selectedPos);
       
   557         ResetSelection();
       
   558         end;
       
   559 end;
       
   560 
       
   561 procedure HandleSelection(enabled: boolean);
       
   562 begin
       
   563 if enabled then
       
   564     begin
       
   565     if selectedPos < 0 then
       
   566         selectedPos:= cursorPos;
       
   567     end
       
   568 else
       
   569     ResetSelection();
       
   570 end;
       
   571 
       
   572 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word);
   512 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0);
   573 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0);
   513 var i, btw, index: integer;
   574 var i, btw, index: integer;
   514     utf8: shortstring;
   575     utf8: shortstring;
   515     action: boolean;
   576     action, selMode, ctrl: boolean;
   516 begin
   577 begin
   517     LastKeyPressTick:= RealTicks;
   578     LastKeyPressTick:= RealTicks;
   518     action:= true;
   579     action:= true;
       
   580 
       
   581     selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0;
       
   582     ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0;
       
   583 
   519     case Sym of
   584     case Sym of
   520         SDLK_BACKSPACE:
   585         SDLK_BACKSPACE:
   521             begin
   586             begin
   522             // remove char before cursor (note: cursorPos is 0-based, char idx isn't)
   587             if selectedPos < 0 then
   523             dec(cursorPos, DelCharFromInputStr(cursorPos));
   588                 begin
       
   589                 // remove char before cursor (note: cursorPos is 0-based, char idx isn't)
       
   590                 dec(cursorPos, DelCharFromInputStr(cursorPos));
       
   591                 end
       
   592             else
       
   593                 DeleteSelected();
   524             UpdateCursorCoords();
   594             UpdateCursorCoords();
   525             end;
   595             end;
   526         SDLK_DELETE:
   596         SDLK_DELETE:
   527             begin
   597             begin
   528             // remove char after cursor
   598             if selectedPos < 0 then
   529             if cursorPos < Length(InputStr.s) then
   599                 begin
   530                 begin
   600                 // remove char after cursor
   531                 DoCursorStepForward();
   601                 if cursorPos < Length(InputStr.s) then
   532                 dec(cursorPos, DelCharFromInputStr(cursorPos));
   602                     begin
   533                 UpdateCursorCoords();
   603                     DoCursorStepForward();
   534                 end;
   604                     dec(cursorPos, DelCharFromInputStr(cursorPos));
       
   605                     end;
       
   606                 end
       
   607             else
       
   608                 DeleteSelected();
       
   609             UpdateCursorCoords();
   535             end;
   610             end;
   536         SDLK_ESCAPE:
   611         SDLK_ESCAPE:
   537             begin
   612             begin
   538             if Length(InputStr.s) > 0 then
   613             if Length(InputStr.s) > 0 then
   539                 begin
   614                 begin
   567             else
   642             else
   568                 begin
   643                 begin
   569                 SetLine(InputStr, LocalStrs[index], true);
   644                 SetLine(InputStr, LocalStrs[index], true);
   570                 InputStrL:= LocalStrsL[index];
   645                 InputStrL:= LocalStrsL[index];
   571                 end;
   646                 end;
   572             // TODO rebuild/restore InputStrL!!
       
   573             cursorPos:= Length(InputStr.s);
   647             cursorPos:= Length(InputStr.s);
       
   648             ResetSelection();
   574             UpdateCursorCoords();
   649             UpdateCursorCoords();
   575             end;
   650             end;
   576         SDLK_HOME:
   651         SDLK_HOME:
   577             begin
   652             begin
   578             if cursorPos > 0 then
   653             if cursorPos > 0 then
   579                 begin
   654                 begin
       
   655                 HandleSelection(selMode);
   580                 cursorPos:= 0;
   656                 cursorPos:= 0;
   581                 UpdateCursorCoords();
   657                 UpdateCursorCoords();
   582                 end;
   658                 end;
   583             end;
   659             end;
   584         SDLK_END:
   660         SDLK_END:
   585             begin
   661             begin
   586             i:= Length(InputStr.s);
   662             i:= Length(InputStr.s);
   587             if cursorPos < i then
   663             if cursorPos < i then
   588                 begin
   664                 begin
   589                 // TODO uft-8
   665                 HandleSelection(selMode);
   590                 cursorPos:= i;
   666                 cursorPos:= i;
   591                 UpdateCursorCoords();
   667                 UpdateCursorCoords();
   592                 end;
   668                 end;
   593             end;
   669             end;
   594         SDLK_LEFT:
   670         SDLK_LEFT:
   595             begin
   671             begin
   596             if cursorPos > 0 then
   672             if cursorPos > 0 then
   597                 begin
   673                 begin
   598                 // go to end of previous utf8-char
   674                 if selMode or (selectedPos < 0) then
   599                 cursorPos:= InputStrL[cursorPos];
   675                     begin
       
   676                     HandleSelection(selMode);
       
   677                     // go to end of previous utf8-char
       
   678                     cursorPos:= InputStrL[cursorPos];
       
   679                     end
       
   680                 else // if we're leaving selection mode, jump to its left end
       
   681                     begin
       
   682                     cursorPos:= min(cursorPos, selectedPos);
       
   683                     ResetSelection();
       
   684                     end;
   600                 UpdateCursorCoords();
   685                 UpdateCursorCoords();
   601                 end;
   686                 end;
   602             end;
   687             end;
   603         SDLK_RIGHT:
   688         SDLK_RIGHT:
   604             begin
   689             begin
   605             DoCursorStepForward();
   690             if cursorPos < Length(InputStr.s) then
   606             UpdateCursorCoords();
   691                 begin
       
   692                 if selMode or (selectedPos < 0) then
       
   693                     begin
       
   694                     HandleSelection(selMode);
       
   695                     DoCursorStepForward();
       
   696                     end
       
   697                 else // if we're leaving selection mode, jump to its right end
       
   698                     begin
       
   699                     cursorPos:= max(cursorPos, selectedPos);
       
   700                     ResetSelection();
       
   701                     end;
       
   702                 UpdateCursorCoords();
       
   703                 end;
   607             end;
   704             end;
   608         SDLK_PAGEUP, SDLK_PAGEDOWN:
   705         SDLK_PAGEUP, SDLK_PAGEDOWN:
   609             begin
   706             begin
   610             // ignore me!!!
   707             // ignore me!!!
       
   708             end;
       
   709         SDLK_a:
       
   710             begin
       
   711             // select all
       
   712             if ctrl then
       
   713                 begin
       
   714                 ResetSelection();
       
   715                 cursorPos:= Length(InputStr.s);
       
   716                 HandleSelection(true);
       
   717                 cursorPos:= 0;
       
   718                 UpdateCursorCoords();
       
   719                 end
       
   720             else
       
   721                 action:= false;
   611             end;
   722             end;
   612         else
   723         else
   613             action:= false;
   724             action:= false;
   614         end;
   725         end;
   615     if not action and (Key <> 0) then
   726     if not action and (Key <> 0) then
   616         begin
   727         begin
       
   728         DeleteSelected();
       
   729 
   617         if (Key < $80) then
   730         if (Key < $80) then
   618             btw:= 1
   731             btw:= 1
   619         else if (Key < $800) then
   732         else if (Key < $800) then
   620             btw:= 2
   733             btw:= 2
   621         else if (Key < $10000) then
   734         else if (Key < $10000) then