7b83be65b14a8ec99385571165d9d77bc4fd0ead
[ncurses.git] / terminal_interface-curses-forms-field_types.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                           GNAT ncurses Binding                           --
4 --                                                                          --
5 --                 Terminal_Interface.Curses.Forms.Field_Types              --
6 --                                                                          --
7 --                                 B O D Y                                  --
8 --                                                                          --
9 ------------------------------------------------------------------------------
10 -- Copyright (c) 1998 Free Software Foundation, Inc.                        --
11 --                                                                          --
12 -- Permission is hereby granted, free of charge, to any person obtaining a  --
13 -- copy of this software and associated documentation files (the            --
14 -- "Software"), to deal in the Software without restriction, including      --
15 -- without limitation the rights to use, copy, modify, merge, publish,      --
16 -- distribute, distribute with modifications, sublicense, and/or sell       --
17 -- copies of the Software, and to permit persons to whom the Software is    --
18 -- furnished to do so, subject to the following conditions:                 --
19 --                                                                          --
20 -- The above copyright notice and this permission notice shall be included  --
21 -- in all copies or substantial portions of the Software.                   --
22 --                                                                          --
23 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  --
24 -- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               --
25 -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   --
26 -- IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   --
27 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    --
28 -- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    --
29 -- THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               --
30 --                                                                          --
31 -- Except as contained in this notice, the name(s) of the above copyright   --
32 -- holders shall not be used in advertising or otherwise to promote the     --
33 -- sale, use or other dealings in this Software without prior written       --
34 -- authorization.                                                           --
35 ------------------------------------------------------------------------------
36 --  Author:  Juergen Pfeifer, 1996
37 --  Contact: http://www.familiepfeifer.de/Contact.aspx?Lang=en
38 --  Version Control:
39 --  $Revision: 1.13 $
40 --  Binding Version 01.00
41 ------------------------------------------------------------------------------
42 with Interfaces.C;
43 with Terminal_Interface.Curses.Aux; use Terminal_Interface.Curses.Aux;
44 with Ada.Unchecked_Deallocation;
45 with Ada.Unchecked_Conversion;
46 --  |
47 --  |=====================================================================
48 --  | man page form_fieldtype.3x
49 --  |=====================================================================
50 --  |
51 package body Terminal_Interface.Curses.Forms.Field_Types is
52
53    use type Interfaces.C.int;
54    use type System.Address;
55
56    function To_Argument_Access is new Ada.Unchecked_Conversion
57      (System.Address, Argument_Access);
58
59    function Get_Fieldtype (F : Field) return C_Field_Type;
60    pragma Import (C, Get_Fieldtype, "field_type");
61
62    function Get_Arg (F : Field) return System.Address;
63    pragma Import (C, Get_Arg, "field_arg");
64    --  |
65    --  |=====================================================================
66    --  | man page form_field_validation.3x
67    --  |=====================================================================
68    --  |
69    --  |
70    --  |
71    function Get_Type (Fld : in Field) return Field_Type_Access
72    is
73       Low_Level : constant C_Field_Type := Get_Fieldtype (Fld);
74       Arg : Argument_Access;
75    begin
76       if Low_Level = Null_Field_Type then
77          return null;
78       else
79          if Low_Level = M_Builtin_Router or else
80            Low_Level = M_Generic_Type or else
81            Low_Level = M_Choice_Router or else
82            Low_Level = M_Generic_Choice then
83             Arg := To_Argument_Access (Get_Arg (Fld));
84             if Arg = null then
85                raise Form_Exception;
86             else
87                return Arg.Typ;
88             end if;
89          else
90             raise Form_Exception;
91          end if;
92       end if;
93    end Get_Type;
94
95    function Make_Arg (Args : System.Address) return System.Address
96    is
97       --  Actually args is a double indirected pointer to the arguments
98       --  of a C variable argument list. In theory it is now quite
99       --  complicated to write portable routine that reads the arguments,
100       --  because one has to know the growth direction of the stack and
101       --  the sizes of the individual arguments.
102       --  Fortunately we are only interested in the first argument (#0),
103       --  we know its size and for the first arg we don't care about
104       --  into which stack direction we have to proceed. We simply
105       --  resolve the double indirection and thats it.
106       type V is access all System.Address;
107       function To_Access is new Ada.Unchecked_Conversion (System.Address,
108                                                           V);
109    begin
110       return To_Access (To_Access (Args).all).all;
111    end Make_Arg;
112
113    function Copy_Arg (Usr : System.Address) return System.Address
114    is
115    begin
116       return Usr;
117    end Copy_Arg;
118
119    procedure Free_Arg (Usr : in System.Address)
120    is
121       procedure Free_Type is new Ada.Unchecked_Deallocation
122         (Field_Type'Class, Field_Type_Access);
123       procedure Freeargs is new Ada.Unchecked_Deallocation
124         (Argument, Argument_Access);
125
126       To_Be_Free : Argument_Access := To_Argument_Access (Usr);
127       Low_Level  : C_Field_Type;
128    begin
129       if To_Be_Free /= null then
130          if To_Be_Free.Usr /= System.Null_Address then
131             Low_Level := To_Be_Free.Cft;
132             if Low_Level.Freearg /= null then
133                Low_Level.Freearg (To_Be_Free.Usr);
134             end if;
135          end if;
136          if To_Be_Free.Typ /= null then
137             Free_Type (To_Be_Free.Typ);
138          end if;
139          Freeargs (To_Be_Free);
140       end if;
141    end Free_Arg;
142
143
144    procedure Wrap_Builtin (Fld : Field;
145                            Typ : Field_Type'Class;
146                            Cft : C_Field_Type := C_Builtin_Router)
147    is
148       Usr_Arg   : System.Address := Get_Arg (Fld);
149       Low_Level : constant C_Field_Type := Get_Fieldtype (Fld);
150       Arg : Argument_Access;
151       Res : Eti_Error;
152       function Set_Fld_Type (F    : Field := Fld;
153                              Cf   : C_Field_Type := Cft;
154                              Arg1 : Argument_Access) return C_Int;
155       pragma Import (C, Set_Fld_Type, "set_field_type");
156
157    begin
158       pragma Assert (Low_Level /= Null_Field_Type);
159       if Cft /= C_Builtin_Router and then Cft /= C_Choice_Router then
160          raise Form_Exception;
161       else
162          Arg := new Argument'(Usr => System.Null_Address,
163                               Typ => new Field_Type'Class'(Typ),
164                               Cft => Get_Fieldtype (Fld));
165          if Usr_Arg /= System.Null_Address then
166             if Low_Level.Copyarg /= null then
167                Arg.Usr := Low_Level.Copyarg (Usr_Arg);
168             else
169                Arg.Usr := Usr_Arg;
170             end if;
171          end if;
172
173          Res := Set_Fld_Type (Arg1 => Arg);
174          if Res /= E_Ok then
175             Eti_Exception (Res);
176          end if;
177       end if;
178    end Wrap_Builtin;
179
180    function Field_Check_Router (Fld : Field;
181                                 Usr : System.Address) return C_Int
182    is
183       Arg  : constant Argument_Access := To_Argument_Access (Usr);
184    begin
185       pragma Assert (Arg /= null and then Arg.Cft /= Null_Field_Type
186                      and then Arg.Typ /= null);
187       if Arg.Cft.Fcheck /= null then
188          return Arg.Cft.Fcheck (Fld, Arg.Usr);
189       else
190          return 1;
191       end if;
192    end Field_Check_Router;
193
194    function Char_Check_Router (Ch  : C_Int;
195                                Usr : System.Address) return C_Int
196    is
197       Arg  : constant Argument_Access := To_Argument_Access (Usr);
198    begin
199       pragma Assert (Arg /= null and then Arg.Cft /= Null_Field_Type
200                      and then Arg.Typ /= null);
201       if Arg.Cft.Ccheck /= null then
202          return Arg.Cft.Ccheck (Ch, Arg.Usr);
203       else
204          return 1;
205       end if;
206    end Char_Check_Router;
207
208    function Next_Router (Fld : Field;
209                          Usr : System.Address) return C_Int
210    is
211       Arg  : constant Argument_Access := To_Argument_Access (Usr);
212    begin
213       pragma Assert (Arg /= null and then Arg.Cft /= Null_Field_Type
214                      and then Arg.Typ /= null);
215       if Arg.Cft.Next /= null then
216          return Arg.Cft.Next (Fld, Arg.Usr);
217       else
218          return 1;
219       end if;
220    end Next_Router;
221
222    function Prev_Router (Fld : Field;
223                          Usr : System.Address) return C_Int
224    is
225       Arg  : constant Argument_Access := To_Argument_Access (Usr);
226    begin
227       pragma Assert (Arg /= null and then Arg.Cft /= Null_Field_Type
228                      and then Arg.Typ /= null);
229       if Arg.Cft.Prev /= null then
230          return Arg.Cft.Prev (Fld, Arg.Usr);
231       else
232          return 1;
233       end if;
234    end Prev_Router;
235
236    --  -----------------------------------------------------------------------
237    --
238    function C_Builtin_Router return C_Field_Type
239    is
240       Res : Eti_Error;
241       T   : C_Field_Type;
242    begin
243       if M_Builtin_Router = Null_Field_Type then
244          T := New_Fieldtype (Field_Check_Router'Access,
245                              Char_Check_Router'Access);
246          if T = Null_Field_Type then
247             raise Form_Exception;
248          else
249             Res := Set_Fieldtype_Arg (T,
250                                       Make_Arg'Access,
251                                       Copy_Arg'Access,
252                                       Free_Arg'Access);
253             if Res /= E_Ok then
254                Eti_Exception (Res);
255             end if;
256          end if;
257          M_Builtin_Router := T;
258       end if;
259       pragma Assert (M_Builtin_Router /= Null_Field_Type);
260       return M_Builtin_Router;
261    end C_Builtin_Router;
262
263    --  -----------------------------------------------------------------------
264    --
265    function C_Choice_Router return C_Field_Type
266    is
267       Res : Eti_Error;
268       T   : C_Field_Type;
269    begin
270       if M_Choice_Router = Null_Field_Type then
271          T := New_Fieldtype (Field_Check_Router'Access,
272                              Char_Check_Router'Access);
273          if T = Null_Field_Type then
274             raise Form_Exception;
275          else
276             Res := Set_Fieldtype_Arg (T,
277                                       Make_Arg'Access,
278                                       Copy_Arg'Access,
279                                       Free_Arg'Access);
280             if Res /= E_Ok then
281                Eti_Exception (Res);
282             end if;
283
284             Res := Set_Fieldtype_Choice (T,
285                                          Next_Router'Access,
286                                          Prev_Router'Access);
287             if Res /= E_Ok then
288                Eti_Exception (Res);
289             end if;
290          end if;
291          M_Choice_Router := T;
292       end if;
293       pragma Assert (M_Choice_Router /= Null_Field_Type);
294       return M_Choice_Router;
295    end C_Choice_Router;
296
297 end Terminal_Interface.Curses.Forms.Field_Types;