-----------------------------------------------------------------------
--  awa-permissions -- Permissions module
--  Copyright (C) 2011, 2012 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Security.Permissions;
with Security.Policies;

with Util.Serialize.IO.XML;

with ADO;

--  == Introduction ==
--  The *AWA.Permissions* framework defines and controls the permissions used by an application
--  to verify and grant access to the data and application service.  The framework provides a
--  set of services and API that helps an application in enforcing its specific permissions.
--  Permissions are verified by a permission controller which uses the service context to
--  have information about the user and other context.  The framework allows to use different
--  kinds of permission controllers.  The `Entity_Controller` is the default permission
--  controller which uses the database and an XML configuration to verify a permission.
--
--  === Declaration ===
--  To be used in the application, the first step is to declare the permission.
--  This is a static definition of the permission that will be used to ask to verify the
--  permission.  The permission is given a unique name that will be used in configuration files:
--
--    package ACL_Create_Post is new Security.Permissions.Definition ("blog-create-post");
--
--  === Checking for a permission ===
--  A permission can be checked in Ada as well as in the presentation pages.
--  This is done by using the `Check` procedure and the permission definition.  This operation
--  acts as a barrier: it does not return anything but returns normally if the permission is
--  granted.  If the permission is denied, it raises the `NO_PERMISSION` exception.
--
--  Several `Check` operation exists.  Some require not argument and some others need a context
--  such as some entity identifier to perform the check.
--
--    AWA.Permissions.Check (Permission => ACL_Create_Post.Permission,
--                           Entity     => Blog_Id);
--
--  === Configuring a permission ===
--  The *AWA.Permissions* framework supports a simple permission model
--  The application configuration file must provide some information to help in checking the
--  permission.  The permission name is referenced by the `name` XML entity.  The `entity-type`
--  refers to the database entity (ie, the table) that the permission concerns.
--  The `sql` XML entity represents the SQL statement that must be used to verify the permission.
--
--    <entity-permission>
--      <name>blog-create-post</name>
--      <entity-type>blog</entity-type>
--      <description>Permission to create a new post.</description>
--      <sql>
--        SELECT acl.id FROM acl
--        WHERE acl.entity_type = :entity_type
--        AND acl.user_id = :user_id
--        AND acl.entity_id = :entity_id
--      </sql>
--    </entity-permission>
--
--  === Adding a permission ===
--  Adding a permission means to create an `ACL` database record that links a given database
--  entity to the user.  This is done easily with the `Add_Permission` procedure:
--
--    AWA.Permissions.Services.Add_Permission (Session => DB,
--                                             User    => User,
--                                             Entity  => Blog);
--
--  == Data Model ==
--  @include Permission.hbm.xml
--
--  == Queries ==
--  @include permissions.xml
--
package AWA.Permissions is

   NAME : constant String := "Entity-Policy";

   --  Exception raised by the Check procedure if the user does not have
   --  the permission.
   NO_PERMISSION : exception;

   type Permission_Type is (READ, WRITE);

   type Entity_Permission is new Security.Permissions.Permission with private;

   --  Verify that the permission represented by Permission is granted.
   --
   procedure Check (Permission : in Security.Permissions.Permission_Index);

   --  Verify that the permission represented by Permission is granted to access the
   --  database entity represented by Entity.
   procedure Check (Permission : in Security.Permissions.Permission_Index;
                    Entity     : in ADO.Identifier);
--
--     --  Get from the security context Context an identifier stored under the
--     --  name Name.  Returns NO_IDENTIFIER if the security context does not define
--     --  such name or the value is not a valid identifier.
--     function Get_Context (Context : in Security.Contexts.Security_Context'Class;
--                           Name    : in String) return ADO.Identifier;

private

   type Entity_Permission is new Security.Permissions.Permission with record
      Entity : ADO.Identifier;
   end record;

   type Entity_Policy is new Security.Policies.Policy with null record;
   type Entity_Policy_Access is access all Entity_Policy'Class;

   --  Get the policy name.
   overriding
   function Get_Name (From : in Entity_Policy) return String;

   --  Setup the XML parser to read the policy description.
   overriding
   procedure Prepare_Config (Policy : in out Entity_Policy;
                             Reader : in out Util.Serialize.IO.XML.Parser);

   --  Finish reading the XML policy configuration.  The security policy implementation can use
   --  this procedure to perform any configuration setup after the configuration is parsed.
   overriding
   procedure Finish_Config (Into    : in out Entity_Policy;
                            Reader  : in out Util.Serialize.IO.XML.Parser);

end AWA.Permissions;

-----------------------------------------------------------------------
--  awa-permissions -- Permissions module
--  Copyright (C) 2011, 2012 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Security.Permissions;
with Security.Policies;

with Util.Serialize.IO.XML;

with ADO;

--  == Introduction ==
--  The *AWA.Permissions* framework defines and controls the permissions used by an application
--  to verify and grant access to the data and application service.  The framework provides a
--  set of services and API that helps an application in enforcing its specific permissions.
--  Permissions are verified by a permission controller which uses the service context to
--  have information about the user and other context.  The framework allows to use different
--  kinds of permission controllers.  The `Entity_Controller` is the default permission
--  controller which uses the database and an XML configuration to verify a permission.
--
--  === Declaration ===
--  To be used in the application, the first step is to declare the permission.
--  This is a static definition of the permission that will be used to ask to verify the
--  permission.  The permission is given a unique name that will be used in configuration files:
--
--    package ACL_Create_Post is new Security.Permissions.Definition ("blog-create-post");
--
--  === Checking for a permission ===
--  A permission can be checked in Ada as well as in the presentation pages.
--  This is done by using the `Check` procedure and the permission definition.  This operation
--  acts as a barrier: it does not return anything but returns normally if the permission is
--  granted.  If the permission is denied, it raises the `NO_PERMISSION` exception.
--
--  Several `Check` operation exists.  Some require not argument and some others need a context
--  such as some entity identifier to perform the check.
--
--    AWA.Permissions.Check (Permission => ACL_Create_Post.Permission,
--                           Entity     => Blog_Id);
--
--  === Configuring a permission ===
--  The *AWA.Permissions* framework supports a simple permission model
--  The application configuration file must provide some information to help in checking the
--  permission.  The permission name is referenced by the `name` XML entity.  The `entity-type`
--  refers to the database entity (ie, the table) that the permission concerns.
--  The `sql` XML entity represents the SQL statement that must be used to verify the permission.
--
--    <entity-permission>
--      <name>blog-create-post</name>
--      <entity-type>blog</entity-type>
--      <description>Permission to create a new post.</description>
--      <sql>
--        SELECT acl.id FROM acl
--        WHERE acl.entity_type = :entity_type
--        AND acl.user_id = :user_id
--        AND acl.entity_id = :entity_id
--      </sql>
--    </entity-permission>
--
--  === Adding a permission ===
--  Adding a permission means to create an `ACL` database record that links a given database
--  entity to the user.  This is done easily with the `Add_Permission` procedure:
--
--    AWA.Permissions.Services.Add_Permission (Session => DB,
--                                             User    => User,
--                                             Entity  => Blog);
--
--  == Data Model ==
--  @include Permission.hbm.xml
--
--  == Queries ==
--  @include permissions.xml
--
package AWA.Permissions is

   NAME : constant String := "Entity-Policy";

   --  Exception raised by the Check procedure if the user does not have
   --  the permission.
   NO_PERMISSION : exception;

   type Permission_Type is (READ, WRITE);

   type Entity_Permission is new Security.Permissions.Permission with private;

   --  Verify that the permission represented by Permission is granted.
   --
   procedure Check (Permission : in Security.Permissions.Permission_Index);

   --  Verify that the permission represented by Permission is granted to access the
   --  database entity represented by Entity.
   procedure Check (Permission : in Security.Permissions.Permission_Index;
                    Entity     : in ADO.Identifier);
--
--     --  Get from the security context Context an identifier stored under the
--     --  name Name.  Returns NO_IDENTIFIER if the security context does not define
--     --  such name or the value is not a valid identifier.
--     function Get_Context (Context : in Security.Contexts.Security_Context'Class;
--                           Name    : in String) return ADO.Identifier;

private

   type Entity_Permission is new Security.Permissions.Permission with record
      Entity : ADO.Identifier;
   end record;

   type Entity_Policy is new Security.Policies.Policy with null record;
   type Entity_Policy_Access is access all Entity_Policy'Class;

   --  Get the policy name.
   overriding
   function Get_Name (From : in Entity_Policy) return String;

   --  Setup the XML parser to read the policy description.
   overriding
   procedure Prepare_Config (Policy : in out Entity_Policy;
                             Reader : in out Util.Serialize.IO.XML.Parser);

end AWA.Permissions;

Remove Finish_Config

Remove Finish_Config


-----------------------------------------------------------------------
--  upload_server -- Example of server with a servlet
--  Copyright (C) 2012 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with ASF.Server.Web;
with ASF.Servlets;
with Upload_Servlet;
with Util.Log.Loggers;

procedure Upload_Server is
   Upload  : aliased Upload_Servlet.Servlet;
   App     : aliased ASF.Servlets.Servlet_Registry;
   WS      : ASF.Server.Web.AWS_Container;
   Log     : Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("Upload_Server");
begin
   --  Register the servlets and filters
   App.Add_Servlet (Name => "upload", Server => Upload'Unchecked_Access);

   --  Define servlet mappings
   App.Add_Mapping (Name => "upload", Pattern => "*.html");

   WS.Register_Application ("/upload", App'Unchecked_Access);

   Log.Info ("Connect you browser to: http://localhost:8080/upload/upload.html");

   WS.Start;

   delay 6000.0;

end Upload_Server;

-----------------------------------------------------------------------
--  upload_server -- Example of server with a servlet
--  Copyright (C) 2012, 2015 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with ASF.Server.Web;
with ASF.Servlets;
with Upload_Servlet;
with Util.Log.Loggers;

procedure Upload_Server is
   Upload  : aliased Upload_Servlet.Servlet;
   App     : aliased ASF.Servlets.Servlet_Registry;
   WS      : ASF.Server.Web.AWS_Container;
   Log     : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("Upload_Server");
begin
   --  Register the servlets and filters
   App.Add_Servlet (Name => "upload", Server => Upload'Unchecked_Access);

   --  Define servlet mappings
   App.Add_Mapping (Name => "upload", Pattern => "*.html");

   WS.Register_Application ("/upload", App'Unchecked_Access);

   Log.Info ("Connect you browser to: http://localhost:8080/upload/upload.html");

   WS.Start;

   delay 6000.0;

end Upload_Server;

Fix compilation warnings

Fix compilation warnings


-----------------------------------------------------------------------
--  gen-utils-gnat -- GNAT utilities
--  Copyright (C) 2011, 2012 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Containers.Vectors;

with Util.Properties;

--  This package encapsulate a set of high level operations on top of the GNAT project
--  files.  It uses the GNAT project reader which is packaged in the GNAT compiler (4.6.0).
--  A minimal supset of GNAT compiler was copied in src/gnat to ensure that a
--  compatible API is defined.  The GNAT files stored in src/gnat are licensed
--  under the GNU General Public License.
package Gen.Utils.GNAT is

   --  Directory which contains the GNAT project files installed on the system.
   --  This is overriden by the configuration property 'generator.gnat.projects.dir'.
   DEFAULT_GNAT_PROJECT_DIR : constant String := "/usr/lib/gnat";

   type Project_Info is record
      Path : Ada.Strings.Unbounded.Unbounded_String;
      Name : Ada.Strings.Unbounded.Unbounded_String;
   end record;

   package Project_Info_Vectors is
      new Ada.Containers.Vectors (Index_Type   => Positive,
                                  Element_Type => Project_Info);

   --  Initialize the GNAT project runtime for reading the GNAT project tree.
   --  Configure it according to the dynamo configuration properties.
   procedure Initialize (Config : in Util.Properties.Manager'Class);

   --  Read the GNAT project file identified by Project_File_Name and get
   --  in Project_List an ordered list of absolute project paths used by
   --  the root project.
   procedure Read_GNAT_Project_List (Project_File_Name : in String;
                                     Project_List      : out Project_Info_Vectors.Vector);

end Gen.Utils.GNAT;

-----------------------------------------------------------------------
--  gen-utils-gnat -- GNAT utilities
--  Copyright (C) 2011, 2012, 2015 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Containers.Vectors;

with Util.Properties;

--  This package encapsulate a set of high level operations on top of the GNAT project
--  files.  It uses the GNAT project reader which is packaged in the GNAT compiler (4.6.0).
--  A minimal supset of GNAT compiler was copied in src/gnat to ensure that a
--  compatible API is defined.  The GNAT files stored in src/gnat are licensed
--  under the GNU General Public License.
package Gen.Utils.GNAT is

   --  Directory which contains the GNAT project files installed on the system.
   --  This is overriden by the configuration property 'generator.gnat.projects.dir'.
   DEFAULT_GNAT_PROJECT_DIR : constant String := "/usr/lib/gnat";

   ADA_PROJECT_PATH_NAME    : constant String := "ADA_PROJECT_PATH";

   type Project_Info is record
      Path : Ada.Strings.Unbounded.Unbounded_String;
      Name : Ada.Strings.Unbounded.Unbounded_String;
   end record;

   package Project_Info_Vectors is
      new Ada.Containers.Vectors (Index_Type   => Positive,
                                  Element_Type => Project_Info);

   --  Initialize the GNAT project runtime for reading the GNAT project tree.
   --  Configure it according to the dynamo configuration properties.
   procedure Initialize (Config : in Util.Properties.Manager'Class);

   --  Read the GNAT project file identified by Project_File_Name and get
   --  in Project_List an ordered list of absolute project paths used by
   --  the root project.
   procedure Read_GNAT_Project_List (Project_File_Name : in String;
                                     Project_List      : out Project_Info_Vectors.Vector);

end Gen.Utils.GNAT;

Declare the ADA_GNAT_PROJECT_NAME constant


--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2017 onox <denkpadje@gmail.com>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

with GL.Fences;

generic
   type Index_Type is mod <>;
   Maximum_Wait : Duration := 0.010;
package Orka.Rendering.Fences is

   type Buffer_Fence is tagged private;

   type Fence_Status is (Not_Initialized, Signaled, Not_Signaled);

   function Create_Buffer_Fence return Buffer_Fence;

   procedure Prepare_Index (Object : in out Buffer_Fence; Status : out Fence_Status);
   --  Perform a client wait sync for the fence corresponding to the
   --  current index

   procedure Advance_Index (Object : in out Buffer_Fence);
   --  Set a fence for the corresponding index and then increment it

private

   type Fence_Array is array (Index_Type) of GL.Fences.Fence;

   type Buffer_Fence is tagged record
      Fences : Fence_Array;
      Index  : Index_Type;
   end record;

end Orka.Rendering.Fences;

--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2017 onox <denkpadje@gmail.com>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

with GL.Fences;

generic
   type Index_Type is mod <>;
   Maximum_Wait : Duration := 0.010;
package Orka.Rendering.Fences is
   pragma Preelaborate;

   type Buffer_Fence is tagged private;

   type Fence_Status is (Not_Initialized, Signaled, Not_Signaled);

   function Create_Buffer_Fence return Buffer_Fence;

   procedure Prepare_Index (Object : in out Buffer_Fence; Status : out Fence_Status);
   --  Perform a client wait sync for the fence corresponding to the
   --  current index

   procedure Advance_Index (Object : in out Buffer_Fence);
   --  Set a fence for the corresponding index and then increment it

private

   type Fence_Array is array (Index_Type) of GL.Fences.Fence;

   type Buffer_Fence is tagged record
      Fences : Fence_Array;
      Index  : Index_Type;
   end record;

end Orka.Rendering.Fences;

orka: Make package Orka.Rendering.Fences preelaborated

Signed-off-by: onox <34c1d3d2d1347bea60a26f46574de21a7a79b6d5@gmail.com>


with Ada.Unchecked_Conversion;
with Interfaces.C.Strings;
with Interfaces.C.Pointers;
with Nanomsg.Errors;
with System;

package body  Nanomsg.Socket is
   package C renames Interfaces.C;
   use type C.Int;

   function Is_Null (Obj : in Socket_T) return Boolean is (Obj.Fd = -1);

   procedure Init (Obj      :    out Socket_T;
                   Domain   : in     Nanomsg.Domains.Domain_T;
                   Protocol : in     Nanomsg.Protocols.Protocol_T
                  ) is

      function C_Nn_Socket (Domain : in C.Int; Protocol : in C.Int) return C.Int
      with Import, Convention => C, External_Name => "nn_socket";

   begin
      Obj.Fd := Integer (C_Nn_Socket (Nanomsg.Domains.To_C (Domain),
                                      Nanomsg.Protocols.To_C (Protocol)));
      if Obj.Fd < 0 then
         raise Socket_Exception with "Init: " & Nanomsg.Errors.Errno_Text;
      end if;
   end Init;

   procedure Close (Obj : in out Socket_T) is
      function C_Nn_Close (Socket : in C.Int) return C.Int
      with Import, Convention => C, External_Name => "nn_close";

   begin
      if C_Nn_Close (C.Int (Obj.Fd)) /= 0 then
         raise Socket_Exception with "Close: " & Nanomsg.Errors.Errno_Text;
      end if;
      Obj.Fd := -1;
   end Close;

   procedure Bind (Obj     : in Socket_T;
                   Address : in String) is

      function C_Bind (Socket : in C.Int; Address : in C.Strings.Chars_Ptr) return C.Int
      with Import, Convention => C, External_Name => "nn_bind";
      Endpoint : C.Int := -1;
      C_Address : C.Strings.Chars_Ptr := C.Strings.New_String (Address);
   begin
      Endpoint := C_Bind(C.Int (Obj.Fd), C_Address);
      C.Strings.Free (C_Address);
      if Endpoint < -1 then
         raise Socket_Exception with "Bind: "  & Nanomsg.Errors.Errno_Text;
      end if;
      -- FIXME
      -- Add endpoints container
   end Bind;

   procedure Connect (Obj     : in Socket_T;
                   Address : in String) is

      function C_Connect (Socket : in C.Int; Address : in C.Strings.Chars_Ptr) return C.Int
      with Import, Convention => C, External_Name => "nn_connect";
      Endpoint : C.Int := -1;
      C_Address : C.Strings.Chars_Ptr := C.Strings.New_String (Address);
   begin
      Endpoint := C_Connect(C.Int (Obj.Fd), C_Address) ;
      C.Strings.Free (C_Address);
      if Endpoint < 0 then
         raise Socket_Exception with "Connect: " & Nanomsg.Errors.Errno_Text;
      end if;
   end Connect;

   function Get_Fd (Obj : in Socket_T) return Integer is (Obj.Fd);

   procedure Receive (Obj : in out Socket_T;
                      Message : out Nanomsg.Messages.Message_T) is

      Payload : System.Address;
      use type System.Address;

      Received : Integer;
      use type C.Size_T;
      Flags : constant C.Int := 0;
      Nn_Msg : constant C.Size_T := C.Size_T'Last;

      function Nn_Recv (Socket     :        C.Int;
                        Buf_Access : in out System.Address;
                        Size       :        C.Size_T;
                        Flags      :        C.Int
                       ) return C.Int with Import, Convention => C, External_Name => "nn_recv";

--      function Free_Msg (Buf_Access : in out System.Address) return C.Int
 --     with Import, Convention => C, External_Name => "nn_freemsg";
   begin
      Received := Integer (Nn_Recv (C.Int (Obj.Fd), Payload, Nn_Msg, Flags));
      if Received < 0 then
         raise Socket_Exception with "Receive: " & Nanomsg.Errors.Errno_Text;
      end if;
      Message.Set_Length (Received);
      declare
         Data :  Nanomsg.Messages.Bytes_Array_T (1 .. Received);
         for Data'Address use Payload;

      begin
         Message.Set_Payload (new Nanomsg.Messages.Bytes_Array_T'(Data));
      end;
      --  if Free_Msg (Payload) < 0 then
      --     raise Socket_Exception;
      --  end if;
   end Receive;

   procedure Send (Obj : in Socket_T; Message : Nanomsg.Messages.Message_T) is
   Flags : C.Int := 0;
      function Nn_Send (Socket     : C.Int;
                        Buf_Access : Nanomsg.Messages.Bytes_Array_T;
                        Size       : C.Size_T;
                        Flags      : C.Int
                       ) return C.Int with Import, Convention => C, External_Name => "nn_send";
      Sent : Integer;
   begin

      Sent := Integer (Nn_Send (C.Int (Obj.Fd),
                                Message.Get_Payload.all,
                                C.Size_T (Message.Get_Length),
                                Flags));
      if Sent < 0 then
         raise Socket_Exception with "Send: " & Nanomsg.Errors.Errno_Text;
      end if;
      if Sent /= Message.Get_Length then
         raise Socket_Exception with "Send/Receive count doesn't match";
      end if;
   end Send;
end Nanomsg.Socket;

with Ada.Unchecked_Conversion;
with Interfaces.C.Strings;
with Interfaces.C.Pointers;
with Nanomsg.Errors;
with System;

package body  Nanomsg.Socket is
   package C renames Interfaces.C;
   use type C.Int;

   function Is_Null (Obj : in Socket_T) return Boolean is (Obj.Fd = -1);

   procedure Init (Obj      :    out Socket_T;
                   Domain   : in     Nanomsg.Domains.Domain_T;
                   Protocol : in     Nanomsg.Protocols.Protocol_T
                  ) is

      function C_Nn_Socket (Domain : in C.Int; Protocol : in C.Int) return C.Int
      with Import, Convention => C, External_Name => "nn_socket";

   begin
      Obj.Fd := Integer (C_Nn_Socket (Nanomsg.Domains.To_C (Domain),
                                      Nanomsg.Protocols.To_C (Protocol)));
      if Obj.Fd < 0 then
         raise Socket_Exception with "Init: " & Nanomsg.Errors.Errno_Text;
      end if;
   end Init;

   procedure Close (Obj : in out Socket_T) is
      function C_Nn_Close (Socket : in C.Int) return C.Int
      with Import, Convention => C, External_Name => "nn_close";

   begin
      if C_Nn_Close (C.Int (Obj.Fd)) /= 0 then
         raise Socket_Exception with "Close: " & Nanomsg.Errors.Errno_Text;
      end if;
      Obj.Fd := -1;
   end Close;

   procedure Bind (Obj     : in Socket_T;
                   Address : in String) is

      function C_Bind (Socket : in C.Int; Address : in C.Strings.Chars_Ptr) return C.Int
      with Import, Convention => C, External_Name => "nn_bind";
      Endpoint : C.Int := -1;
      C_Address : C.Strings.Chars_Ptr := C.Strings.New_String (Address);
   begin
      Endpoint := C_Bind(C.Int (Obj.Fd), C_Address);
      C.Strings.Free (C_Address);
      if Endpoint < -1 then
         raise Socket_Exception with "Bind: "  & Nanomsg.Errors.Errno_Text;
      end if;
      -- FIXME
      -- Add endpoints container
   end Bind;

   procedure Connect (Obj     : in Socket_T;
                   Address : in String) is

      function C_Connect (Socket : in C.Int; Address : in C.Strings.Chars_Ptr) return C.Int
      with Import, Convention => C, External_Name => "nn_connect";
      Endpoint : C.Int := -1;
      C_Address : C.Strings.Chars_Ptr := C.Strings.New_String (Address);
   begin
      Endpoint := C_Connect(C.Int (Obj.Fd), C_Address) ;
      C.Strings.Free (C_Address);
      if Endpoint < 0 then
         raise Socket_Exception with "Connect: " & Nanomsg.Errors.Errno_Text;
      end if;
   end Connect;

   function Get_Fd (Obj : in Socket_T) return Integer is (Obj.Fd);

   procedure Receive (Obj : in out Socket_T;
                      Message : out Nanomsg.Messages.Message_T) is

      type Payload_T is null record;
      type Payload_Access_T is access all Payload_T;

      Payload : Payload_Access_T := new Payload_T;
      use type System.Address;

      Received : Integer;
      use type C.Size_T;
      Flags : constant C.Int := 0;
      Nn_Msg : constant C.Size_T := C.Size_T'Last;

      function Nn_Recv (Socket     :        C.Int;
                        Buf_Access :  out Payload_Access_T;
                        Size       :        C.Size_T;
                        Flags      :        C.Int
                       ) return C.Int with Import, Convention => C, External_Name => "nn_recv";

      function Free_Msg (Buf_Access : in out System.Address) return C.Int
          with Import, Convention => C, External_Name => "nn_freemsg";
   begin
      Received := Integer (Nn_Recv (C.Int (Obj.Fd), Payload, Nn_Msg, Flags));
      if Received < 0 then
         raise Socket_Exception with "Receive: " & Nanomsg.Errors.Errno_Text;
      end if;
      Message.Set_Length (Received);
      declare
         Data :  Nanomsg.Messages.Bytes_Array_T (1 .. Received);
         for Data'Address use Payload.all'Address;
      begin
         Message.Set_Payload (new Nanomsg.Messages.Bytes_Array_T'(Data));
      end;
   end Receive;

   procedure Send (Obj : in Socket_T; Message : Nanomsg.Messages.Message_T) is
   Flags : C.Int := 0;
      function Nn_Send (Socket     : C.Int;
                        Buf_Access : Nanomsg.Messages.Bytes_Array_T;
                        Size       : C.Size_T;
                        Flags      : C.Int
                       ) return C.Int with Import, Convention => C, External_Name => "nn_send";
      Sent : Integer;
   begin

      Sent := Integer (Nn_Send (C.Int (Obj.Fd),
                                Message.Get_Payload.all,
                                C.Size_T (Message.Get_Length),
                                Flags));
      if Sent < 0 then
         raise Socket_Exception with "Send: " & Nanomsg.Errors.Errno_Text;
      end if;
      if Sent /= Message.Get_Length then
         raise Socket_Exception with "Send/Receive count doesn't match";
      end if;
   end Send;
end Nanomsg.Socket;

Use heap instead of stack for message allocation


-----------------------------------------------------------------------
--  wiki-nodes -- Wiki Document Internal representation
--  Copyright (C) 2016, 2019, 2020, 2022 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

package body Wiki.Documents is

   use Wiki.Nodes;
   use Wiki.Nodes.Lists;

   --  ------------------------------
   --  Append a HTML tag start node to the document.
   --  ------------------------------
   procedure Push_Node (Into       : in out Document;
                        Tag        : in Html_Tag;
                        Attributes : in Wiki.Attributes.Attribute_List) is

      Node : constant Node_Type_Access := new Node_Type '(Kind       => N_TAG_START,
                                                          Len        => 0,
                                                          Tag_Start  => Tag,
                                                          Attributes => Attributes,
                                                          Children   => null,
                                                          Parent     => Into.Current);
   begin
      Append (Into, Node);
      Into.Current := Node;
   end Push_Node;

   --  ------------------------------
   --  Pop the HTML tag.
   --  ------------------------------
   procedure Pop_Node (From : in out Document;
                       Tag  : in Html_Tag) is
      pragma Unreferenced (Tag);
   begin
      if From.Current /= null then
         From.Current := From.Current.Parent;
      end if;
   end Pop_Node;

   --  ------------------------------
   --  Returns True if the current node is the root document node.
   --  ------------------------------
   function Is_Root_Node (Doc : in Document) return Boolean is
   begin
      return Doc.Current = null;
   end Is_Root_Node;

   --  ------------------------------
   --  Append a section header at end of the document.
   --  ------------------------------
   procedure Append (Into   : in out Document;
                     Header : in Wiki.Strings.WString;
                     Level  : in Positive) is
   begin
      Append (Into, new Node_Type '(Kind   => N_HEADER,
                                    Len    => Header'Length,
                                    Parent => Into.Current,
                                    Header => Header,
                                    Level  => Level));
   end Append;

   --  ------------------------------
   --  Append a node to the document.
   --  ------------------------------
   procedure Append (Into : in out Document;
                     Node : in Wiki.Nodes.Node_Type_Access) is
   begin
      if Into.Current = null then
         Append (Into.Nodes, Node);
      else
         Append (Into.Current, Node);
      end if;
   end Append;

   --  ------------------------------
   --  Append a simple node such as N_LINE_BREAK, N_HORIZONTAL_RULE or N_PARAGRAPH.
   --  ------------------------------
   procedure Append (Into : in out Document;
                     Kind : in Simple_Node_Kind) is
   begin
      case Kind is
         when N_LINE_BREAK =>
            Append (Into, new Node_Type '(Kind => N_LINE_BREAK, Len => 0,
                                          Parent => Into.Current));

         when N_HORIZONTAL_RULE =>
            Append (Into, new Node_Type '(Kind => N_HORIZONTAL_RULE, Len => 0,
                                          Parent => Into.Current));

         when N_PARAGRAPH =>
            Append (Into, new Node_Type '(Kind => N_PARAGRAPH, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_ITEM =>
            Append (Into, new Node_Type '(Kind => N_LIST_ITEM, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_END =>
            Append (Into, new Node_Type '(Kind => N_LIST_END, Len => 0,
                                          Parent => Into.Current));

         when N_NUM_LIST_END =>
            Append (Into, new Node_Type '(Kind => N_NUM_LIST_END, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_ITEM_END =>
            Append (Into, new Node_Type '(Kind => N_LIST_ITEM_END, Len => 0,
                                          Parent => Into.Current));

         when N_NEWLINE =>
            Append (Into, new Node_Type '(Kind => N_NEWLINE, Len => 0,
                                          Parent => Into.Current));

         when N_END_DEFINITION =>
            Append (Into, new Node_Type '(Kind => N_END_DEFINITION, Len => 0,
                                          Parent => Into.Current));

         when N_TOC_DISPLAY =>
            Append (Into, new Node_Type '(Kind => N_TOC_DISPLAY, Len => 0,
                                          Parent => Into.Current));
            Into.Using_TOC := True;

         when N_NONE =>
            null;

      end  case;
   end Append;

   --  ------------------------------
   --  Append the text with the given format at end of the document.
   --  ------------------------------
   procedure Append (Into   : in out Document;
                     Text   : in Wiki.Strings.WString;
                     Format : in Format_Map) is
   begin
      Append (Into, new Node_Type '(Kind => N_TEXT, Len => Text'Length,
                                    Parent => Into.Current,
                                    Text => Text, Format => Format));
   end Append;

   --  ------------------------------
   --  Add a definition item at end of the document.
   --  ------------------------------
   procedure Add_Definition (Into       : in out Document;
                             Definition : in Wiki.Strings.WString) is
   begin
      Append (Into, new Node_Type '(Kind   => N_DEFINITION,
                                    Len    => Definition'Length,
                                    Parent => Into.Current,
                                    Header => Definition,
                                    Level  => 0));
   end Add_Definition;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   procedure Add_Link (Into       : in out Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_LINK, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Link;

   --  ------------------------------
   --  Add an image.
   --  ------------------------------
   procedure Add_Image (Into       : in out Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_IMAGE, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Image;

   --  ------------------------------
   --  Add a quote.
   --  ------------------------------
   procedure Add_Quote (Into       : in out Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_QUOTE, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Quote;

   --  ------------------------------
   --  Add a list (<ul> or <ol>) starting at the given number.
   --  ------------------------------
   procedure Add_List (Into     : in out Document;
                       Level    : in Positive;
                       Ordered  : in Boolean) is
   begin
      if Ordered then
         Append (Into, new Node_Type '(Kind => N_NUM_LIST_START, Len => 0,
                                       Parent => Into.Current,
                                       Level => Level, others => <>));
      else
         Append (Into, new Node_Type '(Kind => N_LIST_START, Len => 0,
                                       Parent => Into.Current,
                                       Level => Level, others => <>));
      end if;
   end Add_List;

   --  ------------------------------
   --  Add a blockquote (<blockquote>).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   --  ------------------------------
   procedure Add_Blockquote (Into     : in out Document;
                             Level    : in Natural) is
   begin
      Append (Into, new Node_Type '(Kind => N_BLOCKQUOTE, Len => 0,
                                    Parent => Into.Current,
                                    Level => Level, others => <>));
   end Add_Blockquote;

   --  ------------------------------
   --  Add a text block that is pre-formatted.
   --  ------------------------------
   procedure Add_Preformatted (Into     : in out Document;
                               Text     : in Wiki.Strings.WString;
                               Format   : in Wiki.Strings.WString) is
   begin
      Append (Into, new Node_Type '(Kind => N_PREFORMAT, Len => Text'Length,
                                    Parent => Into.Current,
                                    Preformatted => Text,
                                    Language => Strings.To_UString (Format)));
   end Add_Preformatted;

   --  ------------------------------
   --  Add a new row to the current table.
   --  ------------------------------
   procedure Add_Row (Into : in out Document) is
      Table : Node_Type_Access;
      Row   : Node_Type_Access;
   begin
      --  Identify the current table.
      Table := Into.Current;
      while Table /= null and then Table.Kind /= N_TABLE loop
         Table := Table.Parent;
      end loop;

      --  Create the current table.
      if Table = null then
         Table := new Node_Type '(Kind       => N_TABLE,
                                  Len        => 0,
                                  Tag_Start  => TABLE_TAG,
                                  Children   => null,
                                  Parent     => Into.Current,
                                  others     => <>);
         Append (Into, Table);
      end if;

      --  Add the row.
      Row := new Node_Type '(Kind       => N_ROW,
                             Len        => 0,
                             Tag_Start  => TR_TAG,
                             Children   => null,
                             Parent     => Table,
                             others     => <>);
      Append (Table, Row);
      Into.Current := Row;
   end Add_Row;

   --  ------------------------------
   --  Add a column to the current table row.  The column is configured with the
   --  given attributes.  The column content is provided through calls to Append.
   --  ------------------------------
   procedure Add_Column (Into : in out Document;
                         Attributes : in out Wiki.Attributes.Attribute_List) is
      Row  : Node_Type_Access;
      Col  : Node_Type_Access;
   begin
      --  Identify the current row.
      Row := Into.Current;
      while Row /= null and then Row.Kind /= N_ROW loop
         Row := Row.Parent;
      end loop;

      --  Add the new column.
      Col := new Node_Type '(Kind       => N_COLUMN,
                             Len        => 0,
                             Tag_Start  => TD_TAG,
                             Children   => null,
                             Parent     => Row,
                             Attributes => Attributes);
      Append (Row, Col);
      Into.Current := Col;
   end Add_Column;

   --  ------------------------------
   --  Finish the creation of the table.
   --  ------------------------------
   procedure Finish_Table (Into : in out Document) is
      Table : Node_Type_Access;
   begin
      --  Identify the current table.
      Table := Into.Current;
      while Table /= null and then Table.Kind /= N_TABLE loop
         Table := Table.Parent;
      end loop;
      if Table /= null then
         Into.Current := Table.Parent;
      else
         Into.Current := null;
      end if;
   end Finish_Table;

   --  ------------------------------
   --  Iterate over the nodes of the list and call the <tt>Process</tt> procedure with
   --  each node instance.
   --  ------------------------------
   procedure Iterate (Doc     : in Document;
                      Process : not null access procedure (Node : in Node_Type)) is
   begin
      Iterate (Doc.Nodes, Process);
   end Iterate;

   --  ------------------------------
   --  Returns True if the document is empty.
   --  ------------------------------
   function Is_Empty (Doc : in Document) return Boolean is
   begin
      return Wiki.Nodes.Lists.Is_Empty (Doc.Nodes);
   end Is_Empty;

   --  ------------------------------
   --  Returns True if the document displays the table of contents by itself.
   --  ------------------------------
   function Is_Using_TOC (Doc : in Document) return Boolean is
   begin
      return Doc.Using_TOC;
   end Is_Using_TOC;

   --  ------------------------------
   --  Returns True if the table of contents is visible and must be rendered.
   --  ------------------------------
   function Is_Visible_TOC (Doc : in Document) return Boolean is
   begin
      return Doc.Visible_TOC;
   end Is_Visible_TOC;

   --  ------------------------------
   --  Hide the table of contents.
   --  ------------------------------
   procedure Hide_TOC (Doc : in out Document) is
   begin
      Doc.Visible_TOC := False;
   end Hide_TOC;

   --  ------------------------------
   --  Get the table of content node associated with the document.
   --  ------------------------------
   procedure Get_TOC (Doc : in out Document;
                      TOC : out Wiki.Nodes.Lists.Node_List_Ref) is
   begin
      if Wiki.Nodes.Lists.Is_Empty (Doc.TOC) then
         Append (Doc.TOC, new Node_Type '(Kind => N_TOC, Len => 0, others => <>));
      end if;
      TOC := Doc.TOC;
   end Get_TOC;

   --  ------------------------------
   --  Get the table of content node associated with the document.
   --  ------------------------------
   function Get_TOC (Doc : in Document) return Wiki.Nodes.Lists.Node_List_Ref is
   begin
      return Doc.TOC;
   end Get_TOC;

   --  ------------------------------
   --  Set a link definition.
   --  ------------------------------
   procedure Set_Link (Doc  : in out Document;
                       Name : in Wiki.Strings.WString;
                       Link : in Wiki.Strings.WString) is
   begin
      Doc.Links.Include (Name, Link);
   end Set_Link;

   --  ------------------------------
   --  Get a link definition.
   --  ------------------------------
   function Get_Link (Doc  : in out Document;
                      Name : in Wiki.Strings.WString) return Wiki.Strings.WString is
      Pos : constant Wiki.Strings.Maps.Cursor := Doc.Links.Find (Name);
   begin
      if Wiki.Strings.Maps.Has_Element (Pos) then
         return Wiki.Strings.Maps.Element (Pos);
      else
         return "";
      end if;
   end Get_Link;

end Wiki.Documents;

-----------------------------------------------------------------------
--  wiki-nodes -- Wiki Document Internal representation
--  Copyright (C) 2016, 2019, 2020, 2022 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Wide_Wide_Characters.Handling;
package body Wiki.Documents is

   use Wiki.Nodes;
   use Wiki.Nodes.Lists;

   --  ------------------------------
   --  Append a HTML tag start node to the document.
   --  ------------------------------
   procedure Start_Block (Into  : in out Document;
                          Kind  : in Wiki.Nodes.Node_Kind;
                          Level : in Natural) is
      Node : Node_Type_Access;
   begin
      case Kind is
         when N_HEADER =>
            Node := new Node_Type '(Kind       => N_HEADER,
                                    Len        => 0,
                                    Level      => Level,
                                    Content    => null,
                                    Parent     => Into.Current);

         when others =>
            return;

      end case;
      Append (Into, Node);
      Into.Current := Node;
   end Start_Block;

   procedure End_Block (From : in out Document;
                        Kind  : in Wiki.Nodes.Node_Kind) is
   begin
      if From.Current /= null then
         From.Current := From.Current.Parent;
      end if;
   end End_Block;

   --  ------------------------------
   --  Append a HTML tag start node to the document.
   --  ------------------------------
   procedure Push_Node (Into       : in out Document;
                        Tag        : in Html_Tag;
                        Attributes : in Wiki.Attributes.Attribute_List) is

      Node : constant Node_Type_Access := new Node_Type '(Kind       => N_TAG_START,
                                                          Len        => 0,
                                                          Tag_Start  => Tag,
                                                          Attributes => Attributes,
                                                          Children   => null,
                                                          Parent     => Into.Current);
   begin
      Append (Into, Node);
      Into.Current := Node;
   end Push_Node;

   --  ------------------------------
   --  Pop the HTML tag.
   --  ------------------------------
   procedure Pop_Node (From : in out Document;
                       Tag  : in Html_Tag) is
      pragma Unreferenced (Tag);
   begin
      if From.Current /= null then
         From.Current := From.Current.Parent;
      end if;
   end Pop_Node;

   --  ------------------------------
   --  Returns True if the current node is the root document node.
   --  ------------------------------
   function Is_Root_Node (Doc : in Document) return Boolean is
   begin
      return Doc.Current = null;
   end Is_Root_Node;

   --  ------------------------------
   --  Append a node to the document.
   --  ------------------------------
   procedure Append (Into : in out Document;
                     Node : in Wiki.Nodes.Node_Type_Access) is
   begin
      if Into.Current = null then
         Append (Into.Nodes, Node);
      else
         Append (Into.Current, Node);
      end if;
   end Append;

   --  ------------------------------
   --  Append a simple node such as N_LINE_BREAK, N_HORIZONTAL_RULE or N_PARAGRAPH.
   --  ------------------------------
   procedure Append (Into : in out Document;
                     Kind : in Simple_Node_Kind) is
   begin
      case Kind is
         when N_LINE_BREAK =>
            Append (Into, new Node_Type '(Kind => N_LINE_BREAK, Len => 0,
                                          Parent => Into.Current));

         when N_HORIZONTAL_RULE =>
            Append (Into, new Node_Type '(Kind => N_HORIZONTAL_RULE, Len => 0,
                                          Parent => Into.Current));

         when N_PARAGRAPH =>
            Append (Into, new Node_Type '(Kind => N_PARAGRAPH, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_ITEM =>
            Append (Into, new Node_Type '(Kind => N_LIST_ITEM, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_END =>
            Append (Into, new Node_Type '(Kind => N_LIST_END, Len => 0,
                                          Parent => Into.Current));

         when N_NUM_LIST_END =>
            Append (Into, new Node_Type '(Kind => N_NUM_LIST_END, Len => 0,
                                          Parent => Into.Current));

         when N_LIST_ITEM_END =>
            Append (Into, new Node_Type '(Kind => N_LIST_ITEM_END, Len => 0,
                                          Parent => Into.Current));

         when N_NEWLINE =>
            Append (Into, new Node_Type '(Kind => N_NEWLINE, Len => 0,
                                          Parent => Into.Current));

         when N_END_DEFINITION =>
            Append (Into, new Node_Type '(Kind => N_END_DEFINITION, Len => 0,
                                          Parent => Into.Current));

         when N_TOC_DISPLAY =>
            Append (Into, new Node_Type '(Kind => N_TOC_DISPLAY, Len => 0,
                                          Parent => Into.Current));
            Into.Using_TOC := True;

         when N_NONE =>
            null;

      end  case;
   end Append;

   --  ------------------------------
   --  Append the text with the given format at end of the document.
   --  ------------------------------
   procedure Append (Into   : in out Document;
                     Text   : in Wiki.Strings.WString;
                     Format : in Format_Map) is
   begin
      Append (Into, new Node_Type '(Kind => N_TEXT, Len => Text'Length,
                                    Parent => Into.Current,
                                    Text => Text, Format => Format));
   end Append;

   --  ------------------------------
   --  Add a definition item at end of the document.
   --  ------------------------------
   procedure Add_Definition (Into       : in out Document;
                             Definition : in Wiki.Strings.WString) is
   begin
   --   Append (Into, new Node_Type '(Kind   => N_DEFINITION,
   --                                 Len    => Definition'Length,
   --                                 Parent => Into.Current,
   --                                 Header => Definition,
   --                                 Level  => 0));
      null;
   end Add_Definition;

   --  ------------------------------
   --  Add a link.
   --  ------------------------------
   procedure Add_Link (Into       : in out Document;
                       Name       : in Wiki.Strings.WString;
                       Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_LINK, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Link;

   --  ------------------------------
   --  Add a link reference with the given label.
   --  ------------------------------
   procedure Add_Link_Ref (Into   : in out Document;
                           Label  : in Wiki.Strings.WString) is
   begin
      Append (Into, new Node_Type '(Kind => N_LINK_REF, Len => Label'Length,
                                    Parent => Into.Current,
                                    Title => Label, others => <>));
   end Add_Link_Ref;

   --  ------------------------------
   --  Add an image.
   --  ------------------------------
   procedure Add_Image (Into       : in out Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_IMAGE, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Image;

   --  ------------------------------
   --  Add a quote.
   --  ------------------------------
   procedure Add_Quote (Into       : in out Document;
                        Name       : in Wiki.Strings.WString;
                        Attributes : in out Wiki.Attributes.Attribute_List) is
   begin
      Append (Into, new Node_Type '(Kind => N_QUOTE, Len => Name'Length,
                                    Parent => Into.Current,
                                    Title => Name, Link_Attr => Attributes));
   end Add_Quote;

   --  ------------------------------
   --  Add a list (<ul> or <ol>) starting at the given number.
   --  ------------------------------
   procedure Add_List (Into     : in out Document;
                       Level    : in Natural;
                       Ordered  : in Boolean) is
   begin
      if Ordered then
         Append (Into, new Node_Type '(Kind => N_NUM_LIST_START, Len => 0,
                                       Parent => Into.Current,
                                       Level => Level, others => <>));
      else
         Append (Into, new Node_Type '(Kind => N_LIST_START, Len => 0,
                                       Parent => Into.Current,
                                       Level => Level, others => <>));
      end if;
   end Add_List;

   --  ------------------------------
   --  Add a blockquote (<blockquote>).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   --  ------------------------------
   procedure Add_Blockquote (Into     : in out Document;
                             Level    : in Natural) is
   begin
      Append (Into, new Node_Type '(Kind => N_BLOCKQUOTE, Len => 0,
                                    Parent => Into.Current,
                                    Level => Level, others => <>));
   end Add_Blockquote;

   --  ------------------------------
   --  Add a text block that is pre-formatted.
   --  ------------------------------
   procedure Add_Preformatted (Into     : in out Document;
                               Text     : in Wiki.Strings.WString;
                               Format   : in Wiki.Strings.WString) is
   begin
      Append (Into, new Node_Type '(Kind => N_PREFORMAT, Len => Text'Length,
                                    Parent => Into.Current,
                                    Preformatted => Text,
                                    Language => Strings.To_UString (Format)));
   end Add_Preformatted;

   --  ------------------------------
   --  Add a new row to the current table.
   --  ------------------------------
   procedure Add_Row (Into : in out Document) is
      Table : Node_Type_Access;
      Row   : Node_Type_Access;
   begin
      --  Identify the current table.
      Table := Into.Current;
      while Table /= null and then Table.Kind /= N_TABLE loop
         Table := Table.Parent;
      end loop;

      --  Create the current table.
      if Table = null then
         Table := new Node_Type '(Kind       => N_TABLE,
                                  Len        => 0,
                                  Tag_Start  => TABLE_TAG,
                                  Children   => null,
                                  Parent     => Into.Current,
                                  others     => <>);
         Append (Into, Table);
      end if;

      --  Add the row.
      Row := new Node_Type '(Kind       => N_ROW,
                             Len        => 0,
                             Tag_Start  => TR_TAG,
                             Children   => null,
                             Parent     => Table,
                             others     => <>);
      Append (Table, Row);
      Into.Current := Row;
   end Add_Row;

   --  ------------------------------
   --  Add a column to the current table row.  The column is configured with the
   --  given attributes.  The column content is provided through calls to Append.
   --  ------------------------------
   procedure Add_Column (Into : in out Document;
                         Attributes : in out Wiki.Attributes.Attribute_List) is
      Row  : Node_Type_Access;
      Col  : Node_Type_Access;
   begin
      --  Identify the current row.
      Row := Into.Current;
      while Row /= null and then Row.Kind /= N_ROW loop
         Row := Row.Parent;
      end loop;

      --  Add the new column.
      Col := new Node_Type '(Kind       => N_COLUMN,
                             Len        => 0,
                             Tag_Start  => TD_TAG,
                             Children   => null,
                             Parent     => Row,
                             Attributes => Attributes);
      Append (Row, Col);
      Into.Current := Col;
   end Add_Column;

   --  ------------------------------
   --  Finish the creation of the table.
   --  ------------------------------
   procedure Finish_Table (Into : in out Document) is
      Table : Node_Type_Access;
   begin
      --  Identify the current table.
      Table := Into.Current;
      while Table /= null and then Table.Kind /= N_TABLE loop
         Table := Table.Parent;
      end loop;
      if Table /= null then
         Into.Current := Table.Parent;
      else
         Into.Current := null;
      end if;
   end Finish_Table;

   --  ------------------------------
   --  Iterate over the nodes of the list and call the <tt>Process</tt> procedure with
   --  each node instance.
   --  ------------------------------
   procedure Iterate (Doc     : in Document;
                      Process : not null access procedure (Node : in Node_Type)) is
   begin
      Iterate (Doc.Nodes, Process);
   end Iterate;

   --  ------------------------------
   --  Returns True if the document is empty.
   --  ------------------------------
   function Is_Empty (Doc : in Document) return Boolean is
   begin
      return Wiki.Nodes.Lists.Is_Empty (Doc.Nodes);
   end Is_Empty;

   --  ------------------------------
   --  Returns True if the document displays the table of contents by itself.
   --  ------------------------------
   function Is_Using_TOC (Doc : in Document) return Boolean is
   begin
      return Doc.Using_TOC;
   end Is_Using_TOC;

   --  ------------------------------
   --  Returns True if the table of contents is visible and must be rendered.
   --  ------------------------------
   function Is_Visible_TOC (Doc : in Document) return Boolean is
   begin
      return Doc.Visible_TOC;
   end Is_Visible_TOC;

   --  ------------------------------
   --  Hide the table of contents.
   --  ------------------------------
   procedure Hide_TOC (Doc : in out Document) is
   begin
      Doc.Visible_TOC := False;
   end Hide_TOC;

   --  ------------------------------
   --  Get the table of content node associated with the document.
   --  ------------------------------
   procedure Get_TOC (Doc : in out Document;
                      TOC : out Wiki.Nodes.Lists.Node_List_Ref) is
   begin
      if Wiki.Nodes.Lists.Is_Empty (Doc.TOC) then
         Append (Doc.TOC, new Node_Type '(Kind => N_TOC, Len => 0, others => <>));
      end if;
      TOC := Doc.TOC;
   end Get_TOC;

   --  ------------------------------
   --  Get the table of content node associated with the document.
   --  ------------------------------
   function Get_TOC (Doc : in Document) return Wiki.Nodes.Lists.Node_List_Ref is
   begin
      return Doc.TOC;
   end Get_TOC;

   --  ------------------------------
   --  Set a link definition.
   --  ------------------------------
   procedure Set_Link (Doc   : in out Document;
                       Name  : in Wiki.Strings.WString;
                       Link  : in Wiki.Strings.WString;
                       Title : in Wiki.Strings.WString) is
      Upper : constant Wiki.Strings.WString
           := Ada.Wide_Wide_Characters.Handling.To_Upper (Name);
   begin
      if not Doc.Links.Contains (Upper) then
         Doc.Links.Include (Upper, Link);
         if Title'Length > 0 then
            Doc.Titles.Include (Upper, Title);
         end if;
      end if;
   end Set_Link;

   --  ------------------------------
   --  Get a link definition.
   --  ------------------------------
   function Get_Link (Doc   : in Document;
                      Label : in Wiki.Strings.WString) return Wiki.Strings.WString is
      Upper : constant Wiki.Strings.WString
           := Ada.Wide_Wide_Characters.Handling.To_Upper (Label);
      Pos : constant Wiki.Strings.Maps.Cursor := Doc.Links.Find (Upper);
   begin
      if Wiki.Strings.Maps.Has_Element (Pos) then
         return Wiki.Strings.Maps.Element (Pos);
      else
         return "";
      end if;
   end Get_Link;

   --  ------------------------------
   --  Get a link definition.
   --  ------------------------------
   function Get_Link_Title (Doc   : in Document;
                            Label : in Wiki.Strings.WString) return Wiki.Strings.WString is
      Upper : constant Wiki.Strings.WString
           := Ada.Wide_Wide_Characters.Handling.To_Upper (Label);
      Pos : constant Wiki.Strings.Maps.Cursor := Doc.Titles.Find (Upper);
   begin
      if Wiki.Strings.Maps.Has_Element (Pos) then
         return Wiki.Strings.Maps.Element (Pos);
      else
         return "";
      end if;
   end Get_Link_Title;

end Wiki.Documents;

Implement Start_Block, End_Block, Get_Link_Title


-----------------------------------------------------------------------
--  druss-commands -- Commands available for Druss
--  Copyright (C) 2017 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Util.Commands.Drivers;
with Util.Commands.Consoles;
with Util.Commands.Consoles.Text;
with Druss.Gateways;
package Druss.Commands is

   --  The list of fields that are printed on the console.
   type Field_Type is (F_IP_ADDR,
                       F_COUNT,
                       F_BOOL,
                       F_CHANNEL,
                       F_PROTOCOL,
                       F_ENCRYPTION,
                       F_SSID);

   --  The type of notice that are reported.
   type Notice_Type is (N_HELP,
                        N_INFO);

   --  Make the generic abstract console interface.
   package Consoles is
     new Util.Commands.Consoles (Field_Type  => Field_Type,
                                 Notice_Type => Notice_Type);

   --  And the text console to write on stdout (a Gtk console could be done someday).
   package Text_Consoles is
      new Consoles.Text;

   type Context_Type is limited record
      Gateways : Druss.Gateways.Gateway_Vector;
      Console  : Consoles.Console_Access;
   end record;

   package Drivers is
     new Util.Commands.Drivers (Context_Type => Context_Type,
                                Driver_Name  => "druss-drivers");

   subtype Argument_List is Util.Commands.Argument_List;

   Driver : Drivers.Driver_Type;

   procedure Gateway_Command (Command   : in Drivers.Command_Type'Class;
                              Args      : in Util.Commands.Argument_List'Class;
                              Arg_Pos   : in Positive;
                              Process   : access procedure (Gateway : in out Gateways.Gateway_Type;
                                                            Param   : in String);
                              Context   : in out Context_Type);

   procedure Initialize;

end Druss.Commands;

-----------------------------------------------------------------------
--  druss-commands -- Commands available for Druss
--  Copyright (C) 2017 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Util.Commands.Drivers;
with Util.Commands.Consoles;
with Util.Commands.Consoles.Text;
with Druss.Gateways;
package Druss.Commands is

   --  The list of fields that are printed on the console.
   type Field_Type is (F_IP_ADDR,
                       F_WAN_IP,
                       F_INTERNET,
                       F_VOIP,
                       F_WIFI,
                       F_WIFI5,
                       F_ACCESS_CONTROL,
                       F_DYNDNS,
                       F_DEVICES,
                       F_COUNT,
                       F_BOOL,
                       F_CHANNEL,
                       F_PROTOCOL,
                       F_ENCRYPTION,
                       F_SSID);

   --  The type of notice that are reported.
   type Notice_Type is (N_HELP,
                        N_INFO);

   --  Make the generic abstract console interface.
   package Consoles is
     new Util.Commands.Consoles (Field_Type  => Field_Type,
                                 Notice_Type => Notice_Type);

   --  And the text console to write on stdout (a Gtk console could be done someday).
   package Text_Consoles is
      new Consoles.Text;

   type Context_Type is limited record
      Gateways : Druss.Gateways.Gateway_Vector;
      Console  : Consoles.Console_Access;
   end record;

   package Drivers is
     new Util.Commands.Drivers (Context_Type => Context_Type,
                                Driver_Name  => "druss-drivers");

   subtype Argument_List is Util.Commands.Argument_List;

   Driver : Drivers.Driver_Type;

   procedure Gateway_Command (Command   : in Drivers.Command_Type'Class;
                              Args      : in Util.Commands.Argument_List'Class;
                              Arg_Pos   : in Positive;
                              Process   : access procedure (Gateway : in out Gateways.Gateway_Type;
                                                            Param   : in String);
                              Context   : in out Context_Type);

   procedure Initialize;

end Druss.Commands;

Declare several new fields for the bbox status command


--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2012 Felix Krause <contact@flyx.org>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

private with GL.Low_Level;

package GL.Enums.Textures is
   pragma Preelaborate;

   -- Texture_Kind is declared in GL.Low_Level.Enums to be accessible for
   -- OpenCLAda

   type Parameter is (Border_Color, Mag_Filter, Min_Filter, Wrap_S,
                      Wrap_T, Wrap_R, Min_LoD, Max_LoD,
                      Base_Level, Max_Level, Immutable_Levels, Max_Anisotropy,
                      LoD_Bias, Compare_Mode, Compare_Func, Cube_Map_Seamless);

   -- needs to be declared here because of subtypes
   for Parameter use (Border_Color    => 16#1004#,
                      Mag_Filter      => 16#2800#,
                      Min_Filter      => 16#2801#,
                      Wrap_S          => 16#2802#,
                      Wrap_T          => 16#2803#,
                      Wrap_R          => 16#8072#,
                      Min_LoD         => 16#813A#,
                      Max_LoD         => 16#813B#,
                      Base_Level      => 16#813C#,
                      Max_Level       => 16#813D#,
                      Immutable_Levels => 16#82DF#,
                      Max_Anisotropy  => 16#84FE#,
                      LoD_Bias        => 16#8501#,
                      Compare_Mode    => 16#884C#,
                      Compare_Func    => 16#884D#,
                      Cube_Map_Seamless => 16#884F#);
   for Parameter'Size use Low_Level.Enum'Size;

   subtype LoD is Parameter range Min_LoD .. Max_Level;

   type Compare_Kind is (None, Compare_R_To_Texture);

   type Env_Parameter is (LoD_Bias, Src1_Alpha);

   type Level_Parameter is (Width, Height, Internal_Format, Red_Size,
                            Green_Size, Blue_Size, Alpha_Size, Depth,
                            Compressed_Image_Size, Compressed,
                            Depth_Size, Stencil_Size,
                            Red_Type, Green_Type, Blue_Type,
                            Alpha_Type, Depth_Type, Shared_Size,
                            Samples, Fixed_Sample_Locations,
                            Buffer_Offset, Buffer_Size);

   Texture_Unit_Start_Rep : constant := 16#84C0#;

private

   for Compare_Kind use (None => 0, Compare_R_To_Texture => 16#884E#);
   for Compare_Kind'Size use Low_Level.Enum'Size;

   for Env_Parameter use (LoD_Bias       => 16#8501#,
                          Src1_Alpha     => 16#8589#);
   for Env_Parameter'Size use Low_Level.Enum'Size;

   for Level_Parameter use (Width           => 16#1000#,
                            Height          => 16#1001#,
                            Internal_Format => 16#1003#,
                            Red_Size        => 16#805C#,
                            Green_Size      => 16#805D#,
                            Blue_Size       => 16#805E#,
                            Alpha_Size      => 16#805F#,
                            Depth           => 16#8071#,
                            Compressed_Image_Size => 16#86A0#,
                            Compressed      => 16#86A1#,
                            Depth_Size      => 16#884A#,
                            Stencil_Size    => 16#88F1#,
                            Red_Type        => 16#8C10#,
                            Green_Type      => 16#8C11#,
                            Blue_Type       => 16#8C12#,
                            Alpha_Type      => 16#8C13#,
                            Depth_Type      => 16#8C16#,
                            Shared_Size     => 16#8C3F#,
                            Samples         => 16#9106#,
                            Fixed_Sample_Locations => 16#9107#,
                            Buffer_Offset   => 16#919D#,
                            Buffer_Size     => 16#919E#);
   for Level_Parameter'Size use Low_Level.Enum'Size;

end GL.Enums.Textures;

--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2012 Felix Krause <contact@flyx.org>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

private with GL.Low_Level;

package GL.Enums.Textures is
   pragma Preelaborate;

   type Parameter is (Border_Color, Mag_Filter, Min_Filter, Wrap_S,
                      Wrap_T, Wrap_R, Min_LoD, Max_LoD,
                      Base_Level, Max_Level, Immutable_Levels, Max_Anisotropy,
                      LoD_Bias, Compare_Mode, Compare_Func, Cube_Map_Seamless);

   type Compare_Kind is (None, Compare_R_To_Texture);

   type Level_Parameter is (Width, Height, Internal_Format, Red_Size,
                            Green_Size, Blue_Size, Alpha_Size, Depth,
                            Compressed_Image_Size, Compressed,
                            Depth_Size, Stencil_Size,
                            Red_Type, Green_Type, Blue_Type,
                            Alpha_Type, Depth_Type, Shared_Size,
                            Samples, Fixed_Sample_Locations,
                            Buffer_Offset, Buffer_Size);

private

   for Parameter use (Border_Color    => 16#1004#,
                      Mag_Filter      => 16#2800#,
                      Min_Filter      => 16#2801#,
                      Wrap_S          => 16#2802#,
                      Wrap_T          => 16#2803#,
                      Wrap_R          => 16#8072#,
                      Min_LoD         => 16#813A#,
                      Max_LoD         => 16#813B#,
                      Base_Level      => 16#813C#,
                      Max_Level       => 16#813D#,
                      Immutable_Levels => 16#82DF#,
                      Max_Anisotropy  => 16#84FE#,
                      LoD_Bias        => 16#8501#,
                      Compare_Mode    => 16#884C#,
                      Compare_Func    => 16#884D#,
                      Cube_Map_Seamless => 16#884F#);
   for Parameter'Size use Low_Level.Enum'Size;

   for Compare_Kind use (None => 0, Compare_R_To_Texture => 16#884E#);
   for Compare_Kind'Size use Low_Level.Enum'Size;

   for Level_Parameter use (Width           => 16#1000#,
                            Height          => 16#1001#,
                            Internal_Format => 16#1003#,
                            Red_Size        => 16#805C#,
                            Green_Size      => 16#805D#,
                            Blue_Size       => 16#805E#,
                            Alpha_Size      => 16#805F#,
                            Depth           => 16#8071#,
                            Compressed_Image_Size => 16#86A0#,
                            Compressed      => 16#86A1#,
                            Depth_Size      => 16#884A#,
                            Stencil_Size    => 16#88F1#,
                            Red_Type        => 16#8C10#,
                            Green_Type      => 16#8C11#,
                            Blue_Type       => 16#8C12#,
                            Alpha_Type      => 16#8C13#,
                            Depth_Type      => 16#8C16#,
                            Shared_Size     => 16#8C3F#,
                            Samples         => 16#9106#,
                            Fixed_Sample_Locations => 16#9107#,
                            Buffer_Offset   => 16#919D#,
                            Buffer_Size     => 16#919E#);
   for Level_Parameter'Size use Low_Level.Enum'Size;

end GL.Enums.Textures;

gl: Remove some unused types and constants in package GL.Enums.Textures

Signed-off-by: onox <34c1d3d2d1347bea60a26f46574de21a7a79b6d5@gmail.com>


-----------------------------------------------------------------------
--  wiki-render-wiki -- Wiki to Wiki renderer
--  Copyright (C) 2015, 2016 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Wiki.Documents;
with Wiki.Attributes;
with Wiki.Writers;
with Wiki.Parsers;

--  == Wiki Renderer ==
--  The <tt>Wiki_Renderer</tt> allows to render a wiki document into another wiki content.
--  The formatting rules are ignored except for the paragraphs and sections.
package Wiki.Render.Wiki is

   use Standard.Wiki.Attributes;

   --  ------------------------------
   --  Wiki to HTML writer
   --  ------------------------------
   type Wiki_Renderer is new Standard.Wiki.Documents.Document_Reader with private;

   --  Set the output writer.
   procedure Set_Writer (Document : in out Wiki_Renderer;
                         Writer   : in Writers.Writer_Type_Access;
                         Format   : in Parsers.Wiki_Syntax_Type);

   --  Add a section header in the document.
   overriding
   procedure Add_Header (Document : in out Wiki_Renderer;
                         Header   : in Unbounded_Wide_Wide_String;
                         Level    : in Positive);

   --  Add a line break (
).
   overriding
   procedure Add_Line_Break (Document : in out Wiki_Renderer);

   --  Add a paragraph (
).  Close the previous paragraph if any.
   --  The paragraph must be closed at the next paragraph or next header.
   overriding
   procedure Add_Paragraph (Document : in out Wiki_Renderer);

   --  Add a blockquote (
).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   overriding
   procedure Add_Blockquote (Document : in out Wiki_Renderer;
                             Level    : in Natural);

   --  Add a list item (
).  Close the previous paragraph and list item if any.
   --  The list item will be closed at the next list item, next paragraph or next header.
   overriding
   procedure Add_List_Item (Document : in out Wiki_Renderer;
                            Level    : in Positive;
                            Ordered  : in Boolean);

   --  Add an horizontal rule (
).
   overriding
   procedure Add_Horizontal_Rule (Document : in out Wiki_Renderer);

   --  Add a link.
   overriding
   procedure Add_Link (Document : in out Wiki_Renderer;
                       Name     : in Unbounded_Wide_Wide_String;
                       Link     : in Unbounded_Wide_Wide_String;
                       Language : in Unbounded_Wide_Wide_String;
                       Title    : in Unbounded_Wide_Wide_String);

   --  Add an image.
   overriding
   procedure Add_Image (Document    : in out Wiki_Renderer;
                        Link        : in Unbounded_Wide_Wide_String;
                        Alt         : in Unbounded_Wide_Wide_String;
                        Position    : in Unbounded_Wide_Wide_String;
                        Description : in Unbounded_Wide_Wide_String);

   --  Add a quote.
   overriding
   procedure Add_Quote (Document : in out Wiki_Renderer;
                        Quote    : in Unbounded_Wide_Wide_String;
                        Link     : in Unbounded_Wide_Wide_String;
                        Language : in Unbounded_Wide_Wide_String);

   --  Add a text block with the given format.
   overriding
   procedure Add_Text (Document : in out Wiki_Renderer;
                       Text     : in Unbounded_Wide_Wide_String;
                       Format   : in Documents.Format_Map);

   --  Add a text block that is pre-formatted.
   procedure Add_Preformatted (Document : in out Wiki_Renderer;
                               Text     : in Unbounded_Wide_Wide_String;
                               Format   : in Unbounded_Wide_Wide_String);

   overriding
   procedure Start_Element (Document   : in out Wiki_Renderer;
                            Name       : in Unbounded_Wide_Wide_String;
                            Attributes : in Attribute_List_Type);

   overriding
   procedure End_Element (Document : in out Wiki_Renderer;
                          Name     : in Unbounded_Wide_Wide_String);

   --  Finish the document after complete wiki text has been parsed.
   overriding
   procedure Finish (Document : in out Wiki_Renderer);

   --  Set the text style format.
   procedure Set_Format (Document : in out Wiki_Renderer;
                         Format   : in Documents.Format_Map);

private

   type Wide_String_Access is access constant Wide_Wide_String;

   type Wiki_Tag_Type is (Header_Start, Header_End,
                          Img_Start, Img_End,
                          Link_Start, Link_End, Link_Separator,
                          Preformat_Start, Preformat_End,
                          List_Start, List_Item, List_Ordered_Item,
                          Line_Break, Escape_Rule,
                          Horizontal_Rule,
                          Blockquote_Start, Blockquote_End);

   type Wiki_Tag_Array is array (Wiki_Tag_Type) of Wide_String_Access;

   type Wiki_Format_Array is array (Documents.Format_Type) of Wide_String_Access;

   --  Emit a new line.
   procedure New_Line (Document : in out Wiki_Renderer);

   procedure Close_Paragraph (Document : in out Wiki_Renderer);
   procedure Open_Paragraph (Document : in out Wiki_Renderer);
   procedure Start_Keep_Content (Document : in out Wiki_Renderer);

   type List_Style_Array is array (1 .. 32) of Boolean;

   EMPTY_TAG : aliased constant Wide_Wide_String := "";

   type Wiki_Renderer is new Documents.Document_Reader with record
      Writer              : Writers.Writer_Type_Access := null;
      Syntax              : Parsers.Wiki_Syntax_Type := Parsers.SYNTAX_CREOLE;
      Format              : Documents.Format_Map := (others => False);
      Tags                : Wiki_Tag_Array := (others => EMPTY_TAG'Access);
      Style_Start_Tags    : Wiki_Format_Array := (others => EMPTY_TAG'Access);
      Style_End_Tags      : Wiki_Format_Array := (others => EMPTY_TAG'Access);
      Has_Paragraph       : Boolean := False;
      Has_Item            : Boolean := False;
      Need_Paragraph      : Boolean := False;
      Empty_Line          : Boolean := True;
      Keep_Content        : Boolean := False;
      In_List             : Boolean := False;
      Invert_Header_Level : Boolean := False;
      Allow_Link_Language : Boolean := False;
      Current_Level       : Natural := 0;
      Quote_Level         : Natural := 0;
      UL_List_Level       : Natural := 0;
      OL_List_Level       : Natural := 0;
      Current_Style       : Documents.Format_Map := (others => False);
      Content             : Unbounded_Wide_Wide_String;
      Link_Href           : Unbounded_Wide_Wide_String;
      Link_Title          : Unbounded_Wide_Wide_String;
      Link_Lang           : Unbounded_Wide_Wide_String;
   end record;

end Wiki.Render.Wiki;

-----------------------------------------------------------------------
--  wiki-render-wiki -- Wiki to Wiki renderer
--  Copyright (C) 2015, 2016 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Ada.Strings.Wide_Wide_Maps;

with Wiki.Documents;
with Wiki.Attributes;
with Wiki.Writers;
with Wiki.Parsers;

--  == Wiki Renderer ==
--  The <tt>Wiki_Renderer</tt> allows to render a wiki document into another wiki content.
--  The formatting rules are ignored except for the paragraphs and sections.
package Wiki.Render.Wiki is

   use Standard.Wiki.Attributes;

   --  ------------------------------
   --  Wiki to HTML writer
   --  ------------------------------
   type Wiki_Renderer is new Standard.Wiki.Documents.Document_Reader with private;

   --  Set the output writer.
   procedure Set_Writer (Document : in out Wiki_Renderer;
                         Writer   : in Writers.Writer_Type_Access;
                         Format   : in Parsers.Wiki_Syntax_Type);

   --  Add a section header in the document.
   overriding
   procedure Add_Header (Document : in out Wiki_Renderer;
                         Header   : in Unbounded_Wide_Wide_String;
                         Level    : in Positive);

   --  Add a line break (
).
   overriding
   procedure Add_Line_Break (Document : in out Wiki_Renderer);

   --  Add a paragraph (
).  Close the previous paragraph if any.
   --  The paragraph must be closed at the next paragraph or next header.
   overriding
   procedure Add_Paragraph (Document : in out Wiki_Renderer);

   --  Add a blockquote (
).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   overriding
   procedure Add_Blockquote (Document : in out Wiki_Renderer;
                             Level    : in Natural);

   --  Add a list item (
).  Close the previous paragraph and list item if any.
   --  The list item will be closed at the next list item, next paragraph or next header.
   overriding
   procedure Add_List_Item (Document : in out Wiki_Renderer;
                            Level    : in Positive;
                            Ordered  : in Boolean);

   --  Add an horizontal rule (
).
   overriding
   procedure Add_Horizontal_Rule (Document : in out Wiki_Renderer);

   --  Add a link.
   overriding
   procedure Add_Link (Document : in out Wiki_Renderer;
                       Name     : in Unbounded_Wide_Wide_String;
                       Link     : in Unbounded_Wide_Wide_String;
                       Language : in Unbounded_Wide_Wide_String;
                       Title    : in Unbounded_Wide_Wide_String);

   --  Add an image.
   overriding
   procedure Add_Image (Document    : in out Wiki_Renderer;
                        Link        : in Unbounded_Wide_Wide_String;
                        Alt         : in Unbounded_Wide_Wide_String;
                        Position    : in Unbounded_Wide_Wide_String;
                        Description : in Unbounded_Wide_Wide_String);

   --  Add a quote.
   overriding
   procedure Add_Quote (Document : in out Wiki_Renderer;
                        Quote    : in Unbounded_Wide_Wide_String;
                        Link     : in Unbounded_Wide_Wide_String;
                        Language : in Unbounded_Wide_Wide_String);

   --  Add a text block with the given format.
   overriding
   procedure Add_Text (Document : in out Wiki_Renderer;
                       Text     : in Unbounded_Wide_Wide_String;
                       Format   : in Documents.Format_Map);

   --  Add a text block that is pre-formatted.
   procedure Add_Preformatted (Document : in out Wiki_Renderer;
                               Text     : in Unbounded_Wide_Wide_String;
                               Format   : in Unbounded_Wide_Wide_String);

   overriding
   procedure Start_Element (Document   : in out Wiki_Renderer;
                            Name       : in Unbounded_Wide_Wide_String;
                            Attributes : in Attribute_List_Type);

   overriding
   procedure End_Element (Document : in out Wiki_Renderer;
                          Name     : in Unbounded_Wide_Wide_String);

   --  Finish the document after complete wiki text has been parsed.
   overriding
   procedure Finish (Document : in out Wiki_Renderer);

   --  Set the text style format.
   procedure Set_Format (Document : in out Wiki_Renderer;
                         Format   : in Documents.Format_Map);

private

   type Wide_String_Access is access constant Wide_Wide_String;

   type Wiki_Tag_Type is (Header_Start, Header_End,
                          Img_Start, Img_End,
                          Link_Start, Link_End, Link_Separator,
                          Preformat_Start, Preformat_End,
                          List_Start, List_Item, List_Ordered_Item,
                          Line_Break, Escape_Rule,
                          Horizontal_Rule,
                          Blockquote_Start, Blockquote_End);

   type Wiki_Tag_Array is array (Wiki_Tag_Type) of Wide_String_Access;

   type Wiki_Format_Array is array (Documents.Format_Type) of Wide_String_Access;

   --  Emit a new line.
   procedure New_Line (Document : in out Wiki_Renderer);

   procedure Close_Paragraph (Document : in out Wiki_Renderer);
   procedure Open_Paragraph (Document : in out Wiki_Renderer);
   procedure Start_Keep_Content (Document : in out Wiki_Renderer);

   type List_Style_Array is array (1 .. 32) of Boolean;

   EMPTY_TAG : aliased constant Wide_Wide_String := "";

   type Wiki_Renderer is new Documents.Document_Reader with record
      Writer              : Writers.Writer_Type_Access := null;
      Syntax              : Parsers.Wiki_Syntax_Type := Parsers.SYNTAX_CREOLE;
      Format              : Documents.Format_Map := (others => False);
      Tags                : Wiki_Tag_Array := (others => EMPTY_TAG'Access);
      Style_Start_Tags    : Wiki_Format_Array := (others => EMPTY_TAG'Access);
      Style_End_Tags      : Wiki_Format_Array := (others => EMPTY_TAG'Access);
      Escape_Set          : Ada.Strings.Wide_Wide_Maps.Wide_Wide_Character_Set;
      Has_Paragraph       : Boolean := False;
      Has_Item            : Boolean := False;
      Need_Paragraph      : Boolean := False;
      Empty_Line          : Boolean := True;
      Keep_Content        : Boolean := False;
      In_List             : Boolean := False;
      Invert_Header_Level : Boolean := False;
      Allow_Link_Language : Boolean := False;
      Current_Level       : Natural := 0;
      Quote_Level         : Natural := 0;
      UL_List_Level       : Natural := 0;
      OL_List_Level       : Natural := 0;
      Current_Style       : Documents.Format_Map := (others => False);
      Content             : Unbounded_Wide_Wide_String;
      Link_Href           : Unbounded_Wide_Wide_String;
      Link_Title          : Unbounded_Wide_Wide_String;
      Link_Lang           : Unbounded_Wide_Wide_String;
   end record;

end Wiki.Render.Wiki;

Add Escape_Set member to define the characters to escape