Launching Reduce
================

When Reduce is launched it can start up in either command line or
windowed mode. The simple situation is when the user provides explicit
command-line options that instruct it which to try:

   reduce --gui       open a window.
   reduce --nogui     run in current terminal.
   reduce --guimin    open a window, but initially minimised.
   reduce -- logfile  send output to file not screen or console

When one of these options is given the system tries to follow instructions.
If that leads to failure then it will make a "best efforts" attempt to
report back to the user, but in extreme cases it may be failing because
it is unable to establish any communication link at all, and the failure
will necessarily be fairly silent.

The above options have short forms that were the only versions present in
earlier releases of the software:

   --gui       -w+
   --nogui     -w   or   -w-    (-- has the same sort of effect)
   --guimin    -w.

These short options act as simple synonyms for the longer names and so do
not introduce any additional functionality.

The interesting case arises when none of these options are specified. The
system will try to make what it hopes will count as an intelligent choice.
The principle followed is that if Reduce is being invoked via a pipe or
with its standard input or output redirected then that suggests that it
is expected to take its input from the standard input, and hence it should
run in console mode. Also if it will be unable to create a window it
should run in console mode. Otherwise (and this is expected to be the most
common case) it should run in windowed mode.

On a system that uses X11 the policy can be well approximated by testing
isatty(fileno(stdin)) and getenv("DISPLAY"). If stdin (or stdout) is
not attached to a "tty" or if there is no display for X11 to use then the
code should run in console mode. In some ways this is logically twisted
since the test is as to whether stdin and stdout are available and connect
directly to the user, and if they are the program will launch a window and
interact via that rather than via the standard streams! But the reasoning is
that stdin and stdout not being attached to the console represents a special
circumstance that calls for IO involving them to be performed.

On Windows there are a number of issues that make the situation seriously
more messy:
 (1) an application can be linked in "windowed" or "console" mode. A
     windowed application detaches from any console it may have during
     its startup (before code could override that behaviour) while a
     console application will tend to create a visible console to use
     in a way that is most distracting in the case that that is not
     actually required.
 (2) When run from the current standard cygwin terminal (mintty) the
     Windows API reports both stdin and stdout as connected to pipes
     not the keyboard or screen, and Windows screen management calls
     are not available - making line-editing of input a serious problem.
     However when the same binary is run from the older (cmd-based)
     cygwin shell stdin and stdout do show up as "tty"s, and the proper
     way to manage the screen will be via the Windows API.
     Windows appears not to provide a (clean?) way to identify a parent
     process or distinguish nicely between these cases.
 (3) Windows executables can have suffixes ".com" or ".exe" and different
     shells will choose one over the other. And programs can be launched
     by double-clicking an icon as well as by typing a program name.
     This multiplies the number of variations on launch configurations
     painfully.


On Windows my resolution of this will be that in the directory where binary
versions of Reduce live I will have the following five files:

    reduce             a /bin/sh shell script.
    reduce.com         a native windows "console mode" binary.
    reduce.exe         a native windows "windows mode" binary.
    cygwin-reduce.exe  reduce build for use under cygwin, with X11 support.
    not-under-cygwin.exe   a utility program explained below.
    cygwin-isatty.exe      ditto.

The script named plain "reduce" will have at its core
   if not-under-cygwin $*
   then
      reduce.com $*
   else
      cygwin-reduce.exe $*
   fi
but will need additional coding to allow it to specify reliable paths
to find the various executables on. Any desktop or start-menu link should
refer to reduce.exe.

The behaviour should then be as follows:

If Reduce is launched by double-clicking an icon then that starts up
reduce.exe, which had been linked as a window-mode application and so
does not create a spurious console. In this case only windowed execution
is supported.

If the launch is from a traditional DOS shell and the user types the
word "reduce" then "reduce.com" will be launched in preference to either
"reduce" or "reduce.exe". This is the native Windows console mode version.
It can start a window if it wants to, but it also has full access to the
Windows console that launched it.

There are several cases to consider when Reduce is being launched
from some other form of command-line, but in all cases the expectation is
this is some Unix-compatible shell. In such a case the command "reduce"
should resolve and run the script "reduce". This runs a program to judge
which version of Reduce to use. Such a step slows down the process of
starting the system but provides a great deal of flexibility. So all the
uncertainty gets migrated into the "reduce" script and the program that
it invokes.

The program is compiled as a native windows program and so does not need
any external resources (eg special dlls etc). This is desirable because
the shell it is called from may be msys with no cygwin1.dll available
anywhere.

It starts by calling the function GetConsoleScreenBufferInfo() on a handle
that should refer to the standard output. If this call succeeds then the
scripts is presumed to have been called from a shell that is running
directly from an ordinary Windows console. Then invoking reduce.com
will be sensible because all normal aspects of the Windows API will be
available. This situation arises with the old-style Cygwin arrangements when
bash ran within a Windows console, and I hope it often applies with
msys.

If GetConsoleScreenBufferInfo() fails then the shell script is liable to
have been invoked from one of mintty, a terminal running in an X-window (eg
xterm) or via ssh. In all those cases if Reduce is going to end up running
in console mode then it should be invoked as cygwin-reduce.exe since that
binary will know how to interact with the cygwin modelling of ptys that
provide terminal control. Just for now I intend to ignore the though of
some X server other than the cygwin one...

If the command-line for Reduce includes "-w", "-w-" or "--nogui" then the
system will unconditionally start up in console mode, so if run from
mintty (etc) it should definitely use cygwin-reduce.exe. If the command
line contains "-w+", "-w.", "-gui" or "--guimin" then it should
unconditionally try to start up windowed. To give the best chance of success
if DISPLAY is set and looks reasonable cygwin-reduce will be used. If
DISPLAY is not set an attempt with reduce.com will be made.

This leaves the case where reduce is called via mintty but is left
to choose for itself whether to run windowed or not. If DISPLAY or
SSH_HOST is set then cywin-reduce will be used, in the expectation that
having DISPLAY set indicates a willingness to work via X. So we are
finally left with a state where the call is via mintty (or equivalent)
and the user has not given explicit guidance as to whether windowed
use is desired. The normal idea would be that command-line use would
be used in the case that stdin or stdout had been redirected from a file
or via a pipe. To test for this involves another small utility program,
"cygwin.isatty". This can not be combined with the previous one because
it has to link with cygwin1.dll in order to test the cygwin understanding
of ptys.

A further confusion arises in the build and maintenance scripts for all this.
Cygwin often views the name "reduce" as referring to "reduce.exe", so once
"reduce.exe" exists an attempt to create mere undecorated "reduce" gets
into difficulty. Thus some delicacy is involved in setting up the desired
final configuration.

Finally I note some inconveniences that result from all of this:
 (1) There are several extra binaries in the Reduce directory.
 (2) Starting Reduce on Windows will be slightly slowed down.
 (3) In cases where the scheme falls back to use of cygwin-reduce.exe
     that is necessarily only a 32-bit version of the code. So a
     user wishing to run a 64-bit Reduce so they have more memory
     may be inconvenienced. Such users can force use of the native
     version of Reduce by using "reduce.com" explicitly, but perhaps
     a command-line flag is also needed.
 (4) In order that cygwin-reduce.exe can share an image file with
     reduce.com the default search scheme for image files needs internal
     adjustment for that case.
 (5) With all these variations and options it is essentially certain that
     somebody can come up with a combination that has not been covered
     gracefully.



Summary flowchart of decision:

   Double-click on reduce.exe                 no choice to make
   say "reduce" to DOS prompt                 will run reduce.com
   say "reduce.com" or "reduce.exe"           no choice to make

The remaining cases are then when a command-line user types just "reduce"
from a prompt that is not just running the "cmd" commmand processor. I will
assume it is running one of the various Unix-style shells, and hence will
start the "reduce" shell script.

(1) GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE)) succeeds.
  This means that there is a "windows console" available and so
  the script will launch reduce.com
(2) GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_DISK
    or the same for STD_INPUT_HANDLE.
  This means that input or output had been redirected from a disk file. In
  such cases even if there is no console directly attached the supposition
  will be that things are being run in non-interactive mode and so
  reduce.com will be used. In the case "reduce > some.file" with input
  coming from a terminal the effect will be that line-editing of typed
  input is not available if the code is run via ssh or under mintty.
(3) The command-line contains an item "--".
  The "--" option redirects standard output to a file, and so the behaviour
  adopted will be as in (2) above. Note that the parsing of the command
  line will be incomplete and so if "--" appears somewhere where it will
  end up being treated as data not a keyword it will still trigger this
  behaviour. So for instance an attempt to use an image file called "--"
  by specifying the sequence "-i --" will confuse matters.
(4) Now because of (1) we are running in a window that is not based on
  a Windows console. The cases that obviously arise are
     (a) a mintty console
     (b) an X terminal, or via SSH with X forwarding enabled
     (c) via SSH but without X available
  Run a cygwin test program that checks isatty(fileno(stdin)),
  isatty(fileno(stdout)), getenv("DISPLAY") and getenv("SSH_HOST").
(5) If DISPLAY and SSH_HOST are both unset and the two isatty calls both
  say "1" (ie that IO is direct to a (cygwin-style) terminal), add
  "--gui" to the command-line and invoke reduce.com. The belief is that
  this should be a case of usage directly from mintty.
(6) If at least one isatty says "0" then use reduce.com.
(7) use cygwin-reduce.exe




                                                       A C Norman June 2012



