Есть: Lazarus+Linux
Есть консольно приложение, которое выводит содержимое файла, и содержит еще пару рабочих потоков.
Как этим потокам что либо передать с клавиатуры?
Read в потоке - плохой вариант, так как весь мусор появляется на экране.
Каким образом это решается?
Консоль + клавиатура
Модератор: Модераторы
Ладно, пока вырезал вот такого кадавра из CRT. Потом разберемся что к чему. Это вроде работает.
Код: Выделить всё
//------------------------------------------------------------------------------
// Cut from CRT.pas
//------------------------------------------------------------------------------
unit KeyboardWork;
{$mode objfpc}{$H+}
interface
uses
BaseUnix ,unix, termio,
Classes, SysUtils;
function ReadKey:char;
implementation
{*************************************************************************
KeyBoard
*************************************************************************}
Const
InSize=256;
OutSize=1024;
KeyBufferSize = 20;
ttyIn=0; {Handles for stdin/stdout}
var
KeyBuffer : Array[0..KeyBufferSize-1] of Char;
KeyPut,
KeySend : longint;
InCnt: longint;
InHead: longint;
InTail : longint;
InBuf : array[0..InSize-1] of char;
Procedure PushKey(Ch:char);
Var
Tmp : Longint;
Begin
Tmp:=KeyPut;
Inc(KeyPut);
If KeyPut>=KeyBufferSize Then
KeyPut:=0;
If KeyPut<>KeySend Then
KeyBuffer[Tmp]:=Ch
Else
KeyPut:=Tmp;
End;
Function PopKey:char;
Begin
If KeyPut<>KeySend Then
Begin
PopKey:=KeyBuffer[KeySend];
Inc(KeySend);
If KeySend>=KeyBufferSize Then
KeySend:=0;
End
Else
PopKey:=#0;
End;
Procedure PushExt(b:byte);
begin
PushKey(#0);
PushKey(chr(b));
end;
{Get Char from Remote}
function ttyRecvChar:char;
var
Readed,i : longint;
begin
{Buffer Empty? Yes, Input from StdIn}
if (InHead=InTail) then
begin
{Calc Amount of Chars to Read}
i:=InSize-InHead;
if InTail>InHead then
i:=InTail-InHead;
{Read}
Readed:=fpread(TTYIn, InBuf[InHead],i);
{Increase Counters}
inc(InCnt,Readed);
inc(InHead,Readed);
{Wrap if End has Reached}
if InHead>=InSize then
InHead:=0;
end;
{Check Buffer}
if (InCnt=0) then
ttyRecvChar:=#0
else
begin
ttyRecvChar:=InBuf[InTail];
dec(InCnt);
inc(InTail);
if InTail>=InSize then
InTail:=0;
end;
end;
const
AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-=';
AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+
#044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131;
Function FAltKey(ch:char):byte;
var
Idx : longint;
Begin
Idx:=Pos(ch,AltKeyStr);
if Idx>0 then
FAltKey:=byte(AltCodeStr[Idx])
else
FAltKey:=0;
End;
{ This one doesn't care about keypresses already processed by readkey }
{ and waiting in the KeyBuffer, only about waiting keypresses at the }
{ TTYLevel (including ones that are waiting in the TTYRecvChar buffer) }
function sysKeyPressed: boolean;
var
fdsin : tfdSet;
begin
if (InCnt>0) then
sysKeyPressed:=true
else
begin
fpFD_ZERO(fdsin);
fpFD_SET(TTYin,fdsin);
sysKeypressed:=(fpSelect(TTYIn+1,@fdsin,nil,nil,0)>0);
end;
end;
Function KeyPressed:Boolean;
Begin
Keypressed := (KeySend<>KeyPut) or sysKeyPressed;
End;
function ReadKey:char;
Var
ch : char;
OldState,
State : longint;
FDS : TFDSet;
Begin
{Check Buffer first}
if KeySend<>KeyPut then
begin
ReadKey:=PopKey;
exit;
end;
{Wait for Key}
{ Only if none are waiting! (JM) }
if not sysKeyPressed then
begin
FpFD_ZERO (FDS);
fpFD_SET (0,FDS);
fpSelect (1,@FDS,nil,nil,nil);
end;
ch:=ttyRecvChar;
{Esc Found ?}
CASE ch OF
#27: begin
State:=1;
Sleep(10);
{ This has to be sysKeyPressed and not "keyPressed", since after }
{ one iteration keyPressed will always be true because of the }
{ pushKey commands (JM) }
while (State<>0) and (sysKeyPressed) do
begin
ch:=ttyRecvChar;
OldState:=State;
State:=0;
case OldState of
1 : begin {Esc}
case ch of
'a'..'z',
'0'..'9',
'-','=' : PushExt(FAltKey(ch));
#10 : PushKey(#10);
'[' : State:=2;
{$IFDEF Unix}
'O': State:=7;
{$ENDIF}
else
begin
PushKey(ch);
PushKey(#27);
end;
end;
end;
2 : begin {Esc[}
case ch of
'[' : State:=3;
'A' : PushExt(72);
'B' : PushExt(80);
'C' : PushExt(77);
'D' : PushExt(75);
{$IFDEF FREEBSD}
{'E' - Center key, not handled in DOS TP7}
'F' : PushExt(79); {End}
'G': PushExt(81); {PageDown}
{$ELSE}
'G' : PushKey('5'); {Center key, Linux}
{$ENDIF}
'H' : PushExt(71);
{$IFDEF FREEBSD}
'I' : PushExt(73); {PageUp}
{$ENDIF}
'K' : PushExt(79);
{$IFDEF FREEBSD}
'L' : PushExt(82); {Insert - Deekoo}
'M' : PushExt(59); {F1-F10 - Deekoo}
'N' : PushExt(60); {F2}
'O' : PushExt(61); {F3}
'P' : PushExt(62); {F4}
'Q' : PushExt(63); {F5}
'R' : PushExt(64); {F6}
'S' : PushExt(65); {F7}
'T' : PushExt(66); {F8}
'U' : PushExt(67); {F9}
'V' : PushExt(68); {F10}
{Not sure if TP/BP handles F11 and F12 like this normally;
In pcemu, a TP7 executable handles 'em this way, though.}
'W' : PushExt(133); {F11}
'X' : PushExt(134); {F12}
'Y' : PushExt(84); {Shift-F1}
'Z' : PushExt(85); {Shift-F2}
'a' : PushExt(86); {Shift-F3}
'b' : PushExt(87); {Shift-F4}
'c' : PushExt(88); {Shift-F5}
'd' : PushExt(89); {Shift-F6}
'e' : PushExt(90); {Shift-F7}
'f' : PushExt(91); {Shift-F8}
'g' : PushExt(92); {Shift-F9}
'h' : PushExt(93); {Shift-F10}
'i' : PushExt(135); {Shift-F11}
'j' : PushExt(136); {Shift-F12}
'k' : PushExt(94); {Ctrl-F1}
'l' : PushExt(95);
'm' : PushExt(96);
'n' : PushExt(97);
'o' : PushExt(98);
'p' : PushExt(99);
'q' : PushExt(100);
'r' : PushExt(101);
's' : PushExt(102);
't' : PushExt(103); {Ctrl-F10}
'u' : PushExt(137); {Ctrl-F11}
'v' : PushExt(138); {Ctrl-F12}
{$ENDIF}
'1' : State:=4;
'2' : State:=5;
'3' : State:=6;
'4' : PushExt(79);
'5' : PushExt(73);
'6' : PushExt(81);
else
begin
PushKey(ch);
PushKey('[');
PushKey(#27);
end;
end;
if ch in ['4'..'6'] then
State:=255;
end;
3 : begin {Esc[[}
case ch of
'A' : PushExt(59);
'B' : PushExt(60);
'C' : PushExt(61);
'D' : PushExt(62);
'E' : PushExt(63);
end;
end;
4 : begin {Esc[1}
case ch of
'~' : PushExt(71);
'5' : State := 8;
'7' : PushExt(64);
'8' : PushExt(65);
'9' : PushExt(66);
end;
if not (Ch in ['~', '5']) then
State:=255;
end;
5 : begin {Esc[2}
case ch of
'~' : PushExt(82);
'0' : pushExt(67);
'1' : PushExt(68);
'3' : PushExt(133); {F11}
{Esc[23~ is also shift-F1,shift-F11}
'4' : PushExt(134); {F12}
{Esc[24~ is also shift-F2,shift-F12}
'5' : PushExt(86); {Shift-F3}
'6' : PushExt(87); {Shift-F4}
'8' : PushExt(88); {Shift-F5}
'9' : PushExt(89); {Shift-F6}
end;
if (Ch<>'~') then
State:=255;
end;
6 : begin {Esc[3}
case ch of
'~' : PushExt(83); {Del}
'1' : PushExt(90); {Shift-F7}
'2' : PushExt(91); {Shift-F8}
'3' : PushExt(92); {Shift-F9}
'4' : PushExt(93); {Shift-F10}
end;
if (Ch<>'~') then
State:=255;
end;
{$ifdef Unix}
7 : begin {Esc[O}
case ch of
'A' : PushExt(72);
'B' : PushExt(80);
'C' : PushExt(77);
'D' : PushExt(75);
'P' : PushExt(59);
'Q' : PushExt(60);
'R' : PushExt(61);
'S' : PushExt(62);
end;
end;
{$endif}
8 : begin {Esc[15}
case ch of
'~' : PushExt(63);
end;
end;
255 : ;
end;
if State<>0 then
Sleep(10);
end;
if State=1 then
PushKey(ch);
end;
#127: PushKey(#8);
else PushKey(ch);
End;
ReadKey:=PopKey;
End;
Procedure Delay(MS: Word);
{
Wait for DTime milliseconds.
}
Begin
fpSelect(0,nil,nil,nil,MS);
End;
end.
-
Mirage
- энтузиаст
- Сообщения: 881
- Зарегистрирован: 06.05.2005 20:29:07
- Откуда: Russia
- Контактная информация:
А где здесь синхронизация? Как это может работать, будучи вызываемым в разных потоках? Тут же data race будет.
А одно лишь то, что оно "вроде работает" еще не значит, что оно работает.
И почему бы не читать с клавиатуры в одном потоке, а затем раздавать прочитанное другим, не забывая синхронизировать доступ?
А одно лишь то, что оно "вроде работает" еще не значит, что оно работает.
И почему бы не читать с клавиатуры в одном потоке, а затем раздавать прочитанное другим, не забывая синхронизировать доступ?
Mirage писал(а):А где здесь синхронизация? Как это может работать, будучи вызываемым в разных потоках? Тут же data race будет.
А одно лишь то, что оно "вроде работает" еще не значит, что оно работает.
Оно работает. В пустом потоке читаю состояние ReadKey, и раздаю остальным. Собственно и все.
Mirage писал(а):И почему бы не читать с клавиатуры в одном потоке, а затем раздавать прочитанное другим, не забывая синхронизировать доступ
Как это сделать? Чем клаву читать?
Добавлено спустя 2 часа 41 минуту 9 секунд:
Еще вопрос, возможно у TApplication есть какие то методы борьбы с клавиатурой. Должны же быть.
Добавлено спустя 3 минуты 24 секунды:
Точнее у TCustomApplication.
TApplication потянет за собой GUI.
