Größe eines Konsolenfensters ermitteln (Linux)
Größe eines Konsolenfensters ermitteln (Linux)
Guten Tag,
ich betreibe einige Raspi headless. Zugriff ist über SSH, da wird auch mein Programm gestartet.
Mit Initialisierung der Unit CRT steht dann auch die Größen des Bildschirmes in der Variable CRT.WindMax zur Ferfügung.
Diese Variable ist dann Basis für die Errechnung bestimmter Ausgaben innerhalb meines Programmes (GotoXY...Write).
Es funktioniert alles, wie es soll - bis ich die Größe des Konsolenfenster mit z.B. putty verändere.
Kann ich denn überhaupt mit CRT oder einem anderen Unit die Größe des aktuellen Bildschirmes/Konsolenfensters dynamisch abfragen?
Es soll so funktionieren wie bspw. beim Midnight-Commander.
Danke.
jrx
ich betreibe einige Raspi headless. Zugriff ist über SSH, da wird auch mein Programm gestartet.
Mit Initialisierung der Unit CRT steht dann auch die Größen des Bildschirmes in der Variable CRT.WindMax zur Ferfügung.
Diese Variable ist dann Basis für die Errechnung bestimmter Ausgaben innerhalb meines Programmes (GotoXY...Write).
Es funktioniert alles, wie es soll - bis ich die Größe des Konsolenfenster mit z.B. putty verändere.
Kann ich denn überhaupt mit CRT oder einem anderen Unit die Größe des aktuellen Bildschirmes/Konsolenfensters dynamisch abfragen?
Es soll so funktionieren wie bspw. beim Midnight-Commander.
Danke.
jrx
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Größe eines Konsolenfensters ermitteln (Linux)
Kannst dir ja mal diese lib von mir anschauen: https://github.com/Warfley/LazTermUtils
Du musst die lib dann statt crt benutzen (sonst funktioniert die wahrscheinlich nicht). D.h. CRT darf nirgendwo mehr in den uses liegen (das macht sehr unanständige dinge zu den IO filedescriptoren bei der initialization)
Sollte aber alles können was die CRT kann (und mehr).
Du musst die lib dann statt crt benutzen (sonst funktioniert die wahrscheinlich nicht). D.h. CRT darf nirgendwo mehr in den uses liegen (das macht sehr unanständige dinge zu den IO filedescriptoren bei der initialization)
Sollte aber alles können was die CRT kann (und mehr).
Re: Größe eines Konsolenfensters ermitteln (Linux)
Vielen Dank,
ich bin kurz durch die Quellen gestöbert.
Da sind ja einige Sachen drin, die ich sicher gut gebrauchen kann.
Vielen Dank !
Gibt es auch eine Dokumentation?
Zumindest eine Liste der Funktionen/proceduren, Variablen und Konstanten nebst kurzer Beschreibung.
Sorry, dass ich frage
. Das ist ja alles noch ziemlich frisch auf dem Github.
ich bin kurz durch die Quellen gestöbert.
Da sind ja einige Sachen drin, die ich sicher gut gebrauchen kann.
Vielen Dank !
Gibt es auch eine Dokumentation?
Zumindest eine Liste der Funktionen/proceduren, Variablen und Konstanten nebst kurzer Beschreibung.
Sorry, dass ich frage

-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Größe eines Konsolenfensters ermitteln (Linux)
Nö, zum doc schreiben war ich zu faul 
Gibt einige Beispiele:
ColorTest: Zeigt wie man Farben verwendet, den cursor bewegt sowie die fenstergröße ermittelt (und ist ein benchmark für wie schnell deine konsole reagiert), sowie output buffering damit nicht jeder char einzeln ausgegeben wird
NonBlockingReadTest: Updated kontinuierlich die Konsole und checkt regelmäßig ob escape gedrückt wurde, wartet aber nicht darauf das was gemacht wird sondern falls nix gedrückt wurde updated einfach weiter
ReadKeyExample: Zeigt wie man key downs ausliest inklusiver kombinationen wie Strg + Key oder Alt + Key, etc. (Ohne das dabei das was man eintippt von der konsole geechoed wird, wie das normalerweise bei Read oder Readln ist)
TextMod ist ein beispiel für die ausgabemodifikationen (farbe, unterstrichen, etc.) sowie ein benchmark was deine konsole alles unterstützt (z.b. fraktur wird von den meisten konsolen nicht unterstützt).
Ansonsten, relevant sind die Terminal Streams (Input, Output und Error), wobei die Relevanten funktionen für den Output streams (Error und Output) sind:
und für den Input stream:
Außerdem bieten die streams noch einige Read und Write funktionen (Readln, writeln, etc.) zur verfügung die du statt den normalen Readln und writeln funktionen benutzen solltest, da die lib so gebaut ist das sie versucht die normalen Readln und Writeln funktionen möglichst in ruhe zu lassen.
Vor allem gibt es ein paar besonderheiten, wenn DirectRead true ist, wird beim einlesen newline durch #13 (keycode für enter) ersetzt, weshalb ReadLn womöglich nicht funktioniert. Terminal.Input.Readln ist aber so gebaut das es damit klar kommt.
Eine andere besonderheit ist das unter Linux (das teil funktioniert auch unter windows) im direct read modus bei einem writeln der cursor nicht an den anfang der zeile wandert, man muss also CR+LF statt nur LF benutzen (also bei WriteLn müsste man WriteLn(Line, #13); schreiben statt WriteLn(Line)), während sich Terminal.Output.WriteLn darum selbst kümmert.
Du kannst natürlich trozdem (system) readln und writeln benutzen, auf sowas muss man halt nur achten, dann geht das auch. Ich empfehle nur es nicht zu machen, das spart dir viele kopfschmerzen die ich bereits hatte

Gibt einige Beispiele:
ColorTest: Zeigt wie man Farben verwendet, den cursor bewegt sowie die fenstergröße ermittelt (und ist ein benchmark für wie schnell deine konsole reagiert), sowie output buffering damit nicht jeder char einzeln ausgegeben wird
NonBlockingReadTest: Updated kontinuierlich die Konsole und checkt regelmäßig ob escape gedrückt wurde, wartet aber nicht darauf das was gemacht wird sondern falls nix gedrückt wurde updated einfach weiter
ReadKeyExample: Zeigt wie man key downs ausliest inklusiver kombinationen wie Strg + Key oder Alt + Key, etc. (Ohne das dabei das was man eintippt von der konsole geechoed wird, wie das normalerweise bei Read oder Readln ist)
TextMod ist ein beispiel für die ausgabemodifikationen (farbe, unterstrichen, etc.) sowie ein benchmark was deine konsole alles unterstützt (z.b. fraktur wird von den meisten konsolen nicht unterstützt).
Ansonsten, relevant sind die Terminal Streams (Input, Output und Error), wobei die Relevanten funktionen für den Output streams (Error und Output) sind:
Code: Alles auswählen
function WindowSize: TTerminalSize; inline;
function IsATTY: Boolean; inline;
function isOpen: Boolean; inline;
procedure Close; inline;
procedure ModifyOutput(const AModifier: TTerminalModifier); inline;
procedure ResetModifiers; inline;
procedure Clear(ClearMode: TClearMode = cmTotalScreen; Flush: Boolean = False); inline;
procedure ClearLine(ClearMode: TLineClearMode = lcmTotalLine; Flush: Boolean = False); inline;
procedure CursorStartOfLine(Flush: Boolean = False); inline;
procedure CursorMove(X: Integer; Y: Integer; Flush: Boolean = False); inline;
procedure CursorGoto(X: Integer; Y: Integer; Flush: Boolean = False); inline;
procedure CursorGotoX(X: Integer; Flush: Boolean = False); inline;
procedure CursorGotoY(Y: Integer; Flush: Boolean = False); inline;
procedure Bell; inline;
procedure HideCursor; inline;
procedure ShowCursor; inline;
procedure FlushControls; inline;
procedure FlushBuffer; inline;
Code: Alles auswählen
function IsATTY: Boolean; inline;
property DirectRead: Boolean read FDirectRead write SetDirectRead;
Vor allem gibt es ein paar besonderheiten, wenn DirectRead true ist, wird beim einlesen newline durch #13 (keycode für enter) ersetzt, weshalb ReadLn womöglich nicht funktioniert. Terminal.Input.Readln ist aber so gebaut das es damit klar kommt.
Eine andere besonderheit ist das unter Linux (das teil funktioniert auch unter windows) im direct read modus bei einem writeln der cursor nicht an den anfang der zeile wandert, man muss also CR+LF statt nur LF benutzen (also bei WriteLn müsste man WriteLn(Line, #13); schreiben statt WriteLn(Line)), während sich Terminal.Output.WriteLn darum selbst kümmert.
Du kannst natürlich trozdem (system) readln und writeln benutzen, auf sowas muss man halt nur achten, dann geht das auch. Ich empfehle nur es nicht zu machen, das spart dir viele kopfschmerzen die ich bereits hatte
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Größe eines Konsolenfensters ermitteln (Linux)
Irgendwo muss dies in den fpc-sourcen vorhanden sein.Größe eines Konsolenfensters ermitteln (Linux)
Man beachte die fpc-ide, welche in FreeVision läuft.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 955
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: Größe eines Konsolenfensters ermitteln (Linux)
Die IDE, beziehungsweise FreeVision nutzt allerdings die Video Unit, nicht die Crt Unit. Erstere ist mehr für „Vollbild”-Anwendungen gedacht.
Edit: BBCodes gefixt.
Edit: BBCodes gefixt.
Zuletzt geändert von PascalDragon am Di 18. Aug 2020, 13:27, insgesamt 1-mal geändert.
FPC Compiler Entwickler
Re: Größe eines Konsolenfensters ermitteln (Linux)
Den Gedanken hatte ich auch schon, aber tp-ide ermittelt nicht wirklich die aktuelle Fenstergröße der Konsole.
Da wird einfach von links nach rechts geschrieben und am Rand abgeschnitten.
Da wird einfach von links nach rechts geschrieben und am Rand abgeschnitten.
Re: Größe eines Konsolenfensters ermitteln (Linux)
Ich habe mir das heruntergeladen und das *.lpk geöffnet.Warf hat geschrieben: Mo 17. Aug 2020, 23:23 Kannst dir ja mal diese lib von mir anschauen: https://github.com/Warfley/LazTermUtils
Nun habe ich ein example auf meinem Raspi kompiliert. Leider bricht das ab mit der Fehlermeldung
Code: Alles auswählen
Nachrichten, Warnungen: 1
Warning: other unit files search path (aka unit path) of "ReadkeyExample" contains "/home/pi/pascal/Steampi3/LazTermUtils-master/src", which belongs to package "TermUtils"
Projekt kompilieren, Ziel: /home/pi/pascal/Steampi3/LazTermUtils-master/bin/arm-linux/ReadkeyExample: Exit code 1, Fehler: 2, Warnungen: 2, Hinweise: 6
terminalmodifier.pas(149,28) Warning: Function result does not seem to be set
terminalmodifier.pas(156,27) Warning: Function result does not seem to be set
terminalmodifier.pas(99,29) Hint: Parameter "AReset" not used
terminalmodifier.pas(100,29) Hint: Parameter "AReset" not used
terminalmodifier.pas(102,29) Hint: Parameter "AInvert" not used
terminalmodifier.pas(103,29) Hint: Parameter "AInvert" not used
terminalmodifier.pas(501,76) Error: Incompatible type for arg no. 1: Got "{Array Of Const/Constant Open} Array of TTerminalModifier", expected "TModifiers"
terminalmodifier.pas(494,10) Hint: Found declaration: ModifyString(TModifiers;const AnsiString):AnsiString;
terminalmodifier.pas(508,54) Error: Incompatible type for arg no. 1: Got "{Array Of Const/Constant Open} Array of TTerminalModifier", expected "TModifiers"
terminalmodifier.pas(494,10) Hint: Found declaration: ModifyString(TModifiers;const AnsiString):AnsiString;
Code: Alles auswählen
function ColorText(const AString: string; const Foreground: TTextColor): string;
begin
Result := ModifyString([TTerminalModifier.ForegroundModifier(Foreground)], AString);
end;
function ColorText(const AString: string; const Foreground: TTextColor;
const Background: TTextColor): string;
begin
Result := ModifyString([TTerminalModifier.ForegroundModifier(Foreground),
TTerminalModifier.BackgroundModifier(Background)], AString);
end;
jrx
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Größe eines Konsolenfensters ermitteln (Linux)
Was für eine FPC version benutzt du denn? Es kann sein das du 3.2 benötigst an dieser stelle, da ich dort einen dynamischen Array via [...] initialisiere. Kann sein das das erst mit 3.2 kam.
Ansonsten, als fix dafür:
Und ersetzt dann die [...] durch CreateModifierArray([...]);
Das gesagt, wenn du eine ältere FPC version benutzt kann es sein das es dir noch wo anders um die ohren fliegt
Ansonsten, als fix dafür:
Code: Alles auswählen
function CreateModifierArray(Modifiers: Array of TTerminalModifier): TModifiers; inline;
var
i: SizeInt;
begin
SetLength(Result, Length(Modifiers));
for i:=Low(Modifiers) to High(Modifiers) do
Result[i] := Modifiers[i];
end;
Das gesagt, wenn du eine ältere FPC version benutzt kann es sein das es dir noch wo anders um die ohren fliegt
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Größe eines Konsolenfensters ermitteln (Linux)
Muss es aber, und dies sogar sehr komfortabel.jrx hat geschrieben: Di 18. Aug 2020, 11:43 Den Gedanken hatte ich auch schon, aber tp-ide ermittelt nicht wirklich die aktuelle Fenstergröße der Konsole.
Da wird einfach von links nach rechts geschrieben und am Rand abgeschnitten.
Da muss sogar etwas Interruptgesteuertes sein, ansonsten würde die IDE sich nicht automatisch anpassen, wen man zur Laufzeit die Terminal-Grösse ändert.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Größe eines Konsolenfensters ermitteln (Linux)
Kann man auch polling mäßig realisieren. Mit meiner lib z.b. würde ich das so machen:Mathias hat geschrieben: Di 18. Aug 2020, 15:22 Da muss sogar etwas Interruptgesteuertes sein, ansonsten würde die IDE sich nicht automatisch anpassen, wen man zur Laufzeit die Terminal-Grösse ändert.
Code: Alles auswählen
While not Terminated do // global variable oder was auch immer
begin
// für nen resize checken
windowSize := Terminal.Output.GetWindowSize;
if (windowSize.X <> oldWindowSize.y) or (windowSize.y <> oldWindowSize.y) then
begin
HandleResize(oldWindowSize, windowSize);
oldWindowSize := windowSize;
end;
// key downs checken, ohne das dabei was geprinted wird
Terminal.Input.DirectRead := true;
try
if Terminal.Input.ReadKeyNonBlocking(k) then
HandleKeyDown(k);
finally
Terminal.Input.DirectRead := true;
end;
// Fenster zeichnen, wenn man große sachen zeichnet cursor hiden sonst flackerts
Terminal.Output.HideCursor;
try
// buffering aktivieren um performanter zu schreiben
Terminal.Output.BufferSize := SizeInt.MaxValue;
try
RedrawWindow(Terminal.Output, windowSize);
finally
Terminal.Output.FlushBuffer;
Terminal.Output.BufferSize := 0;
end;
finally
Terminal.Output.ShowCursor;
end;
end;
Damit kann ich bei nem full screen terminal (auf nem 1080p bildschirm mit font size 12) problemlos 60-70 fps erreichen. Damit könnte man sogar spiele (mit miserabeler auflösung) programmieren.
Diese Lib ist übrigens nicht mein erster Versuch in diese Richtug, sondern ich hab bereits schon mal eine lib geschrieben genau für solche full screen terminal Applications, allerdings hab ich mich da extrem in Kompatibilitätsprobleme zwischen Windows und *Nix (xterm) verrannt, weshalb mir kein besseres wort für diesen Code als clusterfuck einfällt.
Link: https://github.com/Warfley/LazTextForms
Die neue lib benutzt ausschließlich xterm kompatible escape sequences, was mittlerweile sogar mit windows kompatibel ist, ist aber konzeptionell sehr an das ursprungsprojekt von mir angelehnt.
Während ich zwar der meinung bin das man den alten code von mir nur verwenden sollte wenn man wirklich sehr mutig ist, hat der code aber sogar zu nem gewissen grad funktioniert, eine beispiel TUI anwendung kann man z.b. hier finden: https://github.com/Warfley/PokeTeamBuilder
Re: Größe eines Konsolenfensters ermitteln (Linux)
Unit Video ist mein Schlüssel zum Glück.
Hier der "Brachial Code" zum ausprobieren.
Strg-C beendet dieses Machwerk.
Das geht sicher noch ordentlicher. 
Hier der "Brachial Code" zum ausprobieren.
Strg-C beendet dieses Machwerk.

Code: Alles auswählen
program project1;
uses
video,sysutils;
begin
InitVideo;
repeat
Writeln('VideobufSize: ',VideoBufSize);
SetCursorPos(ScreenWidth-10,ScreenHeight-1);
Write('Rechts u.');
sleep(300);
DoneVideo;
InitVideo;
until False;
end.

-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Größe eines Konsolenfensters ermitteln (Linux)
Und sogar Plattfomübergreifend.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Größe eines Konsolenfensters ermitteln (Linux)
Wobei ich den Ansatz von Warf sehr ordentlich finde, nachzuschauen, ob sich etwas geändert hat und erst dann zu reagieren 

Gruß, Michael
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Größe eines Konsolenfensters ermitteln (Linux)
Ich habe mal ein bisschen rumprobiert, da bleibt tatsächlich die Ausgabe immer gleich, wen ich das Termin-Fenster zu Laufzeit in der Grösse verändere.
Für Linux-User gibt es noch eine Möglichkeit mit der Unit ncurses.
Der Vorteil dabei, es muss keine externe Package für Lazarus installiert werden.
Einziger Wermutstropfen, folgende Packet muss installiert werden:
Aber das werden die meisten Linuxler sowieso schon installiert haben.
Code: Alles auswählen
uses Crt;
begin
repeat
WriteLn(WindMaxX, ' ', WindMaxY);
until KeyPressed;
end.
Der Vorteil dabei, es muss keine externe Package für Lazarus installiert werden.
Einziger Wermutstropfen, folgende Packet muss installiert werden:
Code: Alles auswählen
sudo apt install libncurses-dev
Code: Alles auswählen
uses ncurses;
var
x, y: integer;
begin
initscr;
repeat
refresh;
getmaxyx(stdscr, y, x);
mvprintw(4, 5, 'X: %d, Y: %d', y, x);
until False;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot