------------------------------------------------------------------------------
-- WINDOWS                                                                  --
--                                                                          --
-- Part of TextTools                                                        --
-- Designed and Programmed by Ken O. Burtch                                 --
--                                                                          --
------------------------------------------------------------------------------
--                                                                          --
--                 Copyright (C) 1999-2007 Ken O. Burtch                    --
--                                                                          --
-- This is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  This is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
-- for  more details.  You should have  received  a copy of the GNU General --
-- Public License  distributed with this;  see file COPYING.  If not, write --
-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
-- MA 02111-1307, USA.                                                      --
--                                                                          --
-- As a special exception,  if other files  instantiate  generics from this --
-- unit, or you link  this unit with other files  to produce an executable, --
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
-- covered  by the  GNU  General  Public  License.  This exception does not --
-- however invalidate  any other reasons why  the executable file  might be --
-- covered by the  GNU Public License.                                      --
--                                                                          --
-- This is maintained at http://www.pegasoft.ca/tt.html                     --
--                                                                          --
------------------------------------------------------------------------------
with common; use common;
  pragma Elaborate( Common );
with os; use os;
with userio; use userio;
with controls; use controls;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package windows is

---> Housekeeping

procedure StartupWindows;
procedure IdleWindows( IdlePeriod : in Duration );
procedure ShutdownWindows;

---> Windows

type AWindowStyle is (Normal, Frameless, Success, Warning, Danger, Status,
                      Emphasis, Subdued, Floating, MenuBar, Menu);
pragma convention( C, AWindowStyle );
type AWindowNumber is new short_integer range 0..16; -- number of windows
CurrentWindow : AWindowNumber;                       -- the active window

type RedrawingAmounts is (none, frame, whole );
pragma convention( C, RedrawingAmounts );
-- You can optimize the redrawing:
--   none: draw only controls, don't redraw window itself
--   frame: draw window frame only and controls
--   whole: erase and redraw whole window and controls

type AWindowDrawingCallBack is access procedure;

type LongLineHandling is (none, justify, wrap );
pragma convention( C, LongLineHandling );

function  OpenWindow( title : in String ; l, t, r, b : integer;
          Style : AWindowStyle := Normal; HasInfoBar : boolean := false;
          CallBack : AWindowDrawingCallBack := null ) return AWindowNumber;
procedure OpenWindow( title : in String ; l, t, r, b : integer;
          Style : AWindowStyle := Normal; HasInfoBar : boolean := false;
          CallBack : AWindowDrawingCallBack := null );
procedure SaveWindow( path : string; arch : APathName := "" );
procedure LoadWindow( path : string; arch : APathName := "" );
procedure EraseWindow;
procedure DrawWindow( id : AWindowNumber;
              Redraw : RedrawingAmounts := none );
procedure DrawWindow( Redraw : RedrawingAmounts := none );
procedure MoveWindow( id : AWindowNumber; dx, dy : integer );
procedure MoveWindow( dx, dy : integer );
procedure ScrollWindow( id : AWindowNumber; dx, dy : integer );
procedure ScrollWindow( dx, dy : integer );
procedure CloseWindow; -- clears controls, too.
procedure ShellOut( cmd : In String );
procedure SetInfoText( text : in String );
procedure SetWindowTimeout( c : AControlNumber; t : in Duration );
procedure SetWindowTitle( title : in String );

function  GetWindowTitle( id : AWindowNumber ) return String;
function  GetWindowStyle( id : AWindowNumber ) return AWindowStyle;
function  GetWindowCallBack(id : AWindowNumber) return AWindowDrawingCallBack;
function  GetWindowHasFrame( id : AWindowNumber ) return boolean;
function  GetWindowFrame( id : AWindowNumber ) return ARect;
function  GetWindowFrameColour( id : AWindowNumber ) return APenColourName;
function  GetWindowContent( id : AWindowNumber ) return ARect;
function  GetWindowHasInfoBar( id : AWindowNumber ) return boolean;
function  GetWindowInfoText( id : AWindowNumber ) return string;
function  GetWindowXScroll( id : AWindowNumber ) return integer;
function  GetWindowYScroll( id : AWindowNumber ) return integer;

--procedure SwapWindows( id1, id2 : AWindowNumber );
--procedure MoveToFront( id : AWindowNumber );
--procedure MoveToBack( id : AWindowNumber );

procedure ResetWindow( id : AWindowNumber );
procedure ResetWindow;
procedure RefreshDesktop;

---> Controls in Windows
--

procedure AddControl( ptr : AControlPtr;  -- pointer to the control
          IsGlobal : boolean := true ; -- true if control in global coords.
          Control  : boolean := true );-- false if pgm wants to handle hits
procedure DeleteControl( id : AControlNumber );
function  FindControl( x, y : integer ) return AControlNumber;
function  GetControl( id : AControlNumber ) return AControlPtr;
procedure InvalidateControls( ThisWindow : AWindowNumber );


---> Dialog Manager
--
-- The dialog routines are responsible for all control interactions.
-- Wherever possible, dialog details are kept out of the controls.  One
-- exception is instant simple buttons: the button needs to know how to
-- draw itself (thus, the instant flag must be in it's fields), and it
-- doesn't know when it's selected by a hotkey scan so the dialog manager
-- must "manually" check to see if it hit an instant simple button.
-- Luckily only simple buttons are the only controls that can be instant
-- (unless a make a list of instant simple buttons later).
--
-- Also, scroll bar / list associations are kept in the fields of the
-- controls, though this is not strictly necessary since the controls
-- don't need to know this.  Probably store it in the Window's control
-- list at some later point.
--
-- Dialog Tasks:
--
-- None          -- time out
-- DialogError   -- no controls in window so can't dialog it
-- Hit           -- control was hit and control to program
-- Complete      -- dialog is finished
-- NonControlHit -- window was hit, but not the control
--
-- Whether or not a particular control is handled is determined
-- when the control is added to the window.  This is different than
-- the Apple IIgs where common tasks (over all controls) can be turned
-- on and off.

-- Window updates, focus changes not yet implemented.

type ADialogTask is (None, DialogError, Hit, Complete, NonControlHit);

-- Dialog Record
--
-- Control should be initialized to 1

type ADialogTaskRecord is record
    MyTask   : ADialogTask;    -- what DoDialog is reporting
    InputRec : AnInputRecord;  -- input record received
    Control  : AControlNumber; -- control that is affected
    Action   : ADialogAction;  -- result to return??
end record;
type ADialogTaskCallBack is access
     procedure( DialogTask : in out ADialogTaskRecord);

-- DoDialog
--
-- DialogTask - record returned as result of the dialog
-- TaskCB     - callback for handling manual controls
-- HearInCB   - callback for filtering incoming InputRec
-- HearOutCB  - callback for filtering outgoing Action

procedure DoDialog( DialogTask : in out ADialogTaskRecord;
                    TaskCB    : in ADialogTaskCallBack := null;
                    HearInCB  : in ADialogTaskCallBack := null;
                    HearOutCB : in ADialogTaskCallBack := null );

---> Standard Dialogs

procedure NoteAlert( message : string );    -- OK button
procedure CautionAlert( message : string ); -- OK button
procedure StopAlert( message : string );    -- OK button

function YesAlert( message : string; kind : BeepStyles )
  return boolean; -- Yes (default) or No
function NoAlert( message : string; kind : BeepStyles )
  return boolean; -- No (default) or Yes
function CancelAlert( message, OKCaption : string; kind : BeepStyles )
  return boolean; -- OK (default,customized) or Cancel
function YesCancelAlert( message : string; kind : BeepStyles )
  return AControlNumber; -- Yes, No or Cancel

---> General Window I/O

procedure MoveTo( x, y : integer );    -- move to local x, y
procedure Move( dx, dy : integer );    -- move by indicated x, y change

procedure ToLocal(    r : in out ARect );   -- global to local
procedure ToLocal( x, y : in out integer ); --   coordinates
procedure ToGlobal(   r : in out ARect );   -- local to global
procedure ToGlobal(x, y : in out integer ); --   coordinates

procedure print;                    -- move to next line
procedure print( s : string );      -- print a string
procedure print( i : integer );     -- print an integer
procedure print( l : long_integer );-- print a long integer

---> Standard File Dialogs

type AValidateFilenameRec is record
     Filename : Unbounded_String;  -- filename to be validated
     Replied  : boolean; -- true if not cancelled
end record;
procedure ValidateFilename( desc : in out AValidateFilenameRec );

-- These are based on the Apple IIgs file dialogs

type ASelectOpenFileRec is record
     Prompt  : unbounded_string;  -- prompt for user
     Replied : boolean; -- true if file was selected
     Suffix  : unbounded_string;  -- desired file suffix
     Direct  : boolean; -- true if can select directories
     Path    : unbounded_string;  -- file path
     Fname   : unbounded_string;  -- file name (or "" if "accept"ed)
end record;

type ASelectSaveFileRec is record
     Prompt  : unbounded_string;  -- prompt for user
     Replied : boolean; -- true if file was selected
     Default : unbounded_string;  -- default file name
     Path    : unbounded_string;  -- chosen path
     Fname   : unbounded_string;  -- file name
end record;

procedure SelectOpenFile( sofrec : in out ASelectOpenFileRec );
procedure SelectSaveFile( ssfrec : in out ASelectSaveFileRec );

-- Display a dialog box for opening/saving a file and returning the
-- path chosen by the user.

procedure ShowListInfo( title : string;
                        t : integer;
                        lst : in out StrList.Vector;
                        last : boolean := false;
                        longLines : LongLineHandling := none);
-- display a list for the user to view; list isn't cleared.  List is
-- full-screen except for the top of the window at t.
procedure ShowListInfo( title : string;
                        l, t, r, b : integer;
                        lst : in out StrList.vector;
                        last : boolean := false;
                        longLines : LongLineHandling := none);
procedure EditListInfo( title : string;
                        t : integer;
                        lst : in out StrList.vector;
                        result : out boolean;
                        last : boolean := false);
procedure EditListInfo( title : string;
                        l, t, r, b : integer;
                        lst : in out StrList.vector;
                        result : out boolean;
                        last : boolean := false );

-- Put up a window in the given coordinates and display the string list
-- that you specify.  If you use EditListInfo, the user can edit the
-- list and result is true if the list has been changed.

procedure AppendNotepad( s : in StrList.Vector);

-- Add contents of list to end of notepad accessory

--- These entries for use by Window Editor program ONLY
--- pretend they're private, will ya?!

--- Control Table Definitions (for Windows)

type AControlTableRecord is record
     ptr    : AControlPtr;    -- pointer to a control
     mine   : boolean;        -- true if controlled by Window Manager
end record;
type ControlTableEntries is array(1..AControlNumber'Last)
     of AControlTableRecord;
type AControlTable is record     -- a control table is
     size    : AControlNumber;      --   number of entries in the table
     current : AControlNumber;      --   currently active control
     control : ControlTableEntries; --   the actual table
end record;

---> Window Definition (should be tagged)

type AWindow is record
     Title    : unbounded_string;        -- title of the window
     HasFrame : boolean;       -- true if the window has a visible frame
     Relative : boolean;       -- frame relative to last window (NYI)
     Frame    : ARect;         -- rectangle around whole window
     FrameColour : APenColourName; -- colour of frame
     Content  : ARect;         -- rectangle inside window border
     table    : AControlTable; -- list of controls in the window
     HasInfoBar : boolean;     -- true if has an info bar
     InfoBar  : ARect;         -- dimensions of the info bar
     InfoText : unbounded_string;        -- text in the info bar
     Style    : AWindowStyle;  -- style (purpose) of window
     Loaded   : Boolean;       -- true if loaded with LoadWindow
     SaveX, SaveY : integer;   -- for saving X & Y of Curses' cursor
     DrawCB   : AWindowDrawingCallBack; -- drawing routine (or null)
     SoundPath : Unbounded_string;    -- path for sound to play on openx
     SoundID  : unbounded_string;        -- id for same
     SongPath : unbounded_string;     -- path for song to play on open
     SongID   : unbounded_string;         -- id for same
     Timeout  : Duration := -1.0;  -- timeout in seconds (-1 = none)
     TimeoutControl : AControlNumber; -- control to execute on timeout (NYI)
     ParentFile : unbounded_string;   -- file to inherit controls from (NYI)
     XScroll  : integer;       -- amount of scrolling from home position
     YScroll  : integer;       -- ditto
end record;
pragma Pack( AWindow );

Window : array( 1..AWindowNumber'Last ) of AWindow; -- stack of windows
NextWindow : AWindowNumber; -- next free window, 0 = no more

private
   pragma InLine( ToGlobal );
   pragma InLine( ToLocal );
end windows;
