diff -r 64aba90811a2 -r 6369d148cfff hedgewars/uInputHandler.pas --- a/hedgewars/uInputHandler.pas Sat Feb 24 15:24:36 2018 +0100 +++ b/hedgewars/uInputHandler.pas Sun Feb 25 18:57:30 2018 +0100 @@ -99,15 +99,19 @@ // if it has been bound. // Returns -1 if the control has not been bound. function KeyBindToCode(bind: shortstring): LongInt; -var code: LongInt; +var code, index: LongInt; begin - code:= 0; - while (code <= cKeyMaxIndex) and (CurrentBinds[code] <> bind) do inc(code); - if code > cKeyMaxIndex then + index:= 0; + while (index <= High(CurrentBinds.binds)) and (CurrentBinds.binds[index] <> bind) do inc(index); + if index > High(CurrentBinds.binds) then // Return error KeyBindToCode:= -1 - else + else begin + code:= 0; + while (code <= High(CurrentBinds.indices)) and (CurrentBinds.indices[code] <> index) do inc(code); + checkFails(code <= High(CurrentBinds.indices), 'binds registry inconsistency', True); KeyBindToCode:= code; + end; end; // Takes a control name (e.g. 'quit') and returns the corresponding @@ -209,18 +213,23 @@ {$ELSE} // on other systems use this shortcut only if the keys are not bound to any command if tkbd[KeyNameToCode('left_ctrl')] or tkbd[KeyNameToCode('right_ctrl')] then - if ((CurrentBinds[KeyNameToCode('left_ctrl')] = '') or - (CurrentBinds[KeyNameToCode('right_ctrl')] = '')) and - (CurrentBinds[SDLK_w] = '') then + if ((CurrentBinds.indices[KeyNameToCode('left_ctrl')] = 0) or + (CurrentBinds.indices[KeyNameToCode('right_ctrl')] = 0)) and + (CurrentBinds.indices[SDLK_w] = 0) then {$ENDIF} ParseCommand('forcequit', true); end; -if CurrentBinds[code][0] <> #0 then +if CurrentBinds.indices[code] > 0 then begin if (code < cKeyMaxIndex - 2) // means not mouse buttons and KeyDown - and (not ((CurrentBinds[code] = 'put') or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r'))) + and (not ((CurrentBinds.binds[CurrentBinds.indices[code]] = 'put') + or (CurrentBinds.binds[CurrentBinds.indices[code]] = 'ammomenu') + or (CurrentBinds.binds[CurrentBinds.indices[code]] = '+cur_u') + or (CurrentBinds.binds[CurrentBinds.indices[code]] = '+cur_d') + or (CurrentBinds.binds[CurrentBinds.indices[code]] = '+cur_l') + or (CurrentBinds.binds[CurrentBinds.indices[code]] = '+cur_r'))) and (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) then bShowAmmoMenu:= false; @@ -229,20 +238,20 @@ begin Trusted:= Trusted and (not isPaused); //releasing keys during pause should be allowed on the other hand - if CurrentBinds[code] = 'switch' then + if CurrentBinds.binds[CurrentBinds.indices[code]] = 'switch' then LocalMessage:= LocalMessage or gmSwitch - else if CurrentBinds[code] = '+precise' then + else if CurrentBinds.binds[CurrentBinds.indices[code]] = '+precise' then LocalMessage:= LocalMessage or gmPrecise; - ParseCommand(CurrentBinds[code], Trusted); + ParseCommand(CurrentBinds.binds[CurrentBinds.indices[code]], Trusted); if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then ParseCommand('gencmd R', true) end - else if (CurrentBinds[code][1] = '+') then + else if (CurrentBinds.binds[CurrentBinds.indices[code]][1] = '+') then begin - if CurrentBinds[code] = '+precise' then + if CurrentBinds.binds[CurrentBinds.indices[code]] = '+precise' then LocalMessage:= LocalMessage and (not gmPrecise); - s:= CurrentBinds[code]; + s:= CurrentBinds.binds[CurrentBinds.indices[code]]; s[1]:= '-'; ParseCommand(s, Trusted); if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then @@ -250,7 +259,7 @@ end else begin - if CurrentBinds[code] = 'switch' then + if CurrentBinds.binds[CurrentBinds.indices[code]] = 'switch' then LocalMessage:= LocalMessage and (not gmSwitch) end end @@ -321,56 +330,69 @@ ProcessKey(t, False); end; +procedure RegisterBind(var binds: TBinds; key, value: shortstring); +var code: LongInt; +begin + checkFails(binds.lastIndex < 255, 'too many binds', true); + + code:= KeyNameToCode(key); + + checkFails(code >= 0, 'unknown key', true); + + inc(binds.lastIndex); + binds.indices[code]:= binds.lastIndex; + binds.binds[binds.lastIndex]:= value +end; procedure InitDefaultBinds; var i: Longword; begin - DefaultBinds[KeyNameToCode('escape')]:= 'quit'; - DefaultBinds[KeyNameToCode(_S'`')]:= 'history'; - DefaultBinds[KeyNameToCode('delete')]:= 'rotmask'; - DefaultBinds[KeyNameToCode('home')]:= 'rottags'; + RegisterBind(DefaultBinds, 'escape', 'quit'); + RegisterBind(DefaultBinds, _S'`', 'history'); + RegisterBind(DefaultBinds, 'delete', 'rotmask'); + RegisterBind(DefaultBinds, 'home', 'rottags'); //numpad //DefaultBinds[265]:= '+volup'; //DefaultBinds[256]:= '+voldown'; - DefaultBinds[KeyNameToCode(_S'0')]:= '+volup'; - DefaultBinds[KeyNameToCode(_S'9')]:= '+voldown'; - DefaultBinds[KeyNameToCode(_S'8')]:= 'mute'; - DefaultBinds[KeyNameToCode(_S'c')]:= 'capture'; - DefaultBinds[KeyNameToCode(_S'r')]:= 'record'; - DefaultBinds[KeyNameToCode(_S'h')]:= 'findhh'; - DefaultBinds[KeyNameToCode(_S'p')]:= 'pause'; - DefaultBinds[KeyNameToCode(_S's')]:= '+speedup'; - DefaultBinds[KeyNameToCode(_S't')]:= 'chat'; - DefaultBinds[KeyNameToCode(_S'y')]:= 'confirm'; + RegisterBind(DefaultBinds, _S'0', '+volup'); + RegisterBind(DefaultBinds, _S'9', '+voldown'); + RegisterBind(DefaultBinds, _S'8', 'mute'); + RegisterBind(DefaultBinds, _S'c', 'capture'); + RegisterBind(DefaultBinds, _S'r', 'record'); + RegisterBind(DefaultBinds, _S'h', 'findhh'); + RegisterBind(DefaultBinds, _S'p', 'pause'); + RegisterBind(DefaultBinds, _S's', '+speedup'); + RegisterBind(DefaultBinds, _S't', 'chat'); + RegisterBind(DefaultBinds, _S'y', 'confirm'); - DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset'; - DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomin'; - DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomout'; + RegisterBind(DefaultBinds, 'mousem', 'zoomreset'); + RegisterBind(DefaultBinds, 'wheelup', 'zoomin'); + RegisterBind(DefaultBinds, 'wheeldown', 'zoomout'); - DefaultBinds[KeyNameToCode('f12')]:= 'fullscr'; + RegisterBind(DefaultBinds, 'f12', 'fullscr'); - DefaultBinds[KeyNameToCode('mousel')]:= '/put'; - DefaultBinds[KeyNameToCode('mouser')]:= 'ammomenu'; - DefaultBinds[KeyNameToCode('backspace')]:= 'hjump'; - DefaultBinds[KeyNameToCode('tab')]:= 'switch'; - DefaultBinds[KeyNameToCode('return')]:= 'ljump'; - DefaultBinds[KeyNameToCode('space')]:= '+attack'; - DefaultBinds[KeyNameToCode('up')]:= '+up'; - DefaultBinds[KeyNameToCode('down')]:= '+down'; - DefaultBinds[KeyNameToCode('left')]:= '+left'; - DefaultBinds[KeyNameToCode('right')]:= '+right'; - DefaultBinds[KeyNameToCode('left_shift')]:= '+precise'; + RegisterBind(DefaultBinds, 'mousel', '/put'); + RegisterBind(DefaultBinds, 'mouser', 'ammomenu'); + RegisterBind(DefaultBinds, 'backspace', 'hjump'); + RegisterBind(DefaultBinds, 'tab', 'switch'); + RegisterBind(DefaultBinds, 'return', 'ljump'); + RegisterBind(DefaultBinds, 'space', '+attack'); + RegisterBind(DefaultBinds, 'up', '+up'); + RegisterBind(DefaultBinds, 'down', '+down'); + RegisterBind(DefaultBinds, 'left', '+left'); + RegisterBind(DefaultBinds, 'right', '+right'); + RegisterBind(DefaultBinds, 'left_shift', '+precise'); - DefaultBinds[KeyNameToCode('j0a0u')]:= '+left'; - DefaultBinds[KeyNameToCode('j0a0d')]:= '+right'; - DefaultBinds[KeyNameToCode('j0a1u')]:= '+up'; - DefaultBinds[KeyNameToCode('j0a1d')]:= '+down'; - for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+char(48+i); - for i:= 1 to 5 do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i); + RegisterBind(DefaultBinds, 'j0a0u', '+left'); + RegisterBind(DefaultBinds, 'j0a0d', '+right'); + RegisterBind(DefaultBinds, 'j0a1u', '+up'); + RegisterBind(DefaultBinds, 'j0a1d', '+down'); + for i:= 1 to 10 do RegisterBind(DefaultBinds, 'f'+IntToStr(i), 'slot '+char(48+i)); + for i:= 1 to 5 do RegisterBind(DefaultBinds, IntToStr(i), 'timer '+IntToStr(i)); loadBinds('dbind', cPathz[ptConfig] + '/settings.ini'); end; @@ -437,7 +459,7 @@ t: LongInt; begin for t:= 0 to cKbdMaxIndex do - if (CurrentBinds[t] <> binds[t]) and tkbd[t] then + if (CurrentBinds.binds[CurrentBinds.indices[t]] <> binds.binds[binds.indices[t]]) and tkbd[t] then ProcessKey(t, False); CurrentBinds:= binds; @@ -627,7 +649,7 @@ procedure addBind(var binds: TBinds; var id: shortstring); var KeyName, Modifier, tmp: shortstring; - i, b: LongInt; + i, code, b: LongInt; begin KeyName:= ''; Modifier:= ''; @@ -651,14 +673,26 @@ else begin // add bind: first check if this cmd is already bound, and remove old bind - i:= cKbdMaxIndex; + code:= High(binds.binds); repeat - dec(i) - until (i < 0) or (binds[i] = KeyName); - if (i >= 0) then - binds[i]:= ''; + dec(code) + until (code < 0) or (binds.binds[code] = KeyName); + if (code >= 0) then + begin + i:= 0; + while (i <= High(binds.indices)) and (binds.indices[i] <> code) do inc(i); + checkFails(i <= High(binds.indices), 'binds registry inconsistency', true); + binds.binds[i]:= ''; + binds.indices[code]:= 0 + end else + begin + inc(binds.lastIndex); + checkFails(binds.lastIndex < High(binds.binds), 'too many binds', true); + i:= binds.lastIndex + end; - binds[b]:= KeyName; + binds.indices[b]:= i; + binds.binds[i]:= KeyName end end;