Ruby  2.0.0p247(2013-06-27revision41674)
ext/curses/curses.c
Go to the documentation of this file.
00001 /* -*- C -*-
00002  * $Id: curses.c 40388 2013-04-19 17:39:44Z nagachika $
00003  *
00004  * ext/curses/curses.c
00005  *
00006  * by MAEDA Shugo (ender@pic-internet.or.jp)
00007  * modified by Yukihiro Matsumoto (matz@netlab.co.jp),
00008  *         Toki Yoshinori,
00009  *         Hitoshi Takahashi,
00010  *         and Takaaki Tateishi (ttate@kt.jaist.ac.jp)
00011  *
00012  * maintainers:
00013  * - Takaaki Tateishi (ttate@kt.jaist.ac.jp)
00014  *
00015  * doumentation:
00016  * - Vincent Batts (vbatts@hashbangbash.com)
00017  */
00018 
00019 #include "ruby.h"
00020 #include "ruby/io.h"
00021 #include "ruby/thread.h"
00022 
00023 #if defined(HAVE_NCURSES_H)
00024 # include <ncurses.h>
00025 #elif defined(HAVE_NCURSES_CURSES_H)
00026 # include <ncurses/curses.h>
00027 #elif defined(HAVE_CURSES_COLR_CURSES_H)
00028 # ifdef HAVE_STDARG_PROTOTYPES
00029 #  include <stdarg.h>
00030 # else
00031 #  include <varargs.h>
00032 # endif
00033 # include <curses_colr/curses.h>
00034 #else
00035 # include <curses.h>
00036 # if defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)
00037 #  if !defined(_maxx)
00038 #  define _maxx maxx
00039 #  endif
00040 #  if !defined(_maxy)
00041 #  define _maxy maxy
00042 #  endif
00043 #  if !defined(_begx)
00044 #  define _begx begx
00045 #  endif
00046 #  if !defined(_begy)
00047 #  define _begy begy
00048 #  endif
00049 # endif
00050 #endif
00051 
00052 #ifdef HAVE_INIT_COLOR
00053 # define USE_COLOR 1
00054 #endif
00055 
00056 /* supports only ncurses mouse routines */
00057 #ifdef NCURSES_MOUSE_VERSION
00058 # define USE_MOUSE 1
00059 #endif
00060 
00061 #define NUM2CH NUM2CHR
00062 #define CH2FIX CHR2FIX
00063 
00064 static VALUE mCurses;
00065 static VALUE mKey;
00066 static VALUE cWindow;
00067 static VALUE cPad;
00068 #ifdef USE_MOUSE
00069 static VALUE cMouseEvent;
00070 #endif
00071 
00072 static VALUE rb_stdscr;
00073 
00074 struct windata {
00075     WINDOW *window;
00076 };
00077 
00078 static VALUE window_attroff(VALUE obj, VALUE attrs);
00079 static VALUE window_attron(VALUE obj, VALUE attrs);
00080 static VALUE window_attrset(VALUE obj, VALUE attrs);
00081 
00082 static void
00083 no_window(void)
00084 {
00085     rb_raise(rb_eRuntimeError, "already closed window");
00086 }
00087 
00088 #define GetWINDOW(obj, winp) do {\
00089     if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
00090         rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\
00091     TypedData_Get_Struct((obj), struct windata, &windata_type, (winp));\
00092     if ((winp)->window == 0) no_window();\
00093 } while (0)
00094 
00095 static void
00096 window_free(void *p)
00097 {
00098     struct windata *winp = p;
00099     if (winp->window && winp->window != stdscr) delwin(winp->window);
00100     winp->window = 0;
00101     xfree(winp);
00102 }
00103 
00104 static size_t
00105 window_memsize(const void *p)
00106 {
00107     const struct windata *winp = p;
00108     size_t size = sizeof(*winp);
00109     if (!winp) return 0;
00110     if (winp->window && winp->window != stdscr) size += sizeof(winp->window);
00111     return size;
00112 }
00113 
00114 static const rb_data_type_t windata_type = {
00115     "windata",
00116     {0, window_free, window_memsize,}
00117 };
00118 
00119 static VALUE
00120 prep_window(VALUE class, WINDOW *window)
00121 {
00122     VALUE obj;
00123     struct windata *winp;
00124 
00125     if (window == NULL) {
00126         rb_raise(rb_eRuntimeError, "failed to create window");
00127     }
00128 
00129     obj = rb_obj_alloc(class);
00130     TypedData_Get_Struct(obj, struct windata, &windata_type, winp);
00131     winp->window = window;
00132 
00133     return obj;
00134 }
00135 
00136 /*-------------------------- module Curses --------------------------*/
00137 
00138 /*
00139  * Document-method: Curses.init_screen
00140  *
00141  * Initialize a standard screen
00142  *
00143  * see also Curses.stdscr
00144  */
00145 static VALUE
00146 curses_init_screen(void)
00147 {
00148     rb_secure(4);
00149     if (rb_stdscr) return rb_stdscr;
00150     initscr();
00151     if (stdscr == 0) {
00152         rb_raise(rb_eRuntimeError, "can't initialize curses");
00153     }
00154     clear();
00155     rb_stdscr = prep_window(cWindow, stdscr);
00156     return rb_stdscr;
00157 }
00158 
00159 /*
00160  * Document-method: Curses.stdscr
00161  *
00162  * The Standard Screen.
00163  *
00164  * Upon initializing curses, a default window called stdscr,
00165  * which is the size of the terminal screen, is created.
00166  *
00167  * Many curses functions use this window.
00168  */
00169 #define curses_stdscr curses_init_screen
00170 
00171 /*
00172  * Document-method: Curses.close_screen
00173  *
00174  * A program should always call Curses.close_screen before exiting or
00175  * escaping from curses mode temporarily. This routine
00176  * restores tty modes, moves the cursor to the lower
00177  * left-hand corner of the screen and resets the terminal
00178  * into the proper non-visual mode.
00179  *
00180  * Calling Curses.refresh or Curses.doupdate after a temporary
00181  * escape causes the program to resume visual mode.
00182  *
00183  */
00184 static VALUE
00185 curses_close_screen(void)
00186 {
00187     curses_stdscr();
00188 #ifdef HAVE_ISENDWIN
00189     if (!isendwin())
00190 #endif
00191         endwin();
00192     rb_stdscr = 0;
00193     return Qnil;
00194 }
00195 
00196 /*
00197  * This is no runtime method,
00198  * but a function called before the proc ends
00199  *
00200  * Similar to Curses.close_screen, except that it also
00201  * garbage collects/unregisters the Curses.stdscr
00202  */
00203 static void
00204 curses_finalize(VALUE dummy)
00205 {
00206     if (stdscr
00207 #ifdef HAVE_ISENDWIN
00208         && !isendwin()
00209 #endif
00210         )
00211         endwin();
00212     rb_stdscr = 0;
00213     rb_gc_unregister_address(&rb_stdscr);
00214 }
00215 
00216 #ifdef HAVE_ISENDWIN
00217 /*
00218  * Document-method: Curses.closed?
00219  *
00220  * Returns +true+ if the window/screen has been closed,
00221  * without any subsequent Curses.refresh calls,
00222  * returns +false+ otherwise.
00223  */
00224 static VALUE
00225 curses_closed(void)
00226 {
00227     curses_stdscr();
00228     if (isendwin()) {
00229         return Qtrue;
00230     }
00231     return Qfalse;
00232 }
00233 #else
00234 #define curses_closed rb_f_notimplement
00235 #endif
00236 
00237 /*
00238  * Document-method: Curses.clear
00239  *
00240  * Clears every position on the screen completely,
00241  * so that a subsequent call by Curses.refresh for the screen/window
00242  * will be repainted from scratch.
00243  */
00244 static VALUE
00245 curses_clear(VALUE obj)
00246 {
00247     curses_stdscr();
00248     wclear(stdscr);
00249     return Qnil;
00250 }
00251 
00252 /*
00253  * Document-method: Curses.clrtoeol
00254  *
00255  * Clears to the end of line, that the cursor is currently on.
00256  */
00257 static VALUE
00258 curses_clrtoeol(void)
00259 {
00260     curses_stdscr();
00261     clrtoeol();
00262     return Qnil;
00263 }
00264 
00265 /*
00266  * Document-method: Curses.refresh
00267  *
00268  * Refreshes the windows and lines.
00269  *
00270  */
00271 static VALUE
00272 curses_refresh(VALUE obj)
00273 {
00274     curses_stdscr();
00275     refresh();
00276     return Qnil;
00277 }
00278 
00279 /*
00280  * Document-method: Curses.doupdate
00281  *
00282  * Refreshes the windows and lines.
00283  *
00284  * Curses.doupdate allows multiple updates with
00285  * more efficiency than Curses.refresh alone.
00286  */
00287 static VALUE
00288 curses_doupdate(VALUE obj)
00289 {
00290     curses_stdscr();
00291 #ifdef HAVE_DOUPDATE
00292     doupdate();
00293 #else
00294     refresh();
00295 #endif
00296     return Qnil;
00297 }
00298 
00299 /*
00300  * Document-method: Curses.echo
00301  *
00302  * Enables characters typed by the user
00303  * to be echoed by Curses.getch as they are typed.
00304  */
00305 static VALUE
00306 curses_echo(VALUE obj)
00307 {
00308     curses_stdscr();
00309     echo();
00310     return Qnil;
00311 }
00312 
00313 /*
00314  * Document-method: Curses.noecho
00315  *
00316  * Disables characters typed by the user
00317  * to be echoed by Curses.getch as they are typed.
00318  */
00319 static VALUE
00320 curses_noecho(VALUE obj)
00321 {
00322     curses_stdscr();
00323     noecho();
00324     return Qnil;
00325 }
00326 
00327 /*
00328  * Document-method: Curses.raw
00329  *
00330  * Put the terminal into raw mode.
00331  *
00332  * Raw mode is similar to Curses.cbreak mode, in that characters typed
00333  * are immediately passed through to the user program.
00334  *
00335  * The differences are that in raw mode, the interrupt, quit,
00336  * suspend, and flow control characters are all passed through
00337  * uninterpreted, instead of generating a signal. The behavior
00338  * of the BREAK key depends on other bits in the tty driver
00339  * that are not set by curses.
00340  */
00341 static VALUE
00342 curses_raw(VALUE obj)
00343 {
00344     curses_stdscr();
00345     raw();
00346     return Qnil;
00347 }
00348 
00349 /*
00350  * Document-method: Curses.noraw
00351  *
00352  * Put the terminal out of raw mode.
00353  *
00354  * see Curses.raw for more detail
00355  */
00356 static VALUE
00357 curses_noraw(VALUE obj)
00358 {
00359     curses_stdscr();
00360     noraw();
00361     return Qnil;
00362 }
00363 
00364 /*
00365  * Document-method: Curses.cbreak
00366  *
00367  * Put the terminal into cbreak mode.
00368  *
00369  * Normally, the tty driver buffers typed characters until
00370  * a newline or carriage return is typed. The Curses.cbreak
00371  * routine disables line buffering and erase/kill
00372  * character-processing (interrupt and flow control characters
00373  * are unaffected), making characters typed by the user
00374  * immediately available to the program.
00375  *
00376  * The Curses.nocbreak routine returns the terminal to normal (cooked) mode.
00377  *
00378  * Initially the terminal may or may not be in cbreak mode,
00379  * as the mode is inherited; therefore, a program should
00380  * call Curses.cbreak or Curses.nocbreak explicitly.
00381  * Most interactive programs using curses set the cbreak mode.
00382  * Note that Curses.cbreak overrides Curses.raw.
00383  *
00384  * see also Curses.raw
00385  */
00386 static VALUE
00387 curses_cbreak(VALUE obj)
00388 {
00389     curses_stdscr();
00390     cbreak();
00391     return Qnil;
00392 }
00393 
00394 /*
00395  * Document-method: Curses.nocbreak
00396  *
00397  * Put the terminal into normal mode (out of cbreak mode).
00398  *
00399  * See Curses.cbreak for more detail.
00400  */
00401 static VALUE
00402 curses_nocbreak(VALUE obj)
00403 {
00404     curses_stdscr();
00405     nocbreak();
00406     return Qnil;
00407 }
00408 
00409 /*
00410  * Document-method: Curses.nl
00411  *
00412  * Enable the underlying display device to translate
00413  * the return key into newline on input, and whether it
00414  * translates newline into return and line-feed on output
00415  * (in either case, the call Curses.addch('\n') does the
00416  * equivalent of return and line feed on the virtual screen).
00417  *
00418  * Initially, these translations do occur. If you disable
00419  * them using Curses.nonl, curses will be able to make better use
00420  * of the line-feed capability, resulting in faster cursor
00421  * motion. Also, curses will then be able to detect the return key.
00422  */
00423 static VALUE
00424 curses_nl(VALUE obj)
00425 {
00426     curses_stdscr();
00427     nl();
00428     return Qnil;
00429 }
00430 
00431 /*
00432  * Document-method: Curses.nl
00433  *
00434  * Disable the underlying display device to translate
00435  * the return key into newline on input
00436  *
00437  * See Curses.nl for more detail
00438  */
00439 static VALUE
00440 curses_nonl(VALUE obj)
00441 {
00442     curses_stdscr();
00443     nonl();
00444     return Qnil;
00445 }
00446 
00447 /*
00448  * Document-method: Curses.beep
00449  *
00450  * Sounds an audible alarm on the terminal, if possible;
00451  * otherwise it flashes the screen (visual bell).
00452  *
00453  * see also Curses.flash
00454  */
00455 static VALUE
00456 curses_beep(VALUE obj)
00457 {
00458 #ifdef HAVE_BEEP
00459     curses_stdscr();
00460     beep();
00461 #endif
00462     return Qnil;
00463 }
00464 
00465 /*
00466  * Document-method: Curses.flash
00467  *
00468  * Flashs the screen, for visual alarm on the terminal, if possible;
00469  * otherwise it sounds the alert.
00470  *
00471  * see also Curses.beep
00472  */
00473 static VALUE
00474 curses_flash(VALUE obj)
00475 {
00476 #ifdef HAVE_FLASH
00477     curses_stdscr();
00478     flash();
00479 #endif
00480     return Qnil;
00481 }
00482 
00483 static int
00484 curses_char(VALUE c)
00485 {
00486     if (FIXNUM_P(c)) {
00487         return NUM2INT(c);
00488     }
00489     else {
00490         int cc;
00491 
00492         StringValue(c);
00493         if (RSTRING_LEN(c) == 0 || RSTRING_LEN(c) > 1) {
00494             rb_raise(rb_eArgError, "string not corresponding a character");
00495         }
00496         cc = RSTRING_PTR(c)[0];
00497         if (cc > 0x7f) {
00498             rb_raise(rb_eArgError, "no multibyte string supported (yet)");
00499         }
00500         return cc;
00501     }
00502 }
00503 
00504 #ifdef HAVE_UNGETCH
00505 /*
00506  * Document-method: Curses.ungetch
00507  * call-seq: ungetch(ch)
00508  *
00509  * Places +ch+ back onto the input queue to be returned by
00510  * the next call to Curses.getch.
00511  *
00512  * There is just one input queue for all windows.
00513  */
00514 static VALUE
00515 curses_ungetch(VALUE obj, VALUE ch)
00516 {
00517     int c = curses_char(ch);
00518     curses_stdscr();
00519     ungetch(c);
00520     return Qnil;
00521 }
00522 #else
00523 #define curses_ungetch rb_f_notimplement
00524 #endif
00525 
00526 /*
00527  * Document-method: Curses.setpos
00528  * call-seq: setpos(y, x)
00529  *
00530  * A setter for the position of the cursor,
00531  * using coordinates +x+ and +y+
00532  *
00533  */
00534 static VALUE
00535 curses_setpos(VALUE obj, VALUE y, VALUE x)
00536 {
00537     curses_stdscr();
00538     move(NUM2INT(y), NUM2INT(x));
00539     return Qnil;
00540 }
00541 
00542 /*
00543  * Document-method: Curses.standout
00544  *
00545  * Enables the best highlighting mode of the terminal.
00546  *
00547  * This is equivalent to Curses:Window.attron(A_STANDOUT)
00548  *
00549  * see also Curses::Window.attrset additional information
00550  */
00551 static VALUE
00552 curses_standout(VALUE obj)
00553 {
00554     curses_stdscr();
00555     standout();
00556     return Qnil;
00557 }
00558 
00559 /*
00560  * Document-method: Curses.standend
00561  *
00562  * Enables the Normal display (no highlight)
00563  *
00564  * This is equivalent to Curses.attron(A_NORMAL)
00565  *
00566  * see also Curses::Window.attrset for additional information.
00567  */
00568 static VALUE
00569 curses_standend(VALUE obj)
00570 {
00571     curses_stdscr();
00572     standend();
00573     return Qnil;
00574 }
00575 
00576 /*
00577  * Document-method: Curses.inch
00578  *
00579  * Returns the character at the current position.
00580  */
00581 static VALUE
00582 curses_inch(VALUE obj)
00583 {
00584     curses_stdscr();
00585     return CH2FIX(inch());
00586 }
00587 
00588 /*
00589  * Document-method: Curses.addch
00590  * call-seq: addch(ch)
00591  *
00592  * Add a character +ch+, with attributes, then advance the cursor.
00593  *
00594  * see also the system manual for curs_addch(3)
00595  */
00596 static VALUE
00597 curses_addch(VALUE obj, VALUE ch)
00598 {
00599     curses_stdscr();
00600     addch(NUM2CH(ch));
00601     return Qnil;
00602 }
00603 
00604 /*
00605  * Document-method: Curses.insch
00606  * call-seq: insch(ch)
00607  *
00608  * Insert a character +ch+, before the cursor.
00609  *
00610  */
00611 static VALUE
00612 curses_insch(VALUE obj, VALUE ch)
00613 {
00614     curses_stdscr();
00615     insch(NUM2CH(ch));
00616     return Qnil;
00617 }
00618 
00619 /*
00620  * Document-method: Curses.addstr
00621  * call-seq: addstr(str)
00622  *
00623  * add a string of characters +str+, to the window and advance cursor
00624  *
00625  */
00626 static VALUE
00627 curses_addstr(VALUE obj, VALUE str)
00628 {
00629     StringValue(str);
00630     str = rb_str_export_locale(str);
00631     curses_stdscr();
00632     if (!NIL_P(str)) {
00633         addstr(StringValueCStr(str));
00634     }
00635     return Qnil;
00636 }
00637 
00638 static void *
00639 getch_func(void *arg)
00640 {
00641     int *ip = (int *)arg;
00642     *ip = getch();
00643     return 0;
00644 }
00645 
00646 /*
00647  * Document-method: Curses.getch
00648  *
00649  * Read and returns a character from the window.
00650  *
00651  * See Curses::Key to all the function KEY_* available
00652  *
00653  */
00654 static VALUE
00655 curses_getch(VALUE obj)
00656 {
00657     int c;
00658 
00659     curses_stdscr();
00660     rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0);
00661     if (c == EOF) return Qnil;
00662     if (rb_isprint(c)) {
00663         char ch = (char)c;
00664 
00665         return rb_locale_str_new(&ch, 1);
00666     }
00667     return UINT2NUM(c);
00668 }
00669 
00670 /* This should be big enough.. I hope */
00671 #define GETSTR_BUF_SIZE 1024
00672 
00673 static void *
00674 getstr_func(void *arg)
00675 {
00676     char *rtn = (char *)arg;
00677 #if defined(HAVE_GETNSTR)
00678     getnstr(rtn,GETSTR_BUF_SIZE-1);
00679 #else
00680     getstr(rtn);
00681 #endif
00682     return 0;
00683 }
00684 
00685 /*
00686  * Document-method: Curses.getstr
00687  *
00688  * This is equivalent to a series f Curses::Window.getch calls
00689  *
00690  */
00691 static VALUE
00692 curses_getstr(VALUE obj)
00693 {
00694     char rtn[GETSTR_BUF_SIZE];
00695 
00696     curses_stdscr();
00697     rb_thread_call_without_gvl(getstr_func, rtn, RUBY_UBF_IO, 0);
00698     return rb_locale_str_new_cstr(rtn);
00699 }
00700 
00701 /*
00702  * Document-method: Curses.delch
00703  *
00704  * Delete the character under the cursor
00705  *
00706  */
00707 static VALUE
00708 curses_delch(VALUE obj)
00709 {
00710     curses_stdscr();
00711     delch();
00712     return Qnil;
00713 }
00714 
00715 /*
00716  * Document-method: Curses.deleteln
00717  *
00718  * Delete the line under the cursor.
00719  *
00720  */
00721 static VALUE
00722 curses_deleteln(VALUE obj)
00723 {
00724     curses_stdscr();
00725 #if defined(HAVE_DELETELN) || defined(deleteln)
00726     deleteln();
00727 #endif
00728     return Qnil;
00729 }
00730 
00731 /*
00732  * Document-method: Curses.insertln
00733  *
00734  * Inserts a line above the cursor, and the bottom line is lost
00735  *
00736  */
00737 static VALUE
00738 curses_insertln(VALUE obj)
00739 {
00740     curses_stdscr();
00741 #if defined(HAVE_INSERTLN) || defined(insertln)
00742     insertln();
00743 #endif
00744     return Qnil;
00745 }
00746 
00747 /*
00748  * Document-method: Curses.keyname
00749  * call-seq: keyname(c)
00750  *
00751  * Returns the character string corresponding to key +c+
00752  */
00753 static VALUE
00754 curses_keyname(VALUE obj, VALUE c)
00755 {
00756 #ifdef HAVE_KEYNAME
00757     int cc = curses_char(c);
00758     const char *name;
00759 
00760     curses_stdscr();
00761     name = keyname(cc);
00762     if (name) {
00763         return rb_str_new_cstr(name);
00764     }
00765     else {
00766         return Qnil;
00767     }
00768 #else
00769     return Qnil;
00770 #endif
00771 }
00772 
00773 /*
00774  * Document-method: Curses.lines
00775  *
00776  * Returns the number of lines on the screen
00777  */
00778 static VALUE
00779 curses_lines(void)
00780 {
00781     return INT2FIX(LINES);
00782 }
00783 
00784 /*
00785  * Document-method: Curses.cols
00786  *
00787  * Returns the number of columns on the screen
00788  */
00789 static VALUE
00790 curses_cols(void)
00791 {
00792     return INT2FIX(COLS);
00793 }
00794 
00795 /*
00796  * Document-method: Curses.curs_set
00797  * call-seq: curs_set(visibility)
00798  *
00799  * Sets Cursor Visibility.
00800  * 0: invisible
00801  * 1: visible
00802  * 2: very visible
00803  */
00804 static VALUE
00805 curses_curs_set(VALUE obj, VALUE visibility)
00806 {
00807 #ifdef HAVE_CURS_SET
00808     int n;
00809     curses_stdscr();
00810     return (n = curs_set(NUM2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil;
00811 #else
00812     return Qnil;
00813 #endif
00814 }
00815 
00816 /*
00817  * Document-method: Curses.scrl
00818  * call-seq: scrl(num)
00819  *
00820  * Scrolls the current window Fixnum +num+ lines.
00821  * The current cursor position is not changed.
00822  *
00823  * For positive +num+, it scrolls up.
00824  *
00825  * For negative +num+, it scrolls down.
00826  *
00827  */
00828 static VALUE
00829 curses_scrl(VALUE obj, VALUE n)
00830 {
00831     /* may have to raise exception on ERR */
00832 #ifdef HAVE_SCRL
00833     curses_stdscr();
00834     return (scrl(NUM2INT(n)) == OK) ? Qtrue : Qfalse;
00835 #else
00836     return Qfalse;
00837 #endif
00838 }
00839 
00840 /*
00841  * Document-method: Curses.setscrreg
00842  *
00843  * call-seq:
00844  *   setscrreg(top, bottom)
00845  *
00846  * Set a software scrolling region in a window.
00847  * +top+ and +bottom+ are lines numbers of the margin.
00848  *
00849  * If this option and Curses.scrollok are enabled, an attempt to move off
00850  * the bottom margin line causes all lines in the scrolling region
00851  * to scroll one line in the direction of the first line.
00852  * Only the text of the window is scrolled.
00853  *
00854  */
00855 static VALUE
00856 curses_setscrreg(VALUE obj, VALUE top, VALUE bottom)
00857 {
00858     /* may have to raise exception on ERR */
00859 #ifdef HAVE_SETSCRREG
00860     curses_stdscr();
00861     return (setscrreg(NUM2INT(top), NUM2INT(bottom)) == OK) ? Qtrue : Qfalse;
00862 #else
00863     return Qfalse;
00864 #endif
00865 }
00866 
00867 /*
00868  * Document-method: Curses.attroff
00869  * call-seq: attroff(attrs)
00870  *
00871  * Turns on the named attributes +attrs+ without affecting any others.
00872  *
00873  * See also Curses::Window.attrset for additional information.
00874  */
00875 static VALUE
00876 curses_attroff(VALUE obj, VALUE attrs)
00877 {
00878     curses_stdscr();
00879     return window_attroff(rb_stdscr,attrs);
00880     /* return INT2FIX(attroff(NUM2INT(attrs))); */
00881 }
00882 
00883 /*
00884  * Document-method: Curses.attron
00885  * call-seq: attron(attrs)
00886  *
00887  * Turns off the named attributes +attrs+
00888  * without turning any other attributes on or off.
00889  *
00890  * See also Curses::Window.attrset for additional information.
00891  */
00892 static VALUE
00893 curses_attron(VALUE obj, VALUE attrs)
00894 {
00895     curses_stdscr();
00896     return window_attron(rb_stdscr,attrs);
00897     /* return INT2FIX(attroff(NUM2INT(attrs))); */
00898 }
00899 
00900 /*
00901  * Document-method: Curses.attrset
00902  * call-seq: attrset(attrs)
00903  *
00904  * Sets the current attributes of the given window to +attrs+.
00905  *
00906  * see also Curses::Window.attrset
00907  *
00908  */
00909 static VALUE
00910 curses_attrset(VALUE obj, VALUE attrs)
00911 {
00912     curses_stdscr();
00913     return window_attrset(rb_stdscr,attrs);
00914     /* return INT2FIX(attroff(NUM2INT(attrs))); */
00915 }
00916 
00917 /*
00918  * Document-method: Curses.bkgdset
00919  * call-seq: bkgdset(ch)
00920  *
00921  * Manipulate the background of the named window
00922  * with character Integer +ch+
00923  *
00924  * The background becomes a property of the character
00925  * and moves with the character through any scrolling
00926  * and insert/delete line/character operations.
00927  *
00928  * see also the system manual for curs_bkgd(3)
00929  */
00930 static VALUE
00931 curses_bkgdset(VALUE obj, VALUE ch)
00932 {
00933 #ifdef HAVE_BKGDSET
00934     curses_stdscr();
00935     bkgdset(NUM2CH(ch));
00936 #endif
00937     return Qnil;
00938 }
00939 
00940 /*
00941  * call-seq: bkgd(ch)
00942  *
00943  * Window background manipulation routines.
00944  *
00945  * Set the background property of the current
00946  * and then apply the character Integer +ch+ setting
00947  * to every character position in that window.
00948  *
00949  * see also the system manual for curs_bkgd(3)
00950  */
00951 static VALUE
00952 curses_bkgd(VALUE obj, VALUE ch)
00953 {
00954 #ifdef HAVE_BKGD
00955     curses_stdscr();
00956     return (bkgd(NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
00957 #else
00958     return Qfalse;
00959 #endif
00960 }
00961 
00962 #if defined(HAVE_USE_DEFAULT_COLORS)
00963 /*
00964  * tells the curses library to use terminal's default colors.
00965  *
00966  * see also the system manual for default_colors(3)
00967  */
00968 static VALUE
00969 curses_use_default_colors(VALUE obj)
00970 {
00971     curses_stdscr();
00972     use_default_colors();
00973     return Qnil;
00974 }
00975 #else
00976 #define curses_use_default_colors rb_f_notimplement
00977 #endif
00978 
00979 #if defined(HAVE_TABSIZE)
00980 /*
00981  * Document-method: Curses.TABSIZE=
00982  * call-seq: TABSIZE=(value)
00983  *
00984  * Sets the TABSIZE to Integer +value+
00985  */
00986 static VALUE
00987 curses_tabsize_set(VALUE obj, VALUE val)
00988 {
00989     TABSIZE = NUM2INT(val);
00990     return INT2NUM(TABSIZE);
00991 }
00992 #else
00993 #define curses_tabsize_set rb_f_notimplement
00994 #endif
00995 
00996 #if defined(HAVE_TABSIZE)
00997 /*
00998  * Returns the number of positions in a tab.
00999  */
01000 static VALUE
01001 curses_tabsize_get(VALUE ojb)
01002 {
01003     return INT2NUM(TABSIZE);
01004 }
01005 #else
01006 #define curses_tabsize_get rb_f_notimplement
01007 #endif
01008 
01009 #if defined(HAVE_ESCDELAY)
01010 /*
01011  * call-seq: Curses.ESCDELAY=(value)
01012  *
01013  * Sets the ESCDELAY to Integer +value+
01014  */
01015 static VALUE
01016 curses_escdelay_set(VALUE obj, VALUE val)
01017 {
01018     ESCDELAY = NUM2INT(val);
01019     return INT2NUM(ESCDELAY);
01020 }
01021 #else
01022 #define curses_escdelay_set rb_f_notimplement
01023 #endif
01024 
01025 #if defined(HAVE_ESCDELAY)
01026 /*
01027  * Returns the total time, in milliseconds, for which
01028  * curses will await a character sequence, e.g., a function key
01029  */
01030 static VALUE
01031 curses_escdelay_get(VALUE obj)
01032 {
01033     return INT2NUM(ESCDELAY);
01034 }
01035 #else
01036 #define curses_escdelay_get rb_f_notimplement
01037 #endif
01038 
01039 /*
01040  * Document-method: Curses.resize
01041  * call-seq: resize(lines, cols)
01042  *
01043  * alias for Curses.resizeterm
01044  *
01045  */
01046 
01047 /*
01048  * Document-method: Curses.resizeterm
01049  * call-seq: resizeterm(lines, cols)
01050  *
01051  * Resize the current term to Fixnum +lines+ and Fixnum +cols+
01052  *
01053  */
01054 static VALUE
01055 curses_resizeterm(VALUE obj, VALUE lin, VALUE col)
01056 {
01057 #if defined(HAVE_RESIZETERM)
01058     curses_stdscr();
01059     return (resizeterm(NUM2INT(lin),NUM2INT(col)) == OK) ? Qtrue : Qfalse;
01060 #else
01061     return Qnil;
01062 #endif
01063 }
01064 
01065 #ifdef USE_COLOR
01066 /*
01067  * Document-method: Curses.start_color
01068  *
01069  * Initializes the color attributes, for terminals that support it.
01070  *
01071  * This must be called, in order to use color attributes.
01072  * It is good practice to call it just after Curses.init_screen
01073  */
01074 static VALUE
01075 curses_start_color(VALUE obj)
01076 {
01077     /* may have to raise exception on ERR */
01078     curses_stdscr();
01079     return (start_color() == OK) ? Qtrue : Qfalse;
01080 }
01081 
01082 /*
01083  * Document-method: Curses.init_pair
01084  * call-seq: init_pair(pair, f, b)
01085  *
01086  * Changes the definition of a color-pair.
01087  *
01088  * It takes three arguments: the number of the color-pair to be changed +pair+,
01089  * the foreground color number +f+, and the background color number +b+.
01090  *
01091  * If the color-pair was previously initialized, the screen is
01092  * refreshed and all occurrences of that color-pair are changed
01093  * to the new definition.
01094  *
01095  */
01096 static VALUE
01097 curses_init_pair(VALUE obj, VALUE pair, VALUE f, VALUE b)
01098 {
01099     /* may have to raise exception on ERR */
01100     curses_stdscr();
01101     return (init_pair(NUM2INT(pair),NUM2INT(f),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
01102 }
01103 
01104 /*
01105  * Document-method: Curses.init_color
01106  * call-seq: init_color(color, r, g, b)
01107  *
01108  * Changes the definition of a color. It takes four arguments:
01109  * * the number of the color to be changed, +color+
01110  * * the amount of red, +r+
01111  * * the amount of green, +g+
01112  * * the amount of blue, +b+
01113  *
01114  * The value of the first argument must be between 0 and  COLORS.
01115  * (See the section Colors for the default color index.)  Each
01116  * of the last three arguments must be a value between 0 and 1000.
01117  * When Curses.init_color is used, all occurrences of that color
01118  * on the screen immediately change to the new definition.
01119  */
01120 static VALUE
01121 curses_init_color(VALUE obj, VALUE color, VALUE r, VALUE g, VALUE b)
01122 {
01123     /* may have to raise exception on ERR */
01124     curses_stdscr();
01125     return (init_color(NUM2INT(color),NUM2INT(r),
01126                        NUM2INT(g),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
01127 }
01128 
01129 /*
01130  * Document-method: Curses.has_colors?
01131  *
01132  * Returns +true+ or +false+ depending on whether the terminal has color capbilities.
01133  */
01134 static VALUE
01135 curses_has_colors(VALUE obj)
01136 {
01137     curses_stdscr();
01138     return has_colors() ? Qtrue : Qfalse;
01139 }
01140 
01141 /*
01142  * Document-method: Curses.can_change_color?
01143  *
01144  * Returns +true+ or +false+ depending on whether the terminal can change color attributes
01145  */
01146 static VALUE
01147 curses_can_change_color(VALUE obj)
01148 {
01149     curses_stdscr();
01150     return can_change_color() ? Qtrue : Qfalse;
01151 }
01152 
01153 #if defined(HAVE_COLORS)
01154 /*
01155  * Document-method: Curses.color
01156  *
01157  * returns COLORS
01158  */
01159 static VALUE
01160 curses_colors(VALUE obj)
01161 {
01162     return INT2FIX(COLORS);
01163 }
01164 #else
01165 #define curses_colors rb_f_notimplement
01166 #endif
01167 
01168 /*
01169  * Document-method: Curses.color_content
01170  * call-seq: color_content(color)
01171  *
01172  * Returns an 3 item Array of the RGB values in +color+
01173  */
01174 static VALUE
01175 curses_color_content(VALUE obj, VALUE color)
01176 {
01177     short r,g,b;
01178 
01179     curses_stdscr();
01180     color_content(NUM2INT(color),&r,&g,&b);
01181     return rb_ary_new3(3,INT2FIX(r),INT2FIX(g),INT2FIX(b));
01182 }
01183 
01184 
01185 #if defined(HAVE_COLOR_PAIRS)
01186 /*
01187  * Document-method: Curses.color_pairs
01188  *
01189  * Returns the COLOR_PAIRS available, if the curses library supports it.
01190  */
01191 static VALUE
01192 curses_color_pairs(VALUE obj)
01193 {
01194     return INT2FIX(COLOR_PAIRS);
01195 }
01196 #else
01197 #define curses_color_pairs rb_f_notimplement
01198 #endif
01199 
01200 /*
01201  * Document-method: Curses.pair_content
01202  * call-seq: pair_content(pair)
01203  *
01204  * Returns a 2 item Array, with the foreground and
01205  * background color, in +pair+
01206  */
01207 static VALUE
01208 curses_pair_content(VALUE obj, VALUE pair)
01209 {
01210     short f,b;
01211 
01212     curses_stdscr();
01213     pair_content(NUM2INT(pair),&f,&b);
01214     return rb_ary_new3(2,INT2FIX(f),INT2FIX(b));
01215 }
01216 
01217 /*
01218  * Document-method: Curses.color_pair
01219  * call-seq: color_pair(attrs)
01220  *
01221  * Sets the color pair attributes to +attrs+.
01222  *
01223  * This should be equivalent to Curses.attrset(COLOR_PAIR(+attrs+))
01224  *
01225  * TODO: validate that equivalency
01226  */
01227 static VALUE
01228 curses_color_pair(VALUE obj, VALUE attrs)
01229 {
01230     return INT2FIX(COLOR_PAIR(NUM2INT(attrs)));
01231 }
01232 
01233 /*
01234  * Document-method: Curses.pair_number
01235  * call-seq: pair_number(attrs)
01236  *
01237  * Returns the Fixnum color pair number of attributes +attrs+.
01238  */
01239 static VALUE
01240 curses_pair_number(VALUE obj, VALUE attrs)
01241 {
01242     curses_stdscr();
01243     return INT2FIX(PAIR_NUMBER(NUM2LONG(attrs)));
01244 }
01245 #endif /* USE_COLOR */
01246 
01247 #ifdef USE_MOUSE
01248 struct mousedata {
01249     MEVENT *mevent;
01250 };
01251 
01252 static void
01253 no_mevent(void)
01254 {
01255     rb_raise(rb_eRuntimeError, "no such mouse event");
01256 }
01257 
01258 #define GetMOUSE(obj, data) do {\
01259     if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
01260         rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\
01261     TypedData_Get_Struct((obj), struct mousedata, &mousedata_type, (data));\
01262     if ((data)->mevent == 0) no_mevent();\
01263 } while (0)
01264 
01265 static void
01266 curses_mousedata_free(void *p)
01267 {
01268     struct mousedata *mdata = p;
01269     if (mdata->mevent)
01270         xfree(mdata->mevent);
01271 }
01272 
01273 static size_t
01274 curses_mousedata_memsize(const void *p)
01275 {
01276     const struct mousedata *mdata = p;
01277     size_t size = sizeof(*mdata);
01278     if (!mdata) return 0;
01279     if (mdata->mevent) size += sizeof(mdata->mevent);
01280     return size;
01281 }
01282 
01283 static const rb_data_type_t mousedata_type = {
01284     "mousedata",
01285     {0, curses_mousedata_free, curses_mousedata_memsize,}
01286 };
01287 
01288 /*
01289  * Document-method: Curses.getmouse
01290  *
01291  * Returns coordinates of the mouse.
01292  *
01293  * This will read and pop the mouse event data off the queue
01294  *
01295  * See the BUTTON*, ALL_MOUSE_EVENTS and REPORT_MOUSE_POSITION constants, to examine the mask of the event
01296  */
01297 static VALUE
01298 curses_getmouse(VALUE obj)
01299 {
01300     struct mousedata *mdata;
01301     VALUE val;
01302 
01303     curses_stdscr();
01304     val = TypedData_Make_Struct(cMouseEvent,struct mousedata,
01305                                 &mousedata_type,mdata);
01306     mdata->mevent = (MEVENT*)xmalloc(sizeof(MEVENT));
01307     return (getmouse(mdata->mevent) == OK) ? val : Qnil;
01308 }
01309 
01310 /*
01311  * Document-method: Curses.ungetmouse
01312  *
01313  * It pushes a KEY_MOUSE event onto the input queue, and associates with that
01314  * event the given state data and screen-relative character-cell coordinates.
01315  *
01316  * The Curses.ungetmouse function behaves analogously to Curses.ungetch.
01317  */
01318 static VALUE
01319 curses_ungetmouse(VALUE obj, VALUE mevent)
01320 {
01321     struct mousedata *mdata;
01322 
01323     curses_stdscr();
01324     GetMOUSE(mevent,mdata);
01325     return (ungetmouse(mdata->mevent) == OK) ? Qtrue : Qfalse;
01326 }
01327 
01328 /*
01329  * Document-method: Curses.mouseinterval
01330  * call-seq: mouseinterval(interval)
01331  *
01332  * The Curses.mouseinterval function sets the maximum time
01333  * (in thousands of a second) that can elapse between press
01334  * and release events for them to be recognized as a click.
01335  *
01336  * Use Curses.mouseinterval(0) to disable click resolution.
01337  * This function returns the previous interval value.
01338  *
01339  * Use Curses.mouseinterval(-1) to obtain the interval without
01340  * altering it.
01341  *
01342  * The default is one sixth of a second.
01343  */
01344 static VALUE
01345 curses_mouseinterval(VALUE obj, VALUE interval)
01346 {
01347     curses_stdscr();
01348     return mouseinterval(NUM2INT(interval)) ? Qtrue : Qfalse;
01349 }
01350 
01351 /*
01352  * Document-method: Curses.mousemask
01353  * call-seq: mousemask(mask)
01354  *
01355  * Returns the +mask+ of the reportable events
01356  */
01357 static VALUE
01358 curses_mousemask(VALUE obj, VALUE mask)
01359 {
01360     curses_stdscr();
01361     return INT2NUM(mousemask(NUM2UINT(mask),NULL));
01362 }
01363 
01364 #define DEFINE_MOUSE_GET_MEMBER(func_name,mem) \
01365 static VALUE func_name (VALUE mouse) \
01366 { \
01367     struct mousedata *mdata; \
01368     GetMOUSE(mouse, mdata); \
01369     return (UINT2NUM(mdata->mevent -> mem)); \
01370 }
01371 
01372 /*
01373  * Document-method: Curses::MouseEvent.eid
01374  *
01375  * Returns the current mouse id
01376  */
01377 DEFINE_MOUSE_GET_MEMBER(curs_mouse_id, id)
01378 /*
01379  * Document-method: Curses::MouseEvent.x
01380  *
01381  * Returns the current mouse's X coordinate
01382  */
01383 DEFINE_MOUSE_GET_MEMBER(curs_mouse_x, x)
01384 /*
01385  * Document-method: Curses::MouseEvent.y
01386  *
01387  * Returns the current mouse's Y coordinate
01388  */
01389 DEFINE_MOUSE_GET_MEMBER(curs_mouse_y, y)
01390 /*
01391  * Document-method: Curses::MouseEvent.z
01392  *
01393  * Returns the current mouse's Z coordinate
01394  */
01395 DEFINE_MOUSE_GET_MEMBER(curs_mouse_z, z)
01396 /*
01397  * Document-method: Curses::MouseEvent.bstate
01398  *
01399  * Returns the current mouse's button state.  Use this with the button state
01400  * constants to determine which buttons were pressed.
01401  */
01402 DEFINE_MOUSE_GET_MEMBER(curs_mouse_bstate, bstate)
01403 #undef define_curs_mouse_member
01404 #endif /* USE_MOUSE */
01405 
01406 #ifdef HAVE_TIMEOUT
01407 /*
01408  * Document-method: Curses.timeout=
01409  * call-seq: timeout=(delay)
01410  *
01411  * Sets block and non-blocking reads for the window.
01412  * - If delay is negative, blocking read is used (i.e., waits indefinitely for input).
01413  * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting).
01414  * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input.
01415  *
01416  */
01417 static VALUE
01418 curses_timeout(VALUE obj, VALUE delay)
01419 {
01420     curses_stdscr();
01421     timeout(NUM2INT(delay));
01422     return Qnil;
01423 }
01424 #else
01425 #define curses_timeout rb_f_notimplement
01426 #endif
01427 
01428 #ifdef HAVE_DEF_PROG_MODE
01429 /*
01430  * Document-method: Curses.def_prog_mode
01431  *
01432  * Save the current terminal modes as the "program"
01433  * state for use by the Curses.reset_prog_mode
01434  *
01435  * This is done automatically by Curses.init_screen
01436  */
01437 static VALUE
01438 curses_def_prog_mode(VALUE obj)
01439 {
01440     curses_stdscr();
01441     return def_prog_mode() == OK ? Qtrue : Qfalse;
01442 }
01443 #else
01444 #define curses_def_prog_mode rb_f_notimplement
01445 #endif
01446 
01447 #ifdef HAVE_RESET_PROG_MODE
01448 /*
01449  * Document-method: Curses.reset_prog_mode
01450  *
01451  * Reset the current terminal modes to the saved state
01452  * by the Curses.def_prog_mode
01453  *
01454  * This is done automatically by Curses.close_screen
01455  */
01456 static VALUE
01457 curses_reset_prog_mode(VALUE obj)
01458 {
01459     curses_stdscr();
01460     return reset_prog_mode() == OK ? Qtrue : Qfalse;
01461 }
01462 #else
01463 #define curses_reset_prog_mode rb_f_notimplement
01464 #endif
01465 
01466 /*-------------------------- class Window --------------------------*/
01467 
01468 /* returns a Curses::Window object */
01469 static VALUE
01470 window_s_allocate(VALUE class)
01471 {
01472     struct windata *winp;
01473 
01474     return TypedData_Make_Struct(class, struct windata, &windata_type, winp);
01475 }
01476 
01477 /*
01478  * Document-method: Curses::Window.new
01479  * call-seq: new(height, width, top, left)
01480  *
01481  * Contruct a new Curses::Window with constraints of
01482  * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column.
01483  *
01484  * A new window using full screen is called as
01485  *      Curses::Window.new(0,0,0,0)
01486  *
01487  */
01488 static VALUE
01489 window_initialize(VALUE obj, VALUE h, VALUE w, VALUE top, VALUE left)
01490 {
01491     struct windata *winp;
01492     WINDOW *window;
01493 
01494     rb_secure(4);
01495     curses_init_screen();
01496     TypedData_Get_Struct(obj, struct windata, &windata_type, winp);
01497     if (winp->window) delwin(winp->window);
01498     window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left));
01499     wclear(window);
01500     winp->window = window;
01501 
01502     return obj;
01503 }
01504 
01505 /*
01506  * Document-method: Curses::Window.subwin
01507  * call-seq: subwin(height, width, top, left)
01508  *
01509  * Contruct a new subwindow with constraints of
01510  * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column.
01511  *
01512  */
01513 static VALUE
01514 window_subwin(VALUE obj, VALUE height, VALUE width, VALUE top, VALUE left)
01515 {
01516     struct windata *winp;
01517     WINDOW *window;
01518     VALUE win;
01519     int h, w, t, l;
01520 
01521     h = NUM2INT(height);
01522     w = NUM2INT(width);
01523     t = NUM2INT(top);
01524     l = NUM2INT(left);
01525     GetWINDOW(obj, winp);
01526     window = subwin(winp->window, h, w, t, l);
01527     win = prep_window(rb_obj_class(obj), window);
01528 
01529     return win;
01530 }
01531 
01532 /*
01533  * Document-method: Curses::Window.close
01534  *
01535  * Deletes the window, and frees the memory
01536  */
01537 static VALUE
01538 window_close(VALUE obj)
01539 {
01540     struct windata *winp;
01541 
01542     GetWINDOW(obj, winp);
01543     delwin(winp->window);
01544     winp->window = 0;
01545 
01546     return Qnil;
01547 }
01548 
01549 /*
01550  * Document-method: Curses::Window.clear
01551  *
01552  * Clear the window.
01553  */
01554 static VALUE
01555 window_clear(VALUE obj)
01556 {
01557     struct windata *winp;
01558 
01559     GetWINDOW(obj, winp);
01560     wclear(winp->window);
01561 
01562     return Qnil;
01563 }
01564 
01565 /*
01566  * Document-method: Curses::Window.clrtoeol
01567  *
01568  * Clear the window to the end of line, that the cursor is currently on.
01569  */
01570 static VALUE
01571 window_clrtoeol(VALUE obj)
01572 {
01573     struct windata *winp;
01574 
01575     GetWINDOW(obj, winp);
01576     wclrtoeol(winp->window);
01577 
01578     return Qnil;
01579 }
01580 
01581 /*
01582  * Document-method: Curses::Window.refresh
01583  *
01584  * Refreshes the windows and lines.
01585  *
01586  */
01587 static VALUE
01588 window_refresh(VALUE obj)
01589 {
01590     struct windata *winp;
01591 
01592     GetWINDOW(obj, winp);
01593     wrefresh(winp->window);
01594 
01595     return Qnil;
01596 }
01597 
01598 /*
01599  * Document-method: Curses::Window.noutrefresh
01600  *
01601  * Refreshes the windows and lines.
01602  *
01603  * Curses::Window.noutrefresh allows multiple updates with
01604  * more efficiency than Curses::Window.refresh alone.
01605  */
01606 static VALUE
01607 window_noutrefresh(VALUE obj)
01608 {
01609     struct windata *winp;
01610 
01611     GetWINDOW(obj, winp);
01612 #ifdef HAVE_DOUPDATE
01613     wnoutrefresh(winp->window);
01614 #else
01615     wrefresh(winp->window);
01616 #endif
01617 
01618     return Qnil;
01619 }
01620 
01621 /*
01622  * Document-method: Curses::Window.move
01623  * call-seq: move(y,x)
01624  *
01625  * Moves the window so that the upper left-hand corner is at position (+y+, +x+)
01626  */
01627 static VALUE
01628 window_move(VALUE obj, VALUE y, VALUE x)
01629 {
01630     struct windata *winp;
01631 
01632     GetWINDOW(obj, winp);
01633     mvwin(winp->window, NUM2INT(y), NUM2INT(x));
01634 
01635     return Qnil;
01636 }
01637 
01638 /*
01639  * Document-method: Curses::Window.setpos
01640  * call-seq: setpos(y, x)
01641  *
01642  * A setter for the position of the cursor
01643  * in the current window,
01644  * using coordinates +x+ and +y+
01645  *
01646  */
01647 static VALUE
01648 window_setpos(VALUE obj, VALUE y, VALUE x)
01649 {
01650     struct windata *winp;
01651 
01652     GetWINDOW(obj, winp);
01653     wmove(winp->window, NUM2INT(y), NUM2INT(x));
01654     return Qnil;
01655 }
01656 
01657 /*
01658  * Document-method: Curses::Window.cury
01659  *
01660  * A getter for the current line (Y coord) of the window
01661  */
01662 static VALUE
01663 window_cury(VALUE obj)
01664 {
01665     struct windata *winp;
01666     int RB_UNUSED_VAR(x), y;
01667 
01668     GetWINDOW(obj, winp);
01669     getyx(winp->window, y, x);
01670     return INT2FIX(y);
01671 }
01672 
01673 /*
01674  * Document-method: Curses::Window.curx
01675  *
01676  * A getter for the current column (X coord) of the window
01677  */
01678 static VALUE
01679 window_curx(VALUE obj)
01680 {
01681     struct windata *winp;
01682     int x, RB_UNUSED_VAR(y);
01683 
01684     GetWINDOW(obj, winp);
01685     getyx(winp->window, y, x);
01686     return INT2FIX(x);
01687 }
01688 
01689 /*
01690  * Document-method: Curses::Window.maxy
01691  *
01692  * A getter for the maximum lines for the window
01693  */
01694 static VALUE
01695 window_maxy(VALUE obj)
01696 {
01697     struct windata *winp;
01698 
01699     GetWINDOW(obj, winp);
01700 #if defined(getmaxy)
01701     return INT2FIX(getmaxy(winp->window));
01702 #elif defined(getmaxyx)
01703     {
01704         int x, y;
01705         getmaxyx(winp->window, y, x);
01706         return INT2FIX(y);
01707     }
01708 #else
01709     return INT2FIX(winp->window->_maxy+1);
01710 #endif
01711 }
01712 
01713 /*
01714  * Document-method: Curses::Window.maxx
01715  *
01716  * A getter for the maximum columns for the window
01717  */
01718 static VALUE
01719 window_maxx(VALUE obj)
01720 {
01721     struct windata *winp;
01722 
01723     GetWINDOW(obj, winp);
01724 #if defined(getmaxx)
01725     return INT2FIX(getmaxx(winp->window));
01726 #elif defined(getmaxyx)
01727     {
01728         int x, y;
01729         getmaxyx(winp->window, y, x);
01730         return INT2FIX(x);
01731     }
01732 #else
01733     return INT2FIX(winp->window->_maxx+1);
01734 #endif
01735 }
01736 
01737 /*
01738  * Document-method: Curses::Window.begy
01739  *
01740  * A getter for the beginning line (Y coord) of the window
01741  */
01742 static VALUE
01743 window_begy(VALUE obj)
01744 {
01745     struct windata *winp;
01746     int RB_UNUSED_VAR(x), y;
01747 
01748     GetWINDOW(obj, winp);
01749 #ifdef getbegyx
01750     getbegyx(winp->window, y, x);
01751 #else
01752     y = winp->window->_begy;
01753 #endif
01754     return INT2FIX(y);
01755 }
01756 
01757 /*
01758  * Document-method: Curses::Window.begx
01759  *
01760  * A getter for the beginning column (X coord) of the window
01761  */
01762 static VALUE
01763 window_begx(VALUE obj)
01764 {
01765     struct windata *winp;
01766     int x, RB_UNUSED_VAR(y);
01767 
01768     GetWINDOW(obj, winp);
01769 #ifdef getbegyx
01770     getbegyx(winp->window, y, x);
01771 #else
01772     x = winp->window->_begx;
01773 #endif
01774     return INT2FIX(x);
01775 }
01776 
01777 /*
01778  * Document-method: Curses::Window.box
01779  * call-seq: box(vert, hor)
01780  *
01781  * set the characters to frame the window in.
01782  * The vertical +vert+ and horizontal +hor+ character.
01783  *
01784  *      win = Curses::Window.new(5,5,5,5)
01785  *      win.box(?|, ?-)
01786  *
01787  */
01788 static VALUE
01789 window_box(int argc, VALUE *argv, VALUE self)
01790 {
01791     struct windata *winp;
01792     VALUE vert, hor, corn;
01793 
01794     rb_scan_args(argc, argv, "21", &vert, &hor, &corn);
01795 
01796     GetWINDOW(self, winp);
01797     box(winp->window, NUM2CH(vert), NUM2CH(hor));
01798 
01799     if (!NIL_P(corn)) {
01800         int cur_x, cur_y, x, y;
01801         chtype c;
01802 
01803         c = NUM2CH(corn);
01804         getyx(winp->window, cur_y, cur_x);
01805         x = NUM2INT(window_maxx(self)) - 1;
01806         y = NUM2INT(window_maxy(self)) - 1;
01807         wmove(winp->window, 0, 0);
01808         waddch(winp->window, c);
01809         wmove(winp->window, y, 0);
01810         waddch(winp->window, c);
01811         wmove(winp->window, y, x);
01812         waddch(winp->window, c);
01813         wmove(winp->window, 0, x);
01814         waddch(winp->window, c);
01815         wmove(winp->window, cur_y, cur_x);
01816     }
01817 
01818     return Qnil;
01819 }
01820 
01821 /*
01822  * Document-method: Curses::Window.standout
01823  *
01824  * Enables the best highlighting mode of the terminal.
01825  *
01826  * This is equivalent to Curses::Window.attron(A_STANDOUT)
01827  *
01828  * see also Curses::Window.attrset
01829  */
01830 static VALUE
01831 window_standout(VALUE obj)
01832 {
01833     struct windata *winp;
01834 
01835     GetWINDOW(obj, winp);
01836     wstandout(winp->window);
01837     return Qnil;
01838 }
01839 
01840 /*
01841  * Document-method: Curses::Window.standend
01842  *
01843  * Enables the Normal display (no highlight)
01844  *
01845  * This is equivalent to Curses::Window.attron(A_NORMAL)
01846  *
01847  * see also Curses::Window.attrset
01848  */
01849 static VALUE
01850 window_standend(VALUE obj)
01851 {
01852     struct windata *winp;
01853 
01854     GetWINDOW(obj, winp);
01855     wstandend(winp->window);
01856     return Qnil;
01857 }
01858 
01859 /*
01860  * Document-method: Curses::Window.inch
01861  *
01862  * Returns the character at the current position of the window.
01863  */
01864 static VALUE
01865 window_inch(VALUE obj)
01866 {
01867     struct windata *winp;
01868 
01869     GetWINDOW(obj, winp);
01870     return CH2FIX(winch(winp->window));
01871 }
01872 
01873 /*
01874  * Document-method: Curses::Window.addch
01875  * call-seq: addch(ch)
01876  *
01877  * Add a character +ch+, with attributes, to the window, then advance the cursor.
01878  *
01879  * see also the system manual for curs_addch(3)
01880  */
01881 static VALUE
01882 window_addch(VALUE obj, VALUE ch)
01883 {
01884     struct windata *winp;
01885 
01886     GetWINDOW(obj, winp);
01887     waddch(winp->window, NUM2CH(ch));
01888 
01889     return Qnil;
01890 }
01891 
01892 /*
01893  * Document-method: Curses::Window.insch
01894  * call-seq: insch(ch)
01895  *
01896  * Insert a character +ch+, before the cursor, in the current window
01897  *
01898  */
01899 static VALUE
01900 window_insch(VALUE obj, VALUE ch)
01901 {
01902     struct windata *winp;
01903 
01904     GetWINDOW(obj, winp);
01905     winsch(winp->window, NUM2CH(ch));
01906 
01907     return Qnil;
01908 }
01909 
01910 /*
01911  * Document-method: Curses::Window.addstr
01912  * call-seq: addstr(str)
01913  *
01914  * add a string of characters +str+, to the window and advance cursor
01915  *
01916  */
01917 static VALUE
01918 window_addstr(VALUE obj, VALUE str)
01919 {
01920     if (!NIL_P(str)) {
01921         struct windata *winp;
01922 
01923         StringValue(str);
01924         str = rb_str_export_locale(str);
01925         GetWINDOW(obj, winp);
01926         waddstr(winp->window, StringValueCStr(str));
01927     }
01928     return Qnil;
01929 }
01930 
01931 /*
01932  * Document-method: Curses::Window.<<
01933  *
01934  * call-seq:
01935  *   <<(str)
01936  *
01937  * Add String +str+ to the current string.
01938  *
01939  * See also Curses::Window.addstr
01940  */
01941 static VALUE
01942 window_addstr2(VALUE obj, VALUE str)
01943 {
01944     window_addstr(obj, str);
01945     return obj;
01946 }
01947 
01948 struct wgetch_arg {
01949     WINDOW *win;
01950     int c;
01951 };
01952 
01953 static void *
01954 wgetch_func(void *_arg)
01955 {
01956     struct wgetch_arg *arg = (struct wgetch_arg *)_arg;
01957     arg->c = wgetch(arg->win);
01958     return 0;
01959 }
01960 
01961 /*
01962  * Document-method: Curses::Window.getch
01963  *
01964  * Read and returns a character from the window.
01965  *
01966  * See Curses::Key to all the function KEY_* available
01967  *
01968  */
01969 static VALUE
01970 window_getch(VALUE obj)
01971 {
01972     struct windata *winp;
01973     struct wgetch_arg arg;
01974     int c;
01975 
01976     GetWINDOW(obj, winp);
01977     arg.win = winp->window;
01978     rb_thread_call_without_gvl(wgetch_func, (void *)&arg, RUBY_UBF_IO, 0);
01979     c = arg.c;
01980     if (c == EOF) return Qnil;
01981     if (rb_isprint(c)) {
01982         char ch = (char)c;
01983 
01984         return rb_locale_str_new(&ch, 1);
01985     }
01986     return UINT2NUM(c);
01987 }
01988 
01989 struct wgetstr_arg {
01990     WINDOW *win;
01991     char rtn[GETSTR_BUF_SIZE];
01992 };
01993 
01994 static void *
01995 wgetstr_func(void *_arg)
01996 {
01997     struct wgetstr_arg *arg = (struct wgetstr_arg *)_arg;
01998 #if defined(HAVE_WGETNSTR)
01999     wgetnstr(arg->win, arg->rtn, GETSTR_BUF_SIZE-1);
02000 #else
02001     wgetstr(arg->win, arg->rtn);
02002 #endif
02003     return 0;
02004 }
02005 
02006 /*
02007  * Document-method: Curses::Window.getstr
02008  *
02009  * This is equivalent to a series f Curses::Window.getch calls
02010  *
02011  */
02012 static VALUE
02013 window_getstr(VALUE obj)
02014 {
02015     struct windata *winp;
02016     struct wgetstr_arg arg;
02017 
02018     GetWINDOW(obj, winp);
02019     arg.win = winp->window;
02020     rb_thread_call_without_gvl(wgetstr_func, (void *)&arg, RUBY_UBF_IO, 0);
02021     return rb_locale_str_new_cstr(arg.rtn);
02022 }
02023 
02024 /*
02025  * Document-method: Curses::Window.delch
02026  *
02027  * Delete the character under the cursor
02028  *
02029  */
02030 static VALUE
02031 window_delch(VALUE obj)
02032 {
02033     struct windata *winp;
02034 
02035     GetWINDOW(obj, winp);
02036     wdelch(winp->window);
02037     return Qnil;
02038 }
02039 
02040 /*
02041  * Document-method: Curses::Window.deleteln
02042  *
02043  * Delete the line under the cursor.
02044  *
02045  */
02046 static VALUE
02047 window_deleteln(VALUE obj)
02048 {
02049 #if defined(HAVE_WDELETELN) || defined(wdeleteln)
02050     struct windata *winp;
02051 
02052     GetWINDOW(obj, winp);
02053     wdeleteln(winp->window);
02054 #endif
02055     return Qnil;
02056 }
02057 
02058 /*
02059  * Document-method: Curses::Window.insertln
02060  *
02061  * Inserts a line above the cursor, and the bottom line is lost
02062  *
02063  */
02064 static VALUE
02065 window_insertln(VALUE obj)
02066 {
02067 #if defined(HAVE_WINSERTLN) || defined(winsertln)
02068     struct windata *winp;
02069 
02070     GetWINDOW(obj, winp);
02071     winsertln(winp->window);
02072 #endif
02073     return Qnil;
02074 }
02075 
02076 /*
02077  * Document-method: Curses::Window.scrollok
02078  * call-seq: scrollok(bool)
02079  *
02080  * Controls what happens when the cursor of a window
02081  * is moved off the edge of the window or scrolling region,
02082  * either as a result of a newline action on the bottom line,
02083  * or typing the last character of the last line.
02084  *
02085  * If disabled, (+bool+ is false), the cursor is left on the bottom line.
02086  *
02087  * If enabled, (+bool+ is true), the window is scrolled up one line
02088  * (Note that to get the physical scrolling effect on the terminal,
02089  * it is also necessary to call Curses::Window.idlok)
02090  */
02091 static VALUE
02092 window_scrollok(VALUE obj, VALUE bf)
02093 {
02094     struct windata *winp;
02095 
02096     GetWINDOW(obj, winp);
02097     scrollok(winp->window, RTEST(bf) ? TRUE : FALSE);
02098     return Qnil;
02099 }
02100 
02101 /*
02102  * Document-method: Curses::Window.idlok
02103  * call-seq: idlok(bool)
02104  *
02105  * If +bool+ is +true+ curses considers using the hardware insert/delete
02106  * line feature of terminals so equipped.
02107  *
02108  * If +bool+ is +false+, disables use of line insertion and deletion.
02109  * This option should be enabled only if the application needs insert/delete
02110  * line, for example, for a screen editor.
02111  *
02112  * It is disabled by default because insert/delete line tends to be visually
02113  * annoying when used in applications where it is not really needed.
02114  * If insert/delete line cannot be used, curses redraws the changed portions of all lines.
02115  *
02116  */
02117 static VALUE
02118 window_idlok(VALUE obj, VALUE bf)
02119 {
02120     struct windata *winp;
02121 
02122     GetWINDOW(obj, winp);
02123     idlok(winp->window, RTEST(bf) ? TRUE : FALSE);
02124     return Qnil;
02125 }
02126 
02127 /*
02128  * Document-method: Curses::Window.setscrreg
02129  * call-seq:
02130  *   setscrreg(top, bottom)
02131  *
02132  * Set a software scrolling region in a window.
02133  * +top+ and +bottom+ are lines numbers of the margin.
02134  *
02135  * If this option and Curses::Window.scrollok are enabled, an attempt to move
02136  * off the bottom margin line causes all lines in the scrolling region to
02137  * scroll one line in the direction of the first line.  Only the text of the
02138  * window is scrolled.
02139  *
02140  */
02141 static VALUE
02142 window_setscrreg(VALUE obj, VALUE top, VALUE bottom)
02143 {
02144 #ifdef HAVE_WSETSCRREG
02145     struct windata *winp;
02146     int res;
02147 
02148     GetWINDOW(obj, winp);
02149     res = wsetscrreg(winp->window, NUM2INT(top), NUM2INT(bottom));
02150     /* may have to raise exception on ERR */
02151     return (res == OK) ? Qtrue : Qfalse;
02152 #else
02153     return Qfalse;
02154 #endif
02155 }
02156 
02157 #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
02158 /*
02159  * Document-method: Curses::Window.color_set
02160  * call-seq: color_set(col)
02161  *
02162  * Sets the current color of the given window to the
02163  * foreground/background combination described by the Fixnum +col+.
02164  */
02165 static VALUE
02166 window_color_set(VALUE obj, VALUE col)
02167 {
02168     struct windata *winp;
02169     int res;
02170 
02171     GetWINDOW(obj, winp);
02172     res = wcolor_set(winp->window, NUM2INT(col), NULL);
02173     return (res == OK) ? Qtrue : Qfalse;
02174 }
02175 #endif /* defined(USE_COLOR) && defined(HAVE_WCOLOR_SET) */
02176 
02177 /*
02178  * Document-method: Curses::Window.scroll
02179  *
02180  * Scrolls the current window up one line.
02181  */
02182 static VALUE
02183 window_scroll(VALUE obj)
02184 {
02185     struct windata *winp;
02186 
02187     GetWINDOW(obj, winp);
02188     /* may have to raise exception on ERR */
02189     return (scroll(winp->window) == OK) ? Qtrue : Qfalse;
02190 }
02191 
02192 /*
02193  * Document-method: Curses::Window.scrl
02194  * call-seq: scrl(num)
02195  *
02196  * Scrolls the current window Fixnum +num+ lines.
02197  * The current cursor position is not changed.
02198  *
02199  * For positive +num+, it scrolls up.
02200  *
02201  * For negative +num+, it scrolls down.
02202  *
02203  */
02204 static VALUE
02205 window_scrl(VALUE obj, VALUE n)
02206 {
02207 #ifdef HAVE_WSCRL
02208     struct windata *winp;
02209 
02210     GetWINDOW(obj, winp);
02211     /* may have to raise exception on ERR */
02212     return (wscrl(winp->window,NUM2INT(n)) == OK) ? Qtrue : Qfalse;
02213 #else
02214     return Qfalse;
02215 #endif
02216 }
02217 
02218 /*
02219  * Document-method: Curses::Window.attroff
02220  * call-seq: attroff(attrs)
02221  *
02222  * Turns on the named attributes +attrs+ without affecting any others.
02223  *
02224  * See also Curses::Window.attrset
02225  */
02226 static VALUE
02227 window_attroff(VALUE obj, VALUE attrs)
02228 {
02229 #ifdef HAVE_WATTROFF
02230     struct windata *winp;
02231 
02232     GetWINDOW(obj,winp);
02233     return INT2FIX(wattroff(winp->window,NUM2INT(attrs)));
02234 #else
02235     return Qtrue;
02236 #endif
02237 }
02238 
02239 /*
02240  * Document-method: Curses::Window.attron
02241  * call-seq: attron(attrs)
02242  *
02243  * Turns off the named attributes +attrs+
02244  * without turning any other attributes on or off.
02245  *
02246  * See also Curses::Window.attrset
02247  */
02248 static VALUE
02249 window_attron(VALUE obj, VALUE attrs)
02250 {
02251 #ifdef HAVE_WATTRON
02252     struct windata *winp;
02253     VALUE val;
02254 
02255     GetWINDOW(obj,winp);
02256     val = INT2FIX(wattron(winp->window,NUM2INT(attrs)));
02257     if (rb_block_given_p()) {
02258         rb_yield(val);
02259         wattroff(winp->window,NUM2INT(attrs));
02260         return val;
02261     }
02262     else{
02263         return val;
02264     }
02265 #else
02266     return Qtrue;
02267 #endif
02268 }
02269 
02270 /*
02271  * Document-method: Curses::Window.attrset
02272  * call-seq: attrset(attrs)
02273  *
02274  * Sets the current attributes of the given window to +attrs+.
02275  *
02276  * The following video attributes, defined in <curses.h>, can
02277  * be passed to the routines Curses::Window.attron, Curses::Window.attroff,
02278  * and Curses::Window.attrset, or OR'd with the characters passed to addch.
02279  *   A_NORMAL        Normal display (no highlight)
02280  *   A_STANDOUT      Best highlighting mode of the terminal.
02281  *   A_UNDERLINE     Underlining
02282  *   A_REVERSE       Reverse video
02283  *   A_BLINK         Blinking
02284  *   A_DIM           Half bright
02285  *   A_BOLD          Extra bright or bold
02286  *   A_PROTECT       Protected mode
02287  *   A_INVIS         Invisible or blank mode
02288  *   A_ALTCHARSET    Alternate character set
02289  *   A_CHARTEXT      Bit-mask to extract a character
02290  *   COLOR_PAIR(n)   Color-pair number n
02291  *
02292  * TODO: provide some examples here.
02293  *
02294  * see also system manual curs_attr(3)
02295  */
02296 static VALUE
02297 window_attrset(VALUE obj, VALUE attrs)
02298 {
02299 #ifdef HAVE_WATTRSET
02300     struct windata *winp;
02301 
02302     GetWINDOW(obj,winp);
02303     return INT2FIX(wattrset(winp->window,NUM2INT(attrs)));
02304 #else
02305     return Qtrue;
02306 #endif
02307 }
02308 
02309 /*
02310  * Document-method: Curses::Window.bkgdset
02311  * call-seq: bkgdset(ch)
02312  *
02313  * Manipulate the background of the current window
02314  * with character Integer +ch+
02315  *
02316  * see also Curses.bkgdset
02317  */
02318 static VALUE
02319 window_bkgdset(VALUE obj, VALUE ch)
02320 {
02321 #ifdef HAVE_WBKGDSET
02322     struct windata *winp;
02323 
02324     GetWINDOW(obj,winp);
02325     wbkgdset(winp->window, NUM2CH(ch));
02326 #endif
02327     return Qnil;
02328 }
02329 
02330 /*
02331  * Document-method: Curses::Window.bkgd
02332  * call-seq: bkgd(ch)
02333  *
02334  * Set the background of the current window
02335  * and apply character Integer +ch+ to every character.
02336  *
02337  * see also Curses.bkgd
02338  */
02339 static VALUE
02340 window_bkgd(VALUE obj, VALUE ch)
02341 {
02342 #ifdef HAVE_WBKGD
02343     struct windata *winp;
02344 
02345     GetWINDOW(obj,winp);
02346     return (wbkgd(winp->window, NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
02347 #else
02348     return Qfalse;
02349 #endif
02350 }
02351 
02352 /*
02353  * Document-method: Curses::Window.getbkgd
02354  *
02355  * Returns an Interer (+ch+) for the character property in the current window.
02356  */
02357 static VALUE
02358 window_getbkgd(VALUE obj)
02359 {
02360 #ifdef HAVE_WGETBKGD
02361     chtype c;
02362     struct windata *winp;
02363 
02364     GetWINDOW(obj,winp);
02365     return (c = getbkgd(winp->window) != ERR) ? CH2FIX(c) : Qnil;
02366 #else
02367     return Qnil;
02368 #endif
02369 }
02370 
02371 /*
02372  * Document-method: Curses::Window.resize
02373  * call-seq: resize(lines, cols)
02374  *
02375  * Resize the current window to Fixnum +lines+ and Fixnum +cols+
02376  *
02377  */
02378 static VALUE
02379 window_resize(VALUE obj, VALUE lin, VALUE col)
02380 {
02381 #if defined(HAVE_WRESIZE)
02382     struct windata *winp;
02383 
02384     GetWINDOW(obj,winp);
02385     return wresize(winp->window, NUM2INT(lin), NUM2INT(col)) == OK ? Qtrue : Qfalse;
02386 #else
02387     return Qnil;
02388 #endif
02389 }
02390 
02391 
02392 #ifdef HAVE_KEYPAD
02393 /*
02394  * Document-method: Curses::Window.keypad=
02395  * call-seq:
02396  *   keypad=(bool)
02397  *
02398  * See Curses::Window.keypad
02399  */
02400 
02401 /*
02402  * Document-method: Curses::Window.keypad
02403  * call-seq:
02404  *   keypad(bool)
02405  *
02406  * Enables the keypad of the user's terminal.
02407  *
02408  * If enabled (+bool+ is +true+), the user can press a function key
02409  * (such as an arrow key) and wgetch returns a single value representing
02410  * the function key, as in KEY_LEFT.  If disabled (+bool+ is +false+),
02411  * curses does not treat function keys specially and the program has to
02412  * interpret the escape sequences itself.  If the keypad in the terminal
02413  * can be turned on (made to transmit) and off (made to work locally),
02414  * turning on this option causes the terminal keypad to be turned on when
02415  * Curses::Window.getch is called.
02416  *
02417  * The default value for keypad is false.
02418  *
02419  */
02420 static VALUE
02421 window_keypad(VALUE obj, VALUE val)
02422 {
02423     struct windata *winp;
02424 
02425     GetWINDOW(obj,winp);
02426     /* keypad() of NetBSD's libcurses returns no value */
02427 #if defined(__NetBSD__) && !defined(NCURSES_VERSION)
02428     keypad(winp->window,(RTEST(val) ? TRUE : FALSE));
02429     return Qnil;
02430 #else
02431     /* may have to raise exception on ERR */
02432     return (keypad(winp->window,RTEST(val) ? TRUE : FALSE)) == OK ?
02433         Qtrue : Qfalse;
02434 #endif
02435 }
02436 #else
02437 #define window_keypad rb_f_notimplement
02438 #endif
02439 
02440 #ifdef HAVE_NODELAY
02441 /*
02442  * Document-method: Curses::Window.nodelay
02443  * call-seq:
02444  *   window.nodelay = bool
02445  *
02446  * When in no-delay mode Curses::Window#getch is a non-blocking call.  If no
02447  * input is ready #getch returns ERR.
02448  *
02449  * When in delay mode (+bool+ is +false+ which is the default),
02450  * Curses::Window#getch blocks until a key is pressed.
02451  *
02452  */
02453 static VALUE
02454 window_nodelay(VALUE obj, VALUE val)
02455 {
02456     struct windata *winp;
02457     GetWINDOW(obj,winp);
02458 
02459     /* nodelay() of NetBSD's libcurses returns no value */
02460 #if defined(__NetBSD__) && !defined(NCURSES_VERSION)
02461     nodelay(winp->window, RTEST(val) ? TRUE : FALSE);
02462     return Qnil;
02463 #else
02464     return nodelay(winp->window,RTEST(val) ? TRUE : FALSE) == OK ? Qtrue : Qfalse;
02465 #endif
02466 }
02467 #else
02468 #define window_nodelay rb_f_notimplement
02469 #endif
02470 
02471 #ifdef HAVE_WTIMEOUT
02472 /*
02473  * Document-method: Curses::Window.timeout=
02474  * call-seq: timeout=(delay)
02475  *
02476  * Sets block and non-blocking reads for the window.
02477  * - If delay is negative, blocking read is used (i.e., waits indefinitely for input).
02478  * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting).
02479  * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input.
02480  *
02481  */
02482 static VALUE
02483 window_timeout(VALUE obj, VALUE delay)
02484 {
02485     struct windata *winp;
02486     GetWINDOW(obj,winp);
02487 
02488     wtimeout(winp->window,NUM2INT(delay));
02489     return Qnil;
02490 }
02491 #else
02492 #define window_timeout rb_f_notimplement
02493 #endif
02494 
02495 /*--------------------------- class Pad ----------------------------*/
02496 
02497 #ifdef HAVE_NEWPAD
02498 /*
02499  * Document-method: Curses::Pad.new
02500  *
02501  * call-seq:
02502  *   new(height, width)
02503  *
02504  * Contruct a new Curses::Pad with constraints of +height+ lines, +width+
02505  * columns
02506  *
02507  */
02508 static VALUE
02509 pad_initialize(VALUE obj, VALUE h, VALUE w)
02510 {
02511     struct windata *padp;
02512     WINDOW *window;
02513 
02514     rb_secure(4);
02515     curses_init_screen();
02516     TypedData_Get_Struct(obj, struct windata, &windata_type, padp);
02517     if (padp->window) delwin(padp->window);
02518     window = newpad(NUM2INT(h), NUM2INT(w));
02519     wclear(window);
02520     padp->window = window;
02521 
02522     return obj;
02523 }
02524 
02525 #if 1
02526 #define pad_subpad window_subwin
02527 #else
02528 /*
02529  * Document-method: Curses::Pad.subpad
02530  * call-seq:
02531  *   subpad(height, width, begin_x, begin_y)
02532  *
02533  * Contruct a new subpad with constraints of +height+ lines, +width+ columns,
02534  * begin at +begin_x+ line, and +begin_y+ columns on the pad.
02535  *
02536  */
02537 static VALUE
02538 pad_subpad(VALUE obj, VALUE height, VALUE width, VALUE begin_x, VALUE begin_y)
02539 {
02540     struct windata *padp;
02541     WINDOW *subpad;
02542     VALUE pad;
02543     int h, w, x, y;
02544 
02545     h = NUM2INT(height);
02546     w = NUM2INT(width);
02547     x = NUM2INT(begin_x);
02548     y = NUM2INT(begin_y);
02549     GetWINDOW(obj, padp);
02550     subpad = subwin(padp->window, h, w, x, y);
02551     pad = prep_window(rb_obj_class(obj), subpad);
02552 
02553     return pad;
02554 }
02555 #endif
02556 
02557 /*
02558  * Document-method: Curses::Pad.refresh
02559  *
02560  * call-seq:
02561  *   pad.refresh(pad_minrow, pad_mincol, screen_minrow, screen_mincol, screen_maxrow, screen_maxcol)
02562  *
02563  * Refreshes the pad.  +pad_minrow+ and pad_mincol+ define the upper-left
02564  * corner of the rectangle to be displayed.  +screen_minrow+, +screen_mincol+,
02565  * +screen_maxrow+, +screen_maxcol+ define the edges of the rectangle to be
02566  * displayed on the screen.
02567  *
02568  */
02569 static VALUE
02570 pad_refresh(VALUE obj, VALUE pminrow, VALUE pmincol, VALUE sminrow,
02571             VALUE smincol, VALUE smaxrow, VALUE smaxcol)
02572 {
02573     struct windata *padp;
02574     int pmr, pmc, smr, smc, sxr, sxc;
02575 
02576     pmr = NUM2INT(pminrow);
02577     pmc = NUM2INT(pmincol);
02578     smr = NUM2INT(sminrow);
02579     smc = NUM2INT(smincol);
02580     sxr = NUM2INT(smaxrow);
02581     sxc = NUM2INT(smaxcol);
02582 
02583     GetWINDOW(obj, padp);
02584     prefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc);
02585 
02586     return Qnil;
02587 }
02588 
02589 /*
02590  * Document-method: Curses::Pad.noutrefresh
02591  *
02592  * call-seq:
02593  *   pad.noutrefresh(pad_minrow, pad_mincol, screen_minrow, screen_mincol, screen_maxrow, screen_maxcol)
02594  *
02595  * Refreshes the pad.  +pad_minrow+ and pad_mincol+ define the upper-left
02596  * corner of the rectangle to be displayed.  +screen_minrow+, +screen_mincol+,
02597  * +screen_maxrow+, +screen_maxcol+ define the edges of the rectangle to be
02598  * displayed on the screen.
02599  *
02600  */
02601 static VALUE
02602 pad_noutrefresh(VALUE obj, VALUE pminrow, VALUE pmincol, VALUE sminrow,
02603                 VALUE smincol, VALUE smaxrow, VALUE smaxcol)
02604 {
02605     struct windata *padp;
02606     int pmr, pmc, smr, smc, sxr, sxc;
02607 
02608     pmr = NUM2INT(pminrow);
02609     pmc = NUM2INT(pmincol);
02610     smr = NUM2INT(sminrow);
02611     smc = NUM2INT(smincol);
02612     sxr = NUM2INT(smaxrow);
02613     sxc = NUM2INT(smaxcol);
02614 
02615     GetWINDOW(obj, padp);
02616 #ifdef HAVE_DOUPDATE
02617     pnoutrefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc);
02618 #else
02619     prefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc);
02620 #endif
02621 
02622     return Qnil;
02623 }
02624 #endif /* HAVE_NEWPAD */
02625 
02626 /*------------------------- Initialization -------------------------*/
02627 
02628 /*
02629  * Document-module: Curses
02630  *
02631  * == Description
02632  * An implementation of the CRT screen handling and optimization library.
02633  *
02634  * == Structures and such
02635  *
02636  * === Classes
02637  *
02638  * * Curses::Window - class with the means to draw a window or box
02639  * * Curses::MouseEvent - class for collecting mouse events
02640  *
02641  * === Modules
02642  *
02643  * Curses:: The curses implementation
02644  * Curses::Key:: Collection of constants for keypress events
02645  *
02646  * == Examples
02647  *
02648  * * hello.rb
02649  *     :include: hello.rb
02650  *
02651  *
02652  * * rain.rb
02653  *     :include: rain.rb
02654  *
02655  *
02656  */
02657 void
02658 Init_curses(void)
02659 {
02660     mCurses    = rb_define_module("Curses");
02661 
02662     /*
02663      * Document-module: Curses::Key
02664      *
02665      *
02666      * a container for the KEY_* values.
02667      *
02668      * See also system manual for getch(3)
02669      *
02670      */
02671     mKey       = rb_define_module_under(mCurses, "Key");
02672 
02673     rb_gc_register_address(&rb_stdscr);
02674 
02675 #ifdef USE_MOUSE
02676     /*
02677      * Document-class: Curses::MouseEvent
02678      *
02679      * == Description
02680      *
02681      * Curses::MouseEvent
02682      *
02683      * == Example
02684      *
02685      * * mouse.rb
02686      *     :include: mouse.rb
02687      *
02688      */
02689     cMouseEvent = rb_define_class_under(mCurses,"MouseEvent",rb_cObject);
02690     rb_undef_method(CLASS_OF(cMouseEvent),"new");
02691     rb_define_method(cMouseEvent, "eid", curs_mouse_id, 0);
02692     rb_define_method(cMouseEvent, "x", curs_mouse_x, 0);
02693     rb_define_method(cMouseEvent, "y", curs_mouse_y, 0);
02694     rb_define_method(cMouseEvent, "z", curs_mouse_z, 0);
02695     rb_define_method(cMouseEvent, "bstate", curs_mouse_bstate, 0);
02696 #endif /* USE_MOUSE */
02697 
02698     rb_define_module_function(mCurses, "ESCDELAY=", curses_escdelay_set, 1);
02699     rb_define_module_function(mCurses, "ESCDELAY", curses_escdelay_get, 0);
02700     rb_define_module_function(mCurses, "TABSIZE", curses_tabsize_get, 0);
02701     rb_define_module_function(mCurses, "TABSIZE=", curses_tabsize_set, 1);
02702 
02703     rb_define_module_function(mCurses, "use_default_colors", curses_use_default_colors, 0);
02704     rb_define_module_function(mCurses, "init_screen", curses_init_screen, 0);
02705     rb_define_module_function(mCurses, "close_screen", curses_close_screen, 0);
02706     rb_define_module_function(mCurses, "closed?", curses_closed, 0);
02707     rb_define_module_function(mCurses, "stdscr", curses_stdscr, 0);
02708     rb_define_module_function(mCurses, "refresh", curses_refresh, 0);
02709     rb_define_module_function(mCurses, "doupdate", curses_doupdate, 0);
02710     rb_define_module_function(mCurses, "clear", curses_clear, 0);
02711     rb_define_module_function(mCurses, "clrtoeol", curses_clrtoeol, 0);
02712     rb_define_module_function(mCurses, "echo", curses_echo, 0);
02713     rb_define_module_function(mCurses, "noecho", curses_noecho, 0);
02714     rb_define_module_function(mCurses, "raw", curses_raw, 0);
02715     rb_define_module_function(mCurses, "noraw", curses_noraw, 0);
02716     rb_define_module_function(mCurses, "cbreak", curses_cbreak, 0);
02717     rb_define_module_function(mCurses, "nocbreak", curses_nocbreak, 0);
02718     rb_define_module_function(mCurses, "crmode", curses_cbreak, 0);
02719     rb_define_module_function(mCurses, "nocrmode", curses_nocbreak, 0);
02720     rb_define_module_function(mCurses, "nl", curses_nl, 0);
02721     rb_define_module_function(mCurses, "nonl", curses_nonl, 0);
02722     rb_define_module_function(mCurses, "beep", curses_beep, 0);
02723     rb_define_module_function(mCurses, "flash", curses_flash, 0);
02724     rb_define_module_function(mCurses, "ungetch", curses_ungetch, 1);
02725     rb_define_module_function(mCurses, "setpos", curses_setpos, 2);
02726     rb_define_module_function(mCurses, "standout", curses_standout, 0);
02727     rb_define_module_function(mCurses, "standend", curses_standend, 0);
02728     rb_define_module_function(mCurses, "inch", curses_inch, 0);
02729     rb_define_module_function(mCurses, "addch", curses_addch, 1);
02730     rb_define_module_function(mCurses, "insch", curses_insch, 1);
02731     rb_define_module_function(mCurses, "addstr", curses_addstr, 1);
02732     rb_define_module_function(mCurses, "getch", curses_getch, 0);
02733     rb_define_module_function(mCurses, "getstr", curses_getstr, 0);
02734     rb_define_module_function(mCurses, "delch", curses_delch, 0);
02735     rb_define_module_function(mCurses, "deleteln", curses_deleteln, 0);
02736     rb_define_module_function(mCurses, "insertln", curses_insertln, 0);
02737     rb_define_module_function(mCurses, "keyname", curses_keyname, 1);
02738     rb_define_module_function(mCurses, "lines", curses_lines, 0);
02739     rb_define_module_function(mCurses, "cols", curses_cols, 0);
02740     rb_define_module_function(mCurses, "curs_set", curses_curs_set, 1);
02741     rb_define_module_function(mCurses, "scrl", curses_scrl, 1);
02742     rb_define_module_function(mCurses, "setscrreg", curses_setscrreg, 2);
02743     rb_define_module_function(mCurses, "attroff", curses_attroff, 1);
02744     rb_define_module_function(mCurses, "attron", curses_attron, 1);
02745     rb_define_module_function(mCurses, "attrset", curses_attrset, 1);
02746     rb_define_module_function(mCurses, "bkgdset", curses_bkgdset, 1);
02747     rb_define_module_function(mCurses, "bkgd", curses_bkgd, 1);
02748     rb_define_module_function(mCurses, "resizeterm", curses_resizeterm, 2);
02749     rb_define_module_function(mCurses, "resize", curses_resizeterm, 2);
02750 #ifdef USE_COLOR
02751     rb_define_module_function(mCurses, "start_color", curses_start_color, 0);
02752     rb_define_module_function(mCurses, "init_pair", curses_init_pair, 3);
02753     rb_define_module_function(mCurses, "init_color", curses_init_color, 4);
02754     rb_define_module_function(mCurses, "has_colors?", curses_has_colors, 0);
02755     rb_define_module_function(mCurses, "can_change_color?",
02756                               curses_can_change_color, 0);
02757     rb_define_module_function(mCurses, "colors", curses_colors, 0);
02758     rb_define_module_function(mCurses, "color_content", curses_color_content, 1);
02759     rb_define_module_function(mCurses, "color_pairs", curses_color_pairs, 0);
02760     rb_define_module_function(mCurses, "pair_content", curses_pair_content, 1);
02761     rb_define_module_function(mCurses, "color_pair", curses_color_pair, 1);
02762     rb_define_module_function(mCurses, "pair_number", curses_pair_number, 1);
02763 #endif /* USE_COLOR */
02764 #ifdef USE_MOUSE
02765     rb_define_module_function(mCurses, "getmouse", curses_getmouse, 0);
02766     rb_define_module_function(mCurses, "ungetmouse", curses_ungetmouse, 1);
02767     rb_define_module_function(mCurses, "mouseinterval", curses_mouseinterval, 1);
02768     rb_define_module_function(mCurses, "mousemask", curses_mousemask, 1);
02769 #endif /* USE_MOUSE */
02770 
02771     rb_define_module_function(mCurses, "timeout=", curses_timeout, 1);
02772     rb_define_module_function(mCurses, "def_prog_mode", curses_def_prog_mode, 0);
02773     rb_define_module_function(mCurses, "reset_prog_mode", curses_reset_prog_mode, 0);
02774 
02775     {
02776         VALUE version;
02777 #if defined(HAVE_FUNC_CURSES_VERSION)
02778         /* ncurses and PDcurses */
02779         version = rb_str_new2(curses_version());
02780 #elif defined(HAVE_VAR_CURSES_VERSION)
02781         /* SVR4 curses has an undocumented and undeclared variable, curses_version.
02782          * It contains a string, "SVR4".  */
02783         RUBY_EXTERN char *curses_version;
02784         version = rb_sprintf("curses (%s)", curses_version);
02785 #else
02786         /* BSD curses, perhaps.  NetBSD 5 still use it. */
02787         version = rb_str_new2("curses (unknown)");
02788 #endif
02789         /*
02790          * Identifies curses library version.
02791          *
02792          * - "ncurses 5.9.20110404"
02793          * - "PDCurses 3.4 - Public Domain 2008"
02794          * - "curses (SVR4)" (System V curses)
02795          * - "curses (unknown)" (The original BSD curses?  NetBSD maybe.)
02796          *
02797          */
02798         rb_define_const(mCurses, "VERSION", version);
02799     }
02800 
02801     /*
02802      * Document-class: Curses::Window
02803      *
02804      * == Description
02805      *
02806      * The means by which to create and manage frames or windows.
02807      * While there may be more than one window at a time, only one window
02808      * will receive input.
02809      *
02810      * == Usage
02811      *
02812      *   require 'curses'
02813      *
02814      *   Curses.init_screen()
02815      *
02816      *   my_str = "LOOK! PONIES!"
02817      *   win = Curses::Window.new( 8, (my_str.length + 10),
02818      *                             (Curses.lines - 8) / 2,
02819      *                             (Curses.cols - (my_str.length + 10)) / 2 )
02820      *   win.box("|", "-")
02821      *   win.setpos(2,3)
02822      *   win.addstr(my_str)
02823      *   # or even
02824      *   win << "\nORLY"
02825      *   win << "\nYES!! " + my_str
02826      *   win.refresh
02827      *   win.getch
02828      *   win.close
02829      *
02830      */
02831     cWindow = rb_define_class_under(mCurses, "Window", rb_cData);
02832     rb_define_alloc_func(cWindow, window_s_allocate);
02833     rb_define_method(cWindow, "initialize", window_initialize, 4);
02834     rb_define_method(cWindow, "subwin", window_subwin, 4);
02835     rb_define_method(cWindow, "close", window_close, 0);
02836     rb_define_method(cWindow, "clear", window_clear, 0);
02837     rb_define_method(cWindow, "clrtoeol", window_clrtoeol, 0);
02838     rb_define_method(cWindow, "refresh", window_refresh, 0);
02839     rb_define_method(cWindow, "noutrefresh", window_noutrefresh, 0);
02840     rb_define_method(cWindow, "box", window_box, -1);
02841     rb_define_method(cWindow, "move", window_move, 2);
02842     rb_define_method(cWindow, "setpos", window_setpos, 2);
02843 #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
02844     rb_define_method(cWindow, "color_set", window_color_set, 1);
02845 #endif /* USE_COLOR && HAVE_WCOLOR_SET */
02846     rb_define_method(cWindow, "cury", window_cury, 0);
02847     rb_define_method(cWindow, "curx", window_curx, 0);
02848     rb_define_method(cWindow, "maxy", window_maxy, 0);
02849     rb_define_method(cWindow, "maxx", window_maxx, 0);
02850     rb_define_method(cWindow, "begy", window_begy, 0);
02851     rb_define_method(cWindow, "begx", window_begx, 0);
02852     rb_define_method(cWindow, "standout", window_standout, 0);
02853     rb_define_method(cWindow, "standend", window_standend, 0);
02854     rb_define_method(cWindow, "inch", window_inch, 0);
02855     rb_define_method(cWindow, "addch", window_addch, 1);
02856     rb_define_method(cWindow, "insch", window_insch, 1);
02857     rb_define_method(cWindow, "addstr", window_addstr, 1);
02858     rb_define_method(cWindow, "<<", window_addstr2, 1);
02859     rb_define_method(cWindow, "getch", window_getch, 0);
02860     rb_define_method(cWindow, "getstr", window_getstr, 0);
02861     rb_define_method(cWindow, "delch", window_delch, 0);
02862     rb_define_method(cWindow, "deleteln", window_deleteln, 0);
02863     rb_define_method(cWindow, "insertln", window_insertln, 0);
02864     rb_define_method(cWindow, "scroll", window_scroll, 0);
02865     rb_define_method(cWindow, "scrollok", window_scrollok, 1);
02866     rb_define_method(cWindow, "idlok", window_idlok, 1);
02867     rb_define_method(cWindow, "setscrreg", window_setscrreg, 2);
02868     rb_define_method(cWindow, "scrl", window_scrl, 1);
02869     rb_define_method(cWindow, "resize", window_resize, 2);
02870     rb_define_method(cWindow, "keypad", window_keypad, 1);
02871     rb_define_method(cWindow, "keypad=", window_keypad, 1);
02872 
02873     rb_define_method(cWindow, "attroff", window_attroff, 1);
02874     rb_define_method(cWindow, "attron", window_attron, 1);
02875     rb_define_method(cWindow, "attrset", window_attrset, 1);
02876     rb_define_method(cWindow, "bkgdset", window_bkgdset, 1);
02877     rb_define_method(cWindow, "bkgd", window_bkgd, 1);
02878     rb_define_method(cWindow, "getbkgd", window_getbkgd, 0);
02879 
02880     rb_define_method(cWindow, "nodelay=", window_nodelay, 1);
02881     rb_define_method(cWindow, "timeout=", window_timeout, 1);
02882 
02883 #ifdef HAVE_NEWPAD
02884     /*
02885      * Document-class: Curses::Pad
02886      *
02887      * == Description
02888      *
02889      * A Pad is like a Window but allows for scrolling of contents that cannot
02890      * fit on the screen.  Pads do not refresh automatically, use Pad#refresh
02891      * or Pad#noutrefresh instead.
02892      *
02893      */
02894     cPad = rb_define_class_under(mCurses, "Pad", cWindow);
02895     /* inherits alloc_func from cWindow */
02896     rb_define_method(cPad, "initialize", pad_initialize, 2);
02897     rb_define_method(cPad, "subpad", pad_subpad, 4);
02898     rb_define_method(cPad, "refresh", pad_refresh, 6);
02899     rb_define_method(cPad, "noutrefresh", pad_noutrefresh, 6);
02900     rb_undef_method(cPad, "subwin");
02901 #endif
02902 
02903 #define rb_curses_define_const(c) rb_define_const(mCurses,#c,UINT2NUM(c))
02904 
02905 #ifdef USE_COLOR
02906     /* Document-const: A_ATTRIBUTES
02907      *
02908      * Character attribute mask:
02909      * Bit-mask to extract attributes
02910      *
02911      * See Curses.inch or Curses::Window.inch
02912      */
02913     rb_curses_define_const(A_ATTRIBUTES);
02914 #ifdef A_NORMAL
02915     /* Document-const: A_NORMAL
02916      *
02917      * Attribute mask:
02918      * Normal display (no highlight)
02919      *
02920      * See Curses.attrset
02921      */
02922     rb_curses_define_const(A_NORMAL);
02923 #endif
02924     /* Document-const: A_STANDOUT
02925      *
02926      * Attribute mask:
02927      * Best highlighting mode of the terminal.
02928      *
02929      * See Curses.attrset
02930      */
02931     rb_curses_define_const(A_STANDOUT);
02932     /* Document-const: A_UNDERLINE
02933      *
02934      * Attribute mask:
02935      * Underlining
02936      *
02937      * See Curses.attrset
02938      */
02939     rb_curses_define_const(A_UNDERLINE);
02940     /* Document-const: A_REVERSE
02941      *
02942      * Attribute mask:
02943      * Reverse video
02944      *
02945      * See Curses.attrset
02946      */
02947     rb_curses_define_const(A_REVERSE);
02948     /* Document-const: A_BLINK
02949      *
02950      * Attribute mask:
02951      * Blinking
02952      *
02953      * See Curses.attrset
02954      */
02955     rb_curses_define_const(A_BLINK);
02956     /* Document-const: A_DIM
02957      *
02958      * Attribute mask:
02959      * Half bright
02960      *
02961      * See Curses.attrset
02962      */
02963     rb_curses_define_const(A_DIM);
02964     /* Document-const: A_BOLD
02965      *
02966      * Attribute mask:
02967      * Extra bright or bold
02968      *
02969      * See Curses.attrset
02970      */
02971     rb_curses_define_const(A_BOLD);
02972     /* Document-const: A_PROTECT
02973      *
02974      * Attribute mask:
02975      * Protected mode
02976      *
02977      * See Curses.attrset
02978      */
02979     rb_curses_define_const(A_PROTECT);
02980 #ifdef A_INVIS /* for NetBSD */
02981     /* Document-const: A_INVIS
02982      *
02983      * Attribute mask:
02984      * Invisible or blank mode
02985      *
02986      * See Curses.attrset
02987      */
02988     rb_curses_define_const(A_INVIS);
02989 #endif
02990     /* Document-const: A_ALTCHARSET
02991      *
02992      * Attribute mask:
02993      * Alternate character set
02994      *
02995      * See Curses.attrset
02996      */
02997     rb_curses_define_const(A_ALTCHARSET);
02998     /* Document-const: A_CHARTEXT
02999      *
03000      * Attribute mask:
03001      * Bit-mask to extract a character
03002      *
03003      * See Curses.attrset
03004      */
03005     rb_curses_define_const(A_CHARTEXT);
03006 #ifdef A_HORIZONTAL
03007     /* Document-const: A_HORIZONTAL
03008      *
03009      * Attribute mask:
03010      * horizontal highlight
03011      *
03012      * Check system curs_attr(3x) for support
03013      */
03014     rb_curses_define_const(A_HORIZONTAL);
03015 #endif
03016 #ifdef A_LEFT
03017     /* Document-const: A_LEFT
03018      *
03019      * Attribute mask:
03020      * left highlight
03021      *
03022      * Check system curs_attr(3x) for support
03023      */
03024     rb_curses_define_const(A_LEFT);
03025 #endif
03026 #ifdef A_LOW
03027     /* Document-const: A_LOW
03028      *
03029      * Attribute mask:
03030      * low highlight
03031      *
03032      * Check system curs_attr(3x) for support
03033      */
03034     rb_curses_define_const(A_LOW);
03035 #endif
03036 #ifdef A_RIGHT
03037     /* Document-const: A_RIGHT
03038      *
03039      * Attribute mask:
03040      * right highlight
03041      *
03042      * Check system curs_attr(3x) for support
03043      */
03044     rb_curses_define_const(A_RIGHT);
03045 #endif
03046 #ifdef A_TOP
03047     /* Document-const: A_TOP
03048      *
03049      * Attribute mask:
03050      * top highlight
03051      *
03052      * Check system curs_attr(3x) for support
03053      */
03054     rb_curses_define_const(A_TOP);
03055 #endif
03056 #ifdef A_VERTICAL
03057     /* Document-const: A_VERTICAL
03058      *
03059      * Attribute mask:
03060      * vertical highlight
03061      *
03062      * Check system curs_attr(3x) for support
03063      */
03064     rb_curses_define_const(A_VERTICAL);
03065 #endif
03066     /* Document-const: A_COLOR
03067      *
03068      * Character attribute mask:
03069      * Bit-mask to extract color-pair field information
03070      *
03071      * See Curses.inch or Curses::Window.inch
03072      */
03073     rb_curses_define_const(A_COLOR);
03074 
03075 #ifdef COLORS
03076     /*
03077      * Document-const: Curses::COLORS
03078      *
03079      * Number of the colors available
03080      */
03081     rb_curses_define_const(COLORS);
03082 #endif
03083     /*
03084      * Document-const: Curses::COLOR_BLACK
03085      *
03086      * Value of the color black
03087      */
03088     rb_curses_define_const(COLOR_BLACK);
03089     /*
03090      * Document-const: COLOR_RED
03091      *
03092      * Value of the color red
03093      */
03094     rb_curses_define_const(COLOR_RED);
03095     /*
03096      * Document-const: COLOR_GREEN
03097      *
03098      * Value of the color green
03099      */
03100     rb_curses_define_const(COLOR_GREEN);
03101     /*
03102      * Document-const: COLOR_YELLOW
03103      *
03104      * Value of the color yellow
03105      */
03106     rb_curses_define_const(COLOR_YELLOW);
03107     /*
03108      * Document-const: COLOR_BLUE
03109      *
03110      * Value of the color blue
03111      */
03112     rb_curses_define_const(COLOR_BLUE);
03113     /*
03114      * Document-const: COLOR_MAGENTA
03115      *
03116      * Value of the color magenta
03117      */
03118     rb_curses_define_const(COLOR_MAGENTA);
03119     /*
03120      * Document-const: COLOR_CYAN
03121      *
03122      * Value of the color cyan
03123      */
03124     rb_curses_define_const(COLOR_CYAN);
03125     /*
03126      * Document-const: COLOR_WHITE
03127      *
03128      * Value of the color white
03129      */
03130     rb_curses_define_const(COLOR_WHITE);
03131 #endif /* USE_COLOR */
03132 #ifdef USE_MOUSE
03133 #ifdef BUTTON1_PRESSED
03134     /* Document-const: BUTTON1_PRESSED
03135      *
03136      * Mouse event mask:
03137      * mouse button 1 down
03138      *
03139      * See Curses.getmouse
03140      */
03141     rb_curses_define_const(BUTTON1_PRESSED);
03142 #endif
03143 #ifdef BUTTON1_RELEASED
03144     /* Document-const: BUTTON1_RELEASED
03145      *
03146      * Mouse event mask:
03147      * mouse button 1 up
03148      *
03149      * See Curses.getmouse
03150      */
03151     rb_curses_define_const(BUTTON1_RELEASED);
03152 #endif
03153 #ifdef BUTTON1_CLICKED
03154     /* Document-const: BUTTON1_CLICKED
03155      *
03156      * Mouse event mask:
03157      * mouse button 1 clicked
03158      *
03159      * See Curses.getmouse
03160      */
03161     rb_curses_define_const(BUTTON1_CLICKED);
03162 #endif
03163 #ifdef BUTTON1_DOUBLE_CLICKED
03164     /* Document-const: BUTTON1_DOUBLE_CLICKED
03165      *
03166      * Mouse event mask:
03167      * mouse button 1 double clicked
03168      *
03169      * See Curses.getmouse
03170      */
03171     rb_curses_define_const(BUTTON1_DOUBLE_CLICKED);
03172 #endif
03173 #ifdef BUTTON1_TRIPLE_CLICKED
03174     /* Document-const: BUTTON1_TRIPLE_CLICKED
03175      *
03176      * Mouse event mask:
03177      * mouse button 1 triple clicked
03178      *
03179      * See Curses.getmouse
03180      */
03181     rb_curses_define_const(BUTTON1_TRIPLE_CLICKED);
03182 #endif
03183 #ifdef BUTTON2_PRESSED
03184     /* Document-const: BUTTON2_PRESSED
03185      *
03186      * Mouse event mask:
03187      * mouse button 2 down
03188      *
03189      * See Curses.getmouse
03190      */
03191     rb_curses_define_const(BUTTON2_PRESSED);
03192 #endif
03193 #ifdef BUTTON2_RELEASED
03194     /* Document-const: BUTTON2_RELEASED
03195      *
03196      * Mouse event mask:
03197      * mouse button 2 up
03198      *
03199      * See Curses.getmouse
03200      */
03201     rb_curses_define_const(BUTTON2_RELEASED);
03202 #endif
03203 #ifdef BUTTON2_CLICKED
03204     /* Document-const: BUTTON2_CLICKED
03205      *
03206      * Mouse event mask:
03207      * mouse button 2 clicked
03208      *
03209      * See Curses.getmouse
03210      */
03211     rb_curses_define_const(BUTTON2_CLICKED);
03212 #endif
03213 #ifdef BUTTON2_DOUBLE_CLICKED
03214     /* Document-const: BUTTON2_DOUBLE_CLICKED
03215      *
03216      * Mouse event mask:
03217      * mouse button 2 double clicked
03218      *
03219      * See Curses.getmouse
03220      */
03221     rb_curses_define_const(BUTTON2_DOUBLE_CLICKED);
03222 #endif
03223 #ifdef BUTTON2_TRIPLE_CLICKED
03224     /* Document-const: BUTTON2_TRIPLE_CLICKED
03225      *
03226      * Mouse event mask:
03227      * mouse button 2 triple clicked
03228      *
03229      * See Curses.getmouse
03230      */
03231     rb_curses_define_const(BUTTON2_TRIPLE_CLICKED);
03232 #endif
03233 #ifdef BUTTON3_PRESSED
03234     /* Document-const: BUTTON3_PRESSED
03235      *
03236      * Mouse event mask:
03237      * mouse button 3 down
03238      *
03239      * See Curses.getmouse
03240      */
03241     rb_curses_define_const(BUTTON3_PRESSED);
03242 #endif
03243 #ifdef BUTTON3_RELEASED
03244     /* Document-const: BUTTON3_RELEASED
03245      *
03246      * Mouse event mask:
03247      * mouse button 3 up
03248      *
03249      * See Curses.getmouse
03250      */
03251     rb_curses_define_const(BUTTON3_RELEASED);
03252 #endif
03253 #ifdef BUTTON3_CLICKED
03254     /* Document-const: BUTTON3_CLICKED
03255      *
03256      * Mouse event mask:
03257      * mouse button 3 clicked
03258      *
03259      * See Curses.getmouse
03260      */
03261     rb_curses_define_const(BUTTON3_CLICKED);
03262 #endif
03263 #ifdef BUTTON3_DOUBLE_CLICKED
03264     /* Document-const: BUTTON3_DOUBLE_CLICKED
03265      *
03266      * Mouse event mask:
03267      * mouse button 3 double clicked
03268      *
03269      * See Curses.getmouse
03270      */
03271     rb_curses_define_const(BUTTON3_DOUBLE_CLICKED);
03272 #endif
03273 #ifdef BUTTON3_TRIPLE_CLICKED
03274     /* Document-const: BUTTON3_TRIPLE_CLICKED
03275      *
03276      * Mouse event mask:
03277      * mouse button 3 triple clicked
03278      *
03279      * See Curses.getmouse
03280      */
03281     rb_curses_define_const(BUTTON3_TRIPLE_CLICKED);
03282 #endif
03283 #ifdef BUTTON4_PRESSED
03284     /* Document-const: BUTTON4_PRESSED
03285      *
03286      * Mouse event mask:
03287      * mouse button 4 down
03288      *
03289      * See Curses.getmouse
03290      */
03291     rb_curses_define_const(BUTTON4_PRESSED);
03292 #endif
03293 #ifdef BUTTON4_RELEASED
03294     /* Document-const: BUTTON4_RELEASED
03295      *
03296      * Mouse event mask:
03297      * mouse button 4 up
03298      *
03299      * See Curses.getmouse
03300      */
03301     rb_curses_define_const(BUTTON4_RELEASED);
03302 #endif
03303 #ifdef BUTTON4_CLICKED
03304     /* Document-const: BUTTON4_CLICKED
03305      *
03306      * Mouse event mask:
03307      * mouse button 4 clicked
03308      *
03309      * See Curses.getmouse
03310      */
03311     rb_curses_define_const(BUTTON4_CLICKED);
03312 #endif
03313 #ifdef BUTTON4_DOUBLE_CLICKED
03314     /* Document-const: BUTTON4_DOUBLE_CLICKED
03315      *
03316      * Mouse event mask:
03317      * mouse button 4 double clicked
03318      *
03319      * See Curses.getmouse
03320      */
03321     rb_curses_define_const(BUTTON4_DOUBLE_CLICKED);
03322 #endif
03323 #ifdef BUTTON4_TRIPLE_CLICKED
03324     /* Document-const: BUTTON4_TRIPLE_CLICKED
03325      *
03326      * Mouse event mask:
03327      * mouse button 4 triple clicked
03328      *
03329      * See Curses.getmouse
03330      */
03331     rb_curses_define_const(BUTTON4_TRIPLE_CLICKED);
03332 #endif
03333 #ifdef BUTTON_SHIFT
03334     /* Document-const: BUTTON_SHIFT
03335      *
03336      * Mouse event mask:
03337      * shift was down during button state change
03338      *
03339      * See Curses.getmouse
03340      */
03341     rb_curses_define_const(BUTTON_SHIFT);
03342 #endif
03343 #ifdef BUTTON_CTRL
03344     /* Document-const: BUTTON_CTRL
03345      *
03346      * Mouse event mask:
03347      * control was down during button state change
03348      *
03349      * See Curses.getmouse
03350      */
03351     rb_curses_define_const(BUTTON_CTRL);
03352 #endif
03353 #ifdef BUTTON_ALT
03354     /* Document-const: BUTTON_ALT
03355      *
03356      * Mouse event mask:
03357      * alt was down during button state change
03358      *
03359      * See Curses.getmouse
03360      */
03361     rb_curses_define_const(BUTTON_ALT);
03362 #endif
03363 #ifdef ALL_MOUSE_EVENTS
03364     /* Document-const: ALL_MOUSE_EVENTS
03365      *
03366      * Mouse event mask:
03367      * report all button state changes
03368      *
03369      * See Curses.getmouse
03370      */
03371     rb_curses_define_const(ALL_MOUSE_EVENTS);
03372 #endif
03373 #ifdef REPORT_MOUSE_POSITION
03374     /* Document-const: REPORT_MOUSE_POSITION
03375      *
03376      * Mouse event mask:
03377      * report mouse movement
03378      *
03379      * See Curses.getmouse
03380      */
03381     rb_curses_define_const(REPORT_MOUSE_POSITION);
03382 #endif
03383 #endif /* USE_MOUSE */
03384 
03385 #if defined(KEY_MOUSE) && defined(USE_MOUSE)
03386     /* Document-const: KEY_MOUSE
03387      * Mouse event read
03388      */
03389     /* Document-const: MOUSE
03390      * Mouse event read
03391      */
03392     rb_curses_define_const(KEY_MOUSE);
03393     rb_define_const(mKey, "MOUSE", INT2NUM(KEY_MOUSE));
03394 #endif
03395 #ifdef KEY_MIN
03396     /* Document-const: KEY_MIN
03397      * The minimum allowed curses key value.
03398      */
03399     /* Document-const: MIN
03400      * The minimum allowed curses key value.
03401      */
03402     rb_curses_define_const(KEY_MIN);
03403     rb_define_const(mKey, "MIN", INT2NUM(KEY_MIN));
03404 #endif
03405 #ifdef KEY_BREAK
03406     /* Document-const: KEY_BREAK
03407      * Break key
03408      */
03409     /* Document-const: BREAK
03410      * Break key
03411      */
03412     rb_curses_define_const(KEY_BREAK);
03413     rb_define_const(mKey, "BREAK", INT2NUM(KEY_BREAK));
03414 #endif
03415 #ifdef KEY_DOWN
03416     /* Document-const: KEY_DOWN
03417      * the down arrow key
03418      */
03419     /* Document-const: DOWN
03420      * the down arrow key
03421      */
03422     rb_curses_define_const(KEY_DOWN);
03423     rb_define_const(mKey, "DOWN", INT2NUM(KEY_DOWN));
03424 #endif
03425 #ifdef KEY_UP
03426     /* Document-const: KEY_UP
03427      * the up arrow key
03428      */
03429     /* Document-const: UP
03430      * the up arrow key
03431      */
03432     rb_curses_define_const(KEY_UP);
03433     rb_define_const(mKey, "UP", INT2NUM(KEY_UP));
03434 #endif
03435 #ifdef KEY_LEFT
03436     /* Document-const: KEY_LEFT
03437      * the left arrow key
03438      */
03439     /* Document-const: LEFT
03440      * the left arrow key
03441      */
03442     rb_curses_define_const(KEY_LEFT);
03443     rb_define_const(mKey, "LEFT", INT2NUM(KEY_LEFT));
03444 #endif
03445 #ifdef KEY_RIGHT
03446     /* Document-const: KEY_RIGHT
03447      * the right arrow key
03448      */
03449     /* Document-const: RIGHT
03450      * the right arrow key
03451      */
03452     rb_curses_define_const(KEY_RIGHT);
03453     rb_define_const(mKey, "RIGHT", INT2NUM(KEY_RIGHT));
03454 #endif
03455 #ifdef KEY_HOME
03456     /* Document-const: KEY_HOME
03457      * Home key (upward+left arrow)
03458      */
03459     /* Document-const: HOME
03460      * Home key (upward+left arrow)
03461      */
03462     rb_curses_define_const(KEY_HOME);
03463     rb_define_const(mKey, "HOME", INT2NUM(KEY_HOME));
03464 #endif
03465 #ifdef KEY_BACKSPACE
03466     /* Document-const: KEY_BACKSPACE
03467      * Backspace
03468      */
03469     /* Document-const: BACKSPACE
03470      * Backspace
03471      */
03472     rb_curses_define_const(KEY_BACKSPACE);
03473     rb_define_const(mKey, "BACKSPACE", INT2NUM(KEY_BACKSPACE));
03474 #endif
03475 #ifdef KEY_F
03476     /* KEY_F(n) : 0 <= n <= 63 */
03477     {
03478         int i;
03479         char c[8];
03480         for (i=0; i<64; i++) {
03481             sprintf(c, "KEY_F%d", i);
03482             rb_define_const(mCurses, c, INT2NUM(KEY_F(i)));
03483             sprintf(c, "F%d", i);
03484             rb_define_const(mKey, c, INT2NUM(KEY_F(i)));
03485         }
03486     }
03487 #endif
03488 #ifdef KEY_DL
03489     /* Document-const: KEY_DL
03490      * Delete line
03491      */
03492     /* Document-const: DL
03493      * Delete line
03494      */
03495     rb_curses_define_const(KEY_DL);
03496     rb_define_const(mKey, "DL", INT2NUM(KEY_DL));
03497 #endif
03498 #ifdef KEY_IL
03499     /* Document-const: KEY_IL
03500      * Insert line
03501      */
03502     /* Document-const: IL
03503      * Insert line
03504      */
03505     rb_curses_define_const(KEY_IL);
03506     rb_define_const(mKey, "IL", INT2NUM(KEY_IL));
03507 #endif
03508 #ifdef KEY_DC
03509     /* Document-const: KEY_DC
03510      * Delete character
03511      */
03512     /* Document-const: DC
03513      * Delete character
03514      */
03515     rb_curses_define_const(KEY_DC);
03516     rb_define_const(mKey, "DC", INT2NUM(KEY_DC));
03517 #endif
03518 #ifdef KEY_IC
03519     /* Document-const: KEY_IC
03520      * Insert char or enter insert mode
03521      */
03522     /* Document-const: IC
03523      * Insert char or enter insert mode
03524      */
03525     rb_curses_define_const(KEY_IC);
03526     rb_define_const(mKey, "IC", INT2NUM(KEY_IC));
03527 #endif
03528 #ifdef KEY_EIC
03529     /* Document-const: KEY_EIC
03530      * Enter insert char mode
03531      */
03532     /* Document-const: EIC
03533      * Enter insert char mode
03534      */
03535     rb_curses_define_const(KEY_EIC);
03536     rb_define_const(mKey, "EIC", INT2NUM(KEY_EIC));
03537 #endif
03538 #ifdef KEY_CLEAR
03539     /* Document-const: KEY_CLEAR
03540      * Clear Screen
03541      */
03542     /* Document-const: CLEAR
03543      * Clear Screen
03544      */
03545     rb_curses_define_const(KEY_CLEAR);
03546     rb_define_const(mKey, "CLEAR", INT2NUM(KEY_CLEAR));
03547 #endif
03548 #ifdef KEY_EOS
03549     /* Document-const: KEY_EOS
03550      * Clear to end of screen
03551      */
03552     /* Document-const: EOS
03553      * Clear to end of screen
03554      */
03555     rb_curses_define_const(KEY_EOS);
03556     rb_define_const(mKey, "EOS", INT2NUM(KEY_EOS));
03557 #endif
03558 #ifdef KEY_EOL
03559     /* Document-const: KEY_EOL
03560      * Clear to end of line
03561      */
03562     /* Document-const: EOL
03563      * Clear to end of line
03564      */
03565     rb_curses_define_const(KEY_EOL);
03566     rb_define_const(mKey, "EOL", INT2NUM(KEY_EOL));
03567 #endif
03568 #ifdef KEY_SF
03569     /* Document-const: KEY_SF
03570      * Scroll 1 line forward
03571      */
03572     /* Document-const: SF
03573      * Scroll 1 line forward
03574      */
03575     rb_curses_define_const(KEY_SF);
03576     rb_define_const(mKey, "SF", INT2NUM(KEY_SF));
03577 #endif
03578 #ifdef KEY_SR
03579     /* Document-const: KEY_SR
03580      * Scroll 1 line backware (reverse)
03581      */
03582     /* Document-const: SR
03583      * Scroll 1 line backware (reverse)
03584      */
03585     rb_curses_define_const(KEY_SR);
03586     rb_define_const(mKey, "SR", INT2NUM(KEY_SR));
03587 #endif
03588 #ifdef KEY_NPAGE
03589     /* Document-const: KEY_NPAGE
03590      * Next page
03591      */
03592     /* Document-const: NPAGE
03593      * Next page
03594      */
03595     rb_curses_define_const(KEY_NPAGE);
03596     rb_define_const(mKey, "NPAGE", INT2NUM(KEY_NPAGE));
03597 #endif
03598 #ifdef KEY_PPAGE
03599     /* Document-const: KEY_PPAGE
03600      * Previous page
03601      */
03602     /* Document-const: PPAGE
03603      * Previous page
03604      */
03605     rb_curses_define_const(KEY_PPAGE);
03606     rb_define_const(mKey, "PPAGE", INT2NUM(KEY_PPAGE));
03607 #endif
03608 #ifdef KEY_STAB
03609     /* Document-const: KEY_STAB
03610      * Set tab
03611      */
03612     /* Document-const: STAB
03613      * Set tab
03614      */
03615     rb_curses_define_const(KEY_STAB);
03616     rb_define_const(mKey, "STAB", INT2NUM(KEY_STAB));
03617 #endif
03618 #ifdef KEY_CTAB
03619     /* Document-const: KEY_CTAB
03620      * Clear tab
03621      */
03622     /* Document-const: CTAB
03623      * Clear tab
03624      */
03625     rb_curses_define_const(KEY_CTAB);
03626     rb_define_const(mKey, "CTAB", INT2NUM(KEY_CTAB));
03627 #endif
03628 #ifdef KEY_CATAB
03629     /* Document-const: KEY_CATAB
03630      * Clear all tabs
03631      */
03632     /* Document-const: CATAB
03633      * Clear all tabs
03634      */
03635     rb_curses_define_const(KEY_CATAB);
03636     rb_define_const(mKey, "CATAB", INT2NUM(KEY_CATAB));
03637 #endif
03638 #ifdef KEY_ENTER
03639     /* Document-const: KEY_ENTER
03640      * Enter or send
03641      */
03642     /* Document-const: ENTER
03643      * Enter or send
03644      */
03645     rb_curses_define_const(KEY_ENTER);
03646     rb_define_const(mKey, "ENTER", INT2NUM(KEY_ENTER));
03647 #endif
03648 #ifdef KEY_SRESET
03649     /* Document-const: KEY_SRESET
03650      * Soft (partial) reset
03651      */
03652     /* Document-const: SRESET
03653      * Soft (partial) reset
03654      */
03655     rb_curses_define_const(KEY_SRESET);
03656     rb_define_const(mKey, "SRESET", INT2NUM(KEY_SRESET));
03657 #endif
03658 #ifdef KEY_RESET
03659     /* Document-const: KEY_RESET
03660      * Reset or hard reset
03661      */
03662     /* Document-const: RESET
03663      * Reset or hard reset
03664      */
03665     rb_curses_define_const(KEY_RESET);
03666     rb_define_const(mKey, "RESET", INT2NUM(KEY_RESET));
03667 #endif
03668 #ifdef KEY_PRINT
03669     /* Document-const: KEY_PRINT
03670      * Print or copy
03671      */
03672     /* Document-const: PRINT
03673      * Print or copy
03674      */
03675     rb_curses_define_const(KEY_PRINT);
03676     rb_define_const(mKey, "PRINT", INT2NUM(KEY_PRINT));
03677 #endif
03678 #ifdef KEY_LL
03679     /* Document-const: KEY_LL
03680      * Home down or bottom (lower left)
03681      */
03682     /* Document-const: LL
03683      * Home down or bottom (lower left)
03684      */
03685     rb_curses_define_const(KEY_LL);
03686     rb_define_const(mKey, "LL", INT2NUM(KEY_LL));
03687 #endif
03688 #ifdef KEY_A1
03689     /* Document-const: KEY_A1
03690      * Upper left of keypad
03691      */
03692     /* Document-const: A1
03693      * Upper left of keypad
03694      */
03695     rb_curses_define_const(KEY_A1);
03696     rb_define_const(mKey, "A1", INT2NUM(KEY_A1));
03697 #endif
03698 #ifdef KEY_A3
03699     /* Document-const: KEY_A3
03700      * Upper right of keypad
03701      */
03702     /* Document-const: A3
03703      * Upper right of keypad
03704      */
03705     rb_curses_define_const(KEY_A3);
03706     rb_define_const(mKey, "A3", INT2NUM(KEY_A3));
03707 #endif
03708 #ifdef KEY_B2
03709     /* Document-const: KEY_B2
03710      * Center of keypad
03711      */
03712     /* Document-const: B2
03713      * Center of keypad
03714      */
03715     rb_curses_define_const(KEY_B2);
03716     rb_define_const(mKey, "B2", INT2NUM(KEY_B2));
03717 #endif
03718 #ifdef KEY_C1
03719     /* Document-const: KEY_C1
03720      * Lower left of keypad
03721      */
03722     /* Document-const: C1
03723      * Lower left of keypad
03724      */
03725     rb_curses_define_const(KEY_C1);
03726     rb_define_const(mKey, "C1", INT2NUM(KEY_C1));
03727 #endif
03728 #ifdef KEY_C3
03729     /* Document-const: KEY_C3
03730      * Lower right of keypad
03731      */
03732     /* Document-const: C3
03733      * Lower right of keypad
03734      */
03735     rb_curses_define_const(KEY_C3);
03736     rb_define_const(mKey, "C3", INT2NUM(KEY_C3));
03737 #endif
03738 #ifdef KEY_BTAB
03739     /* Document-const: BTAB
03740      * Back tab key
03741      */
03742     /* Document-const: KEY_BTAB
03743      * Back tab key
03744      */
03745     rb_curses_define_const(KEY_BTAB);
03746     rb_define_const(mKey, "BTAB", INT2NUM(KEY_BTAB));
03747 #endif
03748 #ifdef KEY_BEG
03749     /* Document-const: KEY_BEG
03750      * Beginning key
03751      */
03752     /* Document-const: BEG
03753      * Beginning key
03754      */
03755     rb_curses_define_const(KEY_BEG);
03756     rb_define_const(mKey, "BEG", INT2NUM(KEY_BEG));
03757 #endif
03758 #ifdef KEY_CANCEL
03759     /* Document-const: KEY_CANCEL
03760      * Cancel key
03761      */
03762     /* Document-const: CANCEL
03763      * Cancel key
03764      */
03765     rb_curses_define_const(KEY_CANCEL);
03766     rb_define_const(mKey, "CANCEL", INT2NUM(KEY_CANCEL));
03767 #endif
03768 #ifdef KEY_CLOSE
03769     /* Document-const: KEY_CLOSE
03770      * Close key
03771      */
03772     /* Document-const: CLOSE
03773      * Close key
03774      */
03775     rb_curses_define_const(KEY_CLOSE);
03776     rb_define_const(mKey, "CLOSE", INT2NUM(KEY_CLOSE));
03777 #endif
03778 #ifdef KEY_COMMAND
03779     /* Document-const: KEY_COMMAND
03780      * Cmd (command) key
03781      */
03782     /* Document-const: COMMAND
03783      * Cmd (command) key
03784      */
03785     rb_curses_define_const(KEY_COMMAND);
03786     rb_define_const(mKey, "COMMAND", INT2NUM(KEY_COMMAND));
03787 #endif
03788 #ifdef KEY_COPY
03789     /* Document-const: KEY_COPY
03790      * Copy key
03791      */
03792     /* Document-const: COPY
03793      * Copy key
03794      */
03795     rb_curses_define_const(KEY_COPY);
03796     rb_define_const(mKey, "COPY", INT2NUM(KEY_COPY));
03797 #endif
03798 #ifdef KEY_CREATE
03799     /* Document-const: KEY_CREATE
03800      * Create key
03801      */
03802     /* Document-const: CREATE
03803      * Create key
03804      */
03805     rb_curses_define_const(KEY_CREATE);
03806     rb_define_const(mKey, "CREATE", INT2NUM(KEY_CREATE));
03807 #endif
03808 #ifdef KEY_END
03809     /* Document-const: KEY_END
03810      * End key
03811      */
03812     /* Document-const: END
03813      * End key
03814      */
03815     rb_curses_define_const(KEY_END);
03816     rb_define_const(mKey, "END", INT2NUM(KEY_END));
03817 #endif
03818 #ifdef KEY_EXIT
03819     /* Document-const: KEY_EXIT
03820      * Exit key
03821      */
03822     /* Document-const: EXIT
03823      * Exit key
03824      */
03825     rb_curses_define_const(KEY_EXIT);
03826     rb_define_const(mKey, "EXIT", INT2NUM(KEY_EXIT));
03827 #endif
03828 #ifdef KEY_FIND
03829     /* Document-const: KEY_FIND
03830      * Find key
03831      */
03832     /* Document-const: FIND
03833      * Find key
03834      */
03835     rb_curses_define_const(KEY_FIND);
03836     rb_define_const(mKey, "FIND", INT2NUM(KEY_FIND));
03837 #endif
03838 #ifdef KEY_HELP
03839     /* Document-const: KEY_HELP
03840      * Help key
03841      */
03842     /* Document-const: HELP
03843      * Help key
03844      */
03845     rb_curses_define_const(KEY_HELP);
03846     rb_define_const(mKey, "HELP", INT2NUM(KEY_HELP));
03847 #endif
03848 #ifdef KEY_MARK
03849     /* Document-const: KEY_MARK
03850      * Mark key
03851      */
03852     /* Document-const: MARK
03853      * Mark key
03854      */
03855     rb_curses_define_const(KEY_MARK);
03856     rb_define_const(mKey, "MARK", INT2NUM(KEY_MARK));
03857 #endif
03858 #ifdef KEY_MESSAGE
03859     /* Document-const: KEY_MESSAGE
03860      * Message key
03861      */
03862     /* Document-const: MESSAGE
03863      * Message key
03864      */
03865     rb_curses_define_const(KEY_MESSAGE);
03866     rb_define_const(mKey, "MESSAGE", INT2NUM(KEY_MESSAGE));
03867 #endif
03868 #ifdef KEY_MOVE
03869     /* Document-const: KEY_MOVE
03870      * Move key
03871      */
03872     /* Document-const: MOVE
03873      * Move key
03874      */
03875     rb_curses_define_const(KEY_MOVE);
03876     rb_define_const(mKey, "MOVE", INT2NUM(KEY_MOVE));
03877 #endif
03878 #ifdef KEY_NEXT
03879     /* Document-const: KEY_NEXT
03880      * Next object key
03881      */
03882     /* Document-const: NEXT
03883      * Next object key
03884      */
03885     rb_curses_define_const(KEY_NEXT);
03886     rb_define_const(mKey, "NEXT", INT2NUM(KEY_NEXT));
03887 #endif
03888 #ifdef KEY_OPEN
03889     /* Document-const: KEY_OPEN
03890      * Open key
03891      */
03892     /* Document-const: OPEN
03893      * Open key
03894      */
03895     rb_curses_define_const(KEY_OPEN);
03896     rb_define_const(mKey, "OPEN", INT2NUM(KEY_OPEN));
03897 #endif
03898 #ifdef KEY_OPTIONS
03899     /* Document-const: KEY_OPTIONS
03900      * Options key
03901      */
03902     /* Document-const: OPTIONS
03903      * Options key
03904      */
03905     rb_curses_define_const(KEY_OPTIONS);
03906     rb_define_const(mKey, "OPTIONS", INT2NUM(KEY_OPTIONS));
03907 #endif
03908 #ifdef KEY_PREVIOUS
03909     /* Document-const: KEY_PREVIOUS
03910      * Previous object key
03911      */
03912     /* Document-const: PREVIOUS
03913      * Previous object key
03914      */
03915     rb_curses_define_const(KEY_PREVIOUS);
03916     rb_define_const(mKey, "PREVIOUS", INT2NUM(KEY_PREVIOUS));
03917 #endif
03918 #ifdef KEY_REDO
03919     /* Document-const: KEY_REDO
03920      * Redo key
03921      */
03922     /* Document-const: REDO
03923      * Redo key
03924      */
03925     rb_curses_define_const(KEY_REDO);
03926     rb_define_const(mKey, "REDO", INT2NUM(KEY_REDO));
03927 #endif
03928 #ifdef KEY_REFERENCE
03929     /* Document-const: KEY_REFERENCE
03930      * Reference key
03931      */
03932     /* Document-const: REFERENCE
03933      * Reference key
03934      */
03935     rb_curses_define_const(KEY_REFERENCE);
03936     rb_define_const(mKey, "REFERENCE", INT2NUM(KEY_REFERENCE));
03937 #endif
03938 #ifdef KEY_REFRESH
03939     /* Document-const: KEY_REFRESH
03940      * Refresh key
03941      */
03942     /* Document-const: REFRESH
03943      * Refresh key
03944      */
03945     rb_curses_define_const(KEY_REFRESH);
03946     rb_define_const(mKey, "REFRESH", INT2NUM(KEY_REFRESH));
03947 #endif
03948 #ifdef KEY_REPLACE
03949     /* Document-const: KEY_REPLACE
03950      * Replace key
03951      */
03952     /* Document-const: REPLACE
03953      * Replace key
03954      */
03955     rb_curses_define_const(KEY_REPLACE);
03956     rb_define_const(mKey, "REPLACE", INT2NUM(KEY_REPLACE));
03957 #endif
03958 #ifdef KEY_RESTART
03959     /* Document-const: KEY_RESTART
03960      * Restart key
03961      */
03962     /* Document-const: RESTART
03963      * Restart key
03964      */
03965     rb_curses_define_const(KEY_RESTART);
03966     rb_define_const(mKey, "RESTART", INT2NUM(KEY_RESTART));
03967 #endif
03968 #ifdef KEY_RESUME
03969     /* Document-const: KEY_RESUME
03970      * Resume key
03971      */
03972     /* Document-const: RESUME
03973      * Resume key
03974      */
03975     rb_curses_define_const(KEY_RESUME);
03976     rb_define_const(mKey, "RESUME", INT2NUM(KEY_RESUME));
03977 #endif
03978 #ifdef KEY_SAVE
03979     /* Document-const: KEY_SAVE
03980      * Save key
03981      */
03982     /* Document-const: SAVE
03983      * Save key
03984      */
03985     rb_curses_define_const(KEY_SAVE);
03986     rb_define_const(mKey, "SAVE", INT2NUM(KEY_SAVE));
03987 #endif
03988 #ifdef KEY_SBEG
03989     /* Document-const: KEY_SBEG
03990      * Shifted beginning key
03991      */
03992     /* Document-const: SBEG
03993      * Shifted beginning key
03994      */
03995     rb_curses_define_const(KEY_SBEG);
03996     rb_define_const(mKey, "SBEG", INT2NUM(KEY_SBEG));
03997 #endif
03998 #ifdef KEY_SCANCEL
03999     /* Document-const: KEY_SCANCEL
04000      * Shifted cancel key
04001      */
04002     /* Document-const: SCANCEL
04003      * Shifted cancel key
04004      */
04005     rb_curses_define_const(KEY_SCANCEL);
04006     rb_define_const(mKey, "SCANCEL", INT2NUM(KEY_SCANCEL));
04007 #endif
04008 #ifdef KEY_SCOMMAND
04009     /* Document-const: KEY_SCOMMAND
04010      * Shifted command key
04011      */
04012     /* Document-const: SCOMMAND
04013      * Shifted command key
04014      */
04015     rb_curses_define_const(KEY_SCOMMAND);
04016     rb_define_const(mKey, "SCOMMAND", INT2NUM(KEY_SCOMMAND));
04017 #endif
04018 #ifdef KEY_SCOPY
04019     /* Document-const: KEY_SCOPY
04020      * Shifted copy key
04021      */
04022     /* Document-const: SCOPY
04023      * Shifted copy key
04024      */
04025     rb_curses_define_const(KEY_SCOPY);
04026     rb_define_const(mKey, "SCOPY", INT2NUM(KEY_SCOPY));
04027 #endif
04028 #ifdef KEY_SCREATE
04029     /* Document-const: KEY_SCREATE
04030      * Shifted create key
04031      */
04032     /* Document-const: SCREATE
04033      * Shifted create key
04034      */
04035     rb_curses_define_const(KEY_SCREATE);
04036     rb_define_const(mKey, "SCREATE", INT2NUM(KEY_SCREATE));
04037 #endif
04038 #ifdef KEY_SDC
04039     /* Document-const: KEY_SDC
04040      * Shifted delete char key
04041      */
04042     /* Document-const: SDC
04043      * Shifted delete char key
04044      */
04045     rb_curses_define_const(KEY_SDC);
04046     rb_define_const(mKey, "SDC", INT2NUM(KEY_SDC));
04047 #endif
04048 #ifdef KEY_SDL
04049     /* Document-const: KEY_SDL
04050      * Shifted delete line key
04051      */
04052     /* Document-const: SDL
04053      * Shifted delete line key
04054      */
04055     rb_curses_define_const(KEY_SDL);
04056     rb_define_const(mKey, "SDL", INT2NUM(KEY_SDL));
04057 #endif
04058 #ifdef KEY_SELECT
04059     /* Document-const: KEY_SELECT
04060      * Select key
04061      */
04062     /* Document-const: SELECT
04063      * Select key
04064      */
04065     rb_curses_define_const(KEY_SELECT);
04066     rb_define_const(mKey, "SELECT", INT2NUM(KEY_SELECT));
04067 #endif
04068 #ifdef KEY_SEND
04069     /* Document-const: KEY_SEND
04070      * Shifted end key
04071      */
04072     /* Document-const: SEND
04073      * Shifted end key
04074      */
04075     rb_curses_define_const(KEY_SEND);
04076     rb_define_const(mKey, "SEND", INT2NUM(KEY_SEND));
04077 #endif
04078 #ifdef KEY_SEOL
04079     /* Document-const: KEY_SEOL
04080      * Shifted clear line key
04081      */
04082     /* Document-const: SEOL
04083      * Shifted clear line key
04084      */
04085     rb_curses_define_const(KEY_SEOL);
04086     rb_define_const(mKey, "SEOL", INT2NUM(KEY_SEOL));
04087 #endif
04088 #ifdef KEY_SEXIT
04089     /* Document-const: KEY_SEXIT
04090      * Shifted exit key
04091      */
04092     /* Document-const: SEXIT
04093      * Shifted exit key
04094      */
04095     rb_curses_define_const(KEY_SEXIT);
04096     rb_define_const(mKey, "SEXIT", INT2NUM(KEY_SEXIT));
04097 #endif
04098 #ifdef KEY_SFIND
04099     /* Document-const: KEY_SFIND
04100      * Shifted find key
04101      */
04102     /* Document-const: SFIND
04103      * Shifted find key
04104      */
04105     rb_curses_define_const(KEY_SFIND);
04106     rb_define_const(mKey, "SFIND", INT2NUM(KEY_SFIND));
04107 #endif
04108 #ifdef KEY_SHELP
04109     /* Document-const: KEY_SHELP
04110      * Shifted help key
04111      */
04112     /* Document-const: SHELP
04113      * Shifted help key
04114      */
04115     rb_curses_define_const(KEY_SHELP);
04116     rb_define_const(mKey, "SHELP", INT2NUM(KEY_SHELP));
04117 #endif
04118 #ifdef KEY_SHOME
04119     /* Document-const: KEY_SHOME
04120      * Shifted home key
04121      */
04122     /* Document-const: SHOME
04123      * Shifted home key
04124      */
04125     rb_curses_define_const(KEY_SHOME);
04126     rb_define_const(mKey, "SHOME", INT2NUM(KEY_SHOME));
04127 #endif
04128 #ifdef KEY_SIC
04129     /* Document-const: KEY_SIC
04130      * Shifted input key
04131      */
04132     /* Document-const: SIC
04133      * Shifted input key
04134      */
04135     rb_curses_define_const(KEY_SIC);
04136     rb_define_const(mKey, "SIC", INT2NUM(KEY_SIC));
04137 #endif
04138 #ifdef KEY_SLEFT
04139     /* Document-const: KEY_SLEFT
04140      * Shifted left arrow key
04141      */
04142     /* Document-const: SLEFT
04143      * Shifted left arrow key
04144      */
04145     rb_curses_define_const(KEY_SLEFT);
04146     rb_define_const(mKey, "SLEFT", INT2NUM(KEY_SLEFT));
04147 #endif
04148 #ifdef KEY_SMESSAGE
04149     /* Document-const: KEY_SMESSAGE
04150      * Shifted message key
04151      */
04152     /* Document-const: SMESSAGE
04153      * Shifted message key
04154      */
04155     rb_curses_define_const(KEY_SMESSAGE);
04156     rb_define_const(mKey, "SMESSAGE", INT2NUM(KEY_SMESSAGE));
04157 #endif
04158 #ifdef KEY_SMOVE
04159     /* Document-const: KEY_SMOVE
04160      * Shifted move key
04161      */
04162     /* Document-const: SMOVE
04163      * Shifted move key
04164      */
04165     rb_curses_define_const(KEY_SMOVE);
04166     rb_define_const(mKey, "SMOVE", INT2NUM(KEY_SMOVE));
04167 #endif
04168 #ifdef KEY_SNEXT
04169     /* Document-const: KEY_SNEXT
04170      * Shifted next key
04171      */
04172     /* Document-const: SNEXT
04173      * Shifted next key
04174      */
04175     rb_curses_define_const(KEY_SNEXT);
04176     rb_define_const(mKey, "SNEXT", INT2NUM(KEY_SNEXT));
04177 #endif
04178 #ifdef KEY_SOPTIONS
04179     /* Document-const: KEY_SOPTIONS
04180      * Shifted options key
04181      */
04182     /* Document-const: SOPTIONS
04183      * Shifted options key
04184      */
04185     rb_curses_define_const(KEY_SOPTIONS);
04186     rb_define_const(mKey, "SOPTIONS", INT2NUM(KEY_SOPTIONS));
04187 #endif
04188 #ifdef KEY_SPREVIOUS
04189     /* Document-const: KEY_SPREVIOUS
04190      * Shifted previous key
04191      */
04192     /* Document-const: SPREVIOUS
04193      * Shifted previous key
04194      */
04195     rb_curses_define_const(KEY_SPREVIOUS);
04196     rb_define_const(mKey, "SPREVIOUS", INT2NUM(KEY_SPREVIOUS));
04197 #endif
04198 #ifdef KEY_SPRINT
04199     /* Document-const: KEY_SPRINT
04200      * Shifted print key
04201      */
04202     /* Document-const: SPRINT
04203      * Shifted print key
04204      */
04205     rb_curses_define_const(KEY_SPRINT);
04206     rb_define_const(mKey, "SPRINT", INT2NUM(KEY_SPRINT));
04207 #endif
04208 #ifdef KEY_SREDO
04209     /* Document-const: KEY_SREDO
04210      * Shifted redo key
04211      */
04212     /* Document-const: SREDO
04213      * Shifted redo key
04214      */
04215     rb_curses_define_const(KEY_SREDO);
04216     rb_define_const(mKey, "SREDO", INT2NUM(KEY_SREDO));
04217 #endif
04218 #ifdef KEY_SREPLACE
04219     /* Document-const: KEY_SREPLACE
04220      * Shifted replace key
04221      */
04222     /* Document-const: SREPLACE
04223      * Shifted replace key
04224      */
04225     rb_curses_define_const(KEY_SREPLACE);
04226     rb_define_const(mKey, "SREPLACE", INT2NUM(KEY_SREPLACE));
04227 #endif
04228 #ifdef KEY_SRIGHT
04229     /* Document-const: KEY_SRIGHT
04230      * Shifted right arrow key
04231      */
04232     /* Document-const: SRIGHT
04233      * Shifted right arrow key
04234      */
04235     rb_curses_define_const(KEY_SRIGHT);
04236     rb_define_const(mKey, "SRIGHT", INT2NUM(KEY_SRIGHT));
04237 #endif
04238 #ifdef KEY_SRSUME
04239     /* Document-const: KEY_SRSUME
04240      * Shifted resume key
04241      */
04242     /* Document-const: SRSUME
04243      * Shifted resume key
04244      */
04245     rb_curses_define_const(KEY_SRSUME);
04246     rb_define_const(mKey, "SRSUME", INT2NUM(KEY_SRSUME));
04247 #endif
04248 #ifdef KEY_SSAVE
04249     /* Document-const: KEY_SSAVE
04250      * Shifted save key
04251      */
04252     /* Document-const: SSAVE
04253      * Shifted save key
04254      */
04255     rb_curses_define_const(KEY_SSAVE);
04256     rb_define_const(mKey, "SSAVE", INT2NUM(KEY_SSAVE));
04257 #endif
04258 #ifdef KEY_SSUSPEND
04259     /* Document-const: KEY_SSUSPEND
04260      * Shifted suspend key
04261      */
04262     /* Document-const: SSUSPEND
04263      * Shifted suspend key
04264      */
04265     rb_curses_define_const(KEY_SSUSPEND);
04266     rb_define_const(mKey, "SSUSPEND", INT2NUM(KEY_SSUSPEND));
04267 #endif
04268 #ifdef KEY_SUNDO
04269     /* Document-const: KEY_SUNDO
04270      * Shifted undo key
04271      */
04272     /* Document-const: SUNDO
04273      * Shifted undo key
04274      */
04275     rb_curses_define_const(KEY_SUNDO);
04276     rb_define_const(mKey, "SUNDO", INT2NUM(KEY_SUNDO));
04277 #endif
04278 #ifdef KEY_SUSPEND
04279     /* Document-const: KEY_SUSPEND
04280      * Suspend key
04281      */
04282     /* Document-const: SUSPEND
04283      * Suspend key
04284      */
04285     rb_curses_define_const(KEY_SUSPEND);
04286     rb_define_const(mKey, "SUSPEND", INT2NUM(KEY_SUSPEND));
04287 #endif
04288 #ifdef KEY_UNDO
04289     /* Document-const: KEY_UNDO
04290      * Undo key
04291      */
04292     /* Document-const: UNDO
04293      * Undo key
04294      */
04295     rb_curses_define_const(KEY_UNDO);
04296     rb_define_const(mKey, "UNDO", INT2NUM(KEY_UNDO));
04297 #endif
04298 #ifdef KEY_RESIZE
04299     /* Document-const: KEY_RESIZE
04300      * Screen Resized
04301      */
04302     /* Document-const: RESIZE
04303      * Screen Resized
04304      */
04305     rb_curses_define_const(KEY_RESIZE);
04306     rb_define_const(mKey, "RESIZE", INT2NUM(KEY_RESIZE));
04307 #endif
04308 #ifdef KEY_MAX
04309     /* Document-const: KEY_MAX
04310      * The maximum allowed curses key value.
04311      */
04312     /* Document-const: MAX
04313      * The maximum allowed curses key value.
04314      */
04315     rb_curses_define_const(KEY_MAX);
04316     rb_define_const(mKey, "MAX", INT2NUM(KEY_MAX));
04317 #endif
04318     {
04319         int c;
04320         char name[] = "KEY_CTRL_x";
04321         for (c = 'A'; c <= 'Z'; c++) {
04322             name[sizeof(name) - 2] = c;
04323             rb_define_const(mCurses, name, INT2FIX(c - 'A' + 1));
04324         }
04325     }
04326 #undef rb_curses_define_const
04327 
04328     rb_set_end_proc(curses_finalize, 0);
04329 }
04330