История изменений
Исправление bormant, (текущая версия) :
Посмотрел код, повнимательнее бы надо...
Например, PrepareBuffer
:
Потенциальный выход за границы массива:
1) проверки вроде iBuf[Last - 3]
хорошо бы предварять (Last>=3) and
Неоптимальности:
1) пачка копирований между KeyBuf, iBuf, oBuf: зачем?
2) если и копировать массивы, почему отдельным циклом поэлементно, а не не по Copy()
?
3) внутри циклов SetLength(xBuf, Length(xBuf)+1): зачем?
На первый взгляд, PrepareBuffer
мог бы выглядеть как-то так (если правильно идею уловил):
function IsEvCV(const E: input_event; ACode: cuint16; AValue: cint32): boolean; inline;
begin
with E do Result := (Value = AValue) and (Code = ACode);
end;
procedure PrepareBuffer;
var
i, k, Len: integer;
begin
//get rid of replace keys
Len := Length(KeyBuf);
if (Len >= 4) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 3], Key_RPL, 1) and
(KeyBuf[Len - 2].Value = 0) and (KeyBuf[Len - 2].code in Shifts) and
(KeyBuf[Len - 4].Value = 1) and (KeyBuf[Len - 4].code in Shifts)
then
Dec(Len, 4)
else if (Len >= 2) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 2], Key_RPL, 1)
then
Dec(Len, 2 + Ord((Len >= 3) and (KeyBuf[Len - 3].Value = 1)));
//cut of last line only
i := Len - 2;
while (i >= 0) and not IsEvCV(KeyBuf[i], KEY_ENTER, 0) do Dec(i);
if i >= 0 then
begin
k := Len; Len := 0;
for i := i + 1 to k - 1 do
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
//get rid of shiftdown-shiftup or BS
k := Len; Len := 0;
for i := 0 to k - 1 do
begin
if (Len > 0) and
(KeyBuf[i].code in Shifts) and
(KeyBuf[Len - 1].code in Shifts)
then
Dec(Len)
else if (KeyBuf[i].code = KEY_BACKSPACE) then
begin
if Len > 0 then
begin
Dec(Len);
if (KeyBuf[Len].code in Shifts) and (Len > 0) then
KeyBuf[Len - 1] := KeyBuf[Len];
end;
end
else
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
SetLength(KeyBuf, Len);
sleep(10);
end;
Исправление bormant, :
Посмотрел код, повнимательнее бы надо...
Например, PrepareBuffer
:
Потенциальный выход за границы массива:
1) проверки вроде iBuf[Last - 3]
хорошо бы предварять (Last>=3) and
Неоптимальности:
1) пачка копирований между KeyBuf, iBuf, oBuf: зачем?
2) если и копировать массивы, почему отдельным циклом поэлементно, а не не по Copy()
?
3) внутри циклов SetLength(xBuf, Length(xBuf)+1): зачем?
На первый взгляд, PrepareBuffer
мог бы выглядеть как-то так (если правильно идею уловил):
function IsEvCV(const E: input_event; ACode: cuint16; AValue: cint32): boolean; inline;
begin
with E do Result := (Value = AValue) and (Code = ACode);
end;
procedure PrepareBuffer;
var
i, k, Len: integer;
begin
//get rid of replace keys
Len := Length(KeyBuf);
if (Len >= 4) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 3], Key_RPL, 1) and
(KeyBuf[Len - 2].Value = 0) and (KeyBuf[Len - 2].code in Shifts) and
(KeyBuf[Len - 4].Value = 1) and (KeyBuf[Len - 4].code in Shifts)
then
Dec(Len, 4)
else if (Len >= 2) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 2], Key_RPL, 1)
then
Dec(Len, 2 + Ord((Len >= 3) and (KeyBuf[Len - 3].Value = 1)));
//cut of last line only
i := Len - 2;
while (i >= 0) and not IsEvCV(KeyBuf[i], KEY_ENTER, 0) do Dec(i);
if i > 0 then
begin
k := Len; Len := 0;
for i := i to k - 1 do
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
//get rid of shiftdown-shiftup or BS
k := Len; Len := 0;
for i := 0 to k - 1 do
begin
if (Len > 0) and
(KeyBuf[i].code in Shifts) and
(KeyBuf[Len - 1].code in Shifts)
then
Dec(Len)
else if (KeyBuf[i].code = KEY_BACKSPACE) then
begin
if Len > 0 then
begin
Dec(Len);
if (KeyBuf[Len].code in Shifts) and (Len > 0) then
KeyBuf[Len - 1] := KeyBuf[Len];
end;
end
else
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
SetLength(KeyBuf, Len);
sleep(10);
end;
Исходная версия bormant, :
Посмотрел код, повнимательнее бы надо...
Например, PrepareBuffer
:
Потенциальный выход за границы массива:
1) проверки вроде iBuf[Last - 3]
хорошо бы предварять (Last>=3) and
Неоптимальности:
1) пачка копирований между KeyBuf, iBuf, oBuf: зачем?
2) если и копировать массивы, почему отдельным циклом поэлементно, а не не по Copy()
?
3) внутри циклов SetLength(xBuf, Length(xBuf)+1): зачем?
На первый взгляд, PrepareBuffer
мог бы выглядеть как-то так (если правильно идею уловил):
function IsEvCV(const E: input_event; ACode: cuint16; AValue: cint32): boolean; inline;
begin
with E do Result := (Value = AValue) and (Code = ACode);
end;
procedure PrepareBuffer;
var
i, k, Len: integer;
begin
//get rid of replace keys
Len := Length(KeyBuf);
if (Len >= 4) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 3], Key_RPL, 1) and
(KeyBuf[Len - 2].Value = 0) and (KeyBuf[Len - 2].code in Shifts) and
(KeyBuf[Len - 4].Value = 1) and (KeyBuf[Len - 4].code in Shifts)
then
Dec(Len, 4)
else
if (Len >= 2) and
IsEvCV(KeyBuf[Len - 1], Key_RPL, 0) and
IsEvCV(KeyBuf[Len - 2], Key_RPL, 1)
then
Dec(Len, 2 + Ord((Len >= 3) and (KeyBuf[Len - 3].Value = 1)));
//cut of last line only
i := Len - 2;
while (i >= 0) and not IsEvCV(KeyBuf[i], KEY_ENTER, 0) do Dec(i);
if i > 0 then
begin
k := Len; Len := 0;
for i := i to k - 1 do
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
//get rid of shiftdown-shiftup or BS
k := Len; Len := 0;
for i := 0 to k - 1 do
begin
if (Len > 0) and
(KeyBuf[i].code in Shifts) and
(KeyBuf[Len - 1].code in Shifts)
then
Dec(Len)
else if (KeyBuf[i].code = KEY_BACKSPACE) then
begin
if Len > 0 then
begin
Dec(Len);
if (KeyBuf[Len].code in Shifts) and (Len > 0) then
KeyBuf[Len - 1] := KeyBuf[Len];
end;
end
else
begin
KeyBuf[Len] := KeyBuf[i];
Inc(Len);
end;
end;
SetLength(KeyBuf, Len);
sleep(10);
end;