ncurses2-demo_forms.adb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. ------------------------------------------------------------------------------
  2. -- --
  3. -- GNAT ncurses Binding Samples --
  4. -- --
  5. -- ncurses --
  6. -- --
  7. -- B O D Y --
  8. -- --
  9. ------------------------------------------------------------------------------
  10. -- Copyright (c) 2000-2004,2006 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: Eugene V. Melaragno <aldomel@ix.netcom.com> 2000
  37. -- Version Control
  38. -- $Revision: 1.5 $
  39. -- $Date: 2006/06/25 14:24:40 $
  40. -- Binding Version 01.00
  41. ------------------------------------------------------------------------------
  42. with ncurses2.util; use ncurses2.util;
  43. with Terminal_Interface.Curses; use Terminal_Interface.Curses;
  44. with Terminal_Interface.Curses.Forms; use Terminal_Interface.Curses.Forms;
  45. with Terminal_Interface.Curses.Forms.Field_User_Data;
  46. with Ada.Characters.Handling;
  47. with Ada.Strings;
  48. with Ada.Strings.Bounded;
  49. procedure ncurses2.demo_forms is
  50. package BS is new Ada.Strings.Bounded.Generic_Bounded_Length (80);
  51. type myptr is access Integer;
  52. -- The C version stores a pointer in the userptr and
  53. -- converts it into a long integer.
  54. -- The correct, but inconvenient way to do it is to use a
  55. -- pointer to long and keep the pointer constant.
  56. -- It just adds one memory piece to allocate and deallocate (not done here)
  57. package StringData is new
  58. Terminal_Interface.Curses.Forms.Field_User_Data (Integer, myptr);
  59. function edit_secure (me : Field; c_in : Key_Code) return Key_Code;
  60. function form_virtualize (f : Form; w : Window) return Key_Code;
  61. function my_form_driver (f : Form; c : Key_Code) return Boolean;
  62. function make_label (frow : Line_Position;
  63. fcol : Column_Position;
  64. label : String) return Field;
  65. function make_field (frow : Line_Position;
  66. fcol : Column_Position;
  67. rows : Line_Count;
  68. cols : Column_Count;
  69. secure : Boolean) return Field;
  70. procedure display_form (f : Form);
  71. procedure erase_form (f : Form);
  72. -- prints '*' instead of characters.
  73. -- Not that this keeps a bug from the C version:
  74. -- type in the psasword field then move off and back.
  75. -- the cursor is at position one, but
  76. -- this assumes it as at the end so text gets appended instead
  77. -- of overwtitting.
  78. function edit_secure (me : Field; c_in : Key_Code) return Key_Code is
  79. rows, frow : Line_Position;
  80. nrow : Natural;
  81. cols, fcol : Column_Position;
  82. nbuf : Buffer_Number;
  83. c : Key_Code := c_in;
  84. c2 : Character;
  85. use StringData;
  86. begin
  87. Info (me, rows, cols, frow, fcol, nrow, nbuf);
  88. -- TODO if result = Form_Ok and nbuf > 0 then
  89. -- C version checked the return value
  90. -- of Info, the Ada binding throws an exception I think.
  91. if nbuf > 0 then
  92. declare
  93. temp : BS.Bounded_String;
  94. temps : String (1 .. 10);
  95. -- TODO Get_Buffer povides no information on the field length?
  96. len : myptr;
  97. begin
  98. Get_Buffer (me, 1, Str => temps);
  99. -- strcpy(temp, field_buffer(me, 1));
  100. Get_User_Data (me, len);
  101. temp := BS.To_Bounded_String (temps (1 .. len.all));
  102. if c <= Key_Max then
  103. c2 := Code_To_Char (c);
  104. if Ada.Characters.Handling.Is_Graphic (c2) then
  105. BS.Append (temp, c2);
  106. len.all := len.all + 1;
  107. Set_Buffer (me, 1, BS.To_String (temp));
  108. c := Character'Pos ('*');
  109. else
  110. c := 0;
  111. end if;
  112. else
  113. case c is
  114. when REQ_BEG_FIELD |
  115. REQ_CLR_EOF |
  116. REQ_CLR_EOL |
  117. REQ_DEL_LINE |
  118. REQ_DEL_WORD |
  119. REQ_DOWN_CHAR |
  120. REQ_END_FIELD |
  121. REQ_INS_CHAR |
  122. REQ_INS_LINE |
  123. REQ_LEFT_CHAR |
  124. REQ_NEW_LINE |
  125. REQ_NEXT_WORD |
  126. REQ_PREV_WORD |
  127. REQ_RIGHT_CHAR |
  128. REQ_UP_CHAR =>
  129. c := 0; -- we don't want to do inline editing
  130. when REQ_CLR_FIELD =>
  131. if len.all /= 0 then
  132. temp := BS.To_Bounded_String ("");
  133. Set_Buffer (me, 1, BS.To_String (temp));
  134. len.all := 0;
  135. end if;
  136. when REQ_DEL_CHAR |
  137. REQ_DEL_PREV =>
  138. if len.all /= 0 then
  139. BS.Delete (temp, BS.Length (temp), BS.Length (temp));
  140. Set_Buffer (me, 1, BS.To_String (temp));
  141. len.all := len.all - 1;
  142. end if;
  143. when others => null;
  144. end case;
  145. end if;
  146. end;
  147. end if;
  148. return c;
  149. end edit_secure;
  150. mode : Key_Code := REQ_INS_MODE;
  151. function form_virtualize (f : Form; w : Window) return Key_Code is
  152. type lookup_t is record
  153. code : Key_Code;
  154. result : Key_Code;
  155. -- should be Form_Request_Code, but we need MAX_COMMAND + 1
  156. end record;
  157. lookup : constant array (Positive range <>) of lookup_t :=
  158. (
  159. (
  160. Character'Pos ('A') mod 16#20#, REQ_NEXT_CHOICE
  161. ),
  162. (
  163. Character'Pos ('B') mod 16#20#, REQ_PREV_WORD
  164. ),
  165. (
  166. Character'Pos ('C') mod 16#20#, REQ_CLR_EOL
  167. ),
  168. (
  169. Character'Pos ('D') mod 16#20#, REQ_DOWN_FIELD
  170. ),
  171. (
  172. Character'Pos ('E') mod 16#20#, REQ_END_FIELD
  173. ),
  174. (
  175. Character'Pos ('F') mod 16#20#, REQ_NEXT_PAGE
  176. ),
  177. (
  178. Character'Pos ('G') mod 16#20#, REQ_DEL_WORD
  179. ),
  180. (
  181. Character'Pos ('H') mod 16#20#, REQ_DEL_PREV
  182. ),
  183. (
  184. Character'Pos ('I') mod 16#20#, REQ_INS_CHAR
  185. ),
  186. (
  187. Character'Pos ('K') mod 16#20#, REQ_CLR_EOF
  188. ),
  189. (
  190. Character'Pos ('L') mod 16#20#, REQ_LEFT_FIELD
  191. ),
  192. (
  193. Character'Pos ('M') mod 16#20#, REQ_NEW_LINE
  194. ),
  195. (
  196. Character'Pos ('N') mod 16#20#, REQ_NEXT_FIELD
  197. ),
  198. (
  199. Character'Pos ('O') mod 16#20#, REQ_INS_LINE
  200. ),
  201. (
  202. Character'Pos ('P') mod 16#20#, REQ_PREV_FIELD
  203. ),
  204. (
  205. Character'Pos ('R') mod 16#20#, REQ_RIGHT_FIELD
  206. ),
  207. (
  208. Character'Pos ('S') mod 16#20#, REQ_BEG_FIELD
  209. ),
  210. (
  211. Character'Pos ('U') mod 16#20#, REQ_UP_FIELD
  212. ),
  213. (
  214. Character'Pos ('V') mod 16#20#, REQ_DEL_CHAR
  215. ),
  216. (
  217. Character'Pos ('W') mod 16#20#, REQ_NEXT_WORD
  218. ),
  219. (
  220. Character'Pos ('X') mod 16#20#, REQ_CLR_FIELD
  221. ),
  222. (
  223. Character'Pos ('Y') mod 16#20#, REQ_DEL_LINE
  224. ),
  225. (
  226. Character'Pos ('Z') mod 16#20#, REQ_PREV_CHOICE
  227. ),
  228. (
  229. Character'Pos ('[') mod 16#20#, -- ESCAPE
  230. Form_Request_Code'Last + 1
  231. ),
  232. (
  233. Key_Backspace, REQ_DEL_PREV
  234. ),
  235. (
  236. KEY_DOWN, REQ_DOWN_CHAR
  237. ),
  238. (
  239. Key_End, REQ_LAST_FIELD
  240. ),
  241. (
  242. Key_Home, REQ_FIRST_FIELD
  243. ),
  244. (
  245. KEY_LEFT, REQ_LEFT_CHAR
  246. ),
  247. (
  248. KEY_LL, REQ_LAST_FIELD
  249. ),
  250. (
  251. Key_Next, REQ_NEXT_FIELD
  252. ),
  253. (
  254. KEY_NPAGE, REQ_NEXT_PAGE
  255. ),
  256. (
  257. KEY_PPAGE, REQ_PREV_PAGE
  258. ),
  259. (
  260. Key_Previous, REQ_PREV_FIELD
  261. ),
  262. (
  263. KEY_RIGHT, REQ_RIGHT_CHAR
  264. ),
  265. (
  266. KEY_UP, REQ_UP_CHAR
  267. ),
  268. (
  269. Character'Pos ('Q') mod 16#20#, -- QUIT
  270. Form_Request_Code'Last + 1 -- TODO MAX_FORM_COMMAND + 1
  271. )
  272. );
  273. c : Key_Code := Getchar (w);
  274. me : constant Field := Current (f);
  275. begin
  276. if c = Character'Pos (']') mod 16#20# then
  277. if mode = REQ_INS_MODE then
  278. mode := REQ_OVL_MODE;
  279. else
  280. mode := REQ_INS_MODE;
  281. end if;
  282. c := mode;
  283. else
  284. for n in lookup'Range loop
  285. if lookup (n).code = c then
  286. c := lookup (n).result;
  287. exit;
  288. end if;
  289. end loop;
  290. end if;
  291. -- Force the field that the user is typing into to be in reverse video,
  292. -- while the other fields are shown underlined.
  293. if c <= Key_Max then
  294. c := edit_secure (me, c);
  295. Set_Background (me, (Reverse_Video => True, others => False));
  296. elsif c <= Form_Request_Code'Last then
  297. c := edit_secure (me, c);
  298. Set_Background (me, (Under_Line => True, others => False));
  299. end if;
  300. return c;
  301. end form_virtualize;
  302. function my_form_driver (f : Form; c : Key_Code) return Boolean is
  303. flag : constant Driver_Result := Driver (f, F_Validate_Field);
  304. begin
  305. if c = Form_Request_Code'Last + 1
  306. and flag = Form_Ok then
  307. return True;
  308. else
  309. Beep;
  310. return False;
  311. end if;
  312. end my_form_driver;
  313. function make_label (frow : Line_Position;
  314. fcol : Column_Position;
  315. label : String) return Field is
  316. f : constant Field := Create (1, label'Length, frow, fcol, 0, 0);
  317. o : Field_Option_Set := Get_Options (f);
  318. begin
  319. if f /= Null_Field then
  320. Set_Buffer (f, 0, label);
  321. o.Active := False;
  322. Set_Options (f, o);
  323. end if;
  324. return f;
  325. end make_label;
  326. function make_field (frow : Line_Position;
  327. fcol : Column_Position;
  328. rows : Line_Count;
  329. cols : Column_Count;
  330. secure : Boolean) return Field is
  331. f : Field;
  332. use StringData;
  333. len : myptr;
  334. begin
  335. if secure then
  336. f := Create (rows, cols, frow, fcol, 0, 1);
  337. else
  338. f := Create (rows, cols, frow, fcol, 0, 0);
  339. end if;
  340. if f /= Null_Field then
  341. Set_Background (f, (Under_Line => True, others => False));
  342. len := new Integer;
  343. len.all := 0;
  344. Set_User_Data (f, len);
  345. end if;
  346. return f;
  347. end make_field;
  348. procedure display_form (f : Form) is
  349. w : Window;
  350. rows : Line_Count;
  351. cols : Column_Count;
  352. begin
  353. Scale (f, rows, cols);
  354. w := New_Window (rows + 2, cols + 4, 0, 0);
  355. if w /= Null_Window then
  356. Set_Window (f, w);
  357. Set_Sub_Window (f, Derived_Window (w, rows, cols, 1, 2));
  358. Box (w); -- 0,0
  359. Set_KeyPad_Mode (w, True);
  360. end if;
  361. -- TODO if Post(f) /= Form_Ok then it's a procedure
  362. declare
  363. begin
  364. Post (f);
  365. exception
  366. when
  367. Eti_System_Error |
  368. Eti_Bad_Argument |
  369. Eti_Posted |
  370. Eti_Connected |
  371. Eti_Bad_State |
  372. Eti_No_Room |
  373. Eti_Not_Posted |
  374. Eti_Unknown_Command |
  375. Eti_No_Match |
  376. Eti_Not_Selectable |
  377. Eti_Not_Connected |
  378. Eti_Request_Denied |
  379. Eti_Invalid_Field |
  380. Eti_Current =>
  381. Refresh (w);
  382. end;
  383. -- end if;
  384. end display_form;
  385. procedure erase_form (f : Form) is
  386. w : Window := Get_Window (f);
  387. s : Window := Get_Sub_Window (f);
  388. begin
  389. Post (f, False);
  390. Erase (w);
  391. Refresh (w);
  392. Delete (s);
  393. Delete (w);
  394. end erase_form;
  395. finished : Boolean := False;
  396. f : constant Field_Array_Access := new Field_Array (1 .. 12);
  397. secure : Field;
  398. myform : Form;
  399. w : Window;
  400. c : Key_Code;
  401. result : Driver_Result;
  402. begin
  403. Move_Cursor (Line => 18, Column => 0);
  404. Add (Str => "Defined form-traversal keys: ^Q/ESC- exit form");
  405. Add (Ch => newl);
  406. Add (Str => "^N -- go to next field ^P -- go to previous field");
  407. Add (Ch => newl);
  408. Add (Str => "Home -- go to first field End -- go to last field");
  409. Add (Ch => newl);
  410. Add (Str => "^L -- go to field to left ^R -- go to field to right");
  411. Add (Ch => newl);
  412. Add (Str => "^U -- move upward to field ^D -- move downward to field");
  413. Add (Ch => newl);
  414. Add (Str => "^W -- go to next word ^B -- go to previous word");
  415. Add (Ch => newl);
  416. Add (Str => "^S -- go to start of field ^E -- go to end of field");
  417. Add (Ch => newl);
  418. Add (Str => "^H -- delete previous char ^Y -- delete line");
  419. Add (Ch => newl);
  420. Add (Str => "^G -- delete current word ^C -- clear to end of line");
  421. Add (Ch => newl);
  422. Add (Str => "^K -- clear to end of field ^X -- clear field");
  423. Add (Ch => newl);
  424. Add (Str => "Arrow keys move within a field as you would expect.");
  425. Add (Line => 4, Column => 57, Str => "Forms Entry Test");
  426. Refresh;
  427. -- describe the form
  428. f (1) := make_label (0, 15, "Sample Form");
  429. f (2) := make_label (2, 0, "Last Name");
  430. f (3) := make_field (3, 0, 1, 18, False);
  431. f (4) := make_label (2, 20, "First Name");
  432. f (5) := make_field (3, 20, 1, 12, False);
  433. f (6) := make_label (2, 34, "Middle Name");
  434. f (7) := make_field (3, 34, 1, 12, False);
  435. f (8) := make_label (5, 0, "Comments");
  436. f (9) := make_field (6, 0, 4, 46, False);
  437. f (10) := make_label (5, 20, "Password:");
  438. f (11) := make_field (5, 30, 1, 9, True);
  439. secure := f (11);
  440. f (12) := Null_Field;
  441. myform := New_Form (f);
  442. display_form (myform);
  443. w := Get_Window (myform);
  444. Set_Raw_Mode (SwitchOn => True);
  445. Set_NL_Mode (SwitchOn => True); -- lets us read ^M's
  446. while not finished loop
  447. c := form_virtualize (myform, w);
  448. result := Driver (myform, c);
  449. case result is
  450. when Form_Ok =>
  451. Add (Line => 5, Column => 57, Str => Get_Buffer (secure, 1));
  452. Clear_To_End_Of_Line;
  453. Refresh;
  454. when Unknown_Request =>
  455. finished := my_form_driver (myform, c);
  456. when others =>
  457. Beep;
  458. end case;
  459. end loop;
  460. erase_form (myform);
  461. -- TODO Free_Form(myform);
  462. -- for (c = 0; f[c] != 0; c++) free_field(f[c]);
  463. Set_Raw_Mode (SwitchOn => False);
  464. Set_NL_Mode (SwitchOn => True);
  465. end ncurses2.demo_forms;