Ruby  1.9.3p551(2014-11-13revision48407)
curses.c
Go to the documentation of this file.
1 /* -*- C -*-
2  * $Id: curses.c 32145 2011-06-17 04:10:37Z drbrain $
3  *
4  * ext/curses/curses.c
5  *
6  * by MAEDA Shugo (ender@pic-internet.or.jp)
7  * modified by Yukihiro Matsumoto (matz@netlab.co.jp),
8  * Toki Yoshinori,
9  * Hitoshi Takahashi,
10  * and Takaaki Tateishi (ttate@kt.jaist.ac.jp)
11  *
12  * maintainers:
13  * - Takaaki Tateishi (ttate@kt.jaist.ac.jp)
14  *
15  * doumentation:
16  * - Vincent Batts (vbatts@hashbangbash.com)
17  */
18 
19 #include "ruby.h"
20 #include "ruby/io.h"
21 
22 #if defined(HAVE_NCURSES_H)
23 # include <ncurses.h>
24 #elif defined(HAVE_NCURSES_CURSES_H)
25 # include <ncurses/curses.h>
26 #elif defined(HAVE_CURSES_COLR_CURSES_H)
27 # ifdef HAVE_STDARG_PROTOTYPES
28 # include <stdarg.h>
29 # else
30 # include <varargs.h>
31 # endif
32 # include <curses_colr/curses.h>
33 #else
34 # include <curses.h>
35 # if defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)
36 # if !defined(_maxx)
37 # define _maxx maxx
38 # endif
39 # if !defined(_maxy)
40 # define _maxy maxy
41 # endif
42 # if !defined(_begx)
43 # define _begx begx
44 # endif
45 # if !defined(_begy)
46 # define _begy begy
47 # endif
48 # endif
49 #endif
50 
51 #ifdef HAVE_INIT_COLOR
52 # define USE_COLOR 1
53 #endif
54 
55 /* supports only ncurses mouse routines */
56 #ifdef NCURSES_MOUSE_VERSION
57 # define USE_MOUSE 1
58 #endif
59 
60 #define NUM2CH NUM2CHR
61 #define CH2FIX CHR2FIX
62 
63 static VALUE mCurses;
64 static VALUE mKey;
65 static VALUE cWindow;
66 #ifdef USE_MOUSE
67 static VALUE cMouseEvent;
68 #endif
69 
71 
72 struct windata {
73  WINDOW *window;
74 };
75 
76 static VALUE window_attroff(VALUE obj, VALUE attrs);
77 static VALUE window_attron(VALUE obj, VALUE attrs);
78 static VALUE window_attrset(VALUE obj, VALUE attrs);
79 
80 static void
81 no_window(void)
82 {
83  rb_raise(rb_eRuntimeError, "already closed window");
84 }
85 
86 #define GetWINDOW(obj, winp) do {\
87  if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
88  rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\
89  Data_Get_Struct((obj), struct windata, (winp));\
90  if ((winp)->window == 0) no_window();\
91 } while (0)
92 
93 static void
94 free_window(struct windata *winp)
95 {
96  if (winp->window && winp->window != stdscr) delwin(winp->window);
97  winp->window = 0;
98  xfree(winp);
99 }
100 
101 static VALUE
102 prep_window(VALUE class, WINDOW *window)
103 {
104  VALUE obj;
105  struct windata *winp;
106 
107  if (window == NULL) {
108  rb_raise(rb_eRuntimeError, "failed to create window");
109  }
110 
111  obj = rb_obj_alloc(class);
112  Data_Get_Struct(obj, struct windata, winp);
113  winp->window = window;
114 
115  return obj;
116 }
117 
118 /*-------------------------- module Curses --------------------------*/
119 
120 /*
121  * Document-method: Curses.init_screen
122  *
123  * Initialize a standard screen
124  *
125  * see also Curses.stdscr
126  */
127 static VALUE
129 {
130  rb_secure(4);
131  if (rb_stdscr) return rb_stdscr;
132  initscr();
133  if (stdscr == 0) {
134  rb_raise(rb_eRuntimeError, "can't initialize curses");
135  }
136  clear();
137  rb_stdscr = prep_window(cWindow, stdscr);
138  return rb_stdscr;
139 }
140 
141 /*
142  * Document-method: Curses.stdscr
143  *
144  * The Standard Screen.
145  *
146  * Upon initializing curses, a default window called stdscr,
147  * which is the size of the terminal screen, is created.
148  *
149  * Many curses functions use this window.
150  */
151 #define curses_stdscr curses_init_screen
152 
153 /*
154  * Document-method: Curses.close_screen
155  *
156  * A program should always call Curses.close_screen before exiting or
157  * escaping from curses mode temporarily. This routine
158  * restores tty modes, moves the cursor to the lower
159  * left-hand corner of the screen and resets the terminal
160  * into the proper non-visual mode.
161  *
162  * Calling Curses.refresh or Curses.doupdate after a temporary
163  * escape causes the program to resume visual mode.
164  *
165  */
166 static VALUE
168 {
169  curses_stdscr();
170 #ifdef HAVE_ISENDWIN
171  if (!isendwin())
172 #endif
173  endwin();
174  rb_stdscr = 0;
175  return Qnil;
176 }
177 
178 /*
179  * This is no runtime method,
180  * but a function called before the proc ends
181  *
182  * Similar to Curses.close_screen, except that it also
183  * garbage collects/unregisters the Curses.stdscr
184  */
185 static void
187 {
188  if (stdscr
189 #ifdef HAVE_ISENDWIN
190  && !isendwin()
191 #endif
192  )
193  endwin();
194  rb_stdscr = 0;
196 }
197 
198 #ifdef HAVE_ISENDWIN
199 /*
200  * Document-method: Curses.closed?
201  *
202  * Returns +true+ if the window/screen has been closed,
203  * without any subsequent Curses.refresh calls,
204  * returns +false+ otherwise.
205  */
206 static VALUE
207 curses_closed(void)
208 {
209  curses_stdscr();
210  if (isendwin()) {
211  return Qtrue;
212  }
213  return Qfalse;
214 }
215 #else
216 #define curses_closed rb_f_notimplement
217 #endif
218 
219 /*
220  * Document-method: Curses.clear
221  *
222  * Clears every position on the screen completely,
223  * so that a subsequent call by Curses.refresh for the screen/window
224  * will be repainted from scratch.
225  */
226 static VALUE
228 {
229  curses_stdscr();
230  wclear(stdscr);
231  return Qnil;
232 }
233 
234 /*
235  * Document-method: Curses.clrtoeol
236  *
237  * Clears to the end of line, that the cursor is currently on.
238  */
239 static VALUE
241 {
242  curses_stdscr();
243  clrtoeol();
244  return Qnil;
245 }
246 
247 /*
248  * Document-method: Curses.refresh
249  *
250  * Refreshes the windows and lines.
251  *
252  */
253 static VALUE
255 {
256  curses_stdscr();
257  refresh();
258  return Qnil;
259 }
260 
261 /*
262  * Document-method: Curses.doupdate
263  *
264  * Refreshes the windows and lines.
265  *
266  * Curses.doupdate allows multiple updates with
267  * more efficiency than Curses.refresh alone.
268  */
269 static VALUE
271 {
272  curses_stdscr();
273 #ifdef HAVE_DOUPDATE
274  doupdate();
275 #else
276  refresh();
277 #endif
278  return Qnil;
279 }
280 
281 /*
282  * Document-method: Curses.echo
283  *
284  * Enables characters typed by the user
285  * to be echoed by Curses.getch as they are typed.
286  */
287 static VALUE
289 {
290  curses_stdscr();
291  echo();
292  return Qnil;
293 }
294 
295 /*
296  * Document-method: Curses.noecho
297  *
298  * Disables characters typed by the user
299  * to be echoed by Curses.getch as they are typed.
300  */
301 static VALUE
303 {
304  curses_stdscr();
305  noecho();
306  return Qnil;
307 }
308 
309 /*
310  * Document-method: Curses.raw
311  *
312  * Put the terminal into raw mode.
313  *
314  * Raw mode is similar to Curses.cbreak mode, in that characters typed
315  * are immediately passed through to the user program.
316  *
317  * The differences are that in raw mode, the interrupt, quit,
318  * suspend, and flow control characters are all passed through
319  * uninterpreted, instead of generating a signal. The behavior
320  * of the BREAK key depends on other bits in the tty driver
321  * that are not set by curses.
322  */
323 static VALUE
325 {
326  curses_stdscr();
327  raw();
328  return Qnil;
329 }
330 
331 /*
332  * Document-method: Curses.noraw
333  *
334  * Put the terminal out of raw mode.
335  *
336  * see Curses.raw for more detail
337  */
338 static VALUE
340 {
341  curses_stdscr();
342  noraw();
343  return Qnil;
344 }
345 
346 /*
347  * Document-method: Curses.cbreak
348  *
349  * Put the terminal into cbreak mode.
350  *
351  * Normally, the tty driver buffers typed characters until
352  * a newline or carriage return is typed. The Curses.cbreak
353  * routine disables line buffering and erase/kill
354  * character-processing (interrupt and flow control characters
355  * are unaffected), making characters typed by the user
356  * immediately available to the program.
357  *
358  * The Curses.nocbreak routine returns the terminal to normal (cooked) mode.
359  *
360  * Initially the terminal may or may not be in cbreak mode,
361  * as the mode is inherited; therefore, a program should
362  * call Curses.cbreak or Curses.nocbreak explicitly.
363  * Most interactive programs using curses set the cbreak mode.
364  * Note that Curses.cbreak overrides Curses.raw.
365  *
366  * see also Curses.raw
367  */
368 static VALUE
370 {
371  curses_stdscr();
372  cbreak();
373  return Qnil;
374 }
375 
376 /*
377  * Document-method: Curses.nocbreak
378  *
379  * Put the terminal into normal mode (out of cbreak mode).
380  *
381  * See Curses.cbreak for more detail.
382  */
383 static VALUE
385 {
386  curses_stdscr();
387  nocbreak();
388  return Qnil;
389 }
390 
391 /*
392  * Document-method: Curses.nl
393  *
394  * Enable the underlying display device to translate
395  * the return key into newline on input, and whether it
396  * translates newline into return and line-feed on output
397  * (in either case, the call Curses.addch('\n') does the
398  * equivalent of return and line feed on the virtual screen).
399  *
400  * Initially, these translations do occur. If you disable
401  * them using Curses.nonl, curses will be able to make better use
402  * of the line-feed capability, resulting in faster cursor
403  * motion. Also, curses will then be able to detect the return key.
404  */
405 static VALUE
407 {
408  curses_stdscr();
409  nl();
410  return Qnil;
411 }
412 
413 /*
414  * Document-method: Curses.nl
415  *
416  * Disable the underlying display device to translate
417  * the return key into newline on input
418  *
419  * See Curses.nl for more detail
420  */
421 static VALUE
423 {
424  curses_stdscr();
425  nonl();
426  return Qnil;
427 }
428 
429 /*
430  * Document-method: Curses.beep
431  *
432  * Sounds an audible alarm on the terminal, if possible;
433  * otherwise it flashes the screen (visual bell).
434  *
435  * see also Curses.flash
436  */
437 static VALUE
439 {
440 #ifdef HAVE_BEEP
441  curses_stdscr();
442  beep();
443 #endif
444  return Qnil;
445 }
446 
447 /*
448  * Document-method: Curses.flash
449  *
450  * Flashs the screen, for visual alarm on the terminal, if possible;
451  * otherwise it sounds the alert.
452  *
453  * see also Curses.beep
454  */
455 static VALUE
457 {
458 #ifdef HAVE_FLASH
459  curses_stdscr();
460  flash();
461 #endif
462  return Qnil;
463 }
464 
465 static int
467 {
468  if (FIXNUM_P(c)) {
469  return NUM2INT(c);
470  }
471  else {
472  int cc;
473 
474  StringValue(c);
475  if (RSTRING_LEN(c) == 0 || RSTRING_LEN(c) > 1) {
476  rb_raise(rb_eArgError, "string not corresponding a character");
477  }
478  cc = RSTRING_PTR(c)[0];
479  if (cc > 0x7f) {
480  rb_raise(rb_eArgError, "no multibyte string supported (yet)");
481  }
482  return cc;
483  }
484 }
485 
486 #ifdef HAVE_UNGETCH
487 /*
488  * Document-method: Curses.ungetch
489  * call-seq: ungetch(ch)
490  *
491  * Places +ch+ back onto the input queue to be returned by
492  * the next call to Curses.getch.
493  *
494  * There is just one input queue for all windows.
495  */
496 static VALUE
497 curses_ungetch(VALUE obj, VALUE ch)
498 {
499  int c = curses_char(ch);
500  curses_stdscr();
501  ungetch(c);
502  return Qnil;
503 }
504 #else
505 #define curses_ungetch rb_f_notimplement
506 #endif
507 
508 /*
509  * Document-method: Curses.setpos
510  * call-seq: setpos(y, x)
511  *
512  * A setter for the position of the cursor,
513  * using coordinates +x+ and +y+
514  *
515  */
516 static VALUE
518 {
519  curses_stdscr();
520  move(NUM2INT(y), NUM2INT(x));
521  return Qnil;
522 }
523 
524 /*
525  * Document-method: Curses.standout
526  *
527  * Enables the best highlighting mode of the terminal.
528  *
529  * This is equivalent to Curses:Window.attron(A_STANDOUT)
530  *
531  * see also Curses::Window.attrset additional information
532  */
533 static VALUE
535 {
536  curses_stdscr();
537  standout();
538  return Qnil;
539 }
540 
541 /*
542  * Document-method: Curses.standend
543  *
544  * Enables the Normal display (no highlight)
545  *
546  * This is equivalent to Curses.attron(A_NORMAL)
547  *
548  * see also Curses::Window.attrset for additional information.
549  */
550 static VALUE
552 {
553  curses_stdscr();
554  standend();
555  return Qnil;
556 }
557 
558 /*
559  * Document-method: Curses.inch
560  *
561  * Returns the character at the current position.
562  */
563 static VALUE
565 {
566  curses_stdscr();
567  return CH2FIX(inch());
568 }
569 
570 /*
571  * Document-method: Curses.addch
572  * call-seq: addch(ch)
573  *
574  * Add a character +ch+, with attributes, then advance the cursor.
575  *
576  * see also the system manual for curs_addch(3)
577  */
578 static VALUE
580 {
581  curses_stdscr();
582  addch(NUM2CH(ch));
583  return Qnil;
584 }
585 
586 /*
587  * Document-method: Curses.insch
588  * call-seq: insch(ch)
589  *
590  * Insert a character +ch+, before the cursor.
591  *
592  */
593 static VALUE
595 {
596  curses_stdscr();
597  insch(NUM2CH(ch));
598  return Qnil;
599 }
600 
601 /*
602  * Document-method: Curses.addstr
603  * call-seq: addstr(str)
604  *
605  * add a string of characters +str+, to the window and advance cursor
606  *
607  */
608 static VALUE
610 {
611  StringValue(str);
612  str = rb_str_export_locale(str);
613  curses_stdscr();
614  if (!NIL_P(str)) {
615  addstr(StringValueCStr(str));
616  }
617  return Qnil;
618 }
619 
620 static VALUE
622 {
623  int *ip = (int *)arg;
624  *ip = getch();
625  return Qnil;
626 }
627 
628 /*
629  * Document-method: Curses.getch
630  *
631  * Read and returns a character from the window.
632  *
633  * See Curses::Key to all the function KEY_* available
634  *
635  */
636 static VALUE
638 {
639  int c;
640 
641  curses_stdscr();
643  if (c == EOF) return Qnil;
644  if (rb_isprint(c)) {
645  char ch = (char)c;
646 
647  return rb_locale_str_new(&ch, 1);
648  }
649  return UINT2NUM(c);
650 }
651 
652 /* This should be big enough.. I hope */
653 #define GETSTR_BUF_SIZE 1024
654 
655 static VALUE
657 {
658  char *rtn = (char *)arg;
659 #if defined(HAVE_GETNSTR)
660  getnstr(rtn,GETSTR_BUF_SIZE-1);
661 #else
662  getstr(rtn);
663 #endif
664  return Qnil;
665 }
666 
667 /*
668  * Document-method: Curses.getstr
669  *
670  * This is equivalent to a series f Curses::Window.getch calls
671  *
672  */
673 static VALUE
675 {
676  char rtn[GETSTR_BUF_SIZE];
677 
678  curses_stdscr();
680  return rb_locale_str_new_cstr(rtn);
681 }
682 
683 /*
684  * Document-method: Curses.delch
685  *
686  * Delete the character under the cursor
687  *
688  */
689 static VALUE
691 {
692  curses_stdscr();
693  delch();
694  return Qnil;
695 }
696 
697 /*
698  * Document-method: Curses.deleteln
699  *
700  * Delete the line under the cursor.
701  *
702  */
703 static VALUE
705 {
706  curses_stdscr();
707 #if defined(HAVE_DELETELN) || defined(deleteln)
708  deleteln();
709 #endif
710  return Qnil;
711 }
712 
713 /*
714  * Document-method: Curses.insertln
715  *
716  * Inserts a line above the cursor, and the bottom line is lost
717  *
718  */
719 static VALUE
721 {
722  curses_stdscr();
723 #if defined(HAVE_INSERTLN) || defined(insertln)
724  insertln();
725 #endif
726  return Qnil;
727 }
728 
729 /*
730  * Document-method: Curses.keyname
731  * call-seq: keyname(c)
732  *
733  * Returns the character string corresponding to key +c+
734  */
735 static VALUE
737 {
738 #ifdef HAVE_KEYNAME
739  int cc = curses_char(c);
740  const char *name;
741 
742  curses_stdscr();
743  name = keyname(cc);
744  if (name) {
745  return rb_str_new_cstr(name);
746  }
747  else {
748  return Qnil;
749  }
750 #else
751  return Qnil;
752 #endif
753 }
754 
755 /*
756  * Document-method: Curses.lines
757  *
758  * Returns the number of lines on the screen
759  */
760 static VALUE
762 {
763  return INT2FIX(LINES);
764 }
765 
766 /*
767  * Document-method: Curses.cols
768  *
769  * Returns the number of columns on the screen
770  */
771 static VALUE
773 {
774  return INT2FIX(COLS);
775 }
776 
777 /*
778  * Document-method: Curses.curs_set
779  * call-seq: curs_set(visibility)
780  *
781  * Sets Cursor Visibility.
782  * 0: invisible
783  * 1: visible
784  * 2: very visible
785  */
786 static VALUE
787 curses_curs_set(VALUE obj, VALUE visibility)
788 {
789 #ifdef HAVE_CURS_SET
790  int n;
791  curses_stdscr();
792  return (n = curs_set(NUM2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil;
793 #else
794  return Qnil;
795 #endif
796 }
797 
798 /*
799  * Document-method: Curses.scrl
800  * call-seq: scrl(num)
801  *
802  * Scrolls the current window Fixnum +num+ lines.
803  * The current cursor position is not changed.
804  *
805  * For positive +num+, it scrolls up.
806  *
807  * For negative +num+, it scrolls down.
808  *
809  */
810 static VALUE
812 {
813  /* may have to raise exception on ERR */
814 #ifdef HAVE_SCRL
815  curses_stdscr();
816  return (scrl(NUM2INT(n)) == OK) ? Qtrue : Qfalse;
817 #else
818  return Qfalse;
819 #endif
820 }
821 
822 /*
823  * Document-method: Curses.setscrreg
824  *
825  * call-seq:
826  * setscrreg(top, bottom)
827  *
828  * Set a software scrolling region in a window.
829  * +top+ and +bottom+ are lines numbers of the margin.
830  *
831  * If this option and Curses.scrollok are enabled, an attempt to move off
832  * the bottom margin line causes all lines in the scrolling region
833  * to scroll one line in the direction of the first line.
834  * Only the text of the window is scrolled.
835  *
836  */
837 static VALUE
839 {
840  /* may have to raise exception on ERR */
841 #ifdef HAVE_SETSCRREG
842  curses_stdscr();
843  return (setscrreg(NUM2INT(top), NUM2INT(bottom)) == OK) ? Qtrue : Qfalse;
844 #else
845  return Qfalse;
846 #endif
847 }
848 
849 /*
850  * Document-method: Curses.attroff
851  * call-seq: attroff(attrs)
852  *
853  * Turns on the named attributes +attrs+ without affecting any others.
854  *
855  * See also Curses::Window.attrset for additional information.
856  */
857 static VALUE
859 {
860  curses_stdscr();
861  return window_attroff(rb_stdscr,attrs);
862  /* return INT2FIX(attroff(NUM2INT(attrs))); */
863 }
864 
865 /*
866  * Document-method: Curses.attron
867  * call-seq: attron(attrs)
868  *
869  * Turns off the named attributes +attrs+
870  * without turning any other attributes on or off.
871  *
872  * See also Curses::Window.attrset for additional information.
873  */
874 static VALUE
876 {
877  curses_stdscr();
878  return window_attron(rb_stdscr,attrs);
879  /* return INT2FIX(attroff(NUM2INT(attrs))); */
880 }
881 
882 /*
883  * Document-method: Curses.attrset
884  * call-seq: attrset(attrs)
885  *
886  * Sets the current attributes of the given window to +attrs+.
887  *
888  * see also Curses::Window.attrset
889  *
890  */
891 static VALUE
893 {
894  curses_stdscr();
895  return window_attrset(rb_stdscr,attrs);
896  /* return INT2FIX(attroff(NUM2INT(attrs))); */
897 }
898 
899 /*
900  * Document-method: Curses.bkgdset
901  * call-seq: bkgdset(ch)
902  *
903  * Manipulate the background of the named window
904  * with character Integer +ch+
905  *
906  * The background becomes a property of the character
907  * and moves with the character through any scrolling
908  * and insert/delete line/character operations.
909  *
910  * see also the system manual for curs_bkgd(3)
911  */
912 static VALUE
914 {
915 #ifdef HAVE_BKGDSET
916  curses_stdscr();
917  bkgdset(NUM2CH(ch));
918 #endif
919  return Qnil;
920 }
921 
922 /*
923  * call-seq: bkgd(ch)
924  *
925  * Window background manipulation routines.
926  *
927  * Set the background property of the current
928  * and then apply the character Integer +ch+ setting
929  * to every character position in that window.
930  *
931  * see also the system manual for curs_bkgd(3)
932  */
933 static VALUE
935 {
936 #ifdef HAVE_BKGD
937  curses_stdscr();
938  return (bkgd(NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
939 #else
940  return Qfalse;
941 #endif
942 }
943 
944 #if defined(HAVE_USE_DEFAULT_COLORS)
945 /*
946  * tells the curses library to use terminal's default colors.
947  *
948  * see also the system manual for default_colors(3)
949  */
950 static VALUE
952 {
953  curses_stdscr();
954  use_default_colors();
955  return Qnil;
956 }
957 #else
958 #define curses_use_default_colors rb_f_notimplement
959 #endif
960 
961 #if defined(HAVE_TABSIZE)
962 /*
963  * Document-method: Curses.TABSIZE=
964  * call-seq: TABSIZE=(value)
965  *
966  * Sets the TABSIZE to Integer +value+
967  */
968 static VALUE
970 {
971  TABSIZE = NUM2INT(val);
972  return INT2NUM(TABSIZE);
973 }
974 #else
975 #define curses_tabsize_set rb_f_notimplement
976 #endif
977 
978 #if defined(HAVE_TABSIZE)
979 /*
980  * Returns the number of positions in a tab.
981  */
982 static VALUE
984 {
985  return INT2NUM(TABSIZE);
986 }
987 #else
988 #define curses_tabsize_get rb_f_notimplement
989 #endif
990 
991 #if defined(HAVE_ESCDELAY)
992 /*
993  * call-seq: Curses.ESCDELAY=(value)
994  *
995  * Sets the ESCDELAY to Integer +value+
996  */
997 static VALUE
999 {
1000  ESCDELAY = NUM2INT(val);
1001  return INT2NUM(ESCDELAY);
1002 }
1003 #else
1004 #define curses_escdelay_set rb_f_notimplement
1005 #endif
1006 
1007 #if defined(HAVE_ESCDELAY)
1008 /*
1009  * Returns the total time, in milliseconds, for which
1010  * curses will await a character sequence, e.g., a function key
1011  */
1012 static VALUE
1014 {
1015  return INT2NUM(ESCDELAY);
1016 }
1017 #else
1018 #define curses_escdelay_get rb_f_notimplement
1019 #endif
1020 
1021 /*
1022  * Document-method: Curses.resize
1023  * call-seq: resize(lines, cols)
1024  *
1025  * alias for Curses.resizeterm
1026  *
1027  */
1028 
1029 /*
1030  * Document-method: Curses.resizeterm
1031  * call-seq: resizeterm(lines, cols)
1032  *
1033  * Resize the current term to Fixnum +lines+ and Fixnum +cols+
1034  *
1035  */
1036 static VALUE
1038 {
1039 #if defined(HAVE_RESIZETERM)
1040  curses_stdscr();
1041  return (resizeterm(NUM2INT(lin),NUM2INT(col)) == OK) ? Qtrue : Qfalse;
1042 #else
1043  return Qnil;
1044 #endif
1045 }
1046 
1047 #ifdef USE_COLOR
1048 /*
1049  * Document-method: Curses.start_color
1050  *
1051  * Initializes the color attributes, for terminals that support it.
1052  *
1053  * This must be called, in order to use color attributes.
1054  * It is good practice to call it just after Curses.init_screen
1055  */
1056 static VALUE
1057 curses_start_color(VALUE obj)
1058 {
1059  /* may have to raise exception on ERR */
1060  curses_stdscr();
1061  return (start_color() == OK) ? Qtrue : Qfalse;
1062 }
1063 
1064 /*
1065  * Document-method: Curses.init_pair
1066  * call-seq: init_pair(pair, f, b)
1067  *
1068  * Changes the definition of a color-pair.
1069  *
1070  * It takes three arguments: the number of the color-pair to be changed +pair+,
1071  * the foreground color number +f+, and the background color number +b+.
1072  *
1073  * If the color-pair was previously initialized, the screen is
1074  * refreshed and all occurrences of that color-pair are changed
1075  * to the new definition.
1076  *
1077  */
1078 static VALUE
1079 curses_init_pair(VALUE obj, VALUE pair, VALUE f, VALUE b)
1080 {
1081  /* may have to raise exception on ERR */
1082  curses_stdscr();
1083  return (init_pair(NUM2INT(pair),NUM2INT(f),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
1084 }
1085 
1086 /*
1087  * Document-method: Curses.init_color
1088  * call-seq: init_color(color, r, g, b)
1089  *
1090  * Changes the definition of a color. It takes four arguments:
1091  * * the number of the color to be changed, +color+
1092  * * the amount of red, +r+
1093  * * the amount of green, +g+
1094  * * the amount of blue, +b+
1095  *
1096  * The value of the first argument must be between 0 and COLORS.
1097  * (See the section Colors for the default color index.) Each
1098  * of the last three arguments must be a value between 0 and 1000.
1099  * When Curses.init_color is used, all occurrences of that color
1100  * on the screen immediately change to the new definition.
1101  */
1102 static VALUE
1103 curses_init_color(VALUE obj, VALUE color, VALUE r, VALUE g, VALUE b)
1104 {
1105  /* may have to raise exception on ERR */
1106  curses_stdscr();
1107  return (init_color(NUM2INT(color),NUM2INT(r),
1108  NUM2INT(g),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
1109 }
1110 
1111 /*
1112  * Document-method: Curses.has_colors?
1113  *
1114  * Returns +true+ or +false+ depending on whether the terminal has color capbilities.
1115  */
1116 static VALUE
1117 curses_has_colors(VALUE obj)
1118 {
1119  curses_stdscr();
1120  return has_colors() ? Qtrue : Qfalse;
1121 }
1122 
1123 /*
1124  * Document-method: Curses.can_change_color?
1125  *
1126  * Returns +true+ or +false+ depending on whether the terminal can change color attributes
1127  */
1128 static VALUE
1129 curses_can_change_color(VALUE obj)
1130 {
1131  curses_stdscr();
1132  return can_change_color() ? Qtrue : Qfalse;
1133 }
1134 
1135 #if defined(HAVE_COLORS)
1136 /*
1137  * Document-method: Curses.color
1138  *
1139  * returns COLORS
1140  */
1141 static VALUE
1142 curses_colors(VALUE obj)
1143 {
1144  return INT2FIX(COLORS);
1145 }
1146 #else
1147 #define curses_colors rb_f_notimplement
1148 #endif
1149 
1150 /*
1151  * Document-method: Curses.color_content
1152  * call-seq: color_content(color)
1153  *
1154  * Returns an 3 item Array of the RGB values in +color+
1155  */
1156 static VALUE
1157 curses_color_content(VALUE obj, VALUE color)
1158 {
1159  short r,g,b;
1160 
1161  curses_stdscr();
1162  color_content(NUM2INT(color),&r,&g,&b);
1163  return rb_ary_new3(3,INT2FIX(r),INT2FIX(g),INT2FIX(b));
1164 }
1165 
1166 
1167 #if defined(HAVE_COLOR_PAIRS)
1168 /*
1169  * Document-method: Curses.color_pairs
1170  *
1171  * Returns the COLOR_PAIRS available, if the curses library supports it.
1172  */
1173 static VALUE
1174 curses_color_pairs(VALUE obj)
1175 {
1176  return INT2FIX(COLOR_PAIRS);
1177 }
1178 #else
1179 #define curses_color_pairs rb_f_notimplement
1180 #endif
1181 
1182 /*
1183  * Document-method: Curses.pair_content
1184  * call-seq: pair_content(pair)
1185  *
1186  * Returns a 2 item Array, with the foreground and
1187  * background color, in +pair+
1188  */
1189 static VALUE
1190 curses_pair_content(VALUE obj, VALUE pair)
1191 {
1192  short f,b;
1193 
1194  curses_stdscr();
1195  pair_content(NUM2INT(pair),&f,&b);
1196  return rb_ary_new3(2,INT2FIX(f),INT2FIX(b));
1197 }
1198 
1199 /*
1200  * Document-method: Curses.color_pair
1201  * call-seq: color_pair(attrs)
1202  *
1203  * Sets the color pair attributes to +attrs+.
1204  *
1205  * This should be equivalent to Curses.attrset(COLOR_PAIR(+attrs+))
1206  *
1207  * TODO: validate that equivalency
1208  */
1209 static VALUE
1210 curses_color_pair(VALUE obj, VALUE attrs)
1211 {
1212  return INT2FIX(COLOR_PAIR(NUM2INT(attrs)));
1213 }
1214 
1215 /*
1216  * Document-method: Curses.pair_number
1217  * call-seq: pair_number(attrs)
1218  *
1219  * Returns the Fixnum color pair number of attributes +attrs+.
1220  */
1221 static VALUE
1222 curses_pair_number(VALUE obj, VALUE attrs)
1223 {
1224  curses_stdscr();
1225  return INT2FIX(PAIR_NUMBER(NUM2INT(attrs)));
1226 }
1227 #endif /* USE_COLOR */
1228 
1229 #ifdef USE_MOUSE
1230 struct mousedata {
1231  MEVENT *mevent;
1232 };
1233 
1234 static void
1235 no_mevent(void)
1236 {
1237  rb_raise(rb_eRuntimeError, "no such mouse event");
1238 }
1239 
1240 #define GetMOUSE(obj, data) do {\
1241  if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
1242  rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\
1243  Data_Get_Struct((obj), struct mousedata, (data));\
1244  if ((data)->mevent == 0) no_mevent();\
1245 } while (0)
1246 
1247 static void
1248 curses_mousedata_free(struct mousedata *mdata)
1249 {
1250  if (mdata->mevent)
1251  xfree(mdata->mevent);
1252 }
1253 
1254 /*
1255  * Document-method: Curses.getmouse
1256  *
1257  * Returns coordinates of the mouse.
1258  *
1259  * This will read and pop the mouse event data off the queue
1260  *
1261  * See the BUTTON*, ALL_MOUSE_EVENTS and REPORT_MOUSE_POSITION constants, to examine the mask of the event
1262  */
1263 static VALUE
1264 curses_getmouse(VALUE obj)
1265 {
1266  struct mousedata *mdata;
1267  VALUE val;
1268 
1269  curses_stdscr();
1270  val = Data_Make_Struct(cMouseEvent,struct mousedata,
1271  0,curses_mousedata_free,mdata);
1272  mdata->mevent = (MEVENT*)xmalloc(sizeof(MEVENT));
1273  return (getmouse(mdata->mevent) == OK) ? val : Qnil;
1274 }
1275 
1276 /*
1277  * Document-method: Curses.ungetmouse
1278  *
1279  * It pushes a KEY_MOUSE event onto the input queue, and associates with that
1280  * event the given state data and screen-relative character-cell coordinates.
1281  *
1282  * The Curses.ungetmouse function behaves analogously to Curses.ungetch.
1283  */
1284 static VALUE
1285 curses_ungetmouse(VALUE obj, VALUE mevent)
1286 {
1287  struct mousedata *mdata;
1288 
1289  curses_stdscr();
1290  GetMOUSE(mevent,mdata);
1291  return (ungetmouse(mdata->mevent) == OK) ? Qtrue : Qfalse;
1292 }
1293 
1294 /*
1295  * Document-method: Curses.mouseinterval
1296  * call-seq: mouseinterval(interval)
1297  *
1298  * The Curses.mouseinterval function sets the maximum time
1299  * (in thousands of a second) that can elapse between press
1300  * and release events for them to be recognized as a click.
1301  *
1302  * Use Curses.mouseinterval(0) to disable click resolution.
1303  * This function returns the previous interval value.
1304  *
1305  * Use Curses.mouseinterval(-1) to obtain the interval without
1306  * altering it.
1307  *
1308  * The default is one sixth of a second.
1309  */
1310 static VALUE
1311 curses_mouseinterval(VALUE obj, VALUE interval)
1312 {
1313  curses_stdscr();
1314  return mouseinterval(NUM2INT(interval)) ? Qtrue : Qfalse;
1315 }
1316 
1317 /*
1318  * Document-method: Curses.mousemask
1319  * call-seq: mousemask(mask)
1320  *
1321  * Returns the +mask+ of the reportable events
1322  */
1323 static VALUE
1324 curses_mousemask(VALUE obj, VALUE mask)
1325 {
1326  curses_stdscr();
1327  return INT2NUM(mousemask(NUM2UINT(mask),NULL));
1328 }
1329 
1330 #define DEFINE_MOUSE_GET_MEMBER(func_name,mem) \
1331 static VALUE func_name (VALUE mouse) \
1332 { \
1333  struct mousedata *mdata; \
1334  GetMOUSE(mouse, mdata); \
1335  return (UINT2NUM(mdata->mevent -> mem)); \
1336 }
1337 
1338 /*
1339  * Document-method: Curses::MouseEvent.eid
1340  *
1341  * Returns the current mouse id
1342  */
1343 DEFINE_MOUSE_GET_MEMBER(curs_mouse_id, id)
1344 /*
1345  * Document-method: Curses::MouseEvent.x
1346  *
1347  * Returns the current mouse's X coordinate
1348  */
1349 DEFINE_MOUSE_GET_MEMBER(curs_mouse_x, x)
1350 /*
1351  * Document-method: Curses::MouseEvent.y
1352  *
1353  * Returns the current mouse's Y coordinate
1354  */
1355 DEFINE_MOUSE_GET_MEMBER(curs_mouse_y, y)
1356 /*
1357  * Document-method: Curses::MouseEvent.z
1358  *
1359  * Returns the current mouse's Z coordinate
1360  */
1361 DEFINE_MOUSE_GET_MEMBER(curs_mouse_z, z)
1362 /*
1363  * Document-method: Curses::MouseEvent.bstate
1364  *
1365  * Returns the current mouse's button state. Use this with the button state
1366  * constants to determine which buttons were pressed.
1367  */
1368 DEFINE_MOUSE_GET_MEMBER(curs_mouse_bstate, bstate)
1369 #undef define_curs_mouse_member
1370 #endif /* USE_MOUSE */
1371 
1372 #ifdef HAVE_TIMEOUT
1373 /*
1374  * Document-method: Curses.timeout=
1375  * call-seq: timeout=(delay)
1376  *
1377  * Sets block and non-blocking reads for the window.
1378  * - If delay is negative, blocking read is used (i.e., waits indefinitely for input).
1379  * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting).
1380  * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input.
1381  *
1382  */
1383 static VALUE
1384 curses_timeout(VALUE obj, VALUE delay)
1385 {
1386  curses_stdscr();
1387  timeout(NUM2INT(delay));
1388  return Qnil;
1389 }
1390 #else
1391 #define curses_timeout rb_f_notimplement
1392 #endif
1393 
1394 #ifdef HAVE_DEF_PROG_MODE
1395 /*
1396  * Document-method: Curses.def_prog_mode
1397  *
1398  * Save the current terminal modes as the "program"
1399  * state for use by the Curses.reset_prog_mode
1400  *
1401  * This is done automatically by Curses.init_screen
1402  */
1403 static VALUE
1405 {
1406  curses_stdscr();
1407  return def_prog_mode() == OK ? Qtrue : Qfalse;
1408 }
1409 #else
1410 #define curses_def_prog_mode rb_f_notimplement
1411 #endif
1412 
1413 #ifdef HAVE_RESET_PROG_MODE
1414 /*
1415  * Document-method: Curses.reset_prog_mode
1416  *
1417  * Reset the current terminal modes to the saved state
1418  * by the Curses.def_prog_mode
1419  *
1420  * This is done automatically by Curses.close_screen
1421  */
1422 static VALUE
1424 {
1425  curses_stdscr();
1426  return reset_prog_mode() == OK ? Qtrue : Qfalse;
1427 }
1428 #else
1429 #define curses_reset_prog_mode rb_f_notimplement
1430 #endif
1431 
1432 /*-------------------------- class Window --------------------------*/
1433 
1434 /* returns a Curses::Window object */
1435 static VALUE
1437 {
1438  struct windata *winp;
1439 
1440  return Data_Make_Struct(class, struct windata, 0, free_window, winp);
1441 }
1442 
1443 /*
1444  * Document-method: Curses::Window.new
1445  * call-seq: new(height, width, top, left)
1446  *
1447  * Contruct a new Curses::Window with constraints of
1448  * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column.
1449  *
1450  * A new window using full screen is called as
1451  * Curses::Window.new(0,0,0,0)
1452  *
1453  */
1454 static VALUE
1456 {
1457  struct windata *winp;
1458  WINDOW *window;
1459 
1460  rb_secure(4);
1462  Data_Get_Struct(obj, struct windata, winp);
1463  if (winp->window) delwin(winp->window);
1464  window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left));
1465  wclear(window);
1466  winp->window = window;
1467 
1468  return obj;
1469 }
1470 
1471 /*
1472  * Document-method: Curses::Window.subwin
1473  * call-seq: subwin(height, width, top, left)
1474  *
1475  * Contruct a new subwindow with constraints of
1476  * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column.
1477  *
1478  */
1479 static VALUE
1480 window_subwin(VALUE obj, VALUE height, VALUE width, VALUE top, VALUE left)
1481 {
1482  struct windata *winp;
1483  WINDOW *window;
1484  VALUE win;
1485  int h, w, t, l;
1486 
1487  h = NUM2INT(height);
1488  w = NUM2INT(width);
1489  t = NUM2INT(top);
1490  l = NUM2INT(left);
1491  GetWINDOW(obj, winp);
1492  window = subwin(winp->window, h, w, t, l);
1493  win = prep_window(rb_obj_class(obj), window);
1494 
1495  return win;
1496 }
1497 
1498 /*
1499  * Document-method: Curses::Window.close
1500  *
1501  * Deletes the window, and frees the memory
1502  */
1503 static VALUE
1505 {
1506  struct windata *winp;
1507 
1508  GetWINDOW(obj, winp);
1509  delwin(winp->window);
1510  winp->window = 0;
1511 
1512  return Qnil;
1513 }
1514 
1515 /*
1516  * Document-method: Curses::Window.clear
1517  *
1518  * Clear the window.
1519  */
1520 static VALUE
1522 {
1523  struct windata *winp;
1524 
1525  GetWINDOW(obj, winp);
1526  wclear(winp->window);
1527 
1528  return Qnil;
1529 }
1530 
1531 /*
1532  * Document-method: Curses::Window.clrtoeol
1533  *
1534  * Clear the window to the end of line, that the cursor is currently on.
1535  */
1536 static VALUE
1538 {
1539  struct windata *winp;
1540 
1541  GetWINDOW(obj, winp);
1542  wclrtoeol(winp->window);
1543 
1544  return Qnil;
1545 }
1546 
1547 /*
1548  * Document-method: Curses::Window.refresh
1549  *
1550  * Refreshes the windows and lines.
1551  *
1552  */
1553 static VALUE
1555 {
1556  struct windata *winp;
1557 
1558  GetWINDOW(obj, winp);
1559  wrefresh(winp->window);
1560 
1561  return Qnil;
1562 }
1563 
1564 /*
1565  * Document-method: Curses::Window.noutrefresh
1566  *
1567  * Refreshes the windows and lines.
1568  *
1569  * Curses::Window.noutrefresh allows multiple updates with
1570  * more efficiency than Curses::Window.refresh alone.
1571  */
1572 static VALUE
1574 {
1575  struct windata *winp;
1576 
1577  GetWINDOW(obj, winp);
1578 #ifdef HAVE_DOUPDATE
1579  wnoutrefresh(winp->window);
1580 #else
1581  wrefresh(winp->window);
1582 #endif
1583 
1584  return Qnil;
1585 }
1586 
1587 /*
1588  * Document-method: Curses::Window.move
1589  * call-seq: move(y,x)
1590  *
1591  * Moves the window so that the upper left-hand corner is at position (+y+, +x+)
1592  */
1593 static VALUE
1595 {
1596  struct windata *winp;
1597 
1598  GetWINDOW(obj, winp);
1599  mvwin(winp->window, NUM2INT(y), NUM2INT(x));
1600 
1601  return Qnil;
1602 }
1603 
1604 /*
1605  * Document-method: Curses::Window.setpos
1606  * call-seq: setpos(y, x)
1607  *
1608  * A setter for the position of the cursor
1609  * in the current window,
1610  * using coordinates +x+ and +y+
1611  *
1612  */
1613 static VALUE
1615 {
1616  struct windata *winp;
1617 
1618  GetWINDOW(obj, winp);
1619  wmove(winp->window, NUM2INT(y), NUM2INT(x));
1620  return Qnil;
1621 }
1622 
1623 /*
1624  * Document-method: Curses::Window.cury
1625  *
1626  * A getter for the current line (Y coord) of the window
1627  */
1628 static VALUE
1630 {
1631  struct windata *winp;
1632  int x, y;
1633 
1634  GetWINDOW(obj, winp);
1635  getyx(winp->window, y, x);
1636  return INT2FIX(y);
1637 }
1638 
1639 /*
1640  * Document-method: Curses::Window.curx
1641  *
1642  * A getter for the current column (X coord) of the window
1643  */
1644 static VALUE
1646 {
1647  struct windata *winp;
1648  int x, y;
1649 
1650  GetWINDOW(obj, winp);
1651  getyx(winp->window, y, x);
1652  return INT2FIX(x);
1653 }
1654 
1655 /*
1656  * Document-method: Curses::Window.maxy
1657  *
1658  * A getter for the maximum lines for the window
1659  */
1660 static VALUE
1662 {
1663  struct windata *winp;
1664 
1665  GetWINDOW(obj, winp);
1666 #if defined(getmaxy)
1667  return INT2FIX(getmaxy(winp->window));
1668 #elif defined(getmaxyx)
1669  {
1670  int x, y;
1671  getmaxyx(winp->window, y, x);
1672  return INT2FIX(y);
1673  }
1674 #else
1675  return INT2FIX(winp->window->_maxy+1);
1676 #endif
1677 }
1678 
1679 /*
1680  * Document-method: Curses::Window.maxx
1681  *
1682  * A getter for the maximum columns for the window
1683  */
1684 static VALUE
1686 {
1687  struct windata *winp;
1688 
1689  GetWINDOW(obj, winp);
1690 #if defined(getmaxx)
1691  return INT2FIX(getmaxx(winp->window));
1692 #elif defined(getmaxyx)
1693  {
1694  int x, y;
1695  getmaxyx(winp->window, y, x);
1696  return INT2FIX(x);
1697  }
1698 #else
1699  return INT2FIX(winp->window->_maxx+1);
1700 #endif
1701 }
1702 
1703 /*
1704  * Document-method: Curses::Window.begy
1705  *
1706  * A getter for the beginning line (Y coord) of the window
1707  */
1708 static VALUE
1710 {
1711  struct windata *winp;
1712  int x, y;
1713 
1714  GetWINDOW(obj, winp);
1715 #ifdef getbegyx
1716  getbegyx(winp->window, y, x);
1717  return INT2FIX(y);
1718 #else
1719  return INT2FIX(winp->window->_begy);
1720 #endif
1721 }
1722 
1723 /*
1724  * Document-method: Curses::Window.begx
1725  *
1726  * A getter for the beginning column (X coord) of the window
1727  */
1728 static VALUE
1730 {
1731  struct windata *winp;
1732  int x, y;
1733 
1734  GetWINDOW(obj, winp);
1735 #ifdef getbegyx
1736  getbegyx(winp->window, y, x);
1737  return INT2FIX(x);
1738 #else
1739  return INT2FIX(winp->window->_begx);
1740 #endif
1741 }
1742 
1743 /*
1744  * Document-method: Curses::Window.box
1745  * call-seq: box(vert, hor)
1746  *
1747  * set the characters to frame the window in.
1748  * The vertical +vert+ and horizontal +hor+ character.
1749  *
1750  * win = Curses::Window.new(5,5,5,5)
1751  * win.box(?|, ?-)
1752  *
1753  */
1754 static VALUE
1756 {
1757  struct windata *winp;
1758  VALUE vert, hor, corn;
1759 
1760  rb_scan_args(argc, argv, "21", &vert, &hor, &corn);
1761 
1762  GetWINDOW(self, winp);
1763  box(winp->window, NUM2CH(vert), NUM2CH(hor));
1764 
1765  if (!NIL_P(corn)) {
1766  int cur_x, cur_y, x, y;
1767  chtype c;
1768 
1769  c = NUM2CH(corn);
1770  getyx(winp->window, cur_y, cur_x);
1771  x = NUM2INT(window_maxx(self)) - 1;
1772  y = NUM2INT(window_maxy(self)) - 1;
1773  wmove(winp->window, 0, 0);
1774  waddch(winp->window, c);
1775  wmove(winp->window, y, 0);
1776  waddch(winp->window, c);
1777  wmove(winp->window, y, x);
1778  waddch(winp->window, c);
1779  wmove(winp->window, 0, x);
1780  waddch(winp->window, c);
1781  wmove(winp->window, cur_y, cur_x);
1782  }
1783 
1784  return Qnil;
1785 }
1786 
1787 /*
1788  * Document-method: Curses::Window.standout
1789  *
1790  * Enables the best highlighting mode of the terminal.
1791  *
1792  * This is equivalent to Curses::Window.attron(A_STANDOUT)
1793  *
1794  * see also Curses::Window.attrset
1795  */
1796 static VALUE
1798 {
1799  struct windata *winp;
1800 
1801  GetWINDOW(obj, winp);
1802  wstandout(winp->window);
1803  return Qnil;
1804 }
1805 
1806 /*
1807  * Document-method: Curses::Window.standend
1808  *
1809  * Enables the Normal display (no highlight)
1810  *
1811  * This is equivalent to Curses::Window.attron(A_NORMAL)
1812  *
1813  * see also Curses::Window.attrset
1814  */
1815 static VALUE
1817 {
1818  struct windata *winp;
1819 
1820  GetWINDOW(obj, winp);
1821  wstandend(winp->window);
1822  return Qnil;
1823 }
1824 
1825 /*
1826  * Document-method: Curses::Window.inch
1827  *
1828  * Returns the character at the current position of the window.
1829  */
1830 static VALUE
1832 {
1833  struct windata *winp;
1834 
1835  GetWINDOW(obj, winp);
1836  return CH2FIX(winch(winp->window));
1837 }
1838 
1839 /*
1840  * Document-method: Curses::Window.addch
1841  * call-seq: addch(ch)
1842  *
1843  * Add a character +ch+, with attributes, to the window, then advance the cursor.
1844  *
1845  * see also the system manual for curs_addch(3)
1846  */
1847 static VALUE
1849 {
1850  struct windata *winp;
1851 
1852  GetWINDOW(obj, winp);
1853  waddch(winp->window, NUM2CH(ch));
1854 
1855  return Qnil;
1856 }
1857 
1858 /*
1859  * Document-method: Curses::Window.insch
1860  * call-seq: insch(ch)
1861  *
1862  * Insert a character +ch+, before the cursor, in the current window
1863  *
1864  */
1865 static VALUE
1867 {
1868  struct windata *winp;
1869 
1870  GetWINDOW(obj, winp);
1871  winsch(winp->window, NUM2CH(ch));
1872 
1873  return Qnil;
1874 }
1875 
1876 /*
1877  * Document-method: Curses::Window.addstr
1878  * call-seq: addstr(str)
1879  *
1880  * add a string of characters +str+, to the window and advance cursor
1881  *
1882  */
1883 static VALUE
1885 {
1886  if (!NIL_P(str)) {
1887  struct windata *winp;
1888 
1889  StringValue(str);
1890  str = rb_str_export_locale(str);
1891  GetWINDOW(obj, winp);
1892  waddstr(winp->window, StringValueCStr(str));
1893  }
1894  return Qnil;
1895 }
1896 
1897 /*
1898  * Document-method: Curses::Window.<<
1899  *
1900  * call-seq:
1901  * <<(str)
1902  *
1903  * Add String +str+ to the current string.
1904  *
1905  * See also Curses::Window.addstr
1906  */
1907 static VALUE
1909 {
1910  window_addstr(obj, str);
1911  return obj;
1912 }
1913 
1914 struct wgetch_arg {
1915  WINDOW *win;
1916  int c;
1917 };
1918 
1919 static VALUE
1920 wgetch_func(void *_arg)
1921 {
1922  struct wgetch_arg *arg = (struct wgetch_arg *)_arg;
1923  arg->c = wgetch(arg->win);
1924  return Qnil;
1925 }
1926 
1927 /*
1928  * Document-method: Curses::Window.getch
1929  *
1930  * Read and returns a character from the window.
1931  *
1932  * See Curses::Key to all the function KEY_* available
1933  *
1934  */
1935 static VALUE
1937 {
1938  struct windata *winp;
1939  struct wgetch_arg arg;
1940  int c;
1941 
1942  GetWINDOW(obj, winp);
1943  arg.win = winp->window;
1945  c = arg.c;
1946  if (c == EOF) return Qnil;
1947  if (rb_isprint(c)) {
1948  char ch = (char)c;
1949 
1950  return rb_locale_str_new(&ch, 1);
1951  }
1952  return UINT2NUM(c);
1953 }
1954 
1955 struct wgetstr_arg {
1956  WINDOW *win;
1958 };
1959 
1960 static VALUE
1961 wgetstr_func(void *_arg)
1962 {
1963  struct wgetstr_arg *arg = (struct wgetstr_arg *)_arg;
1964 #if defined(HAVE_WGETNSTR)
1965  wgetnstr(arg->win, arg->rtn, GETSTR_BUF_SIZE-1);
1966 #else
1967  wgetstr(arg->win, arg->rtn);
1968 #endif
1969  return Qnil;
1970 }
1971 
1972 /*
1973  * Document-method: Curses::Window.getstr
1974  *
1975  * This is equivalent to a series f Curses::Window.getch calls
1976  *
1977  */
1978 static VALUE
1980 {
1981  struct windata *winp;
1982  struct wgetstr_arg arg;
1983 
1984  GetWINDOW(obj, winp);
1985  arg.win = winp->window;
1987  return rb_locale_str_new_cstr(arg.rtn);
1988 }
1989 
1990 /*
1991  * Document-method: Curses::Window.delch
1992  *
1993  * Delete the character under the cursor
1994  *
1995  */
1996 static VALUE
1998 {
1999  struct windata *winp;
2000 
2001  GetWINDOW(obj, winp);
2002  wdelch(winp->window);
2003  return Qnil;
2004 }
2005 
2006 /*
2007  * Document-method: Curses::Window.deleteln
2008  *
2009  * Delete the line under the cursor.
2010  *
2011  */
2012 static VALUE
2014 {
2015 #if defined(HAVE_WDELETELN) || defined(wdeleteln)
2016  struct windata *winp;
2017 
2018  GetWINDOW(obj, winp);
2019  wdeleteln(winp->window);
2020 #endif
2021  return Qnil;
2022 }
2023 
2024 /*
2025  * Document-method: Curses::Window.insertln
2026  *
2027  * Inserts a line above the cursor, and the bottom line is lost
2028  *
2029  */
2030 static VALUE
2032 {
2033 #if defined(HAVE_WINSERTLN) || defined(winsertln)
2034  struct windata *winp;
2035 
2036  GetWINDOW(obj, winp);
2037  winsertln(winp->window);
2038 #endif
2039  return Qnil;
2040 }
2041 
2042 /*
2043  * Document-method: Curses::Window.scrollok
2044  * call-seq: scrollok(bool)
2045  *
2046  * Controls what happens when the cursor of a window
2047  * is moved off the edge of the window or scrolling region,
2048  * either as a result of a newline action on the bottom line,
2049  * or typing the last character of the last line.
2050  *
2051  * If disabled, (+bool+ is false), the cursor is left on the bottom line.
2052  *
2053  * If enabled, (+bool+ is true), the window is scrolled up one line
2054  * (Note that to get the physical scrolling effect on the terminal,
2055  * it is also necessary to call Curses::Window.idlok)
2056  */
2057 static VALUE
2059 {
2060  struct windata *winp;
2061 
2062  GetWINDOW(obj, winp);
2063  scrollok(winp->window, RTEST(bf) ? TRUE : FALSE);
2064  return Qnil;
2065 }
2066 
2067 /*
2068  * Document-method: Curses::Window.idlok
2069  * call-seq: idlok(bool)
2070  *
2071  * If +bool+ is +true+ curses considers using the hardware insert/delete
2072  * line feature of terminals so equipped.
2073  *
2074  * If +bool+ is +false+, disables use of line insertion and deletion.
2075  * This option should be enabled only if the application needs insert/delete
2076  * line, for example, for a screen editor.
2077  *
2078  * It is disabled by default because insert/delete line tends to be visually
2079  * annoying when used in applications where it is not really needed.
2080  * If insert/delete line cannot be used, curses redraws the changed portions of all lines.
2081  *
2082  */
2083 static VALUE
2085 {
2086  struct windata *winp;
2087 
2088  GetWINDOW(obj, winp);
2089  idlok(winp->window, RTEST(bf) ? TRUE : FALSE);
2090  return Qnil;
2091 }
2092 
2093 /*
2094  * Document-method: Curses::Window.setscrreg
2095  * call-seq:
2096  * setscrreg(top, bottom)
2097  *
2098  * Set a software scrolling region in a window.
2099  * +top+ and +bottom+ are lines numbers of the margin.
2100  *
2101  * If this option and Curses::Window.scrollok are enabled, an attempt to move
2102  * off the bottom margin line causes all lines in the scrolling region to
2103  * scroll one line in the direction of the first line. Only the text of the
2104  * window is scrolled.
2105  *
2106  */
2107 static VALUE
2109 {
2110 #ifdef HAVE_WSETSCRREG
2111  struct windata *winp;
2112  int res;
2113 
2114  GetWINDOW(obj, winp);
2115  res = wsetscrreg(winp->window, NUM2INT(top), NUM2INT(bottom));
2116  /* may have to raise exception on ERR */
2117  return (res == OK) ? Qtrue : Qfalse;
2118 #else
2119  return Qfalse;
2120 #endif
2121 }
2122 
2123 #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
2124 /*
2125  * Document-method: Curses::Window.color_set
2126  * call-seq: color_set(col)
2127  *
2128  * Sets the current color of the given window to the
2129  * foreground/background combination described by the Fixnum +col+.
2130  */
2131 static VALUE
2132 window_color_set(VALUE obj, VALUE col)
2133 {
2134  struct windata *winp;
2135  int res;
2136 
2137  GetWINDOW(obj, winp);
2138  res = wcolor_set(winp->window, NUM2INT(col), NULL);
2139  return (res == OK) ? Qtrue : Qfalse;
2140 }
2141 #endif /* defined(USE_COLOR) && defined(HAVE_WCOLOR_SET) */
2142 
2143 /*
2144  * Document-method: Curses::Window.scroll
2145  *
2146  * Scrolls the current window up one line.
2147  */
2148 static VALUE
2150 {
2151  struct windata *winp;
2152 
2153  GetWINDOW(obj, winp);
2154  /* may have to raise exception on ERR */
2155  return (scroll(winp->window) == OK) ? Qtrue : Qfalse;
2156 }
2157 
2158 /*
2159  * Document-method: Curses::Window.scrl
2160  * call-seq: scrl(num)
2161  *
2162  * Scrolls the current window Fixnum +num+ lines.
2163  * The current cursor position is not changed.
2164  *
2165  * For positive +num+, it scrolls up.
2166  *
2167  * For negative +num+, it scrolls down.
2168  *
2169  */
2170 static VALUE
2172 {
2173 #ifdef HAVE_WSCRL
2174  struct windata *winp;
2175 
2176  GetWINDOW(obj, winp);
2177  /* may have to raise exception on ERR */
2178  return (wscrl(winp->window,NUM2INT(n)) == OK) ? Qtrue : Qfalse;
2179 #else
2180  return Qfalse;
2181 #endif
2182 }
2183 
2184 /*
2185  * Document-method: Curses::Window.attroff
2186  * call-seq: attroff(attrs)
2187  *
2188  * Turns on the named attributes +attrs+ without affecting any others.
2189  *
2190  * See also Curses::Window.attrset
2191  */
2192 static VALUE
2194 {
2195 #ifdef HAVE_WATTROFF
2196  struct windata *winp;
2197 
2198  GetWINDOW(obj,winp);
2199  return INT2FIX(wattroff(winp->window,NUM2INT(attrs)));
2200 #else
2201  return Qtrue;
2202 #endif
2203 }
2204 
2205 /*
2206  * Document-method: Curses::Window.attron
2207  * call-seq: attron(attrs)
2208  *
2209  * Turns off the named attributes +attrs+
2210  * without turning any other attributes on or off.
2211  *
2212  * See also Curses::Window.attrset
2213  */
2214 static VALUE
2216 {
2217 #ifdef HAVE_WATTRON
2218  struct windata *winp;
2219  VALUE val;
2220 
2221  GetWINDOW(obj,winp);
2222  val = INT2FIX(wattron(winp->window,NUM2INT(attrs)));
2223  if (rb_block_given_p()) {
2224  rb_yield(val);
2225  wattroff(winp->window,NUM2INT(attrs));
2226  return val;
2227  }
2228  else{
2229  return val;
2230  }
2231 #else
2232  return Qtrue;
2233 #endif
2234 }
2235 
2236 /*
2237  * Document-method: Curses::Window.attrset
2238  * call-seq: attrset(attrs)
2239  *
2240  * Sets the current attributes of the given window to +attrs+.
2241  *
2242  * The following video attributes, defined in <curses.h>, can
2243  * be passed to the routines Curses::Window.attron, Curses::Window.attroff,
2244  * and Curses::Window.attrset, or OR'd with the characters passed to addch.
2245  * A_NORMAL Normal display (no highlight)
2246  * A_STANDOUT Best highlighting mode of the terminal.
2247  * A_UNDERLINE Underlining
2248  * A_REVERSE Reverse video
2249  * A_BLINK Blinking
2250  * A_DIM Half bright
2251  * A_BOLD Extra bright or bold
2252  * A_PROTECT Protected mode
2253  * A_INVIS Invisible or blank mode
2254  * A_ALTCHARSET Alternate character set
2255  * A_CHARTEXT Bit-mask to extract a character
2256  * COLOR_PAIR(n) Color-pair number n
2257  *
2258  * TODO: provide some examples here.
2259  *
2260  * see also system manual curs_attr(3)
2261  */
2262 static VALUE
2264 {
2265 #ifdef HAVE_WATTRSET
2266  struct windata *winp;
2267 
2268  GetWINDOW(obj,winp);
2269  return INT2FIX(wattrset(winp->window,NUM2INT(attrs)));
2270 #else
2271  return Qtrue;
2272 #endif
2273 }
2274 
2275 /*
2276  * Document-method: Curses::Window.bkgdset
2277  * call-seq: bkgdset(ch)
2278  *
2279  * Manipulate the background of the current window
2280  * with character Integer +ch+
2281  *
2282  * see also Curses.bkgdset
2283  */
2284 static VALUE
2286 {
2287 #ifdef HAVE_WBKGDSET
2288  struct windata *winp;
2289 
2290  GetWINDOW(obj,winp);
2291  wbkgdset(winp->window, NUM2CH(ch));
2292 #endif
2293  return Qnil;
2294 }
2295 
2296 /*
2297  * Document-method: Curses::Window.bkgd
2298  * call-seq: bkgd(ch)
2299  *
2300  * Set the background of the current window
2301  * and apply character Integer +ch+ to every character.
2302  *
2303  * see also Curses.bkgd
2304  */
2305 static VALUE
2307 {
2308 #ifdef HAVE_WBKGD
2309  struct windata *winp;
2310 
2311  GetWINDOW(obj,winp);
2312  return (wbkgd(winp->window, NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
2313 #else
2314  return Qfalse;
2315 #endif
2316 }
2317 
2318 /*
2319  * Document-method: Curses::Window.getbkgd
2320  *
2321  * Returns an Interer (+ch+) for the character property in the current window.
2322  */
2323 static VALUE
2325 {
2326 #ifdef HAVE_WGETBKGD
2327  chtype c;
2328  struct windata *winp;
2329 
2330  GetWINDOW(obj,winp);
2331  return (c = getbkgd(winp->window) != ERR) ? CH2FIX(c) : Qnil;
2332 #else
2333  return Qnil;
2334 #endif
2335 }
2336 
2337 /*
2338  * Document-method: Curses::Window.resize
2339  * call-seq: resize(lines, cols)
2340  *
2341  * Resize the current window to Fixnum +lines+ and Fixnum +cols+
2342  *
2343  */
2344 static VALUE
2346 {
2347 #if defined(HAVE_WRESIZE)
2348  struct windata *winp;
2349 
2350  GetWINDOW(obj,winp);
2351  return wresize(winp->window, NUM2INT(lin), NUM2INT(col)) == OK ? Qtrue : Qfalse;
2352 #else
2353  return Qnil;
2354 #endif
2355 }
2356 
2357 
2358 #ifdef HAVE_KEYPAD
2359 /*
2360  * Document-method: Curses::Window.keypad=
2361  * call-seq:
2362  * keypad=(bool)
2363  *
2364  * See Curses::Window.keypad
2365  */
2366 
2367 /*
2368  * Document-method: Curses::Window.keypad
2369  * call-seq:
2370  * keypad(bool)
2371  *
2372  * Enables the keypad of the user's terminal.
2373  *
2374  * If enabled (+bool+ is +true+), the user can press a function key
2375  * (such as an arrow key) and wgetch returns a single value representing
2376  * the function key, as in KEY_LEFT. If disabled (+bool+ is +false+),
2377  * curses does not treat function keys specially and the program has to
2378  * interpret the escape sequences itself. If the keypad in the terminal
2379  * can be turned on (made to transmit) and off (made to work locally),
2380  * turning on this option causes the terminal keypad to be turned on when
2381  * Curses::Window.getch is called.
2382  *
2383  * The default value for keypad is false.
2384  *
2385  */
2386 static VALUE
2387 window_keypad(VALUE obj, VALUE val)
2388 {
2389  struct windata *winp;
2390 
2391  GetWINDOW(obj,winp);
2392  /* keypad() of NetBSD's libcurses returns no value */
2393 #if defined(__NetBSD__) && !defined(NCURSES_VERSION)
2394  keypad(winp->window,(RTEST(val) ? TRUE : FALSE));
2395  return Qnil;
2396 #else
2397  /* may have to raise exception on ERR */
2398  return (keypad(winp->window,RTEST(val) ? TRUE : FALSE)) == OK ?
2399  Qtrue : Qfalse;
2400 #endif
2401 }
2402 #else
2403 #define window_keypad rb_f_notimplement
2404 #endif
2405 
2406 #ifdef HAVE_NODELAY
2407 /*
2408  * Document-method: Curses::Window.nodelay
2409  * call-seq: nodelay(bool)
2410  *
2411  * Causes Curses::Window.getch to be a non-blocking call. If no input is ready, getch returns ERR.
2412  *
2413  * If disabled (+bool+ is +false+), Curses::Window.getch waits until a key is pressed.
2414  *
2415  */
2416 static VALUE
2417 window_nodelay(VALUE obj, VALUE val)
2418 {
2419  struct windata *winp;
2420  GetWINDOW(obj,winp);
2421 
2422  /* nodelay() of NetBSD's libcurses returns no value */
2423 #if defined(__NetBSD__) && !defined(NCURSES_VERSION)
2424  nodelay(winp->window, RTEST(val) ? TRUE : FALSE);
2425  return Qnil;
2426 #else
2427  return nodelay(winp->window,RTEST(val) ? TRUE : FALSE) == OK ? Qtrue : Qfalse;
2428 #endif
2429 }
2430 #else
2431 #define window_nodelay rb_f_notimplement
2432 #endif
2433 
2434 #ifdef HAVE_WTIMEOUT
2435 /*
2436  * Document-method: Curses::Window.timeout=
2437  * call-seq: timeout=(delay)
2438  *
2439  * Sets block and non-blocking reads for the window.
2440  * - If delay is negative, blocking read is used (i.e., waits indefinitely for input).
2441  * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting).
2442  * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input.
2443  *
2444  */
2445 static VALUE
2446 window_timeout(VALUE obj, VALUE delay)
2447 {
2448  struct windata *winp;
2449  GetWINDOW(obj,winp);
2450 
2451  wtimeout(winp->window,NUM2INT(delay));
2452  return Qnil;
2453 }
2454 #else
2455 #define window_timeout rb_f_notimplement
2456 #endif
2457 
2458 /*------------------------- Initialization -------------------------*/
2459 
2460 /*
2461  * Document-module: Curses
2462  *
2463  * == Description
2464  * An implementation of the CRT screen handling and optimization library.
2465  *
2466  * == Structures and such
2467  *
2468  * === Classes
2469  *
2470  * * Curses::Window - class with the means to draw a window or box
2471  * * Curses::MouseEvent - class for collecting mouse events
2472  *
2473  * === Modules
2474  *
2475  * Curses:: The curses implementation
2476  * Curses::Key:: Collection of constants for keypress events
2477  *
2478  * == Examples
2479  *
2480  * * hello.rb
2481  * :include: hello.rb
2482  *
2483  *
2484  * * rain.rb
2485  * :include: rain.rb
2486  *
2487  *
2488  */
2489 void
2491 {
2492  mCurses = rb_define_module("Curses");
2493 
2494  /*
2495  * Document-module: Curses::Key
2496  *
2497  *
2498  * a container for the KEY_* values.
2499  *
2500  * See also system manual for getch(3)
2501  *
2502  */
2504 
2506 
2507 #ifdef USE_MOUSE
2508  /*
2509  * Document-class: Curses::MouseEvent
2510  *
2511  * == Description
2512  *
2513  * Curses::MouseEvent
2514  *
2515  * == Example
2516  *
2517  * * mouse.rb
2518  * :include: mouse.rb
2519  *
2520  */
2521  cMouseEvent = rb_define_class_under(mCurses,"MouseEvent",rb_cObject);
2522  rb_undef_method(CLASS_OF(cMouseEvent),"new");
2523  rb_define_method(cMouseEvent, "eid", curs_mouse_id, 0);
2524  rb_define_method(cMouseEvent, "x", curs_mouse_x, 0);
2525  rb_define_method(cMouseEvent, "y", curs_mouse_y, 0);
2526  rb_define_method(cMouseEvent, "z", curs_mouse_z, 0);
2527  rb_define_method(cMouseEvent, "bstate", curs_mouse_bstate, 0);
2528 #endif /* USE_MOUSE */
2529 
2534 
2535  rb_define_module_function(mCurses, "use_default_colors", curses_use_default_colors, 0);
2582 #ifdef USE_COLOR
2583  rb_define_module_function(mCurses, "start_color", curses_start_color, 0);
2584  rb_define_module_function(mCurses, "init_pair", curses_init_pair, 3);
2585  rb_define_module_function(mCurses, "init_color", curses_init_color, 4);
2586  rb_define_module_function(mCurses, "has_colors?", curses_has_colors, 0);
2587  rb_define_module_function(mCurses, "can_change_color?",
2588  curses_can_change_color, 0);
2589  rb_define_module_function(mCurses, "colors", curses_colors, 0);
2590  rb_define_module_function(mCurses, "color_content", curses_color_content, 1);
2591  rb_define_module_function(mCurses, "color_pairs", curses_color_pairs, 0);
2592  rb_define_module_function(mCurses, "pair_content", curses_pair_content, 1);
2593  rb_define_module_function(mCurses, "color_pair", curses_color_pair, 1);
2594  rb_define_module_function(mCurses, "pair_number", curses_pair_number, 1);
2595 #endif /* USE_COLOR */
2596 #ifdef USE_MOUSE
2597  rb_define_module_function(mCurses, "getmouse", curses_getmouse, 0);
2598  rb_define_module_function(mCurses, "ungetmouse", curses_ungetmouse, 1);
2599  rb_define_module_function(mCurses, "mouseinterval", curses_mouseinterval, 1);
2600  rb_define_module_function(mCurses, "mousemask", curses_mousemask, 1);
2601 #endif /* USE_MOUSE */
2602 
2606 
2607  /*
2608  * Document-class: Curses::Window
2609  *
2610  * == Description
2611  *
2612  * The means by which to create and manage frames or windows.
2613  * While there may be more than one window at a time, only one window
2614  * will receive input.
2615  *
2616  * == Usage
2617  *
2618  * require 'curses'
2619  *
2620  * Curses.init_screen()
2621  *
2622  * my_str = "LOOK! PONIES!"
2623  * win = Curses::Window.new( 8, (my_str.length + 10),
2624  * (Curses.lines - 8) / 2,
2625  * (Curses.cols - (my_str.length + 10)) / 2 )
2626  * win.box("|", "-")
2627  * win.setpos(2,3)
2628  * win.addstr(my_str)
2629  * # or even
2630  * win << "\nORLY"
2631  * win << "\nYES!! " + my_str
2632  * win.refresh
2633  * win.getch
2634  * win.close
2635  *
2636  */
2639  rb_define_method(cWindow, "initialize", window_initialize, 4);
2640  rb_define_method(cWindow, "subwin", window_subwin, 4);
2641  rb_define_method(cWindow, "close", window_close, 0);
2642  rb_define_method(cWindow, "clear", window_clear, 0);
2643  rb_define_method(cWindow, "clrtoeol", window_clrtoeol, 0);
2644  rb_define_method(cWindow, "refresh", window_refresh, 0);
2645  rb_define_method(cWindow, "noutrefresh", window_noutrefresh, 0);
2646  rb_define_method(cWindow, "box", window_box, -1);
2647  rb_define_method(cWindow, "move", window_move, 2);
2648  rb_define_method(cWindow, "setpos", window_setpos, 2);
2649 #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
2650  rb_define_method(cWindow, "color_set", window_color_set, 1);
2651 #endif /* USE_COLOR && HAVE_WCOLOR_SET */
2652  rb_define_method(cWindow, "cury", window_cury, 0);
2653  rb_define_method(cWindow, "curx", window_curx, 0);
2654  rb_define_method(cWindow, "maxy", window_maxy, 0);
2655  rb_define_method(cWindow, "maxx", window_maxx, 0);
2656  rb_define_method(cWindow, "begy", window_begy, 0);
2657  rb_define_method(cWindow, "begx", window_begx, 0);
2658  rb_define_method(cWindow, "standout", window_standout, 0);
2659  rb_define_method(cWindow, "standend", window_standend, 0);
2660  rb_define_method(cWindow, "inch", window_inch, 0);
2661  rb_define_method(cWindow, "addch", window_addch, 1);
2662  rb_define_method(cWindow, "insch", window_insch, 1);
2663  rb_define_method(cWindow, "addstr", window_addstr, 1);
2665  rb_define_method(cWindow, "getch", window_getch, 0);
2666  rb_define_method(cWindow, "getstr", window_getstr, 0);
2667  rb_define_method(cWindow, "delch", window_delch, 0);
2668  rb_define_method(cWindow, "deleteln", window_deleteln, 0);
2669  rb_define_method(cWindow, "insertln", window_insertln, 0);
2670  rb_define_method(cWindow, "scroll", window_scroll, 0);
2671  rb_define_method(cWindow, "scrollok", window_scrollok, 1);
2672  rb_define_method(cWindow, "idlok", window_idlok, 1);
2673  rb_define_method(cWindow, "setscrreg", window_setscrreg, 2);
2674  rb_define_method(cWindow, "scrl", window_scrl, 1);
2675  rb_define_method(cWindow, "resize", window_resize, 2);
2676  rb_define_method(cWindow, "keypad", window_keypad, 1);
2677  rb_define_method(cWindow, "keypad=", window_keypad, 1);
2678 
2679  rb_define_method(cWindow, "attroff", window_attroff, 1);
2680  rb_define_method(cWindow, "attron", window_attron, 1);
2681  rb_define_method(cWindow, "attrset", window_attrset, 1);
2682  rb_define_method(cWindow, "bkgdset", window_bkgdset, 1);
2683  rb_define_method(cWindow, "bkgd", window_bkgd, 1);
2684  rb_define_method(cWindow, "getbkgd", window_getbkgd, 0);
2685 
2686  rb_define_method(cWindow, "nodelay=", window_nodelay, 1);
2687  rb_define_method(cWindow, "timeout=", window_timeout, 1);
2688 
2689 #define rb_curses_define_const(c) rb_define_const(mCurses,#c,UINT2NUM(c))
2690 
2691 #ifdef USE_COLOR
2692  /* Document-const: A_ATTRIBUTES
2693  *
2694  * Character attribute mask:
2695  * Bit-mask to extract attributes
2696  *
2697  * See Curses.inch or Curses::Window.inch
2698  */
2699  rb_curses_define_const(A_ATTRIBUTES);
2700 #ifdef A_NORMAL
2701  /* Document-const: A_NORMAL
2702  *
2703  * Attribute mask:
2704  * Normal display (no highlight)
2705  *
2706  * See Curses.attrset
2707  */
2708  rb_curses_define_const(A_NORMAL);
2709 #endif
2710  /* Document-const: A_STANDOUT
2711  *
2712  * Attribute mask:
2713  * Best highlighting mode of the terminal.
2714  *
2715  * See Curses.attrset
2716  */
2717  rb_curses_define_const(A_STANDOUT);
2718  /* Document-const: A_UNDERLINE
2719  *
2720  * Attribute mask:
2721  * Underlining
2722  *
2723  * See Curses.attrset
2724  */
2725  rb_curses_define_const(A_UNDERLINE);
2726  /* Document-const: A_REVERSE
2727  *
2728  * Attribute mask:
2729  * Reverse video
2730  *
2731  * See Curses.attrset
2732  */
2733  rb_curses_define_const(A_REVERSE);
2734  /* Document-const: A_BLINK
2735  *
2736  * Attribute mask:
2737  * Blinking
2738  *
2739  * See Curses.attrset
2740  */
2741  rb_curses_define_const(A_BLINK);
2742  /* Document-const: A_DIM
2743  *
2744  * Attribute mask:
2745  * Half bright
2746  *
2747  * See Curses.attrset
2748  */
2749  rb_curses_define_const(A_DIM);
2750  /* Document-const: A_BOLD
2751  *
2752  * Attribute mask:
2753  * Extra bright or bold
2754  *
2755  * See Curses.attrset
2756  */
2757  rb_curses_define_const(A_BOLD);
2758  /* Document-const: A_PROTECT
2759  *
2760  * Attribute mask:
2761  * Protected mode
2762  *
2763  * See Curses.attrset
2764  */
2765  rb_curses_define_const(A_PROTECT);
2766 #ifdef A_INVIS /* for NetBSD */
2767  /* Document-const: A_INVIS
2768  *
2769  * Attribute mask:
2770  * Invisible or blank mode
2771  *
2772  * See Curses.attrset
2773  */
2774  rb_curses_define_const(A_INVIS);
2775 #endif
2776  /* Document-const: A_ALTCHARSET
2777  *
2778  * Attribute mask:
2779  * Alternate character set
2780  *
2781  * See Curses.attrset
2782  */
2783  rb_curses_define_const(A_ALTCHARSET);
2784  /* Document-const: A_CHARTEXT
2785  *
2786  * Attribute mask:
2787  * Bit-mask to extract a character
2788  *
2789  * See Curses.attrset
2790  */
2791  rb_curses_define_const(A_CHARTEXT);
2792 #ifdef A_HORIZONTAL
2793  /* Document-const: A_HORIZONTAL
2794  *
2795  * Attribute mask:
2796  * horizontal highlight
2797  *
2798  * Check system curs_attr(3x) for support
2799  */
2800  rb_curses_define_const(A_HORIZONTAL);
2801 #endif
2802 #ifdef A_LEFT
2803  /* Document-const: A_LEFT
2804  *
2805  * Attribute mask:
2806  * left highlight
2807  *
2808  * Check system curs_attr(3x) for support
2809  */
2810  rb_curses_define_const(A_LEFT);
2811 #endif
2812 #ifdef A_LOW
2813  /* Document-const: A_LOW
2814  *
2815  * Attribute mask:
2816  * low highlight
2817  *
2818  * Check system curs_attr(3x) for support
2819  */
2820  rb_curses_define_const(A_LOW);
2821 #endif
2822 #ifdef A_RIGHT
2823  /* Document-const: A_RIGHT
2824  *
2825  * Attribute mask:
2826  * right highlight
2827  *
2828  * Check system curs_attr(3x) for support
2829  */
2830  rb_curses_define_const(A_RIGHT);
2831 #endif
2832 #ifdef A_TOP
2833  /* Document-const: A_TOP
2834  *
2835  * Attribute mask:
2836  * top highlight
2837  *
2838  * Check system curs_attr(3x) for support
2839  */
2840  rb_curses_define_const(A_TOP);
2841 #endif
2842 #ifdef A_VERTICAL
2843  /* Document-const: A_VERTICAL
2844  *
2845  * Attribute mask:
2846  * vertical highlight
2847  *
2848  * Check system curs_attr(3x) for support
2849  */
2850  rb_curses_define_const(A_VERTICAL);
2851 #endif
2852  /* Document-const: A_COLOR
2853  *
2854  * Character attribute mask:
2855  * Bit-mask to extract color-pair field information
2856  *
2857  * See Curses.inch or Curses::Window.inch
2858  */
2859  rb_curses_define_const(A_COLOR);
2860 
2861 #ifdef COLORS
2862  /*
2863  * Document-const: Curses::COLORS
2864  *
2865  * Number of the colors available
2866  */
2867  rb_curses_define_const(COLORS);
2868 #endif
2869  /*
2870  * Document-const: Curses::COLOR_BLACK
2871  *
2872  * Value of the color black
2873  */
2874  rb_curses_define_const(COLOR_BLACK);
2875  /*
2876  * Document-const: COLOR_RED
2877  *
2878  * Value of the color red
2879  */
2880  rb_curses_define_const(COLOR_RED);
2881  /*
2882  * Document-const: COLOR_GREEN
2883  *
2884  * Value of the color green
2885  */
2886  rb_curses_define_const(COLOR_GREEN);
2887  /*
2888  * Document-const: COLOR_YELLOW
2889  *
2890  * Value of the color yellow
2891  */
2892  rb_curses_define_const(COLOR_YELLOW);
2893  /*
2894  * Document-const: COLOR_BLUE
2895  *
2896  * Value of the color blue
2897  */
2898  rb_curses_define_const(COLOR_BLUE);
2899  /*
2900  * Document-const: COLOR_MAGENTA
2901  *
2902  * Value of the color magenta
2903  */
2904  rb_curses_define_const(COLOR_MAGENTA);
2905  /*
2906  * Document-const: COLOR_CYAN
2907  *
2908  * Value of the color cyan
2909  */
2910  rb_curses_define_const(COLOR_CYAN);
2911  /*
2912  * Document-const: COLOR_WHITE
2913  *
2914  * Value of the color white
2915  */
2916  rb_curses_define_const(COLOR_WHITE);
2917 #endif /* USE_COLOR */
2918 #ifdef USE_MOUSE
2919 #ifdef BUTTON1_PRESSED
2920  /* Document-const: BUTTON1_PRESSED
2921  *
2922  * Mouse event mask:
2923  * mouse button 1 down
2924  *
2925  * See Curses.getmouse
2926  */
2927  rb_curses_define_const(BUTTON1_PRESSED);
2928 #endif
2929 #ifdef BUTTON1_RELEASED
2930  /* Document-const: BUTTON1_RELEASED
2931  *
2932  * Mouse event mask:
2933  * mouse button 1 up
2934  *
2935  * See Curses.getmouse
2936  */
2937  rb_curses_define_const(BUTTON1_RELEASED);
2938 #endif
2939 #ifdef BUTTON1_CLICKED
2940  /* Document-const: BUTTON1_CLICKED
2941  *
2942  * Mouse event mask:
2943  * mouse button 1 clicked
2944  *
2945  * See Curses.getmouse
2946  */
2947  rb_curses_define_const(BUTTON1_CLICKED);
2948 #endif
2949 #ifdef BUTTON1_DOUBLE_CLICKED
2950  /* Document-const: BUTTON1_DOUBLE_CLICKED
2951  *
2952  * Mouse event mask:
2953  * mouse button 1 double clicked
2954  *
2955  * See Curses.getmouse
2956  */
2957  rb_curses_define_const(BUTTON1_DOUBLE_CLICKED);
2958 #endif
2959 #ifdef BUTTON1_TRIPLE_CLICKED
2960  /* Document-const: BUTTON1_TRIPLE_CLICKED
2961  *
2962  * Mouse event mask:
2963  * mouse button 1 triple clicked
2964  *
2965  * See Curses.getmouse
2966  */
2967  rb_curses_define_const(BUTTON1_TRIPLE_CLICKED);
2968 #endif
2969 #ifdef BUTTON2_PRESSED
2970  /* Document-const: BUTTON2_PRESSED
2971  *
2972  * Mouse event mask:
2973  * mouse button 2 down
2974  *
2975  * See Curses.getmouse
2976  */
2977  rb_curses_define_const(BUTTON2_PRESSED);
2978 #endif
2979 #ifdef BUTTON2_RELEASED
2980  /* Document-const: BUTTON2_RELEASED
2981  *
2982  * Mouse event mask:
2983  * mouse button 2 up
2984  *
2985  * See Curses.getmouse
2986  */
2987  rb_curses_define_const(BUTTON2_RELEASED);
2988 #endif
2989 #ifdef BUTTON2_CLICKED
2990  /* Document-const: BUTTON2_CLICKED
2991  *
2992  * Mouse event mask:
2993  * mouse button 2 clicked
2994  *
2995  * See Curses.getmouse
2996  */
2997  rb_curses_define_const(BUTTON2_CLICKED);
2998 #endif
2999 #ifdef BUTTON2_DOUBLE_CLICKED
3000  /* Document-const: BUTTON2_DOUBLE_CLICKED
3001  *
3002  * Mouse event mask:
3003  * mouse button 2 double clicked
3004  *
3005  * See Curses.getmouse
3006  */
3007  rb_curses_define_const(BUTTON2_DOUBLE_CLICKED);
3008 #endif
3009 #ifdef BUTTON2_TRIPLE_CLICKED
3010  /* Document-const: BUTTON2_TRIPLE_CLICKED
3011  *
3012  * Mouse event mask:
3013  * mouse button 2 triple clicked
3014  *
3015  * See Curses.getmouse
3016  */
3017  rb_curses_define_const(BUTTON2_TRIPLE_CLICKED);
3018 #endif
3019 #ifdef BUTTON3_PRESSED
3020  /* Document-const: BUTTON3_PRESSED
3021  *
3022  * Mouse event mask:
3023  * mouse button 3 down
3024  *
3025  * See Curses.getmouse
3026  */
3027  rb_curses_define_const(BUTTON3_PRESSED);
3028 #endif
3029 #ifdef BUTTON3_RELEASED
3030  /* Document-const: BUTTON3_RELEASED
3031  *
3032  * Mouse event mask:
3033  * mouse button 3 up
3034  *
3035  * See Curses.getmouse
3036  */
3037  rb_curses_define_const(BUTTON3_RELEASED);
3038 #endif
3039 #ifdef BUTTON3_CLICKED
3040  /* Document-const: BUTTON3_CLICKED
3041  *
3042  * Mouse event mask:
3043  * mouse button 3 clicked
3044  *
3045  * See Curses.getmouse
3046  */
3047  rb_curses_define_const(BUTTON3_CLICKED);
3048 #endif
3049 #ifdef BUTTON3_DOUBLE_CLICKED
3050  /* Document-const: BUTTON3_DOUBLE_CLICKED
3051  *
3052  * Mouse event mask:
3053  * mouse button 3 double clicked
3054  *
3055  * See Curses.getmouse
3056  */
3057  rb_curses_define_const(BUTTON3_DOUBLE_CLICKED);
3058 #endif
3059 #ifdef BUTTON3_TRIPLE_CLICKED
3060  /* Document-const: BUTTON3_TRIPLE_CLICKED
3061  *
3062  * Mouse event mask:
3063  * mouse button 3 triple clicked
3064  *
3065  * See Curses.getmouse
3066  */
3067  rb_curses_define_const(BUTTON3_TRIPLE_CLICKED);
3068 #endif
3069 #ifdef BUTTON4_PRESSED
3070  /* Document-const: BUTTON4_PRESSED
3071  *
3072  * Mouse event mask:
3073  * mouse button 4 down
3074  *
3075  * See Curses.getmouse
3076  */
3077  rb_curses_define_const(BUTTON4_PRESSED);
3078 #endif
3079 #ifdef BUTTON4_RELEASED
3080  /* Document-const: BUTTON4_RELEASED
3081  *
3082  * Mouse event mask:
3083  * mouse button 4 up
3084  *
3085  * See Curses.getmouse
3086  */
3087  rb_curses_define_const(BUTTON4_RELEASED);
3088 #endif
3089 #ifdef BUTTON4_CLICKED
3090  /* Document-const: BUTTON4_CLICKED
3091  *
3092  * Mouse event mask:
3093  * mouse button 4 clicked
3094  *
3095  * See Curses.getmouse
3096  */
3097  rb_curses_define_const(BUTTON4_CLICKED);
3098 #endif
3099 #ifdef BUTTON4_DOUBLE_CLICKED
3100  /* Document-const: BUTTON4_DOUBLE_CLICKED
3101  *
3102  * Mouse event mask:
3103  * mouse button 4 double clicked
3104  *
3105  * See Curses.getmouse
3106  */
3107  rb_curses_define_const(BUTTON4_DOUBLE_CLICKED);
3108 #endif
3109 #ifdef BUTTON4_TRIPLE_CLICKED
3110  /* Document-const: BUTTON4_TRIPLE_CLICKED
3111  *
3112  * Mouse event mask:
3113  * mouse button 4 triple clicked
3114  *
3115  * See Curses.getmouse
3116  */
3117  rb_curses_define_const(BUTTON4_TRIPLE_CLICKED);
3118 #endif
3119 #ifdef BUTTON_SHIFT
3120  /* Document-const: BUTTON_SHIFT
3121  *
3122  * Mouse event mask:
3123  * shift was down during button state change
3124  *
3125  * See Curses.getmouse
3126  */
3127  rb_curses_define_const(BUTTON_SHIFT);
3128 #endif
3129 #ifdef BUTTON_CTRL
3130  /* Document-const: BUTTON_CTRL
3131  *
3132  * Mouse event mask:
3133  * control was down during button state change
3134  *
3135  * See Curses.getmouse
3136  */
3137  rb_curses_define_const(BUTTON_CTRL);
3138 #endif
3139 #ifdef BUTTON_ALT
3140  /* Document-const: BUTTON_ALT
3141  *
3142  * Mouse event mask:
3143  * alt was down during button state change
3144  *
3145  * See Curses.getmouse
3146  */
3147  rb_curses_define_const(BUTTON_ALT);
3148 #endif
3149 #ifdef ALL_MOUSE_EVENTS
3150  /* Document-const: ALL_MOUSE_EVENTS
3151  *
3152  * Mouse event mask:
3153  * report all button state changes
3154  *
3155  * See Curses.getmouse
3156  */
3157  rb_curses_define_const(ALL_MOUSE_EVENTS);
3158 #endif
3159 #ifdef REPORT_MOUSE_POSITION
3160  /* Document-const: REPORT_MOUSE_POSITION
3161  *
3162  * Mouse event mask:
3163  * report mouse movement
3164  *
3165  * See Curses.getmouse
3166  */
3167  rb_curses_define_const(REPORT_MOUSE_POSITION);
3168 #endif
3169 #endif /* USE_MOUSE */
3170 
3171 #if defined(KEY_MOUSE) && defined(USE_MOUSE)
3172  /* Document-const: KEY_MOUSE
3173  * Mouse event read
3174  */
3175  /* Document-const: MOUSE
3176  * Mouse event read
3177  */
3178  rb_curses_define_const(KEY_MOUSE);
3179  rb_define_const(mKey, "MOUSE", INT2NUM(KEY_MOUSE));
3180 #endif
3181 #ifdef KEY_MIN
3182  /* Document-const: KEY_MIN
3183  * The minimum allowed curses key value.
3184  */
3185  /* Document-const: MIN
3186  * The minimum allowed curses key value.
3187  */
3188  rb_curses_define_const(KEY_MIN);
3189  rb_define_const(mKey, "MIN", INT2NUM(KEY_MIN));
3190 #endif
3191 #ifdef KEY_BREAK
3192  /* Document-const: KEY_BREAK
3193  * Break key
3194  */
3195  /* Document-const: BREAK
3196  * Break key
3197  */
3198  rb_curses_define_const(KEY_BREAK);
3199  rb_define_const(mKey, "BREAK", INT2NUM(KEY_BREAK));
3200 #endif
3201 #ifdef KEY_DOWN
3202  /* Document-const: KEY_DOWN
3203  * the down arrow key
3204  */
3205  /* Document-const: DOWN
3206  * the down arrow key
3207  */
3208  rb_curses_define_const(KEY_DOWN);
3209  rb_define_const(mKey, "DOWN", INT2NUM(KEY_DOWN));
3210 #endif
3211 #ifdef KEY_UP
3212  /* Document-const: KEY_UP
3213  * the up arrow key
3214  */
3215  /* Document-const: UP
3216  * the up arrow key
3217  */
3218  rb_curses_define_const(KEY_UP);
3219  rb_define_const(mKey, "UP", INT2NUM(KEY_UP));
3220 #endif
3221 #ifdef KEY_LEFT
3222  /* Document-const: KEY_LEFT
3223  * the left arrow key
3224  */
3225  /* Document-const: LEFT
3226  * the left arrow key
3227  */
3228  rb_curses_define_const(KEY_LEFT);
3229  rb_define_const(mKey, "LEFT", INT2NUM(KEY_LEFT));
3230 #endif
3231 #ifdef KEY_RIGHT
3232  /* Document-const: KEY_RIGHT
3233  * the right arrow key
3234  */
3235  /* Document-const: RIGHT
3236  * the right arrow key
3237  */
3238  rb_curses_define_const(KEY_RIGHT);
3239  rb_define_const(mKey, "RIGHT", INT2NUM(KEY_RIGHT));
3240 #endif
3241 #ifdef KEY_HOME
3242  /* Document-const: KEY_HOME
3243  * Home key (upward+left arrow)
3244  */
3245  /* Document-const: HOME
3246  * Home key (upward+left arrow)
3247  */
3248  rb_curses_define_const(KEY_HOME);
3249  rb_define_const(mKey, "HOME", INT2NUM(KEY_HOME));
3250 #endif
3251 #ifdef KEY_BACKSPACE
3252  /* Document-const: KEY_BACKSPACE
3253  * Backspace
3254  */
3255  /* Document-const: BACKSPACE
3256  * Backspace
3257  */
3258  rb_curses_define_const(KEY_BACKSPACE);
3259  rb_define_const(mKey, "BACKSPACE", INT2NUM(KEY_BACKSPACE));
3260 #endif
3261 #ifdef KEY_F
3262  /* KEY_F(n) : 0 <= n <= 63 */
3263  {
3264  int i;
3265  char c[8];
3266  for (i=0; i<64; i++) {
3267  sprintf(c, "KEY_F%d", i);
3268  rb_define_const(mCurses, c, INT2NUM(KEY_F(i)));
3269  sprintf(c, "F%d", i);
3270  rb_define_const(mKey, c, INT2NUM(KEY_F(i)));
3271  }
3272  }
3273 #endif
3274 #ifdef KEY_DL
3275  /* Document-const: KEY_DL
3276  * Delete line
3277  */
3278  /* Document-const: DL
3279  * Delete line
3280  */
3281  rb_curses_define_const(KEY_DL);
3282  rb_define_const(mKey, "DL", INT2NUM(KEY_DL));
3283 #endif
3284 #ifdef KEY_IL
3285  /* Document-const: KEY_IL
3286  * Insert line
3287  */
3288  /* Document-const: IL
3289  * Insert line
3290  */
3291  rb_curses_define_const(KEY_IL);
3292  rb_define_const(mKey, "IL", INT2NUM(KEY_IL));
3293 #endif
3294 #ifdef KEY_DC
3295  /* Document-const: KEY_DC
3296  * Delete character
3297  */
3298  /* Document-const: DC
3299  * Delete character
3300  */
3301  rb_curses_define_const(KEY_DC);
3302  rb_define_const(mKey, "DC", INT2NUM(KEY_DC));
3303 #endif
3304 #ifdef KEY_IC
3305  /* Document-const: KEY_IC
3306  * Insert char or enter insert mode
3307  */
3308  /* Document-const: IC
3309  * Insert char or enter insert mode
3310  */
3311  rb_curses_define_const(KEY_IC);
3312  rb_define_const(mKey, "IC", INT2NUM(KEY_IC));
3313 #endif
3314 #ifdef KEY_EIC
3315  /* Document-const: KEY_EIC
3316  * Enter insert char mode
3317  */
3318  /* Document-const: EIC
3319  * Enter insert char mode
3320  */
3321  rb_curses_define_const(KEY_EIC);
3322  rb_define_const(mKey, "EIC", INT2NUM(KEY_EIC));
3323 #endif
3324 #ifdef KEY_CLEAR
3325  /* Document-const: KEY_CLEAR
3326  * Clear Screen
3327  */
3328  /* Document-const: CLEAR
3329  * Clear Screen
3330  */
3331  rb_curses_define_const(KEY_CLEAR);
3332  rb_define_const(mKey, "CLEAR", INT2NUM(KEY_CLEAR));
3333 #endif
3334 #ifdef KEY_EOS
3335  /* Document-const: KEY_EOS
3336  * Clear to end of screen
3337  */
3338  /* Document-const: EOS
3339  * Clear to end of screen
3340  */
3341  rb_curses_define_const(KEY_EOS);
3342  rb_define_const(mKey, "EOS", INT2NUM(KEY_EOS));
3343 #endif
3344 #ifdef KEY_EOL
3345  /* Document-const: KEY_EOL
3346  * Clear to end of line
3347  */
3348  /* Document-const: EOL
3349  * Clear to end of line
3350  */
3351  rb_curses_define_const(KEY_EOL);
3352  rb_define_const(mKey, "EOL", INT2NUM(KEY_EOL));
3353 #endif
3354 #ifdef KEY_SF
3355  /* Document-const: KEY_SF
3356  * Scroll 1 line forward
3357  */
3358  /* Document-const: SF
3359  * Scroll 1 line forward
3360  */
3361  rb_curses_define_const(KEY_SF);
3362  rb_define_const(mKey, "SF", INT2NUM(KEY_SF));
3363 #endif
3364 #ifdef KEY_SR
3365  /* Document-const: KEY_SR
3366  * Scroll 1 line backware (reverse)
3367  */
3368  /* Document-const: SR
3369  * Scroll 1 line backware (reverse)
3370  */
3371  rb_curses_define_const(KEY_SR);
3372  rb_define_const(mKey, "SR", INT2NUM(KEY_SR));
3373 #endif
3374 #ifdef KEY_NPAGE
3375  /* Document-const: KEY_NPAGE
3376  * Next page
3377  */
3378  /* Document-const: NPAGE
3379  * Next page
3380  */
3381  rb_curses_define_const(KEY_NPAGE);
3382  rb_define_const(mKey, "NPAGE", INT2NUM(KEY_NPAGE));
3383 #endif
3384 #ifdef KEY_PPAGE
3385  /* Document-const: KEY_PPAGE
3386  * Previous page
3387  */
3388  /* Document-const: PPAGE
3389  * Previous page
3390  */
3391  rb_curses_define_const(KEY_PPAGE);
3392  rb_define_const(mKey, "PPAGE", INT2NUM(KEY_PPAGE));
3393 #endif
3394 #ifdef KEY_STAB
3395  /* Document-const: KEY_STAB
3396  * Set tab
3397  */
3398  /* Document-const: STAB
3399  * Set tab
3400  */
3401  rb_curses_define_const(KEY_STAB);
3402  rb_define_const(mKey, "STAB", INT2NUM(KEY_STAB));
3403 #endif
3404 #ifdef KEY_CTAB
3405  /* Document-const: KEY_CTAB
3406  * Clear tab
3407  */
3408  /* Document-const: CTAB
3409  * Clear tab
3410  */
3411  rb_curses_define_const(KEY_CTAB);
3412  rb_define_const(mKey, "CTAB", INT2NUM(KEY_CTAB));
3413 #endif
3414 #ifdef KEY_CATAB
3415  /* Document-const: KEY_CATAB
3416  * Clear all tabs
3417  */
3418  /* Document-const: CATAB
3419  * Clear all tabs
3420  */
3421  rb_curses_define_const(KEY_CATAB);
3422  rb_define_const(mKey, "CATAB", INT2NUM(KEY_CATAB));
3423 #endif
3424 #ifdef KEY_ENTER
3425  /* Document-const: KEY_ENTER
3426  * Enter or send
3427  */
3428  /* Document-const: ENTER
3429  * Enter or send
3430  */
3431  rb_curses_define_const(KEY_ENTER);
3432  rb_define_const(mKey, "ENTER", INT2NUM(KEY_ENTER));
3433 #endif
3434 #ifdef KEY_SRESET
3435  /* Document-const: KEY_SRESET
3436  * Soft (partial) reset
3437  */
3438  /* Document-const: SRESET
3439  * Soft (partial) reset
3440  */
3441  rb_curses_define_const(KEY_SRESET);
3442  rb_define_const(mKey, "SRESET", INT2NUM(KEY_SRESET));
3443 #endif
3444 #ifdef KEY_RESET
3445  /* Document-const: KEY_RESET
3446  * Reset or hard reset
3447  */
3448  /* Document-const: RESET
3449  * Reset or hard reset
3450  */
3451  rb_curses_define_const(KEY_RESET);
3452  rb_define_const(mKey, "RESET", INT2NUM(KEY_RESET));
3453 #endif
3454 #ifdef KEY_PRINT
3455  /* Document-const: KEY_PRINT
3456  * Print or copy
3457  */
3458  /* Document-const: PRINT
3459  * Print or copy
3460  */
3461  rb_curses_define_const(KEY_PRINT);
3462  rb_define_const(mKey, "PRINT", INT2NUM(KEY_PRINT));
3463 #endif
3464 #ifdef KEY_LL
3465  /* Document-const: KEY_LL
3466  * Home down or bottom (lower left)
3467  */
3468  /* Document-const: LL
3469  * Home down or bottom (lower left)
3470  */
3471  rb_curses_define_const(KEY_LL);
3472  rb_define_const(mKey, "LL", INT2NUM(KEY_LL));
3473 #endif
3474 #ifdef KEY_A1
3475  /* Document-const: KEY_A1
3476  * Upper left of keypad
3477  */
3478  /* Document-const: A1
3479  * Upper left of keypad
3480  */
3481  rb_curses_define_const(KEY_A1);
3482  rb_define_const(mKey, "A1", INT2NUM(KEY_A1));
3483 #endif
3484 #ifdef KEY_A3
3485  /* Document-const: KEY_A3
3486  * Upper right of keypad
3487  */
3488  /* Document-const: A3
3489  * Upper right of keypad
3490  */
3491  rb_curses_define_const(KEY_A3);
3492  rb_define_const(mKey, "A3", INT2NUM(KEY_A3));
3493 #endif
3494 #ifdef KEY_B2
3495  /* Document-const: KEY_B2
3496  * Center of keypad
3497  */
3498  /* Document-const: B2
3499  * Center of keypad
3500  */
3501  rb_curses_define_const(KEY_B2);
3502  rb_define_const(mKey, "B2", INT2NUM(KEY_B2));
3503 #endif
3504 #ifdef KEY_C1
3505  /* Document-const: KEY_C1
3506  * Lower left of keypad
3507  */
3508  /* Document-const: C1
3509  * Lower left of keypad
3510  */
3511  rb_curses_define_const(KEY_C1);
3512  rb_define_const(mKey, "C1", INT2NUM(KEY_C1));
3513 #endif
3514 #ifdef KEY_C3
3515  /* Document-const: KEY_C3
3516  * Lower right of keypad
3517  */
3518  /* Document-const: C3
3519  * Lower right of keypad
3520  */
3521  rb_curses_define_const(KEY_C3);
3522  rb_define_const(mKey, "C3", INT2NUM(KEY_C3));
3523 #endif
3524 #ifdef KEY_BTAB
3525  /* Document-const: BTAB
3526  * Back tab key
3527  */
3528  /* Document-const: KEY_BTAB
3529  * Back tab key
3530  */
3531  rb_curses_define_const(KEY_BTAB);
3532  rb_define_const(mKey, "BTAB", INT2NUM(KEY_BTAB));
3533 #endif
3534 #ifdef KEY_BEG
3535  /* Document-const: KEY_BEG
3536  * Beginning key
3537  */
3538  /* Document-const: BEG
3539  * Beginning key
3540  */
3541  rb_curses_define_const(KEY_BEG);
3542  rb_define_const(mKey, "BEG", INT2NUM(KEY_BEG));
3543 #endif
3544 #ifdef KEY_CANCEL
3545  /* Document-const: KEY_CANCEL
3546  * Cancel key
3547  */
3548  /* Document-const: CANCEL
3549  * Cancel key
3550  */
3551  rb_curses_define_const(KEY_CANCEL);
3552  rb_define_const(mKey, "CANCEL", INT2NUM(KEY_CANCEL));
3553 #endif
3554 #ifdef KEY_CLOSE
3555  /* Document-const: KEY_CLOSE
3556  * Close key
3557  */
3558  /* Document-const: CLOSE
3559  * Close key
3560  */
3561  rb_curses_define_const(KEY_CLOSE);
3562  rb_define_const(mKey, "CLOSE", INT2NUM(KEY_CLOSE));
3563 #endif
3564 #ifdef KEY_COMMAND
3565  /* Document-const: KEY_COMMAND
3566  * Cmd (command) key
3567  */
3568  /* Document-const: COMMAND
3569  * Cmd (command) key
3570  */
3571  rb_curses_define_const(KEY_COMMAND);
3572  rb_define_const(mKey, "COMMAND", INT2NUM(KEY_COMMAND));
3573 #endif
3574 #ifdef KEY_COPY
3575  /* Document-const: KEY_COPY
3576  * Copy key
3577  */
3578  /* Document-const: COPY
3579  * Copy key
3580  */
3581  rb_curses_define_const(KEY_COPY);
3582  rb_define_const(mKey, "COPY", INT2NUM(KEY_COPY));
3583 #endif
3584 #ifdef KEY_CREATE
3585  /* Document-const: KEY_CREATE
3586  * Create key
3587  */
3588  /* Document-const: CREATE
3589  * Create key
3590  */
3591  rb_curses_define_const(KEY_CREATE);
3592  rb_define_const(mKey, "CREATE", INT2NUM(KEY_CREATE));
3593 #endif
3594 #ifdef KEY_END
3595  /* Document-const: KEY_END
3596  * End key
3597  */
3598  /* Document-const: END
3599  * End key
3600  */
3601  rb_curses_define_const(KEY_END);
3602  rb_define_const(mKey, "END", INT2NUM(KEY_END));
3603 #endif
3604 #ifdef KEY_EXIT
3605  /* Document-const: KEY_EXIT
3606  * Exit key
3607  */
3608  /* Document-const: EXIT
3609  * Exit key
3610  */
3611  rb_curses_define_const(KEY_EXIT);
3612  rb_define_const(mKey, "EXIT", INT2NUM(KEY_EXIT));
3613 #endif
3614 #ifdef KEY_FIND
3615  /* Document-const: KEY_FIND
3616  * Find key
3617  */
3618  /* Document-const: FIND
3619  * Find key
3620  */
3621  rb_curses_define_const(KEY_FIND);
3622  rb_define_const(mKey, "FIND", INT2NUM(KEY_FIND));
3623 #endif
3624 #ifdef KEY_HELP
3625  /* Document-const: KEY_HELP
3626  * Help key
3627  */
3628  /* Document-const: HELP
3629  * Help key
3630  */
3631  rb_curses_define_const(KEY_HELP);
3632  rb_define_const(mKey, "HELP", INT2NUM(KEY_HELP));
3633 #endif
3634 #ifdef KEY_MARK
3635  /* Document-const: KEY_MARK
3636  * Mark key
3637  */
3638  /* Document-const: MARK
3639  * Mark key
3640  */
3641  rb_curses_define_const(KEY_MARK);
3642  rb_define_const(mKey, "MARK", INT2NUM(KEY_MARK));
3643 #endif
3644 #ifdef KEY_MESSAGE
3645  /* Document-const: KEY_MESSAGE
3646  * Message key
3647  */
3648  /* Document-const: MESSAGE
3649  * Message key
3650  */
3651  rb_curses_define_const(KEY_MESSAGE);
3652  rb_define_const(mKey, "MESSAGE", INT2NUM(KEY_MESSAGE));
3653 #endif
3654 #ifdef KEY_MOVE
3655  /* Document-const: KEY_MOVE
3656  * Move key
3657  */
3658  /* Document-const: MOVE
3659  * Move key
3660  */
3661  rb_curses_define_const(KEY_MOVE);
3662  rb_define_const(mKey, "MOVE", INT2NUM(KEY_MOVE));
3663 #endif
3664 #ifdef KEY_NEXT
3665  /* Document-const: KEY_NEXT
3666  * Next object key
3667  */
3668  /* Document-const: NEXT
3669  * Next object key
3670  */
3671  rb_curses_define_const(KEY_NEXT);
3672  rb_define_const(mKey, "NEXT", INT2NUM(KEY_NEXT));
3673 #endif
3674 #ifdef KEY_OPEN
3675  /* Document-const: KEY_OPEN
3676  * Open key
3677  */
3678  /* Document-const: OPEN
3679  * Open key
3680  */
3681  rb_curses_define_const(KEY_OPEN);
3682  rb_define_const(mKey, "OPEN", INT2NUM(KEY_OPEN));
3683 #endif
3684 #ifdef KEY_OPTIONS
3685  /* Document-const: KEY_OPTIONS
3686  * Options key
3687  */
3688  /* Document-const: OPTIONS
3689  * Options key
3690  */
3691  rb_curses_define_const(KEY_OPTIONS);
3692  rb_define_const(mKey, "OPTIONS", INT2NUM(KEY_OPTIONS));
3693 #endif
3694 #ifdef KEY_PREVIOUS
3695  /* Document-const: KEY_PREVIOUS
3696  * Previous object key
3697  */
3698  /* Document-const: PREVIOUS
3699  * Previous object key
3700  */
3701  rb_curses_define_const(KEY_PREVIOUS);
3702  rb_define_const(mKey, "PREVIOUS", INT2NUM(KEY_PREVIOUS));
3703 #endif
3704 #ifdef KEY_REDO
3705  /* Document-const: KEY_REDO
3706  * Redo key
3707  */
3708  /* Document-const: REDO
3709  * Redo key
3710  */
3711  rb_curses_define_const(KEY_REDO);
3712  rb_define_const(mKey, "REDO", INT2NUM(KEY_REDO));
3713 #endif
3714 #ifdef KEY_REFERENCE
3715  /* Document-const: KEY_REFERENCE
3716  * Reference key
3717  */
3718  /* Document-const: REFERENCE
3719  * Reference key
3720  */
3721  rb_curses_define_const(KEY_REFERENCE);
3722  rb_define_const(mKey, "REFERENCE", INT2NUM(KEY_REFERENCE));
3723 #endif
3724 #ifdef KEY_REFRESH
3725  /* Document-const: KEY_REFRESH
3726  * Refresh key
3727  */
3728  /* Document-const: REFRESH
3729  * Refresh key
3730  */
3731  rb_curses_define_const(KEY_REFRESH);
3732  rb_define_const(mKey, "REFRESH", INT2NUM(KEY_REFRESH));
3733 #endif
3734 #ifdef KEY_REPLACE
3735  /* Document-const: KEY_REPLACE
3736  * Replace key
3737  */
3738  /* Document-const: REPLACE
3739  * Replace key
3740  */
3741  rb_curses_define_const(KEY_REPLACE);
3742  rb_define_const(mKey, "REPLACE", INT2NUM(KEY_REPLACE));
3743 #endif
3744 #ifdef KEY_RESTART
3745  /* Document-const: KEY_RESTART
3746  * Restart key
3747  */
3748  /* Document-const: RESTART
3749  * Restart key
3750  */
3751  rb_curses_define_const(KEY_RESTART);
3752  rb_define_const(mKey, "RESTART", INT2NUM(KEY_RESTART));
3753 #endif
3754 #ifdef KEY_RESUME
3755  /* Document-const: KEY_RESUME
3756  * Resume key
3757  */
3758  /* Document-const: RESUME
3759  * Resume key
3760  */
3761  rb_curses_define_const(KEY_RESUME);
3762  rb_define_const(mKey, "RESUME", INT2NUM(KEY_RESUME));
3763 #endif
3764 #ifdef KEY_SAVE
3765  /* Document-const: KEY_SAVE
3766  * Save key
3767  */
3768  /* Document-const: SAVE
3769  * Save key
3770  */
3771  rb_curses_define_const(KEY_SAVE);
3772  rb_define_const(mKey, "SAVE", INT2NUM(KEY_SAVE));
3773 #endif
3774 #ifdef KEY_SBEG
3775  /* Document-const: KEY_SBEG
3776  * Shifted beginning key
3777  */
3778  /* Document-const: SBEG
3779  * Shifted beginning key
3780  */
3781  rb_curses_define_const(KEY_SBEG);
3782  rb_define_const(mKey, "SBEG", INT2NUM(KEY_SBEG));
3783 #endif
3784 #ifdef KEY_SCANCEL
3785  /* Document-const: KEY_SCANCEL
3786  * Shifted cancel key
3787  */
3788  /* Document-const: SCANCEL
3789  * Shifted cancel key
3790  */
3791  rb_curses_define_const(KEY_SCANCEL);
3792  rb_define_const(mKey, "SCANCEL", INT2NUM(KEY_SCANCEL));
3793 #endif
3794 #ifdef KEY_SCOMMAND
3795  /* Document-const: KEY_SCOMMAND
3796  * Shifted command key
3797  */
3798  /* Document-const: SCOMMAND
3799  * Shifted command key
3800  */
3801  rb_curses_define_const(KEY_SCOMMAND);
3802  rb_define_const(mKey, "SCOMMAND", INT2NUM(KEY_SCOMMAND));
3803 #endif
3804 #ifdef KEY_SCOPY
3805  /* Document-const: KEY_SCOPY
3806  * Shifted copy key
3807  */
3808  /* Document-const: SCOPY
3809  * Shifted copy key
3810  */
3811  rb_curses_define_const(KEY_SCOPY);
3812  rb_define_const(mKey, "SCOPY", INT2NUM(KEY_SCOPY));
3813 #endif
3814 #ifdef KEY_SCREATE
3815  /* Document-const: KEY_SCREATE
3816  * Shifted create key
3817  */
3818  /* Document-const: SCREATE
3819  * Shifted create key
3820  */
3821  rb_curses_define_const(KEY_SCREATE);
3822  rb_define_const(mKey, "SCREATE", INT2NUM(KEY_SCREATE));
3823 #endif
3824 #ifdef KEY_SDC
3825  /* Document-const: KEY_SDC
3826  * Shifted delete char key
3827  */
3828  /* Document-const: SDC
3829  * Shifted delete char key
3830  */
3831  rb_curses_define_const(KEY_SDC);
3832  rb_define_const(mKey, "SDC", INT2NUM(KEY_SDC));
3833 #endif
3834 #ifdef KEY_SDL
3835  /* Document-const: KEY_SDL
3836  * Shifted delete line key
3837  */
3838  /* Document-const: SDL
3839  * Shifted delete line key
3840  */
3841  rb_curses_define_const(KEY_SDL);
3842  rb_define_const(mKey, "SDL", INT2NUM(KEY_SDL));
3843 #endif
3844 #ifdef KEY_SELECT
3845  /* Document-const: KEY_SELECT
3846  * Select key
3847  */
3848  /* Document-const: SELECT
3849  * Select key
3850  */
3851  rb_curses_define_const(KEY_SELECT);
3852  rb_define_const(mKey, "SELECT", INT2NUM(KEY_SELECT));
3853 #endif
3854 #ifdef KEY_SEND
3855  /* Document-const: KEY_SEND
3856  * Shifted end key
3857  */
3858  /* Document-const: SEND
3859  * Shifted end key
3860  */
3861  rb_curses_define_const(KEY_SEND);
3862  rb_define_const(mKey, "SEND", INT2NUM(KEY_SEND));
3863 #endif
3864 #ifdef KEY_SEOL
3865  /* Document-const: KEY_SEOL
3866  * Shifted clear line key
3867  */
3868  /* Document-const: SEOL
3869  * Shifted clear line key
3870  */
3871  rb_curses_define_const(KEY_SEOL);
3872  rb_define_const(mKey, "SEOL", INT2NUM(KEY_SEOL));
3873 #endif
3874 #ifdef KEY_SEXIT
3875  /* Document-const: KEY_SEXIT
3876  * Shifted exit key
3877  */
3878  /* Document-const: SEXIT
3879  * Shifted exit key
3880  */
3881  rb_curses_define_const(KEY_SEXIT);
3882  rb_define_const(mKey, "SEXIT", INT2NUM(KEY_SEXIT));
3883 #endif
3884 #ifdef KEY_SFIND
3885  /* Document-const: KEY_SFIND
3886  * Shifted find key
3887  */
3888  /* Document-const: SFIND
3889  * Shifted find key
3890  */
3891  rb_curses_define_const(KEY_SFIND);
3892  rb_define_const(mKey, "SFIND", INT2NUM(KEY_SFIND));
3893 #endif
3894 #ifdef KEY_SHELP
3895  /* Document-const: KEY_SHELP
3896  * Shifted help key
3897  */
3898  /* Document-const: SHELP
3899  * Shifted help key
3900  */
3901  rb_curses_define_const(KEY_SHELP);
3902  rb_define_const(mKey, "SHELP", INT2NUM(KEY_SHELP));
3903 #endif
3904 #ifdef KEY_SHOME
3905  /* Document-const: KEY_SHOME
3906  * Shifted home key
3907  */
3908  /* Document-const: SHOME
3909  * Shifted home key
3910  */
3911  rb_curses_define_const(KEY_SHOME);
3912  rb_define_const(mKey, "SHOME", INT2NUM(KEY_SHOME));
3913 #endif
3914 #ifdef KEY_SIC
3915  /* Document-const: KEY_SIC
3916  * Shifted input key
3917  */
3918  /* Document-const: SIC
3919  * Shifted input key
3920  */
3921  rb_curses_define_const(KEY_SIC);
3922  rb_define_const(mKey, "SIC", INT2NUM(KEY_SIC));
3923 #endif
3924 #ifdef KEY_SLEFT
3925  /* Document-const: KEY_SLEFT
3926  * Shifted left arrow key
3927  */
3928  /* Document-const: SLEFT
3929  * Shifted left arrow key
3930  */
3931  rb_curses_define_const(KEY_SLEFT);
3932  rb_define_const(mKey, "SLEFT", INT2NUM(KEY_SLEFT));
3933 #endif
3934 #ifdef KEY_SMESSAGE
3935  /* Document-const: KEY_SMESSAGE
3936  * Shifted message key
3937  */
3938  /* Document-const: SMESSAGE
3939  * Shifted message key
3940  */
3941  rb_curses_define_const(KEY_SMESSAGE);
3942  rb_define_const(mKey, "SMESSAGE", INT2NUM(KEY_SMESSAGE));
3943 #endif
3944 #ifdef KEY_SMOVE
3945  /* Document-const: KEY_SMOVE
3946  * Shifted move key
3947  */
3948  /* Document-const: SMOVE
3949  * Shifted move key
3950  */
3951  rb_curses_define_const(KEY_SMOVE);
3952  rb_define_const(mKey, "SMOVE", INT2NUM(KEY_SMOVE));
3953 #endif
3954 #ifdef KEY_SNEXT
3955  /* Document-const: KEY_SNEXT
3956  * Shifted next key
3957  */
3958  /* Document-const: SNEXT
3959  * Shifted next key
3960  */
3961  rb_curses_define_const(KEY_SNEXT);
3962  rb_define_const(mKey, "SNEXT", INT2NUM(KEY_SNEXT));
3963 #endif
3964 #ifdef KEY_SOPTIONS
3965  /* Document-const: KEY_SOPTIONS
3966  * Shifted options key
3967  */
3968  /* Document-const: SOPTIONS
3969  * Shifted options key
3970  */
3971  rb_curses_define_const(KEY_SOPTIONS);
3972  rb_define_const(mKey, "SOPTIONS", INT2NUM(KEY_SOPTIONS));
3973 #endif
3974 #ifdef KEY_SPREVIOUS
3975  /* Document-const: KEY_SPREVIOUS
3976  * Shifted previous key
3977  */
3978  /* Document-const: SPREVIOUS
3979  * Shifted previous key
3980  */
3981  rb_curses_define_const(KEY_SPREVIOUS);
3982  rb_define_const(mKey, "SPREVIOUS", INT2NUM(KEY_SPREVIOUS));
3983 #endif
3984 #ifdef KEY_SPRINT
3985  /* Document-const: KEY_SPRINT
3986  * Shifted print key
3987  */
3988  /* Document-const: SPRINT
3989  * Shifted print key
3990  */
3991  rb_curses_define_const(KEY_SPRINT);
3992  rb_define_const(mKey, "SPRINT", INT2NUM(KEY_SPRINT));
3993 #endif
3994 #ifdef KEY_SREDO
3995  /* Document-const: KEY_SREDO
3996  * Shifted redo key
3997  */
3998  /* Document-const: SREDO
3999  * Shifted redo key
4000  */
4001  rb_curses_define_const(KEY_SREDO);
4002  rb_define_const(mKey, "SREDO", INT2NUM(KEY_SREDO));
4003 #endif
4004 #ifdef KEY_SREPLACE
4005  /* Document-const: KEY_SREPLACE
4006  * Shifted replace key
4007  */
4008  /* Document-const: SREPLACE
4009  * Shifted replace key
4010  */
4011  rb_curses_define_const(KEY_SREPLACE);
4012  rb_define_const(mKey, "SREPLACE", INT2NUM(KEY_SREPLACE));
4013 #endif
4014 #ifdef KEY_SRIGHT
4015  /* Document-const: KEY_SRIGHT
4016  * Shifted right arrow key
4017  */
4018  /* Document-const: SRIGHT
4019  * Shifted right arrow key
4020  */
4021  rb_curses_define_const(KEY_SRIGHT);
4022  rb_define_const(mKey, "SRIGHT", INT2NUM(KEY_SRIGHT));
4023 #endif
4024 #ifdef KEY_SRSUME
4025  /* Document-const: KEY_SRSUME
4026  * Shifted resume key
4027  */
4028  /* Document-const: SRSUME
4029  * Shifted resume key
4030  */
4031  rb_curses_define_const(KEY_SRSUME);
4032  rb_define_const(mKey, "SRSUME", INT2NUM(KEY_SRSUME));
4033 #endif
4034 #ifdef KEY_SSAVE
4035  /* Document-const: KEY_SSAVE
4036  * Shifted save key
4037  */
4038  /* Document-const: SSAVE
4039  * Shifted save key
4040  */
4041  rb_curses_define_const(KEY_SSAVE);
4042  rb_define_const(mKey, "SSAVE", INT2NUM(KEY_SSAVE));
4043 #endif
4044 #ifdef KEY_SSUSPEND
4045  /* Document-const: KEY_SSUSPEND
4046  * Shifted suspend key
4047  */
4048  /* Document-const: SSUSPEND
4049  * Shifted suspend key
4050  */
4051  rb_curses_define_const(KEY_SSUSPEND);
4052  rb_define_const(mKey, "SSUSPEND", INT2NUM(KEY_SSUSPEND));
4053 #endif
4054 #ifdef KEY_SUNDO
4055  /* Document-const: KEY_SUNDO
4056  * Shifted undo key
4057  */
4058  /* Document-const: SUNDO
4059  * Shifted undo key
4060  */
4061  rb_curses_define_const(KEY_SUNDO);
4062  rb_define_const(mKey, "SUNDO", INT2NUM(KEY_SUNDO));
4063 #endif
4064 #ifdef KEY_SUSPEND
4065  /* Document-const: KEY_SUSPEND
4066  * Suspend key
4067  */
4068  /* Document-const: SUSPEND
4069  * Suspend key
4070  */
4071  rb_curses_define_const(KEY_SUSPEND);
4072  rb_define_const(mKey, "SUSPEND", INT2NUM(KEY_SUSPEND));
4073 #endif
4074 #ifdef KEY_UNDO
4075  /* Document-const: KEY_UNDO
4076  * Undo key
4077  */
4078  /* Document-const: UNDO
4079  * Undo key
4080  */
4081  rb_curses_define_const(KEY_UNDO);
4082  rb_define_const(mKey, "UNDO", INT2NUM(KEY_UNDO));
4083 #endif
4084 #ifdef KEY_RESIZE
4085  /* Document-const: KEY_RESIZE
4086  * Screen Resized
4087  */
4088  /* Document-const: RESIZE
4089  * Screen Resized
4090  */
4091  rb_curses_define_const(KEY_RESIZE);
4092  rb_define_const(mKey, "RESIZE", INT2NUM(KEY_RESIZE));
4093 #endif
4094 #ifdef KEY_MAX
4095  /* Document-const: KEY_MAX
4096  * The maximum allowed curses key value.
4097  */
4098  /* Document-const: MAX
4099  * The maximum allowed curses key value.
4100  */
4101  rb_curses_define_const(KEY_MAX);
4102  rb_define_const(mKey, "MAX", INT2NUM(KEY_MAX));
4103 #endif
4104  {
4105  int c;
4106  char name[] = "KEY_CTRL_x";
4107  for (c = 'A'; c <= 'Z'; c++) {
4108  name[sizeof(name) - 2] = c;
4109  rb_define_const(mCurses, name, INT2FIX(c - 'A' + 1));
4110  }
4111  }
4112 #undef rb_curses_define_const
4113 
4115 }
4116