-- Sample program Hello_World.ada  2/27/88  MAN  1.0
--
-- This is a sample program that shows a simple usage of the Ada binding to
-- X Windows. This program shows the basic calls needed to construct
-- a client application based on the binding.
--
-- In specific, this program shows how to:
--
--     Open a display.
--     Get the default Screen.
--     Get the root window of that screen.
--     Create A Window.
--     Create a cursor for that window.
--     Set up input event masks.
--     Set up Icon names.
--     Load a font style.
--     Create a graphic context.
--     Map a window to the display.
--     Set the foreground and backround colors for the window.
--     Read in events from the event queue.
--     Handle those events.
--     Draw strings of text to the window.

--with XK;
with C;         use C;
with low_types; use low_types;
with system;    use system;
with unchecked_conversion;

with Text_Io;
with Xlib;

procedure Hello_World is
  use Xlib;

  function bor(l,r: Xlib.unsigned_long) return Xlib.unsigned_long;
  pragma interface(builtin, bor);

  function "or"(l,r: Xlib.unsigned_long) return Xlib.unsigned_long
        renames bor;

  function ADDR is new unchecked_conversion(system.address,Xlib.caddr_t);

  --
  Buffer                   : String(1..1) := " ";
  Display_Id               : Xlib.XDisplay_p;
  Display_Not_Open         : Exception;
  Done                     : Boolean := False;
  Drawable_Window          : Xlib.Drawable;
  Gc_Value_Mask            : Xlib.Unsigned_Long := Xlib.GcFont;
  Gc_Value_Rec             : Xlib.Xgcvalues;
  Hello_World_Bounds       : Xlib.XRectangle;
  Hello_World_Border_Width : Xlib.Unsigned_Int := 2;
  Main_Attrs               : Xlib.XSetWindowAttributes;
  Main_Screen              : Xlib.Int;
  Main_Window              : Xlib.Window;
  Position_Point           : Xlib.XPoint;
  Pointer_String           : constant String := "Hello World!" & Ascii.nul;
  Root_Wind                : Xlib.Window;
  Status                   : Xlib.XComposeStatus;
  Number                   : Xlib.Int := 0;
  The_Symbol               : Xlib.KeySym;
  Title_Point              : Xlib.XPoint;
  Title_String             : constant String := "Hello World" & Ascii.nul;
  Wa_Values                : Xlib.Unsigned_Long  := 
    Xlib.CWBackPixel or Xlib.CWBorderPixel or Xlib.CWCursor;
  Window_Context           : Xlib.GC;
  X_Event                  : Xlib.XEvent;

  eval: xlib.int;

   --
   -- Beginning of main procedure
   --
 begin
   --
   -- Opening the display, get the new Display_Id, get the default
   -- screen, set up the bouonds of the panel, get the root window id
   -- and then create a window with our new defaults for the screen.
   --
   Text_Io.put_Line ("Started the program");
   Display_Id := Xlib.XOpenDisplay (addr(string'(""&ascii.nul)'address));
 --  Xlib.Synchronize (Display_Id);
   Text_Io.put_Line ("after open display");
   if (Display_Id = Null) then
     raise Display_Not_Open;
   end if;
   Main_Screen := Xlib.XDefaultScreen (Display_Id.all);
   Root_Wind := Xlib.XRootWindow (Display_Id.all, Main_Screen);
   --
   -- Here we are setting up the bounds for our window
   -- after we set up the bounds, we calculate
   -- the starting position point
   -- from those bounds.
   --
   Hello_World_Bounds := (  5,   5, 810, 672);
   Title_Point.x := Short (Hello_World_Bounds.Width / 2);
   Title_Point.y := Short (Hello_World_Bounds.Height / 2);
   --
   -- Create the font cursor with the shape of a dot
   --
   Main_Attrs.Cursor :=
     Xlib.XCreateFontCursor (Display_Id.all, Xlib.XC_Dot);
   Main_Attrs.Border_Pixel := Xlib.XBlackPixel (Display_Id.all, Main_Screen);
   Main_Attrs.Background_Pixel :=
     Xlib.XWhitePixel (Display_Id.all, Main_Screen);
   Main_Attrs.Bit_Gravity := Xlib.CenterGravity;
   --
   -- With many of the parameters that we have just populated
   -- we now create the window. The parameter Main_Window will
   -- be the new window_id associated with this new window.
   --
   Main_Window :=
     Xlib.XCreateWindow
        (Display_Id.all, Root_Wind, Xlib.Int (Hello_World_Bounds.x),
         Xlib.Int (Hello_World_Bounds.y), Xlib.unsigned_Int (Hello_World_Bounds.Width),
         Xlib.unsigned_Int (Hello_World_Bounds.Height), Hello_World_Border_Width,
         Xlib.XDefaultDepth (Display_Id.all, Main_Screen),
         Xlib.InputOutput,
         Xlib.XDefaultVisual (Display_Id.all, Main_Screen).all, Wa_Values,
         Main_Attrs);
   --
   -- Set up the event mask for use with the event handler. Then call
   -- Select_Input to make the mask visable to the server.
   --
   Main_Attrs.Event_Mask  := Xlib.long( Xlib.ExposureMask or Xlib.ButtonPressMask or
                            Xlib.ButtonMotionMask or
                            Xlib.KeyPressMask);
   eval := Xlib.XSelectInput (Display_Id.all, Main_Window, Main_Attrs.Event_Mask);
   --
   -- Set the icon name and the name that would be used as the title
   -- bar if we had one.
   --
   eval := Xlib.XSetIconName (Display_Id.all, Main_Window, addr(string'("Hello_World" & ASCII.nul)'address));
   eval := Xlib.XStoreName (Display_Id.all, Main_Window, addr(string'("Hello World" & ASCII.nul)'address));
   eval := Xlib.XDefineCursor (Display_Id.all, Main_Window,
                                    Main_Attrs.Cursor);
   Drawable_Window := Xlib.Drawable (Main_Window);
   --
   -- Here we set the text font to a 9X15 size and
   -- create a Graphic_Context for the specified drawable
   -- window.
   --
   Gc_Value_Rec.Font := Xlib.XLoadFont (Display_Id.all,
        addr(string'("-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1")'address));
   Window_Context := Xlib.XCreateGc (Display_Id.all, Drawable_Window,
                                               Gc_Value_Mask, Gc_Value_Rec);
   --
   -- Now we are going to Map the Main_Window to the specified display
   --
   eval := Xlib.XMapWindow (Display_Id.all, Main_Window);
   eval := Xlib.XFlush (Display_Id.all);
   --
   -- This sets the text foreground color to be black
   -- and the background color to be white
   --
   eval := Xlib.XSetBackground (Display_Id.all, Window_Context.all,
                        Xlib.XWhitePixel (Display_Id.all, Main_Screen));
   eval := Xlib.XSetForeground (Display_Id.all, Window_Context.all,
                        Xlib.XBlackPixel (Display_Id.all, Main_Screen));

   while not Done loop
     --
     -- Inside this loop is where we process events. The next call,
     -- Next_Event, returns the next event that is in our event queue.
     -- We may then apply the event kind to a case statement
     -- and perform the processing.
     --
     eval := Xlib.XNextEvent (Display_Id.all, X_Event);

     case X_Event.type_id is

       when Xlib.Expose  =>
         if (X_Event.xexpose.Count = 0) then
           --
           -- here we will redraw the title string to the window
           -- each time we receive an expose event, we want to draw the
           -- Title_String at the Title_Point
           --
           eval := Xlib.XDrawImageString
              (Display_Id.all, Drawable_Window, Window_Context.all,
               Xlib.Int (Title_Point.x),
               Xlib.Int (Title_Point.y), addr(Title_String'address), Title_String'Length);
         end if;
       when Xlib.ButtonPress =>
         -- If a button press event is received by this client then
         -- we want to display the pointer string at those coordinates.

         text_io.put_line("got a button press event");

         Position_Point.x := Xlib.Short_int (X_Event.xbutton.x);
         Position_Point.y := Xlib.Short_int (X_Event.xbutton.y);

         eval := Xlib.XDrawImageString
            (Display_Id.all, Drawable_Window, Window_Context.all,
             Xlib.Int (Position_Point.x),
             Xlib.Int (Position_Point.y), addr(Pointer_String'address), Pointer_String'Length);
       when Xlib.KeyPress =>
         -- When a key press event is received by this client, we are
         -- finished so we set the Done flag.

            Text_Io.Put_Line ("Program has been terminated");
            Done := True;
      when others =>
        null;
    end case;
  end loop;
  eval := Xlib.XCloseDisplay (Display_id.all);
exception
  when Display_Not_Open  =>
    Text_Io.Put_Line ("Could not open Display");
end Hello_World;

-------------------------------------------------------------------------------
-- ....................................................................... ----
-- DISTRIBUTION AND COPYRIGHT:
--
-- This software is released to the Public Domain (note:
--   software released to the Public Domain is not subject
--   to copyright protection).
-- Restrictions on use or distribution:  NONE
--
-- DISCLAIMER:
--
-- This software and its documentation are provided "AS IS" and
-- without any expressed or implied warranties whatsoever.
-- No warranties as to performance, merchantability, or fitness
-- for a particular purpose exist.
--
-- Because of the diversity of conditions and hardware under
-- which this software may be used, no warranty of fitness for
-- a particular purpose is offered.  The user is advised to
-- test the software thoroughly before relying on it.  The user
-- must assume the entire risk and liabiliy of using this
-- software.
--
-- In no event shall any person or organization of people be
-- held responsible for any direct, indirect, consequential
-- or inconsequential damages or lost profits.
