merge ☹
authornemo
Sun, 15 Mar 2015 16:14:43 -0400
changeset 10855 1af1a54d740b
parent 10848 231d3e3d3267 (current diff)
parent 10854 4925438f5ab7 (diff)
child 10856 d080b8d4c114
merge ☹
--- a/QTfrontend/game.cpp	Sun Mar 15 16:14:13 2015 -0400
+++ b/QTfrontend/game.cpp	Sun Mar 15 16:14:43 2015 -0400
@@ -16,6 +16,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <QApplication>
+#include <QClipboard>
+
 #include <QString>
 #include <QCheckBox>
 #include <QByteArray>
@@ -258,6 +261,18 @@
                 .arg(QString::fromUtf8(msg.mid(2).left(size - 4))));
             return;
         }
+        case 'y':
+        {
+            // copy string to clipboard
+            QApplication::clipboard()->setText(QString::fromUtf8(msg.mid(2)));
+            break;
+        }
+        case 'Y':
+        {
+            // paste clipboard to game
+            SendIPC(QString("Y").toAscii() + QApplication::clipboard()->text().toUtf8().left(250).replace('\n', ' '));
+            break;
+        }
         case 'i':
         {
             emit GameStats(msg.at(2), QString::fromUtf8(msg.mid(3)));
--- a/hedgewars/SDLh.pas	Sun Mar 15 16:14:13 2015 -0400
+++ b/hedgewars/SDLh.pas	Sun Mar 15 16:14:43 2015 -0400
@@ -307,8 +307,11 @@
     SDLK_RETURN    = 13;
     SDLK_ESCAPE    = 27;
     SDLK_a         = 97;
+    SDLK_c         = 99;
     SDLK_q         = 113;
+    SDLK_v         = 118;
     SDLK_w         = 119;
+    SDLK_x         = 120;
     SDLK_DELETE    = 127;
     SDLK_KP_ENTER  = 271;
     SDLK_UP        = 273;
--- a/hedgewars/uChat.pas	Sun Mar 15 16:14:13 2015 -0400
+++ b/hedgewars/uChat.pas	Sun Mar 15 16:14:43 2015 -0400
@@ -30,11 +30,13 @@
 procedure DrawChat;
 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word);
 procedure SendHogSpeech(s: shortstring);
+procedure CopyToClipboard(var newContent: shortstring);
 
 implementation
 uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils;
 
 const MaxStrIndex = 27;
+      MaxInputStrLen = 240;
 
 type TChatLine = record
     Tex: PTexture;
@@ -63,11 +65,12 @@
     liveLua: boolean;
     ChatHidden: boolean;
     firstDraw: boolean;
-    InputLinePrefix: shortstring;
+    InputLinePrefix: TChatLine;
     // cursor
     cursorPos, cursorX, selectedPos, selectionDx: LongInt;
     LastKeyPressTick: LongWord;
 
+
 const
     InputStrLNoPred: byte = 255;
 
@@ -110,12 +113,12 @@
 
     // calculate cursor offset
 
-    str:= InputLinePrefix + InputStr.s;
+    str:= InputStr.s;
     font:= CheckCJKFont(ansistring(str), fnt16);
 
     // get only substring before cursor to determine length
-    // SetLength(str, Length(InputLinePrefix) + cursorPos); // makes pas2c unhappy
-    str[0]:= char(Length(InputLinePrefix) + cursorPos);
+    // SetLength(str, cursorPos); // makes pas2c unhappy
+    str[0]:= char(cursorPos);
     // get render size of text
     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil);
 
@@ -125,9 +128,9 @@
     if selectedPos >= 0 then
         begin
         if selectedPos > cursorPos then
-            str:= InputLinePrefix + InputStr.s;
-        // SetLength(str, Length(InputLinePrefix) + selectedPos); // makes pas2c unhappy
-        str[0]:= char(Length(InputLinePrefix) + selectedPos);
+            str:= InputStr.s;
+        // SetLength(str, selectedPos); // makes pas2c unhappy
+        str[0]:= char(selectedPos);
         TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil);
         selectionDx:= soff - coff;
         end
@@ -197,7 +200,7 @@
     begin
     cl.s:= str;
     color:= colors[#6];
-    str:= InputLinePrefix + str + ' ';
+    str:= str + ' ';
     end
 else
     begin
@@ -248,6 +251,24 @@
 inc(visibleCount)
 end;
 
+procedure CheckPasteBuffer(); forward;
+
+procedure UpdateInputLinePrefix();
+begin
+if liveLua then
+    begin
+    InputLinePrefix.color:= colors[#1];
+    InputLinePrefix.s:= '[Lua] >';
+    end
+else
+    begin
+    InputLinePrefix.color:= colors[#6];
+    InputLinePrefix.s:= UserNick + '>';
+    end;
+
+FreeAndNilTexture(InputLinePrefix.Tex);
+end;
+
 procedure DrawChat;
 var i, t, left, top, cnt: LongInt;
     selRect: TSDL_Rect;
@@ -264,13 +285,21 @@
 // draw chat input line first and under all other lines
 if (GameState = gsChat) and (InputStr.Tex <> nil) then
     begin
+    CheckPasteBuffer();
+
+    if InputLinePrefix.Tex = nil then
+        RenderChatLineTex(InputLinePrefix, InputLinePrefix.s);
+
+    DrawTexture(left, top, InputLinePrefix.Tex);
+    inc(left, InputLinePrefix.Width);
+    DrawTexture(left, top, InputStr.Tex);
+
     if firstDraw then
         begin
         UpdateCursorCoords();
         firstDraw:= false;
         end;
 
-    DrawTexture(left, top, InputStr.Tex);
     if selectedPos < 0 then
         begin
         // draw cursor
@@ -294,9 +323,10 @@
 
         DrawRect(selRect, $FF, $FF, $FF, $40, true);
         end;
+
+    dec(left, InputLinePrefix.Width);
     end;
 
-
 // draw chat lines
 if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then
     begin
@@ -458,6 +488,7 @@
                 AddFileLog('[Lua] chat input string parsing disabled');
                 AddChatString(#3 + 'Lua parsing: OFF');
                 end;
+            UpdateInputLinePrefix();
             end;
         exit
         end;
@@ -565,6 +596,7 @@
         cursorPos:= min(cursorPos, selectedPos);
         ResetSelection();
         end;
+    UpdateCursorCoords();
 end;
 
 procedure HandleSelection(enabled: boolean);
@@ -660,6 +692,73 @@
     end;
 end;
 
+procedure CopyToClipboard(var newContent: shortstring);
+begin
+    SendIPC(_S'y' + copy(newContent, 1, 253) + #0);
+end;
+
+procedure CopySelectionToClipboard();
+var selection: shortstring;
+begin
+    if selectedPos >= 0 then
+        begin
+        selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos));
+        CopyToClipboard(selection);
+        end;
+end;
+
+// TODO: honor utf8, don't break utf8 chars when shifting chars beyond limit
+procedure InsertIntoInputStr(s: shortstring);
+var i, l, il, lastc: integer;
+begin
+    // safe length for string
+    l:= min(MaxInputStrLen-cursorPos, Length(s));
+    s:= copy(s,1,l);
+
+    // if we insert rather than append, shift info in InputStrL accordingly
+    if cursorPos < Length(InputStr.s) then
+        begin
+        for i:= Length(InputStr.s) downto cursorPos + 1 do
+            begin
+            if InputStrL[i] <> InputStrLNoPred then
+                begin
+                il:= i + l;
+                // only shift if not overflowing
+                if il <= MaxInputStrLen then
+                    InputStrL[il]:= InputStrL[i] + l;
+                InputStrL[i]:= InputStrLNoPred;
+                end;
+            end;
+        end;
+
+    InputStrL[cursorPos + l]:= cursorPos;
+    // insert string truncated to safe length
+    Insert(s, InputStr.s, cursorPos + 1);
+    if Length(InputStr.s) > MaxInputStrLen then
+        InputStr.s[0]:= char(MaxInputStrLen);
+
+    SetLine(InputStr, InputStr.s, true);
+
+    // move cursor to end of inserted string
+    lastc:= MaxInputStrLen;
+    cursorPos:= min(lastc, cursorPos + l);
+    UpdateCursorCoords();
+end;
+
+procedure PasteFromClipboard();
+begin
+    SendIPC(_S'Y');
+end;
+
+procedure CheckPasteBuffer();
+begin
+    if Length(ChatPasteBuffer) > 0 then
+        begin
+        InsertIntoInputStr(ChatPasteBuffer);
+        ChatPasteBuffer:= '';
+        end;
+end;
+
 procedure KeyPressChat(Key, Sym: Longword; Modifier: Word);
 const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0);
 var i, btw, index: integer;
@@ -670,6 +769,8 @@
     LastKeyPressTick:= RealTicks;
     action:= true;
 
+    CheckPasteBuffer();
+
     selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0;
     ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0;
     skip:= none;
@@ -691,11 +792,13 @@
                     HandleSelection(true);
                     SkipInputChars(skip, true);
                     DeleteSelected();
-                    end;
+                    end
+                else
+                    UpdateCursorCoords();
+
                 end
             else
                 DeleteSelected();
-            UpdateCursorCoords();
             end;
         SDLK_DELETE:
             begin
@@ -718,12 +821,12 @@
                         SkipInputChars(skip, false);
                         DeleteSelected();
                         end;
-                    end;
+                    end
+                else
+                    UpdateCursorCoords();
                 end
             else
                 DeleteSelected();
-
-            UpdateCursorCoords();
             end;
         SDLK_ESCAPE:
             begin
@@ -862,6 +965,33 @@
             else
                 action:= false;
             end;
+        SDLK_c:
+            begin
+            // copy
+            if ctrl then
+                CopySelectionToClipboard()
+            else
+                action:= false;
+            end;
+        SDLK_v:
+            begin
+            // paste
+            if ctrl then
+                PasteFromClipboard()
+            else
+                action:= false;
+            end;
+        SDLK_x:
+            begin
+            // cut
+            if ctrl then
+                begin
+                CopySelectionToClipboard();
+                DeleteSelected();
+                end
+            else
+                action:= false;
+            end;
         else
             action:= false;
         end;
@@ -888,28 +1018,10 @@
 
         utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8;
 
-        if Length(InputStr.s) + btw > 240 then
+        if Length(InputStr.s) + btw > MaxInputStrLen then
             exit;
 
-        // if we insert rather than append, shift info in InputStrL accordingly
-        if cursorPos < Length(InputStr.s) then
-            begin
-            for i:= Length(InputStr.s) downto cursorPos + 1 do
-                begin
-                if InputStrL[i] <> InputStrLNoPred then
-                    begin
-                    InputStrL[i+btw]:= InputStrL[i] + btw;
-                    InputStrL[i]:= InputStrLNoPred;
-                    end;
-                end;
-            end;
-
-        InputStrL[cursorPos + btw]:= cursorPos;
-        Insert(utf8, InputStr.s, cursorPos + 1);
-        SetLine(InputStr, InputStr.s, true);
-
-        cursorPos:= cursorPos + btw;
-        UpdateCursorCoords();
+        InsertIntoInputStr(utf8);
         end
 end;
 
@@ -994,7 +1106,8 @@
     ChatHidden:= false;
     firstDraw:= true;
 
-    InputLinePrefix:= UserNick + '> ';
+    InputLinePrefix.Tex:= nil;
+    UpdateInputLinePrefix();
     inputStr.s:= '';
     inputStr.Tex := nil;
     for i:= 0 to MaxStrIndex do
@@ -1009,6 +1122,7 @@
 procedure freeModule;
 var i: ShortInt;
 begin
+    FreeAndNilTexture(InputLinePrefix.Tex);
     FreeAndNilTexture(InputStr.Tex);
     for i:= 0 to MaxStrIndex do
         FreeAndNilTexture(Strs[i].Tex);
--- a/hedgewars/uIO.pas	Sun Mar 15 16:14:13 2015 -0400
+++ b/hedgewars/uIO.pas	Sun Mar 15 16:14:43 2015 -0400
@@ -163,6 +163,7 @@
              ParseChatCommand('chatmsg ' + #4, s, 2)
           else
              isProcessed:= false;
+     'Y': ChatPasteBuffer:= copy(s, 2, Length(s) - 1);
      else
         isProcessed:= false;
      end;
--- a/hedgewars/uVariables.pas	Sun Mar 15 16:14:13 2015 -0400
+++ b/hedgewars/uVariables.pas	Sun Mar 15 16:14:43 2015 -0400
@@ -237,6 +237,8 @@
 
     MaxTextureSize: LongInt;
 
+    ChatPasteBuffer: shortstring;
+
 /////////////////////////////////////
 //Buttons
 {$IFDEF USE_TOUCH_INTERFACE}
@@ -2685,6 +2687,8 @@
     cStereoDepth:= 0;
     cViewLimitsDebug:= false;
     AprilOne := false;
+
+    ChatPasteBuffer:= '';
 end;
 
 procedure freeModule;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/OfficialChallenges/racer_#15.hwmap	Sun Mar 15 16:14:43 2015 -0400
@@ -0,0 +1,1 @@
+AAACYnicFc9NSJRRFAbgc3/PfP8lqGGLIlpIJVktlHAgXaSRLTLMQIQGwwhJF8UIUs7umHExvCn5CcWgiSFo0SBGUrjJjSAIFZWgQdmiggqjdd9sHs7qfc/rZ2UWwnasg6hS1IMzy7ZBn9BbAEfwEXAu6kBl2FNgGTZbcMpFZSEo5+0F+VLfKMiIbczrMbk2H7RpM8+kXs3zEdlR5BLoa6w77/TqK3nvuuzPh1/lmbxXxarzsCCHYr6i0zEe1Cux14k1RY4nHyRX0CLvx3Jc/IxTa6wpxlL+KQ4n4FsctfLGmLWIVstfiArL38GCVS3wzKppPmJTOXXYukdVifWW9CHr1fAd6+dg0uIyzFj+CmOry3DUph7iPevuxT7r7sc+iPZp3zKr7hjxRlUniE4jf8sfJnVA3zb4Tx4z6peIDS6xdeNe5OkiteB8hxnjZOSkcR/rdJFa8HNi0/hZ1WXCniQvNKLC+DmcMmIR75Ju1OeJN6sBYnk5TJAVVQQd0E+8DK4S32LTxFf5ZRLPYZzkEAyR/CAYiY8yR3BBPSD2Gp8UmQKOqEmcTVDncIpwFy4TliY7cRNHCf+oDCGpbUoNq8/kDKguwlviLekGUUp6B3LknCyyzrrJbU96vXqeJl+J0+ROiD5yG+Qe8rS6Sd4X1UthMy5SsJGkBF1ijsLdRQa5obCH/aXgPSsh/xTLUNCWjInmRCdFpJooWtZjFE7oQfoP92i1IA==
\ No newline at end of file
--- a/share/hedgewars/Data/Scripts/OfficialChallenges.lua	Sun Mar 15 16:14:13 2015 -0400
+++ b/share/hedgewars/Data/Scripts/OfficialChallenges.lua	Sun Mar 15 16:14:43 2015 -0400
@@ -32,6 +32,8 @@
             return("Racer Challenge #5")
         elseif LandDigest == "M479034891Scripts/Multiplayer/Racer.lua" then
             return("Racer Challenge #6")
+        elseif LandDigest == "M256715557Scripts/Multiplayer/Racer.lua" then
+            return("Racer Challenge #15")
         end
     end
 end