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