ncurses 6.1 - patch 20191005
[ncurses.git] / Ada95 / samples / ncurses2-acs_and_scroll.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                       GNAT ncurses Binding Samples                       --
4 --                                                                          --
5 --                                 ncurses                                  --
6 --                                                                          --
7 --                                 B O D Y                                  --
8 --                                                                          --
9 ------------------------------------------------------------------------------
10 -- Copyright (c) 2000-2011,2018 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.12 $
39 --  $Date: 2018/07/07 23:31:55 $
40 --  Binding Version 01.00
41 ------------------------------------------------------------------------------
42 --  Windows and scrolling tester.
43 --  Demonstrate windows
44
45 with Ada.Strings.Fixed;
46 with Ada.Strings;
47
48 with ncurses2.util; use ncurses2.util;
49 with ncurses2.genericPuts;
50 with Terminal_Interface.Curses; use Terminal_Interface.Curses;
51 with Terminal_Interface.Curses.Mouse; use Terminal_Interface.Curses.Mouse;
52 with Terminal_Interface.Curses.PutWin; use Terminal_Interface.Curses.PutWin;
53
54 with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
55 with Ada.Streams; use Ada.Streams;
56
57 procedure ncurses2.acs_and_scroll is
58
59    Macro_Quit   : constant Key_Code := Character'Pos ('Q') mod 16#20#;
60    Macro_Escape : constant Key_Code := Character'Pos ('[') mod 16#20#;
61
62    Quit : constant Key_Code := CTRL ('Q');
63    Escape : constant Key_Code := CTRL ('[');
64
65    Botlines : constant Line_Position := 4;
66
67    type pair is record
68       y : Line_Position;
69       x : Column_Position;
70    end record;
71
72    type Frame;
73    type FrameA is access Frame;
74
75    f : File_Type;
76    dumpfile : constant String := "screendump";
77
78    procedure Outerbox (ul, lr : pair; onoff : Boolean);
79    function  HaveKeyPad (w : Window) return Boolean;
80    function  HaveScroll (w : Window) return Boolean;
81    procedure newwin_legend (curpw : Window);
82    procedure transient (curpw : Window; msg : String);
83    procedure newwin_report (win : Window := Standard_Window);
84    procedure selectcell (uli : Line_Position;
85                          ulj : Column_Position;
86                          lri : Line_Position;
87                          lrj : Column_Position;
88                          p   : out pair;
89                          b   : out Boolean);
90    function  getwindow return Window;
91    procedure newwin_move (win : Window;
92                           dy  : Line_Position;
93                           dx  : Column_Position);
94    function delete_framed (fp : FrameA; showit : Boolean) return FrameA;
95
96    --  A linked list
97    --  I  wish there was a standard library linked list. Oh well.
98    type Frame is record
99       next, last : FrameA;
100       do_scroll : Boolean;
101       do_keypad : Boolean;
102       wind : Window;
103    end record;
104
105    current : FrameA;
106
107    c : Key_Code;
108
109    procedure Outerbox (ul, lr : pair; onoff : Boolean) is
110    begin
111       if onoff then
112          --  Note the fix of an obscure bug
113          --  try making a 1x1 box then enlarging it, the is a blank
114          --  upper left corner!
115          Add (Line => ul.y - 1, Column => ul.x - 1,
116              Ch => ACS_Map (ACS_Upper_Left_Corner));
117          Add (Line => ul.y - 1, Column => lr.x + 1,
118              Ch => ACS_Map (ACS_Upper_Right_Corner));
119          Add (Line => lr.y + 1, Column => lr.x + 1,
120              Ch => ACS_Map (ACS_Lower_Right_Corner));
121          Add (Line => lr.y + 1, Column => ul.x - 1,
122              Ch => ACS_Map (ACS_Lower_Left_Corner));
123
124          Move_Cursor (Line => ul.y - 1, Column => ul.x);
125          Horizontal_Line (Line_Symbol => ACS_Map (ACS_Horizontal_Line),
126                           Line_Size => Integer (lr.x - ul.x) + 1);
127          Move_Cursor (Line => ul.y, Column => ul.x - 1);
128          Vertical_Line (Line_Symbol => ACS_Map (ACS_Vertical_Line),
129                         Line_Size => Integer (lr.y - ul.y) + 1);
130          Move_Cursor (Line => lr.y + 1, Column => ul.x);
131          Horizontal_Line (Line_Symbol => ACS_Map (ACS_Horizontal_Line),
132                           Line_Size => Integer (lr.x - ul.x) + 1);
133          Move_Cursor (Line => ul.y, Column => lr.x + 1);
134          Vertical_Line (Line_Symbol => ACS_Map (ACS_Vertical_Line),
135                         Line_Size => Integer (lr.y - ul.y) + 1);
136       else
137          Add (Line => ul.y - 1, Column => ul.x - 1, Ch => ' ');
138          Add (Line => ul.y - 1, Column => lr.x + 1, Ch => ' ');
139          Add (Line => lr.y + 1, Column => lr.x + 1, Ch => ' ');
140          Add (Line => lr.y + 1, Column => ul.x - 1, Ch => ' ');
141
142          Move_Cursor (Line => ul.y - 1, Column => ul.x);
143          Horizontal_Line (Line_Symbol => Blank2,
144                           Line_Size => Integer (lr.x - ul.x) + 1);
145          Move_Cursor (Line => ul.y, Column => ul.x - 1);
146          Vertical_Line (Line_Symbol => Blank2,
147                         Line_Size => Integer (lr.y - ul.y) + 1);
148          Move_Cursor (Line => lr.y + 1, Column => ul.x);
149          Horizontal_Line (Line_Symbol => Blank2,
150                           Line_Size => Integer (lr.x - ul.x) + 1);
151          Move_Cursor (Line => ul.y, Column => lr.x + 1);
152          Vertical_Line (Line_Symbol => Blank2,
153                         Line_Size => Integer (lr.y - ul.y) + 1);
154       end if;
155    end Outerbox;
156
157    function HaveKeyPad (w : Window) return Boolean is
158    begin
159       return Get_KeyPad_Mode (w);
160    exception
161       when Curses_Exception => return False;
162    end HaveKeyPad;
163
164    function HaveScroll (w : Window) return Boolean is
165    begin
166       return Scrolling_Allowed (w);
167    exception
168       when Curses_Exception => return False;
169    end HaveScroll;
170
171    procedure newwin_legend (curpw : Window) is
172
173       package p is new genericPuts (200);
174       use p;
175       use p.BS;
176
177       type string_a is access String;
178
179       type rrr is record
180          msg : string_a;
181          code : Integer range 0 .. 3;
182       end record;
183
184       legend : constant array (Positive range <>) of rrr :=
185         (
186          (
187           new String'("^C = create window"), 0
188           ),
189          (
190           new String'("^N = next window"), 0
191           ),
192          (
193           new String'("^P = previous window"), 0
194           ),
195          (
196           new String'("^F = scroll forward"), 0
197           ),
198          (
199           new String'("^B = scroll backward"), 0
200           ),
201          (
202           new String'("^K = keypad(%s)"), 1
203           ),
204          (
205           new String'("^S = scrollok(%s)"), 2
206           ),
207          (
208           new String'("^W = save window to file"), 0
209           ),
210          (
211           new String'("^R = restore window"), 0
212           ),
213          (
214           new String'("^X = resize"), 0
215           ),
216          (
217           new String'("^Q%s = exit"), 3
218           )
219          );
220
221       buf : Bounded_String;
222       do_keypad : constant Boolean := HaveKeyPad (curpw);
223       do_scroll : constant Boolean := HaveScroll (curpw);
224
225       pos : Natural;
226
227       mypair : pair;
228
229    begin
230       Move_Cursor (Line => Lines - 4, Column => 0);
231       for n in legend'Range loop
232          pos := Ada.Strings.Fixed.Index (Source => legend (n).msg.all,
233                                          Pattern => "%s");
234          buf := To_Bounded_String (legend (n).msg.all);
235          case legend (n).code is
236             when 0 => null;
237             when 1 =>
238                if do_keypad then
239                   Replace_Slice (buf, pos, pos + 1, "yes");
240                else
241                   Replace_Slice (buf, pos, pos + 1, "no");
242                end if;
243             when 2 =>
244                if do_scroll then
245                   Replace_Slice (buf, pos, pos + 1, "yes");
246                else
247                   Replace_Slice (buf, pos, pos + 1, "no");
248                end if;
249             when 3 =>
250                if do_keypad then
251                   Replace_Slice (buf, pos, pos + 1, "/ESC");
252                else
253                   Replace_Slice (buf, pos, pos + 1, "");
254                end if;
255          end case;
256          Get_Cursor_Position (Line => mypair.y, Column => mypair.x);
257          if Columns < mypair.x + 3 + Column_Position (Length (buf)) then
258             Add (Ch => newl);
259          elsif n /= 1 then -- n /= legen'First
260             Add (Str => ", ");
261          end if;
262          myAdd (Str => buf);
263       end loop;
264       Clear_To_End_Of_Line;
265    end newwin_legend;
266
267    procedure transient (curpw : Window; msg : String) is
268    begin
269       newwin_legend (curpw);
270       if msg /= "" then
271          Add (Line => Lines - 1, Column => 0, Str => msg);
272          Refresh;
273          Nap_Milli_Seconds (1000);
274       end if;
275
276       Move_Cursor (Line => Lines - 1, Column => 0);
277
278       if HaveKeyPad (curpw) then
279          Add (Str => "Non-arrow");
280       else
281          Add (Str => "All other");
282       end if;
283       Add (Str => " characters are echoed, window should ");
284       if not HaveScroll (curpw) then
285          Add (Str => "not ");
286       end if;
287       Add (Str => "scroll");
288
289       Clear_To_End_Of_Line;
290    end transient;
291
292    procedure newwin_report (win : Window := Standard_Window) is
293       y : Line_Position;
294       x : Column_Position;
295       use Int_IO;
296       tmp2a : String (1 .. 2);
297       tmp2b : String (1 .. 2);
298    begin
299       if win /= Standard_Window then
300          transient (win, "");
301       end if;
302       Get_Cursor_Position (win, y, x);
303       Move_Cursor (Line => Lines - 1, Column => Columns - 17);
304       Put (tmp2a, Integer (y));
305       Put (tmp2b, Integer (x));
306       Add (Str => "Y = " & tmp2a & " X = " & tmp2b);
307       if win /= Standard_Window then
308          Refresh;
309       else
310          Move_Cursor (win, y, x);
311       end if;
312    end newwin_report;
313
314    procedure selectcell (uli : Line_Position;
315                          ulj : Column_Position;
316                          lri : Line_Position;
317                          lrj : Column_Position;
318                          p   : out pair;
319                          b   : out Boolean) is
320       c : Key_Code;
321       res : pair;
322       i : Line_Position := 0;
323       j : Column_Position := 0;
324       si : constant Line_Position := lri - uli + 1;
325       sj : constant Column_Position := lrj - ulj + 1;
326    begin
327       res.y := uli;
328       res.x := ulj;
329       loop
330          Move_Cursor (Line => uli + i, Column => ulj + j);
331          newwin_report;
332
333          c := Getchar;
334          case c is
335             when
336               Macro_Quit   |
337               Macro_Escape =>
338                --  on the same line macro calls interfere due to the # comment
339                --  this is needed because keypad off affects all windows.
340                --  try removing the ESCAPE and see what happens.
341                b := False;
342                return;
343             when KEY_UP =>
344                i := i + si - 1;
345                --  same as  i := i - 1 because of Modulus arithmetic,
346                --  on Line_Position, which is a Natural
347                --  the C version uses this form too, interestingly.
348             when KEY_DOWN =>
349                i := i + 1;
350             when KEY_LEFT =>
351                j := j + sj - 1;
352             when KEY_RIGHT =>
353                j := j + 1;
354             when Key_Mouse =>
355                declare
356                   event : Mouse_Event;
357                   y : Line_Position;
358                   x : Column_Position;
359                   Button : Mouse_Button;
360                   State : Button_State;
361
362                begin
363                   event := Get_Mouse;
364                   Get_Event (Event => event,
365                              Y => y,
366                              X => x,
367                              Button => Button,
368                              State  => State);
369                   if y > uli and x > ulj then
370                      i := y - uli;
371                      j := x - ulj;
372                      --  same as when others =>
373                      res.y := uli + i;
374                      res.x := ulj + j;
375                      p := res;
376                      b := True;
377                      return;
378                   else
379                      Beep;
380                   end if;
381                end;
382             when others =>
383                res.y := uli + i;
384                res.x := ulj + j;
385                p := res;
386                b := True;
387                return;
388          end case;
389          i := i mod si;
390          j := j mod sj;
391       end loop;
392    end selectcell;
393
394    function getwindow return Window is
395       rwindow : Window;
396       ul, lr : pair;
397       result : Boolean;
398    begin
399       Move_Cursor (Line => 0, Column => 0);
400       Clear_To_End_Of_Line;
401       Add (Str => "Use arrows to move cursor, anything else to mark corner 1");
402       Refresh;
403       selectcell (2, 1, Lines - Botlines - 2, Columns - 2, ul, result);
404       if not result then
405          return Null_Window;
406       end if;
407       Add (Line => ul.y - 1, Column => ul.x - 1,
408            Ch => ACS_Map (ACS_Upper_Left_Corner));
409       Move_Cursor (Line => 0, Column => 0);
410       Clear_To_End_Of_Line;
411       Add (Str => "Use arrows to move cursor, anything else to mark corner 2");
412       Refresh;
413       selectcell (ul.y, ul.x, Lines - Botlines - 2, Columns - 2, lr, result);
414       if not result then
415          return Null_Window;
416       end if;
417
418       rwindow := Sub_Window (Number_Of_Lines => lr.y - ul.y + 1,
419                              Number_Of_Columns => lr.x - ul.x + 1,
420                              First_Line_Position => ul.y,
421                              First_Column_Position => ul.x);
422
423       Outerbox (ul, lr, True);
424       Refresh;
425
426       Refresh (rwindow);
427
428       Move_Cursor (Line => 0, Column => 0);
429       Clear_To_End_Of_Line;
430       return rwindow;
431    end getwindow;
432
433    procedure newwin_move (win : Window;
434                           dy  : Line_Position;
435                           dx  : Column_Position) is
436       cur_y, max_y : Line_Position;
437       cur_x, max_x : Column_Position;
438    begin
439       Get_Cursor_Position (win, cur_y, cur_x);
440       Get_Size (win, max_y, max_x);
441       cur_x := Column_Position'Min (Column_Position'Max (cur_x + dx, 0),
442                                     max_x - 1);
443       cur_y := Line_Position'Min (Line_Position'Max (cur_y + dy, 0),
444                                   max_y - 1);
445
446       Move_Cursor (win, Line => cur_y, Column => cur_x);
447    end newwin_move;
448
449    function delete_framed (fp : FrameA; showit : Boolean) return FrameA is
450       np : FrameA;
451    begin
452       fp.all.last.all.next := fp.all.next;
453       fp.all.next.all.last := fp.all.last;
454
455       if showit then
456          Erase (fp.all.wind);
457          Refresh (fp.all.wind);
458       end if;
459       Delete (fp.all.wind);
460
461       if fp = fp.all.next then
462          np := null;
463       else
464          np := fp.all.next;
465       end if;
466       --  TODO free(fp);
467       return np;
468    end delete_framed;
469
470    Mask : Event_Mask := No_Events;
471    Mask2 : Event_Mask;
472
473    usescr : Window;
474
475 begin
476    if Has_Mouse then
477       Register_Reportable_Event (
478                                  Button => Left,
479                                  State => Clicked,
480                                  Mask => Mask);
481       Mask2 := Start_Mouse (Mask);
482    end if;
483    c := CTRL ('C');
484    Set_Raw_Mode (SwitchOn => True);
485    loop
486       transient (Standard_Window, "");
487       case c is
488          when Character'Pos ('c') mod 16#20# => --  Ctrl('c')
489             declare
490                neww : constant FrameA := new Frame'(null, null,
491                                                     False, False,
492                                                     Null_Window);
493             begin
494                neww.all.wind := getwindow;
495                if neww.all.wind = Null_Window  then
496                   exit;
497                   --  was goto breakout; ha ha ha
498                else
499
500                   if current = null  then
501                      neww.all.next := neww;
502                      neww.all.last := neww;
503                   else
504                      neww.all.next := current.all.next;
505                      neww.all.last := current;
506                      neww.all.last.all.next := neww;
507                      neww.all.next.all.last := neww;
508                   end if;
509                   current := neww;
510
511                   Set_KeyPad_Mode (current.all.wind, True);
512                   current.all.do_keypad := HaveKeyPad (current.all.wind);
513                   current.all.do_scroll := HaveScroll (current.all.wind);
514                end if;
515             end;
516          when Character'Pos ('N') mod 16#20#  => --  Ctrl('N')
517             if current /= null then
518                current := current.all.next;
519             end if;
520          when Character'Pos ('P') mod 16#20#  => --  Ctrl('P')
521             if current /= null then
522                current := current.all.last;
523             end if;
524          when Character'Pos ('F') mod 16#20#  => --  Ctrl('F')
525             if current /= null and then HaveScroll (current.all.wind) then
526                Scroll (current.all.wind, 1);
527             end if;
528          when Character'Pos ('B') mod 16#20#  => --  Ctrl('B')
529             if current /= null and then HaveScroll (current.all.wind) then
530             --  The C version of Scroll may return ERR which is ignored
531             --  we need to avoid the exception
532             --  with the 'and HaveScroll(current.wind)'
533                Scroll (current.all.wind, -1);
534             end if;
535          when Character'Pos ('K') mod 16#20#  => --  Ctrl('K')
536             if current /= null then
537                current.all.do_keypad := not current.all.do_keypad;
538                Set_KeyPad_Mode (current.all.wind, current.all.do_keypad);
539             end if;
540          when Character'Pos ('S') mod 16#20#  => --  Ctrl('S')
541             if current /= null then
542                current.all.do_scroll := not current.all.do_scroll;
543                Allow_Scrolling (current.all.wind, current.all.do_scroll);
544             end if;
545          when Character'Pos ('W') mod 16#20#  => --  Ctrl('W')
546             if current /= current.all.next then
547                Create (f, Name => dumpfile); -- TODO error checking
548                if not Is_Open (f) then
549                   raise Curses_Exception;
550                end if;
551                Put_Window (current.all.wind, f);
552                Close (f);
553                current := delete_framed (current, True);
554             end if;
555          when Character'Pos ('R') mod 16#20#  => --  Ctrl('R')
556             declare
557                neww : FrameA := new Frame'(null, null, False, False,
558                                            Null_Window);
559             begin
560                Open (f, Mode => In_File, Name => dumpfile);
561                neww := new Frame'(null, null, False, False, Null_Window);
562
563                neww.all.next := current.all.next;
564                neww.all.last := current;
565                neww.all.last.all.next := neww;
566                neww.all.next.all.last := neww;
567
568                neww.all.wind := Get_Window (f);
569                Close (f);
570
571                Refresh (neww.all.wind);
572             end;
573          when Character'Pos ('X') mod 16#20# => --  Ctrl('X')
574             if current /= null then
575                declare
576                   tmp, ul, lr : pair;
577                   mx : Column_Position;
578                   my : Line_Position;
579                   tmpbool : Boolean;
580                begin
581                   Move_Cursor (Line => 0, Column => 0);
582                   Clear_To_End_Of_Line;
583                   Add (Str => "Use arrows to move cursor, anything else " &
584                        "to mark new corner");
585                   Refresh;
586
587                   Get_Window_Position (current.all.wind, ul.y, ul.x);
588
589                   selectcell (ul.y, ul.x, Lines - Botlines - 2, Columns - 2,
590                               tmp, tmpbool);
591                   if not tmpbool then
592                      --  the C version had a goto. I refuse gotos.
593                      Beep;
594                   else
595                      Get_Size (current.all.wind, lr.y, lr.x);
596                      lr.y := lr.y + ul.y - 1;
597                      lr.x := lr.x + ul.x - 1;
598                      Outerbox (ul, lr, False);
599                      Refresh_Without_Update;
600
601                      Get_Size (current.all.wind, my, mx);
602                      if my > tmp.y - ul.y then
603                         Get_Cursor_Position (current.all.wind, lr.y, lr.x);
604                         Move_Cursor (current.all.wind, tmp.y - ul.y + 1, 0);
605                         Clear_To_End_Of_Screen (current.all.wind);
606                         Move_Cursor (current.all.wind, lr.y, lr.x);
607                      end if;
608                      if mx > tmp.x - ul.x then
609                         for i in 0 .. my - 1 loop
610                            Move_Cursor (current.all.wind, i, tmp.x - ul.x + 1);
611                            Clear_To_End_Of_Line (current.all.wind);
612                         end loop;
613                      end if;
614                      Refresh_Without_Update (current.all.wind);
615
616                      lr := tmp;
617                      --  The C version passes invalid args to resize
618                      --  which returns an ERR. For Ada we avoid the exception.
619                      if lr.y /= ul.y and lr.x /= ul.x then
620                         Resize (current.all.wind, lr.y - ul.y + 0,
621                                 lr.x - ul.x + 0);
622                      end if;
623
624                      Get_Window_Position (current.all.wind, ul.y, ul.x);
625                      Get_Size (current.all.wind, lr.y, lr.x);
626                      lr.y := lr.y + ul.y - 1;
627                      lr.x := lr.x + ul.x - 1;
628                      Outerbox (ul, lr, True);
629                      Refresh_Without_Update;
630
631                      Refresh_Without_Update (current.all.wind);
632                      Move_Cursor (Line => 0, Column => 0);
633                      Clear_To_End_Of_Line;
634                      Update_Screen;
635                   end if;
636                end;
637             end if;
638          when Key_F10  =>
639             declare tmp : pair; tmpbool : Boolean;
640             begin
641                --  undocumented --- use this to test area clears
642                selectcell (0, 0, Lines - 1, Columns - 1, tmp, tmpbool);
643                Clear_To_End_Of_Screen;
644                Refresh;
645             end;
646          when Key_Cursor_Up =>
647             newwin_move (current.all.wind, -1, 0);
648          when Key_Cursor_Down  =>
649             newwin_move (current.all.wind, 1, 0);
650          when Key_Cursor_Left  =>
651             newwin_move (current.all.wind, 0, -1);
652          when Key_Cursor_Right  =>
653             newwin_move (current.all.wind, 0, 1);
654          when Key_Backspace | Key_Delete_Char  =>
655             declare
656                y : Line_Position;
657                x : Column_Position;
658                tmp : Line_Position;
659             begin
660                Get_Cursor_Position (current.all.wind, y, x);
661                --  x := x - 1;
662                --  I got tricked by the -1 = Max_Natural - 1 result
663                --  y := y - 1;
664                if not (x = 0 and y = 0) then
665                   if x = 0 then
666                      y := y - 1;
667                      Get_Size (current.all.wind, tmp, x);
668                   end if;
669                   x := x - 1;
670                   Delete_Character (current.all.wind, y, x);
671                end if;
672             end;
673          when others =>
674             --  TODO c = '\r' ?
675             if current /= null then
676                declare
677                begin
678                   Add (current.all.wind, Ch => Code_To_Char (c));
679                exception
680                   when Curses_Exception => null;
681                      --  this happens if we are at the
682                      --  lower right of a window and add a character.
683                end;
684             else
685                Beep;
686             end if;
687       end case;
688       newwin_report (current.all.wind);
689       if current /= null then
690          usescr := current.all.wind;
691       else
692          usescr := Standard_Window;
693       end if;
694       Refresh (usescr);
695       c := Getchar (usescr);
696       exit when c = Quit or (c = Escape and HaveKeyPad (usescr));
697       --  TODO when does c = ERR happen?
698    end loop;
699
700    --  TODO while current /= null loop
701    --  current := delete_framed(current, False);
702    --  end loop;
703
704    Allow_Scrolling (Mode => True);
705
706    End_Mouse (Mask2);
707    Set_Raw_Mode (SwitchOn => True);
708    Erase;
709    End_Windows;
710
711 end ncurses2.acs_and_scroll;