ncurses2-demo_pad.adb 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. ------------------------------------------------------------------------------
  2. -- --
  3. -- GNAT ncurses Binding Samples --
  4. -- --
  5. -- ncurses --
  6. -- --
  7. -- B O D Y --
  8. -- --
  9. ------------------------------------------------------------------------------
  10. -- Copyright (c) 2000-2006,2008 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.7 $
  39. -- $Date: 2008/07/26 18:47:06 $
  40. -- Binding Version 01.00
  41. ------------------------------------------------------------------------------
  42. with ncurses2.util; use ncurses2.util;
  43. with Terminal_Interface.Curses; use Terminal_Interface.Curses;
  44. with Interfaces.C;
  45. with System.Storage_Elements;
  46. with System.Address_To_Access_Conversions;
  47. with Ada.Text_IO;
  48. -- with Ada.Real_Time; use Ada.Real_Time;
  49. -- TODO is there a way to use Real_Time or Ada.Calendar in place of
  50. -- gettimeofday?
  51. -- Demonstrate pads.
  52. procedure ncurses2.demo_pad is
  53. type timestruct is record
  54. seconds : Integer;
  55. microseconds : Integer;
  56. end record;
  57. type myfunc is access function (w : Window) return Key_Code;
  58. function gettime return timestruct;
  59. procedure do_h_line (y : Line_Position;
  60. x : Column_Position;
  61. c : Attributed_Character;
  62. to : Column_Position);
  63. procedure do_v_line (y : Line_Position;
  64. x : Column_Position;
  65. c : Attributed_Character;
  66. to : Line_Position);
  67. function padgetch (win : Window) return Key_Code;
  68. function panner_legend (line : Line_Position) return Boolean;
  69. procedure panner_legend (line : Line_Position);
  70. procedure panner_h_cleanup (from_y : Line_Position;
  71. from_x : Column_Position;
  72. to_x : Column_Position);
  73. procedure panner_v_cleanup (from_y : Line_Position;
  74. from_x : Column_Position;
  75. to_y : Line_Position);
  76. procedure panner (pad : Window;
  77. top_xp : Column_Position;
  78. top_yp : Line_Position;
  79. portyp : Line_Position;
  80. portxp : Column_Position;
  81. pgetc : myfunc);
  82. function gettime return timestruct is
  83. retval : timestruct;
  84. use Interfaces.C;
  85. type timeval is record
  86. tv_sec : long;
  87. tv_usec : long;
  88. end record;
  89. pragma Convention (C, timeval);
  90. -- TODO function from_timeval is new Ada.Unchecked_Conversion(
  91. -- timeval_a, System.Storage_Elements.Integer_Address);
  92. -- should Interfaces.C.Pointers be used here?
  93. package myP is new System.Address_To_Access_Conversions (timeval);
  94. use myP;
  95. t : constant Object_Pointer := new timeval;
  96. function gettimeofday
  97. (TP : System.Storage_Elements.Integer_Address;
  98. TZP : System.Storage_Elements.Integer_Address) return int;
  99. pragma Import (C, gettimeofday, "gettimeofday");
  100. tmp : int;
  101. begin
  102. tmp := gettimeofday (System.Storage_Elements.To_Integer
  103. (myP.To_Address (t)),
  104. System.Storage_Elements.To_Integer
  105. (myP.To_Address (null)));
  106. if tmp < 0 then
  107. retval.seconds := 0;
  108. retval.microseconds := 0;
  109. else
  110. retval.seconds := Integer (t.tv_sec);
  111. retval.microseconds := Integer (t.tv_usec);
  112. end if;
  113. return retval;
  114. end gettime;
  115. -- in C, The behavior of mvhline, mvvline for negative/zero length is
  116. -- unspecified, though we can rely on negative x/y values to stop the
  117. -- macro. Except Ada makes Line_Position(-1) = Natural - 1 so forget it.
  118. procedure do_h_line (y : Line_Position;
  119. x : Column_Position;
  120. c : Attributed_Character;
  121. to : Column_Position) is
  122. begin
  123. if to > x then
  124. Move_Cursor (Line => y, Column => x);
  125. Horizontal_Line (Line_Size => Natural (to - x), Line_Symbol => c);
  126. end if;
  127. end do_h_line;
  128. procedure do_v_line (y : Line_Position;
  129. x : Column_Position;
  130. c : Attributed_Character;
  131. to : Line_Position) is
  132. begin
  133. if to > y then
  134. Move_Cursor (Line => y, Column => x);
  135. Vertical_Line (Line_Size => Natural (to - y), Line_Symbol => c);
  136. end if;
  137. end do_v_line;
  138. function padgetch (win : Window) return Key_Code is
  139. c : Key_Code;
  140. c2 : Character;
  141. begin
  142. c := Getchar (win);
  143. c2 := Code_To_Char (c);
  144. case c2 is
  145. when '!' =>
  146. ShellOut (False);
  147. return Key_Refresh;
  148. when Character'Val (Character'Pos ('r') mod 16#20#) => -- CTRL('r')
  149. End_Windows;
  150. Refresh;
  151. return Key_Refresh;
  152. when Character'Val (Character'Pos ('l') mod 16#20#) => -- CTRL('l')
  153. return Key_Refresh;
  154. when 'U' =>
  155. return Key_Cursor_Up;
  156. when 'D' =>
  157. return Key_Cursor_Down;
  158. when 'R' =>
  159. return Key_Cursor_Right;
  160. when 'L' =>
  161. return Key_Cursor_Left;
  162. when '+' =>
  163. return Key_Insert_Line;
  164. when '-' =>
  165. return Key_Delete_Line;
  166. when '>' =>
  167. return Key_Insert_Char;
  168. when '<' =>
  169. return Key_Delete_Char;
  170. -- when ERR=> /* FALLTHRU */
  171. when 'q' =>
  172. return (Key_Exit);
  173. when others =>
  174. return (c);
  175. end case;
  176. end padgetch;
  177. show_panner_legend : Boolean := True;
  178. function panner_legend (line : Line_Position) return Boolean is
  179. legend : constant array (0 .. 3) of String (1 .. 61) :=
  180. (
  181. "Use arrow keys (or U,D,L,R) to pan, q to quit (?,t,s flags) ",
  182. "Use ! to shell-out. Toggle legend:?, timer:t, scroll mark:s.",
  183. "Use +,- (or j,k) to grow/shrink the panner vertically. ",
  184. "Use <,> (or h,l) to grow/shrink the panner horizontally. ");
  185. legendsize : constant := 4;
  186. n : constant Integer := legendsize - Integer (Lines - line);
  187. begin
  188. if line < Lines and n >= 0 then
  189. Move_Cursor (Line => line, Column => 0);
  190. if show_panner_legend then
  191. Add (Str => legend (n));
  192. end if;
  193. Clear_To_End_Of_Line;
  194. return show_panner_legend;
  195. end if;
  196. return False;
  197. end panner_legend;
  198. procedure panner_legend (line : Line_Position) is
  199. begin
  200. if not panner_legend (line) then
  201. Beep;
  202. end if;
  203. end panner_legend;
  204. procedure panner_h_cleanup (from_y : Line_Position;
  205. from_x : Column_Position;
  206. to_x : Column_Position) is
  207. begin
  208. if not panner_legend (from_y) then
  209. do_h_line (from_y, from_x, Blank2, to_x);
  210. end if;
  211. end panner_h_cleanup;
  212. procedure panner_v_cleanup (from_y : Line_Position;
  213. from_x : Column_Position;
  214. to_y : Line_Position) is
  215. begin
  216. if not panner_legend (from_y) then
  217. do_v_line (from_y, from_x, Blank2, to_y);
  218. end if;
  219. end panner_v_cleanup;
  220. procedure panner (pad : Window;
  221. top_xp : Column_Position;
  222. top_yp : Line_Position;
  223. portyp : Line_Position;
  224. portxp : Column_Position;
  225. pgetc : myfunc) is
  226. function f (y : Line_Position) return Line_Position;
  227. function f (x : Column_Position) return Column_Position;
  228. function greater (y1, y2 : Line_Position) return Integer;
  229. function greater (x1, x2 : Column_Position) return Integer;
  230. top_x : Column_Position := top_xp;
  231. top_y : Line_Position := top_yp;
  232. porty : Line_Position := portyp;
  233. portx : Column_Position := portxp;
  234. -- f[x] returns max[x - 1, 0]
  235. function f (y : Line_Position) return Line_Position is
  236. begin
  237. if y > 0 then
  238. return y - 1;
  239. else
  240. return y; -- 0
  241. end if;
  242. end f;
  243. function f (x : Column_Position) return Column_Position is
  244. begin
  245. if x > 0 then
  246. return x - 1;
  247. else
  248. return x; -- 0
  249. end if;
  250. end f;
  251. function greater (y1, y2 : Line_Position) return Integer is
  252. begin
  253. if y1 > y2 then
  254. return 1;
  255. else
  256. return 0;
  257. end if;
  258. end greater;
  259. function greater (x1, x2 : Column_Position) return Integer is
  260. begin
  261. if x1 > x2 then
  262. return 1;
  263. else
  264. return 0;
  265. end if;
  266. end greater;
  267. pymax : Line_Position;
  268. basey : Line_Position := 0;
  269. pxmax : Column_Position;
  270. basex : Column_Position := 0;
  271. c : Key_Code;
  272. scrollers : Boolean := True;
  273. before, after : timestruct;
  274. timing : Boolean := True;
  275. package floatio is new Ada.Text_IO.Float_IO (Long_Float);
  276. begin
  277. Get_Size (pad, pymax, pxmax);
  278. Allow_Scrolling (Mode => False); -- we don't want stdscr to scroll!
  279. c := Key_Refresh;
  280. loop
  281. -- During shell-out, the user may have resized the window. Adjust
  282. -- the port size of the pad to accommodate this. Ncurses
  283. -- automatically resizes all of the normal windows to fit on the
  284. -- new screen.
  285. if top_x > Columns then
  286. top_x := Columns;
  287. end if;
  288. if portx > Columns then
  289. portx := Columns;
  290. end if;
  291. if top_y > Lines then
  292. top_y := Lines;
  293. end if;
  294. if porty > Lines then
  295. porty := Lines;
  296. end if;
  297. case c is
  298. when Key_Refresh | Character'Pos ('?') =>
  299. if c = Key_Refresh then
  300. Erase;
  301. else -- '?'
  302. show_panner_legend := not show_panner_legend;
  303. end if;
  304. panner_legend (Lines - 4);
  305. panner_legend (Lines - 3);
  306. panner_legend (Lines - 2);
  307. panner_legend (Lines - 1);
  308. when Character'Pos ('t') =>
  309. timing := not timing;
  310. if not timing then
  311. panner_legend (Lines - 1);
  312. end if;
  313. when Character'Pos ('s') =>
  314. scrollers := not scrollers;
  315. -- Move the top-left corner of the pad, keeping the
  316. -- bottom-right corner fixed.
  317. when Character'Pos ('h') =>
  318. -- increase-columns: move left edge to left
  319. if top_x = 0 then
  320. Beep;
  321. else
  322. panner_v_cleanup (top_y, top_x, porty);
  323. top_x := top_x - 1;
  324. end if;
  325. when Character'Pos ('j') =>
  326. -- decrease-lines: move top-edge down
  327. if top_y >= porty then
  328. Beep;
  329. else
  330. if top_y /= 0 then
  331. panner_h_cleanup (top_y - 1, f (top_x), portx);
  332. end if;
  333. top_y := top_y + 1;
  334. end if;
  335. when Character'Pos ('k') =>
  336. -- increase-lines: move top-edge up
  337. if top_y = 0 then
  338. Beep;
  339. else
  340. top_y := top_y - 1;
  341. panner_h_cleanup (top_y, top_x, portx);
  342. end if;
  343. when Character'Pos ('l') =>
  344. -- decrease-columns: move left-edge to right
  345. if top_x >= portx then
  346. Beep;
  347. else
  348. if top_x /= 0 then
  349. panner_v_cleanup (f (top_y), top_x - 1, porty);
  350. end if;
  351. top_x := top_x + 1;
  352. end if;
  353. -- Move the bottom-right corner of the pad, keeping the
  354. -- top-left corner fixed.
  355. when Key_Insert_Char =>
  356. -- increase-columns: move right-edge to right
  357. if portx >= pxmax or portx >= Columns then
  358. Beep;
  359. else
  360. panner_v_cleanup (f (top_y), portx - 1, porty);
  361. portx := portx + 1;
  362. -- C had ++portx instead of portx++, weird.
  363. end if;
  364. when Key_Insert_Line =>
  365. -- increase-lines: move bottom-edge down
  366. if porty >= pymax or porty >= Lines then
  367. Beep;
  368. else
  369. panner_h_cleanup (porty - 1, f (top_x), portx);
  370. porty := porty + 1;
  371. end if;
  372. when Key_Delete_Char =>
  373. -- decrease-columns: move bottom edge up
  374. if portx <= top_x then
  375. Beep;
  376. else
  377. portx := portx - 1;
  378. panner_v_cleanup (f (top_y), portx, porty);
  379. end if;
  380. when Key_Delete_Line =>
  381. -- decrease-lines
  382. if porty <= top_y then
  383. Beep;
  384. else
  385. porty := porty - 1;
  386. panner_h_cleanup (porty, f (top_x), portx);
  387. end if;
  388. when Key_Cursor_Left =>
  389. -- pan leftwards
  390. if basex > 0 then
  391. basex := basex - 1;
  392. else
  393. Beep;
  394. end if;
  395. when Key_Cursor_Right =>
  396. -- pan rightwards
  397. -- if (basex + portx - (pymax > porty) < pxmax)
  398. if basex + portx -
  399. Column_Position (greater (pymax, porty)) < pxmax then
  400. -- if basex + portx < pxmax or
  401. -- (pymax > porty and basex + portx - 1 < pxmax) then
  402. basex := basex + 1;
  403. else
  404. Beep;
  405. end if;
  406. when Key_Cursor_Up =>
  407. -- pan upwards
  408. if basey > 0 then
  409. basey := basey - 1;
  410. else
  411. Beep;
  412. end if;
  413. when Key_Cursor_Down =>
  414. -- pan downwards
  415. -- same as if (basey + porty - (pxmax > portx) < pymax)
  416. if basey + porty -
  417. Line_Position (greater (pxmax, portx)) < pymax then
  418. -- if (basey + porty < pymax) or
  419. -- (pxmax > portx and basey + porty - 1 < pymax) then
  420. basey := basey + 1;
  421. else
  422. Beep;
  423. end if;
  424. when Character'Pos ('H') |
  425. Key_Home |
  426. Key_Find =>
  427. basey := 0;
  428. when Character'Pos ('E') |
  429. Key_End |
  430. Key_Select =>
  431. if pymax < porty then
  432. basey := 0;
  433. else
  434. basey := pymax - porty;
  435. end if;
  436. when others =>
  437. Beep;
  438. end case;
  439. -- more writing off the screen.
  440. -- Interestingly, the exception is not handled if
  441. -- we put a block around this.
  442. -- delcare --begin
  443. if top_y /= 0 and top_x /= 0 then
  444. Add (Line => top_y - 1, Column => top_x - 1,
  445. Ch => ACS_Map (ACS_Upper_Left_Corner));
  446. end if;
  447. if top_x /= 0 then
  448. do_v_line (top_y, top_x - 1, ACS_Map (ACS_Vertical_Line), porty);
  449. end if;
  450. if top_y /= 0 then
  451. do_h_line (top_y - 1, top_x, ACS_Map (ACS_Horizontal_Line), portx);
  452. end if;
  453. -- exception when Curses_Exception => null; end;
  454. -- in C was ... pxmax > portx - 1
  455. if scrollers and pxmax >= portx then
  456. declare
  457. length : constant Column_Position := portx - top_x - 1;
  458. lowend, highend : Column_Position;
  459. begin
  460. -- Instead of using floats, I'll use integers only.
  461. lowend := top_x + (basex * length) / pxmax;
  462. highend := top_x + ((basex + length) * length) / pxmax;
  463. do_h_line (porty - 1, top_x, ACS_Map (ACS_Horizontal_Line),
  464. lowend);
  465. if highend < portx then
  466. Switch_Character_Attribute
  467. (Attr => (Reverse_Video => True, others => False),
  468. On => True);
  469. do_h_line (porty - 1, lowend, Blank2, highend + 1);
  470. Switch_Character_Attribute
  471. (Attr => (Reverse_Video => True, others => False),
  472. On => False);
  473. do_h_line (porty - 1, highend + 1,
  474. ACS_Map (ACS_Horizontal_Line), portx);
  475. end if;
  476. end;
  477. else
  478. do_h_line (porty - 1, top_x, ACS_Map (ACS_Horizontal_Line), portx);
  479. end if;
  480. if scrollers and pymax >= porty then
  481. declare
  482. length : constant Line_Position := porty - top_y - 1;
  483. lowend, highend : Line_Position;
  484. begin
  485. lowend := top_y + (basey * length) / pymax;
  486. highend := top_y + ((basey + length) * length) / pymax;
  487. do_v_line (top_y, portx - 1, ACS_Map (ACS_Vertical_Line),
  488. lowend);
  489. if highend < porty then
  490. Switch_Character_Attribute
  491. (Attr => (Reverse_Video => True, others => False),
  492. On => True);
  493. do_v_line (lowend, portx - 1, Blank2, highend + 1);
  494. Switch_Character_Attribute
  495. (Attr => (Reverse_Video => True, others => False),
  496. On => False);
  497. do_v_line (highend + 1, portx - 1,
  498. ACS_Map (ACS_Vertical_Line), porty);
  499. end if;
  500. end;
  501. else
  502. do_v_line (top_y, portx - 1, ACS_Map (ACS_Vertical_Line), porty);
  503. end if;
  504. if top_y /= 0 then
  505. Add (Line => top_y - 1, Column => portx - 1,
  506. Ch => ACS_Map (ACS_Upper_Right_Corner));
  507. end if;
  508. if top_x /= 0 then
  509. Add (Line => porty - 1, Column => top_x - 1,
  510. Ch => ACS_Map (ACS_Lower_Left_Corner));
  511. end if;
  512. declare
  513. begin
  514. -- Here is another place where it is possible
  515. -- to write to the corner of the screen.
  516. Add (Line => porty - 1, Column => portx - 1,
  517. Ch => ACS_Map (ACS_Lower_Right_Corner));
  518. exception
  519. when Curses_Exception => null;
  520. end;
  521. before := gettime;
  522. Refresh_Without_Update;
  523. declare
  524. -- the C version allows the panel to have a zero height
  525. -- wich raise the exception
  526. begin
  527. Refresh_Without_Update
  528. (
  529. pad,
  530. basey, basex,
  531. top_y, top_x,
  532. porty - Line_Position (greater (pxmax, portx)) - 1,
  533. portx - Column_Position (greater (pymax, porty)) - 1);
  534. exception
  535. when Curses_Exception => null;
  536. end;
  537. Update_Screen;
  538. if timing then
  539. declare
  540. s : String (1 .. 7);
  541. elapsed : Long_Float;
  542. begin
  543. after := gettime;
  544. elapsed := (Long_Float (after.seconds - before.seconds) +
  545. Long_Float (after.microseconds
  546. - before.microseconds)
  547. / 1.0e6);
  548. Move_Cursor (Line => Lines - 1, Column => Columns - 20);
  549. floatio.Put (s, elapsed, Aft => 3, Exp => 0);
  550. Add (Str => s);
  551. Refresh;
  552. end;
  553. end if;
  554. c := pgetc (pad);
  555. exit when c = Key_Exit;
  556. end loop;
  557. Allow_Scrolling (Mode => True);
  558. end panner;
  559. Gridsize : constant := 3;
  560. Gridcount : Integer := 0;
  561. Pad_High : constant Line_Count := 200;
  562. Pad_Wide : constant Column_Count := 200;
  563. panpad : Window := New_Pad (Pad_High, Pad_Wide);
  564. begin
  565. if panpad = Null_Window then
  566. Cannot ("cannot create requested pad");
  567. return;
  568. end if;
  569. for i in 0 .. Pad_High - 1 loop
  570. for j in 0 .. Pad_Wide - 1 loop
  571. if i mod Gridsize = 0 and j mod Gridsize = 0 then
  572. if i = 0 or j = 0 then
  573. Add (panpad, '+');
  574. else
  575. -- depends on ASCII?
  576. Add (panpad,
  577. Ch => Character'Val (Character'Pos ('A') +
  578. Gridcount mod 26));
  579. Gridcount := Gridcount + 1;
  580. end if;
  581. elsif i mod Gridsize = 0 then
  582. Add (panpad, '-');
  583. elsif j mod Gridsize = 0 then
  584. Add (panpad, '|');
  585. else
  586. declare
  587. -- handle the write to the lower right corner error
  588. begin
  589. Add (panpad, ' ');
  590. exception
  591. when Curses_Exception => null;
  592. end;
  593. end if;
  594. end loop;
  595. end loop;
  596. panner_legend (Lines - 4);
  597. panner_legend (Lines - 3);
  598. panner_legend (Lines - 2);
  599. panner_legend (Lines - 1);
  600. Set_KeyPad_Mode (panpad, True);
  601. -- Make the pad (initially) narrow enough that a trace file won't wrap.
  602. -- We'll still be able to widen it during a test, since that's required
  603. -- for testing boundaries.
  604. panner (panpad, 2, 2, Lines - 5, Columns - 15, padgetch'Access);
  605. Delete (panpad);
  606. End_Windows; -- Hmm, Erase after End_Windows
  607. Erase;
  608. end ncurses2.demo_pad;