Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2017-04

Startup environment: to Gui, or not to GUI?

16 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

Apologies if this is an FAQ.

Is there an orthodox way that a Lazarus program can very early on look at how it's been started and decide whether it can usefully fall back to a text mode, e.g. to display help info on stdout rather than a messagebox?

I'm tinkering with something (a media test program for SDCards etc.) which I'd like to either run as a conventional console program, or using a GUI. I've previously written stuff where operation was entirely dependant on command-line options, but haven't tried making the decision completely automatically.

Current operating environment is KDE on Debian on an RPi.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Henry Vermaak
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 5 lines
Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very early on look at how it's been started and decide whether it can usefully fall back to a text mode, e.g. to display help info on stdout rather than a messagebox?

isatty() is traditionally used for this on POSIX operating systems. It's in unit termio.

Henry

Reply by email

Graeme Geldenhuys
to Mark Morgan Lloyd: Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very…
Mark Morgan Lloyd wrote
Is there an orthodox way that a Lazarus program can very early on look at how it's been started and decide whether it can usefully fall back to a text mode, e.g. to display help info on stdout rather than a messagebox?

In the past I've used a start-up script (unix) or a start-up console app (unix & windows) to detect the environment, then launch the correct binary executable. At the time I didn't know what this the "correct" way of doing this, but I looked for things like x11 in the process list, or looked at the environment variables (eg: DISPLAY). Under Windows I simply you always know a GUI exists, but you can still test to see if stdout is available or now (eg: I have windows GUI apps that output help to a console or ShowMessage() dialog.).

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Mark Morgan Lloyd
to Henry Vermaak: isatty() is traditionally used for this on POSIX operating systems. It's in unit termio.…
Henry Vermaak wrote
On Tue, Apr 11, 2017 at 09:15:16AM +0000, Mark Morgan Lloyd via Lazarus wrote:> Apologies if this is an FAQ.> > Is there an orthodox way that a Lazarus program can very early on look at> how it's been started and decide whether it can usefully fall back to a text> mode, e.g. to display help info on stdout rather than a messagebox? isatty() is traditionally used for this on POSIX operating systems.It's in unit termio.

Thanks Henry, I'll check. I know I've used it in the past when deciding whether a program was actually being fed piped input etc.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Tony Whyman
to Mark Morgan Lloyd: Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very…

This question could be reformulated as "How do I dynamically determine the correct GUI to use or whether to use the nogui interface."

My understanding is that Lazarus programs usually do this at link time as a result of setting the LCL_PLATFORM environment variable. This forces the requested GUI's "interfaces" unit to be included which, in turn, has an "initialization" section that calls the "CreateWidgetSet" procedure for the selected GUI.

Although I've never tried this, I would have thought it possible to build with LVL_PLATFORM=NOGUI and dynamically to test for a platform specific GUI. If present, then "FreeWidgetSet" can be used to unload the NOGUI and a call to CreateWidgetset used to load the required GUI e.g. under Linux:

CreateWidgetset(TGtk2WidgetSet);

with InterfaceBase and Gtk2Int in the uses clauses.

Just an idea,

Tony Whyman

MWA

Mark Morgan Lloyd wrote 15 lines
Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very early on look at how it's been started and decide whether it can usefully fall back to a text mode, e.g. to display help info on stdout rather than a messagebox? I'm tinkering with something (a media test program for SDCards etc.) which I'd like to either run as a conventional console program, or using a GUI. I've previously written stuff where operation was entirely dependant on command-line options, but haven't tried making the decision completely automatically. Current operating environment is KDE on Debian on an RPi.

Reply by email

Mark Morgan Lloyd
to Tony Whyman: This question could be reformulated as "How do I dynamically determine the correct GUI to…
Tony Whyman wrote
This question could be reformulated as "How do I dynamically determine the correct GUI to use or whether to use the nogui interface." My understanding is that Lazarus programs usually do this at link time as a result of setting the LCL_PLATFORM environment variable.

Well, no, it couldn't :-)

What I'm doing is writing a program using the Lazarus IDE and creating the project as "Application" so that I can easily add a full GUI later. I'm manually inserting code immediately after Application.Initialize to pick up command-line options (including --help and --version) which also gives me the ability to run the entire program from the command line if sufficient options/parameters have been supplied.

My experience in the past has been that this approach is reliable, and that it's also possible to raise a dialog for cases such as a program being run from the GUI but with a --version option.

I'm hoping to use this program as a testbed to run in three ways: non-interactively if sufficient options are supplied, with a GUI if no options are supplied, and /possibly/ using a TUI created by dialedit3b but this very much depends on whether the modifications required to get it working can be done in the limited time available.

What that will mean in practice is that irrespective of what widget set the program is compiled for it will also have the capability of running as a non-interactive (batch) utility. Call me old-school if you like but I find that useful.

http://free-pascal-general.1045716.n5.nabble.com/Free-Vision-etc-form-editor-td5727305.html

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Mark Morgan Lloyd: Thanks Henry, I'll check. I know I've used it in the past when deciding whether a program…
Mark Morgan Lloyd wrote 9 lines
On 11/04/17 10:00, Henry Vermaak via Lazarus wrote:> On Tue, Apr 11, 2017 at 09:15:16AM +0000, Mark Morgan Lloyd via Lazarus wrote:> Apologies if this is an FAQ.> > Is there an orthodox way that a Lazarus program can very early on look at> how it's been started and decide whether it can usefully fall back to a text> mode, e.g. to display help info on stdout rather than a messagebox?> isatty() is traditionally used for this on POSIX operating systems.It's in unit termio. Thanks Henry, I'll check. I know I've used it in the past when deciding whether a program was actually being fed piped input etc.

Something like this does appear to work, tested on Linux only.

function notGui(): boolean;
var     i: integer;
begin
   i := IsaTty(Input);
{$ifdef ISGUI }
   exit false;
{$endif ISGUI }
{$ifdef NOGUI }
   exit true;
{$endif NOGUI }
   result := i  0
end { notGui } ;

The explicit overrides might be needed during debugging, since the involvement of gdb forces the program to think it's being run from a shell session.

Looking back through older sources, I've had to jump through hoops- reopening the input and using GetFileType() under Windows- to find out whether stdin was piped. Fortunately I don't need that here.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Henry Vermaak
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 20 lines
Something like this does appear to work, tested on Linux only. function notGui(): boolean; var i: integer; begin i := IsaTty(Input); {$ifdef ISGUI } exit false; {$endif ISGUI } {$ifdef NOGUI } exit true; {$endif NOGUI } result := i 0 end { notGui } ; The explicit overrides might be needed during debugging, since the involvement of gdb forces the program to think it's being run from a shell session.

I'd recommend making the overrides command line parameters. That way you do away with the ifdefs and a user can always override it if your logic somehow doesn't do the right thing.

Looking back through older sources, I've had to jump through hoops- reopening the input and using GetFileType() under Windows- to find out whether stdin was piped. Fortunately I don't need that here.

The experience on Windows is pretty awful and I've seen some interesting tricks to get a program to do the right thing based on where it was launched from. For example, Visual Studio's devenv.com vs. devenv.exe, using the fact that .com takes preference over .exe in the terminal to handle the command line parameters and sending output to the terminal that it was called from.

Henry

Reply by email

Mark Morgan Lloyd
to Henry Vermaak
Henry Vermaak wrote
On Tue, Apr 11, 2017 at 01:34:35PM +0000, Mark Morgan Lloyd via Lazarus wrote:> Something like this does appear to work, tested on Linux only.> > function notGui(): boolean;> > var i: integer;> > begin> i := IsaTty(Input);> {$ifdef ISGUI }> exit false;> {$endif ISGUI }> {$ifdef NOGUI }> exit true;> {$endif NOGUI }> result := i 0> end { notGui } ;> > The explicit overrides might be needed during debugging, since the> involvement of gdb forces the program to think it's being run from a shell> session. I'd recommend making the overrides command line parameters. That wayyou do away with the ifdefs and a user can always override it if yourlogic somehow doesn't do the right thing.

I agree, --GUI and --TUI by choice (case-sensitive, no short form). But from the POV of getting a statement of what appeared to work and its limitations into the record I didn't want to introduce anything extraneous.

> Looking back through older sources, I've had to jump through hoops-> reopening the input and using GetFileType() under Windows- to find out> whether stdin was piped. Fortunately I don't need that here. The experience on Windows is pretty awful and I've seen some interestingtricks to get a program to do the right thing based on where it waslaunched from. For example, Visual Studio's devenv.com vs. devenv.exe,using the fact that .com takes preference over .exe in the terminal tohandle the command line parameters and sending output to the terminalthat it was called from.

Regrettably, investigating that sort of thing in too much depth can get one flagged as a malware writer. A few days ago I saw something very odd happen as a result of some search terms I used when reading up about a particular comms protocol.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Lukasz Sokol
to Mark Morgan Lloyd

On 11/04/17 19:44, Mark Morgan Lloyd via Lazarus wrote: [...]

Show quoted text 6 lines
Regrettably, investigating that sort of thing in too much depth can get one flagged as a malware writer. A few days ago I saw something very odd happen as a result of some search terms I used when reading up about a particular comms protocol.

In Firefox, use the Private Browsing feature, then (at least Google) does not track what you search (also use Google Search in normal mode while logged on to Google (important) on other terms to have them not correlate searches with your IP address and spew them into your personalized set anyway)

my £0.02p worth ;)

-L.

Reply by email

Mark Morgan Lloyd
to Lukasz Sokol
Lukasz Sokol wrote
On 11/04/17 19:44, Mark Morgan Lloyd via Lazarus wrote:[...]> > Regrettably, investigating that sort of thing in too much depth can> get one flagged as a malware writer. A few days ago I saw something> very odd happen as a result of some search terms I used when reading> up about a particular comms protocol.> In Firefox, use the Private Browsing feature, then (at least Google)does not track what you search (also use Google Search in normal mode whilelogged on to Google (important) on other terms to have them not correlate searches with your IP address and spew them into your personalized set anyway) my £0.02p worth ;)

No, somebody and a document I'd been using was
blocked overnight. I don't want to talk about it, but look at what I've edited recently on Wp.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Mark Morgan Lloyd: Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very…
Mark Morgan Lloyd wrote 9 lines
Apologies if this is an FAQ. Is there an orthodox way that a Lazarus program can very early on look at how it's been started and decide whether it can usefully fall back to a text mode, e.g. to display help info on stdout rather than a messagebox? I'm tinkering with something (a media test program for SDCards etc.) which I'd like to either run as a conventional console program, or using a GUI. I've previously written stuff where operation was entirely dependant on command-line options, but haven't tried making the decision completely automatically.

In case it helps anybody avoid wasted time: looking carefully at what I've been doing, it turns out that it's not possible to make an LCL-based program running on unix (i.e. with X11 etc.) to fall back cleanly to text mode, such that it could be run on e.g. a serial terminal, by manipulating the main program unit (.lpr or whatever).

The problem is that the main unit will import LCL units which assume the presence of X11 or equivalent, and that they will attempt to initialise themselves before the main block in the .lpr is run. Hence any attempted decision in the .lpr is too late to be of much use.

A program can fairly easily be written such that if it's started from a shell wrapped in a GUI (Konsole, xterm or whatever) it can display help or version text and quit in good order. The same applies if it's run from an SSH session provided that X11 tunnelling is enabled. But it won't run over e.g. a serial line or from the main console on a non-GUI system, and will probably give problems is executed as root using sudo or setuid.

There might be ways of working round this using a special unit imported early (i.e. like cmem etc.), I've not experimented with that approach.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Michael Van Canneyt
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 16 lines
On 11/04/17 09:30, Mark Morgan Lloyd via Lazarus wrote: > Apologies if this is an FAQ. > Is there an orthodox way that a Lazarus program can very early on look > at how it's been started and decide whether it can usefully fall back to > a text mode, e.g. to display help info on stdout rather than a messagebox? > I'm tinkering with something (a media test program for SDCards etc.) > which I'd like to either run as a conventional console program, or using > a GUI. I've previously written stuff where operation was entirely > dependant on command-line options, but haven't tried making the decision > completely automatically. In case it helps anybody avoid wasted time: looking carefully at what I've been doing, it turns out that it's not possible to make an LCL-based program running on unix (i.e. with X11 etc.) to fall back cleanly to text mode, such that it could be run on e.g. a serial terminal, by manipulating the main program unit (.lpr or whatever).

The simple solution is to write 2 binaries. A text-only one, and a GUI one. The text-only one starts the GUI one if it detects a GUI (or if a command-line element is present).

I see no added value in having everything in 1 binary.

Michael.

Reply by email

Graeme Geldenhuys
to Mark Morgan Lloyd: In case it helps anybody avoid wasted time: looking carefully at what I've been doing, it…
Mark Morgan Lloyd wrote
In case it helps anybody avoid wasted time: looking carefully at what I've been doing, it turns out that it's not possible to make an LCL-based program running on unix (i.e. with X11 etc.)

And it wouldn’t be right if I didn’t offer up an alternative. fpGUI based applications can indeed do what you want. I do this all the time for command line handling. If a GUI program is run from a terminal (no X11 server), it will still output to the console telling the user what program it is, version info, command line parameters and importantly, that it requires a GUI to function. In a GUI environment (eg: MS Windows) it will display a dialog with all the same information, if the -h command line parameter was passed in.

Here is such output of one of my programs (run from the login terminal - no X11):

=======================================
$ ./osmail -h
Opensoft Mail & News v1.00 (build 18)
Compiled on 2017/05/01 11:09:41

The following parameters are available:

h, help Shows this help
lc Logs debug information to the console lv Logs debug information to a visual screen ls Logs debug information to debug server l Logs debug information to a file
style Applies a custom style to the application. Available options are: "auto", "Win2000", "Motif", "Carbon", "Plastic Dark", "Plastic Dark Gray", "Plastic Medium Gray", "Plastic Light Gray"

NOTE: This program requires a graphical windowing environment to function. $
=======================================

So as you can see, what you want to do is possible. Maybe LCL just needs more work around its initialization code - being less eager to initialize its GUI. ;-)

Michael's suggestion of two binaries is also a good idea.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Mark Morgan Lloyd
to Graeme Geldenhuys
Graeme Geldenhuys wrote
On 2017-05-04 11:18, Mark Morgan Lloyd via Lazarus wrote:> In case it helps anybody avoid wasted time: looking carefully at what > I've been doing, it turns out that it's not possible to make an > LCL-based program running on unix (i.e. with X11 etc.) And it wouldn’t be right if I didn’t offer up an alternative. fpGUIbased applications can indeed do what you want. I do this all the timefor command line handling. If a GUI program is run from a terminal (noX11 server), it will still output to the console telling the user whatprogram it is, version info, command line parameters and importantly,that it requires a GUI to function. In a GUI environment (eg: MSWindows) it will display a dialog with all the same information, if the-h command line parameter was passed in. Here is such output of one of my programs (run from the login terminal -no X11):

Agreed, such as --help or --version output. However it looks as though it's important to check anything that attempts this on e.g. the system text-mode console or over something really crude like telnet... and I hope you're doing that for fpGUI since you keep telling us how good it is :-)

So as you can see, what you want to do is possible. Maybe LCL just needsmore work around its initialization code - being less eager toinitialize its GUI. ;-)

I think it could probably be done by slipping a unit in just before cthreads, provided that this terminated aggressively. That's actually less intrusive that the editing I've been doing in the .lpr initialisation block, but it would mean splitting out e.g. text-mode --help and graphics-mode --about into separate places.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email