curses 1.2.7 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfa821d182e0a62293a794d22c2b09a0167be3c839a5ac67ea596e98fd5b1f55
4
- data.tar.gz: 1249a4e26714cfdb8ac20394e5c1333b3136b9d5275fac18b3618165cdd1d286
3
+ metadata.gz: a4d2078ada136fc3603a23e253c9342efe47cc62daad3db6459c57d1822b740a
4
+ data.tar.gz: 27ee0f6320474baacbe459dc52f40500240d55ce7656663cf8c8074774643fdf
5
5
  SHA512:
6
- metadata.gz: e11281a03551d1104a38e2c9b48c0fa1dc8313c8777f2c8e25c97b7833a75c4ea4d44c6d5b0e6b7e2008f7ee012ae9e0e2719df74adbfb85ca731858b3bc2cae
7
- data.tar.gz: 98b90ee805453cb60ec62f698a7477279631e712b6f83ba1ce4edb5488a06d38694e4d0ac5de4eb00e098d47ce9b77c12b4c988afc42d9b1f123705d3cb2ab18
6
+ metadata.gz: dd21a812ca31bc59dc6e4377a61fc1b19d57779c95b5da48b358b28eb69f29686273de212527744038e508e0a42aed87ead357fe91f85d075eee30eed2aa1a68
7
+ data.tar.gz: e378f6977737d7871074d3fd08436b447823ef347fc67cfe4d367fc245bb7238c2d7514799a2a6324c2ec5cebb544c94f5fabaacfe66adc753ecc6c372970648
@@ -1,3 +1,3 @@
1
1
  [submodule "vendor/PDCurses"]
2
2
  path = vendor/PDCurses
3
- url = https://github.com/Bill-Gray/PDCurses.git
3
+ url = https://github.com/shugo/PDCurses.git
@@ -6,8 +6,11 @@ notifications:
6
6
  - drbrain@segment7.net
7
7
  - shugo@ruby-lang.org
8
8
  rvm:
9
- - 2.2.7
10
- - 2.3.4
11
- - 2.4.1
9
+ - 2.2.10
10
+ - 2.3.8
11
+ - 2.4.5
12
+ - 2.5.3
13
+ - 2.6.1
12
14
  - ruby-head
15
+ before_install: gem install bundler -v '<2'
13
16
  script: rake compile
data/History.md CHANGED
@@ -1,3 +1,17 @@
1
+ ### 1.3.0 / 2019-04-16
2
+
3
+ New features:
4
+
5
+ * Add Curses::Form and Curses::Field.
6
+
7
+ Bug fixes:
8
+
9
+ * Fix TravisCI issues by amatsuda and znz.
10
+ * Fix typo in sample/menu.rb by binford2k.
11
+ * Ctrl-/ should return ^_ on Windows.
12
+ * Workaround for new Windows console.
13
+ https://github.com/Bill-Gray/PDCurses/pull/108
14
+
1
15
  ### 1.2.7 / 2019-01-10
2
16
 
3
17
  Bug fixes:
data/Rakefile CHANGED
@@ -23,15 +23,15 @@ namespace :build do
23
23
  mkdir_p "vendor/#{RUBY_PLATFORM}/PDCurses" if $mswin
24
24
  mkdir_p "vendor/x86-mingw32/PDCurses"
25
25
  mkdir_p "vendor/x64-mingw32/PDCurses"
26
- chdir "vendor/PDCurses/win32" do
26
+ chdir "vendor/PDCurses/wincon" do
27
27
  if $mswin
28
- sh "nmake -f vcwin32.mak clean all WIDE=Y DLL=Y"
28
+ sh "nmake -f Makefile.vc clean all WIDE=Y DLL=Y"
29
29
  cp %w[pdcurses.dll pdcurses.lib], "../../#{RUBY_PLATFORM}/PDCurses"
30
30
  else
31
- sh "make -f mingwin32.mak clean all WIDE=Y DLL=N"
31
+ sh "make -f Makefile.mng clean all WIDE=Y DLL=N"
32
32
  cp "pdcurses.a", "../../x86-mingw32/PDCurses/libpdcurses.a"
33
33
 
34
- sh "make -f mingwin32.mak clean all _w64=1 WIDE=Y DLL=N"
34
+ sh "make -f Makefile.mng clean all _w64=1 WIDE=Y DLL=N"
35
35
  cp "pdcurses.a", "../../x64-mingw32/PDCurses/libpdcurses.a"
36
36
  end
37
37
  end
@@ -41,9 +41,12 @@ end
41
41
  namespace :clean do
42
42
  desc "Clean PDCurses"
43
43
  task :pdcurses do
44
- chdir "vendor/PDCurses/win32" do
45
- sh "nmake -f vcwin32.mak clean" if $mswin
46
- sh "make -f mingwin32.mak clean _linux_w64=1"
44
+ chdir "vendor/PDCurses/wincon" do
45
+ if $mswin
46
+ sh "nmake -f Makefile.vc clean"
47
+ else
48
+ sh "make -f Makefile.mng clean _linux_w64=1"
49
+ end
47
50
  end
48
51
  end
49
52
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new { |s|
2
2
  s.name = "curses"
3
- s.version = "1.2.7"
3
+ s.version = "1.3.0"
4
4
  s.author = ["Shugo Maeda", 'Eric Hodel']
5
5
  s.email = ["shugo@ruby-lang.org", 'drbrain@segment7.net']
6
6
  s.homepage = "https://github.com/ruby/curses"
@@ -61,6 +61,16 @@
61
61
  # include <menu.h>
62
62
  #endif
63
63
 
64
+ #if defined(HAVE_NCURSESW_FORM_H)
65
+ # include <ncursesw/form.h>
66
+ #elif defined(HAVE_NCURSES_FORM_H)
67
+ # include <ncurses/form.h>
68
+ #elif defined(HAVE_CURSES_FORM_H)
69
+ # include <curses/form.h>
70
+ #elif defined(HAVE_FORM_H)
71
+ # include <form.h>
72
+ #endif
73
+
64
74
  #ifdef HAVE_INIT_COLOR
65
75
  # define USE_COLOR 1
66
76
  #endif
@@ -84,6 +94,10 @@ static VALUE cMouseEvent;
84
94
  static VALUE cItem;
85
95
  static VALUE cMenu;
86
96
  #endif
97
+ #ifdef HAVE_FORM
98
+ static VALUE cField;
99
+ static VALUE cForm;
100
+ #endif
87
101
  static VALUE eError;
88
102
  static VALUE eSystemError;
89
103
  static VALUE eBadArgumentError;
@@ -227,7 +241,7 @@ window_memsize(const void *p)
227
241
  const struct windata *winp = p;
228
242
  size_t size = sizeof(*winp);
229
243
  if (!winp) return 0;
230
- if (winp->window && winp->window != stdscr) size += sizeof(winp->window);
244
+ if (winp->window && winp->window != stdscr) size += sizeof(*winp->window);
231
245
  return size;
232
246
  }
233
247
 
@@ -1452,7 +1466,7 @@ curses_mousedata_memsize(const void *p)
1452
1466
  const struct mousedata *mdata = p;
1453
1467
  size_t size = sizeof(*mdata);
1454
1468
  if (!mdata) return 0;
1455
- if (mdata->mevent) size += sizeof(mdata->mevent);
1469
+ if (mdata->mevent) size += sizeof(*mdata->mevent);
1456
1470
  return size;
1457
1471
  }
1458
1472
 
@@ -3049,7 +3063,7 @@ item_memsize(const void *p)
3049
3063
  const struct itemdata *itemp = p;
3050
3064
  size_t size = sizeof(*itemp);
3051
3065
  if (!itemp) return 0;
3052
- if (itemp->item) size += sizeof(itemp->item);
3066
+ if (itemp->item) size += sizeof(*itemp->item);
3053
3067
  return size;
3054
3068
  }
3055
3069
 
@@ -3139,6 +3153,83 @@ item_description_m(VALUE obj)
3139
3153
  return rb_external_str_new_with_enc(desc, strlen(desc), terminal_encoding);
3140
3154
  }
3141
3155
 
3156
+ /*
3157
+ * Document-method: Curses::Item#set_opts
3158
+ *
3159
+ * call-seq:
3160
+ * set_opts(opts)
3161
+ *
3162
+ * Set the option bits of the item.
3163
+ */
3164
+ static VALUE
3165
+ item_set_opts(VALUE obj, VALUE opts)
3166
+ {
3167
+ struct itemdata *itemp;
3168
+ int error;
3169
+
3170
+ GetITEM(obj, itemp);
3171
+ error = set_item_opts(itemp->item, NUM2INT(opts));
3172
+ check_curses_error(error);
3173
+ return obj;
3174
+ }
3175
+
3176
+ /*
3177
+ * Document-method: Curses::Item#opts_on
3178
+ *
3179
+ * call-seq:
3180
+ * opts_on(opts)
3181
+ *
3182
+ * Turn on the option bits of the item.
3183
+ */
3184
+ static VALUE
3185
+ item_opts_on_m(VALUE obj, VALUE opts)
3186
+ {
3187
+ struct itemdata *itemp;
3188
+ int error;
3189
+
3190
+ GetITEM(obj, itemp);
3191
+ error = item_opts_on(itemp->item, NUM2INT(opts));
3192
+ check_curses_error(error);
3193
+ return obj;
3194
+ }
3195
+
3196
+ /*
3197
+ * Document-method: Curses::Item#opts_off
3198
+ *
3199
+ * call-seq:
3200
+ * opts_off(opts)
3201
+ *
3202
+ * Turn off the option bits of the item.
3203
+ */
3204
+ static VALUE
3205
+ item_opts_off_m(VALUE obj, VALUE opts)
3206
+ {
3207
+ struct itemdata *itemp;
3208
+ int error;
3209
+
3210
+ GetITEM(obj, itemp);
3211
+ error = item_opts_off(itemp->item, NUM2INT(opts));
3212
+ check_curses_error(error);
3213
+ return obj;
3214
+ }
3215
+
3216
+ /*
3217
+ * Document-method: Curses::Item#opts
3218
+ *
3219
+ * call-seq:
3220
+ * opts
3221
+ *
3222
+ * Get the current option bits of the item.
3223
+ */
3224
+ static VALUE
3225
+ item_opts_m(VALUE obj, VALUE opts)
3226
+ {
3227
+ struct itemdata *itemp;
3228
+
3229
+ GetITEM(obj, itemp);
3230
+ return INT2NUM(item_opts(itemp->item));
3231
+ }
3232
+
3142
3233
  struct menudata {
3143
3234
  MENU *menu;
3144
3235
  VALUE items;
@@ -3183,7 +3274,7 @@ menu_memsize(const void *p)
3183
3274
  const struct menudata *menup = p;
3184
3275
  size_t size = sizeof(*menup);
3185
3276
  if (!menup) return 0;
3186
- if (menup->menu) size += sizeof(menup->menu);
3277
+ if (menup->menu) size += sizeof(*menup->menu);
3187
3278
  return size;
3188
3279
  }
3189
3280
 
@@ -3205,7 +3296,7 @@ menu_s_allocate(VALUE class)
3205
3296
  * Document-method: Curses::Menu.new
3206
3297
  *
3207
3298
  * call-seq:
3208
- * new(name, description)
3299
+ * new(items)
3209
3300
  *
3210
3301
  * Construct a new Curses::Menu.
3211
3302
  */
@@ -3215,6 +3306,7 @@ menu_initialize(VALUE obj, VALUE items)
3215
3306
  struct menudata *menup;
3216
3307
  ITEM **menu_items;
3217
3308
  int i;
3309
+ ID id_new;
3218
3310
 
3219
3311
  Check_Type(items, T_ARRAY);
3220
3312
  curses_init_screen();
@@ -3222,19 +3314,25 @@ menu_initialize(VALUE obj, VALUE items)
3222
3314
  if (menup->menu) {
3223
3315
  rb_raise(rb_eRuntimeError, "already initialized menu");
3224
3316
  }
3317
+ menup->items = rb_ary_new();
3225
3318
  menu_items = ALLOC_N(ITEM *, RARRAY_LEN(items) + 1);
3319
+ CONST_ID(id_new, "new");
3226
3320
  for (i = 0; i < RARRAY_LEN(items); i++) {
3321
+ VALUE item = RARRAY_AREF(items, i);
3227
3322
  struct itemdata *itemp;
3228
3323
 
3229
- GetITEM(RARRAY_AREF(items, i), itemp);
3324
+ if (RB_TYPE_P(item, T_ARRAY)) {
3325
+ item = rb_apply(cItem, id_new, item);
3326
+ }
3327
+ GetITEM(item, itemp);
3230
3328
  menu_items[i] = itemp->item;
3329
+ rb_ary_push(menup->items, item);
3231
3330
  }
3232
3331
  menu_items[RARRAY_LEN(items)] = NULL;
3233
3332
  menup->menu = new_menu(menu_items);
3234
3333
  if (menup->menu == NULL) {
3235
3334
  check_curses_error(errno);
3236
3335
  }
3237
- menup->items = rb_ary_dup(items);
3238
3336
 
3239
3337
  return obj;
3240
3338
  }
@@ -3426,200 +3524,1077 @@ menu_set_current_item(VALUE obj, VALUE item)
3426
3524
  return item;
3427
3525
  }
3428
3526
 
3429
- #endif /* HAVE_MENU */
3430
-
3431
3527
  /*
3432
- * Document-method: Curses.keyboard_encoding
3433
- * call-seq: Curses.keyboard_encoding
3528
+ * Document-method: Curses::Menu#set_win
3434
3529
  *
3435
- * Returns the encoding for keyboard input.
3530
+ * call-seq:
3531
+ * set_win=(win)
3532
+ *
3533
+ * Set the window of the menu.
3436
3534
  */
3437
3535
  static VALUE
3438
- curses_get_keyboard_encoding(VALUE obj)
3536
+ menu_set_win(VALUE obj, VALUE win)
3439
3537
  {
3440
- return rb_enc_from_encoding(keyboard_encoding);
3538
+ struct menudata *menup;
3539
+ struct windata *winp;
3540
+
3541
+ GetMENU(obj, menup);
3542
+ GetWINDOW(win, winp);
3543
+ set_menu_win(menup->menu, winp->window);
3544
+ return win;
3441
3545
  }
3442
3546
 
3443
3547
  /*
3444
- * Document-method: Curses.keyboard_encoding=
3445
- * call-seq: Curses.keyboard_encoding = encoding
3548
+ * Document-method: Curses::Menu#set_sub
3446
3549
  *
3447
- * Sets the encoding for keyboard input.
3550
+ * call-seq:
3551
+ * set_sub=(win)
3552
+ *
3553
+ * Set the subwindow of the menu.
3448
3554
  */
3449
3555
  static VALUE
3450
- curses_set_keyboard_encoding(VALUE obj, VALUE enc)
3556
+ menu_set_sub(VALUE obj, VALUE win)
3451
3557
  {
3452
- keyboard_encoding = rb_to_encoding(enc);
3453
- return enc;
3558
+ struct menudata *menup;
3559
+ struct windata *winp;
3560
+
3561
+ GetMENU(obj, menup);
3562
+ GetWINDOW(win, winp);
3563
+ set_menu_sub(menup->menu, winp->window);
3564
+ return win;
3454
3565
  }
3455
3566
 
3456
3567
  /*
3457
- * Document-method: Curses.terminal_encoding
3458
- * call-seq: Curses.terminal_encoding
3568
+ * Document-method: Curses::Menu#scale
3459
3569
  *
3460
- * Returns the encoding for terminal output.
3570
+ * call-seq:
3571
+ * scale
3572
+ *
3573
+ * Return the minimum rows and columns required for the subwindow of the menu.
3461
3574
  */
3462
3575
  static VALUE
3463
- curses_get_terminal_encoding(VALUE obj)
3576
+ menu_scale(VALUE obj)
3464
3577
  {
3465
- return rb_enc_from_encoding(terminal_encoding);
3578
+ struct menudata *menup;
3579
+ int error, rows, columns;
3580
+
3581
+ GetMENU(obj, menup);
3582
+ error = scale_menu(menup->menu, &rows, &columns);
3583
+ check_curses_error(error);
3584
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(columns));
3466
3585
  }
3467
3586
 
3468
3587
  /*
3469
- * Document-method: Curses.terminal_encoding=
3470
- * call-seq: Curses.terminal_encoding = encoding
3588
+ * Document-method: Curses::Menu#set_format
3471
3589
  *
3472
- * Sets the encoding for terminal output.
3590
+ * call-seq:
3591
+ * set_format(rows, cols)
3592
+ *
3593
+ * Set the maximum size of the menu.
3473
3594
  */
3474
3595
  static VALUE
3475
- curses_set_terminal_encoding(VALUE obj, VALUE enc)
3596
+ menu_set_format(VALUE obj, VALUE rows, VALUE cols)
3476
3597
  {
3477
- terminal_encoding = rb_to_encoding(enc);
3478
- return enc;
3598
+ struct menudata *menup;
3599
+ int error;
3600
+
3601
+ GetMENU(obj, menup);
3602
+ error = set_menu_format(menup->menu, NUM2INT(rows), NUM2INT(cols));
3603
+ check_curses_error(error);
3604
+ return obj;
3479
3605
  }
3480
3606
 
3481
3607
  /*
3482
- * Document-method: Curses.unget_char
3483
- * call-seq: unget_char(ch)
3608
+ * Document-method: Curses::Menu#format
3484
3609
  *
3485
- * Places +ch+ back onto the input queue to be returned by
3486
- * the next call to Curses.get_char etc.
3610
+ * call-seq:
3611
+ * format
3487
3612
  *
3488
- * There is just one input queue for all windows.
3613
+ * Get the maximum size of the menu.
3489
3614
  */
3490
3615
  static VALUE
3491
- curses_unget_char(VALUE obj, VALUE ch)
3616
+ menu_format_m(VALUE obj)
3492
3617
  {
3493
- ID id_ord;
3494
- unsigned int c;
3618
+ struct menudata *menup;
3619
+ int rows, cols;
3495
3620
 
3496
- curses_stdscr();
3497
- if (FIXNUM_P(ch)) {
3498
- ungetch(NUM2UINT(ch));
3499
- }
3500
- else {
3501
- StringValue(ch);
3502
- CONST_ID(id_ord, "ord");
3503
- c = NUM2UINT(rb_funcall(ch, id_ord, 0));
3504
- #ifdef HAVE_UNGET_WCH
3505
- unget_wch(c);
3506
- #else
3507
- if (c > 0xff) {
3508
- rb_raise(rb_eRangeError, "Out of range: %u", c);
3509
- }
3510
- ungetch(c);
3511
- #endif
3512
- }
3513
- return Qnil;
3621
+ GetMENU(obj, menup);
3622
+ menu_format(menup->menu, &rows, &cols);
3623
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(cols));
3514
3624
  }
3515
3625
 
3626
+ /*
3627
+ * Document-method: Curses::Menu#set_opts
3628
+ *
3629
+ * call-seq:
3630
+ * set_opts(opts)
3631
+ *
3632
+ * Set the option bits of the menu.
3633
+ */
3516
3634
  static VALUE
3517
- keyboard_uint_chr(unsigned int ch)
3635
+ menu_set_opts(VALUE obj, VALUE opts)
3518
3636
  {
3519
- return rb_enc_uint_chr(ch, keyboard_encoding);
3520
- }
3521
-
3522
- #ifdef HAVE_GET_WCH
3523
- struct get_wch_arg {
3524
- int retval;
3525
- wint_t ch;
3526
- };
3637
+ struct menudata *menup;
3638
+ int error;
3527
3639
 
3528
- static void *
3529
- get_wch_func(void *_arg)
3530
- {
3531
- struct get_wch_arg *arg = (struct get_wch_arg *) _arg;
3532
- arg->retval = get_wch(&arg->ch);
3533
- return 0;
3640
+ GetMENU(obj, menup);
3641
+ error = set_menu_opts(menup->menu, NUM2INT(opts));
3642
+ check_curses_error(error);
3643
+ return obj;
3534
3644
  }
3535
- #endif
3536
3645
 
3537
3646
  /*
3538
- * Document-method: Curses.get_char
3539
- *
3540
- * Read and returns a character or function key from the window.
3541
- * A single or multibyte character is represented by a String, and
3542
- * a function key is represented by an Integer.
3543
- * Returns nil if no input is ready.
3647
+ * Document-method: Curses::Menu#opts_on
3544
3648
  *
3545
- * See Curses::Key to all the function KEY_* available
3649
+ * call-seq:
3650
+ * opts_on(opts)
3546
3651
  *
3652
+ * Turn on the option bits of the menu.
3547
3653
  */
3548
3654
  static VALUE
3549
- curses_get_char(VALUE obj)
3655
+ menu_opts_on_m(VALUE obj, VALUE opts)
3550
3656
  {
3551
- #ifdef HAVE_GET_WCH
3552
- struct get_wch_arg arg;
3553
-
3554
- curses_stdscr();
3555
- rb_thread_call_without_gvl(get_wch_func, &arg, RUBY_UBF_IO, 0);
3556
- switch (arg.retval) {
3557
- case OK:
3558
- return keyboard_uint_chr(arg.ch);
3559
- case KEY_CODE_YES:
3560
- return UINT2NUM(arg.ch);
3561
- }
3562
- return Qnil;
3563
- #else
3564
- int c;
3657
+ struct menudata *menup;
3658
+ int error;
3565
3659
 
3566
- curses_stdscr();
3567
- rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0);
3568
- if (c > 0xff) {
3569
- return INT2NUM(c);
3570
- }
3571
- else if (c >= 0) {
3572
- return keyboard_uint_chr(c);
3573
- }
3574
- else {
3575
- return Qnil;
3576
- }
3577
- #endif
3660
+ GetMENU(obj, menup);
3661
+ error = menu_opts_on(menup->menu, NUM2INT(opts));
3662
+ check_curses_error(error);
3663
+ return obj;
3578
3664
  }
3579
3665
 
3580
-
3581
- #ifdef HAVE_WGET_WCH
3582
- struct wget_wch_arg {
3583
- WINDOW *win;
3584
- int retval;
3585
- wint_t ch;
3586
- };
3587
-
3588
- static void *
3589
- wget_wch_func(void *_arg)
3666
+ /*
3667
+ * Document-method: Curses::Menu#opts_off
3668
+ *
3669
+ * call-seq:
3670
+ * opts_off(opts)
3671
+ *
3672
+ * Turn off the option bits of the menu.
3673
+ */
3674
+ static VALUE
3675
+ menu_opts_off_m(VALUE obj, VALUE opts)
3590
3676
  {
3591
- struct wget_wch_arg *arg = (struct wget_wch_arg *) _arg;
3592
- arg->retval = wget_wch(arg->win, &arg->ch);
3593
- return 0;
3677
+ struct menudata *menup;
3678
+ int error;
3679
+
3680
+ GetMENU(obj, menup);
3681
+ error = menu_opts_off(menup->menu, NUM2INT(opts));
3682
+ check_curses_error(error);
3683
+ return obj;
3594
3684
  }
3595
- #endif
3596
3685
 
3597
3686
  /*
3598
- * Document-method: Curses::Window.get_char
3599
- *
3600
- * Read and returns a character or function key from the window.
3601
- * A single or multibyte character is represented by a String, and
3602
- * a function key is represented by an Integer.
3603
- * Returns nil if no input is ready.
3687
+ * Document-method: Curses::Menu#opts
3604
3688
  *
3605
- * See Curses::Key to all the function KEY_* available
3689
+ * call-seq:
3690
+ * opts
3606
3691
  *
3692
+ * Get the current option bits of the menu.
3607
3693
  */
3608
3694
  static VALUE
3609
- window_get_char(VALUE obj)
3695
+ menu_opts_m(VALUE obj, VALUE opts)
3610
3696
  {
3611
- #ifdef HAVE_WGET_WCH
3612
- struct windata *winp;
3613
- struct wget_wch_arg arg;
3697
+ struct menudata *menup;
3614
3698
 
3615
- GetWINDOW(obj, winp);
3616
- arg.win = winp->window;
3617
- rb_thread_call_without_gvl(wget_wch_func, &arg, RUBY_UBF_IO, 0);
3618
- switch (arg.retval) {
3619
- case OK:
3620
- return keyboard_uint_chr(arg.ch);
3621
- case KEY_CODE_YES:
3622
- return UINT2NUM(arg.ch);
3699
+ GetMENU(obj, menup);
3700
+ return INT2NUM(menu_opts(menup->menu));
3701
+ }
3702
+ #endif /* HAVE_MENU */
3703
+
3704
+ #ifdef HAVE_FORM
3705
+ struct fielddata {
3706
+ FIELD *field;
3707
+ };
3708
+
3709
+ static void
3710
+ no_field(void)
3711
+ {
3712
+ rb_raise(rb_eRuntimeError, "already deleted field");
3713
+ }
3714
+
3715
+ #define GetFIELD(obj, fieldp) do {\
3716
+ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
3717
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted field");\
3718
+ TypedData_Get_Struct((obj), struct fielddata, &fielddata_type, (fieldp));\
3719
+ if ((fieldp)->field == 0) no_field();\
3720
+ } while (0)
3721
+
3722
+ static void
3723
+ field_free(void *p)
3724
+ {
3725
+ struct fielddata *fieldp = p;
3726
+ if (fieldp->field) free_field(fieldp->field);
3727
+ fieldp->field = 0;
3728
+ xfree(fieldp);
3729
+ }
3730
+
3731
+ static size_t
3732
+ field_memsize(const void *p)
3733
+ {
3734
+ const struct fielddata *fieldp = p;
3735
+ size_t size = sizeof(*fieldp);
3736
+ if (!fieldp) return 0;
3737
+ if (fieldp->field) size += sizeof(*fieldp->field);
3738
+ return size;
3739
+ }
3740
+
3741
+ static const rb_data_type_t fielddata_type = {
3742
+ "fielddata",
3743
+ {0, field_free, field_memsize,}
3744
+ };
3745
+
3746
+ /* returns a Curses::Menu object */
3747
+ static VALUE
3748
+ field_s_allocate(VALUE class)
3749
+ {
3750
+ struct fielddata *fieldp;
3751
+
3752
+ return TypedData_Make_Struct(class, struct fielddata, &fielddata_type, fieldp);
3753
+ }
3754
+
3755
+ /*
3756
+ * Document-method: Curses::Field.new
3757
+ *
3758
+ * call-seq:
3759
+ * new(height, width, toprow, leftcol, offscreen, nbuffers)
3760
+ *
3761
+ * Construct a new Curses::Field.
3762
+ */
3763
+ static VALUE
3764
+ field_initialize(VALUE obj, VALUE height, VALUE width,
3765
+ VALUE toprow, VALUE leftcol, VALUE offscreen, VALUE nbuffers)
3766
+ {
3767
+ struct fielddata *fieldp;
3768
+
3769
+ curses_init_screen();
3770
+ TypedData_Get_Struct(obj, struct fielddata, &fielddata_type, fieldp);
3771
+ if (fieldp->field) {
3772
+ rb_raise(rb_eRuntimeError, "already initialized field");
3773
+ }
3774
+ fieldp->field = new_field(NUM2INT(height), NUM2INT(width),
3775
+ NUM2INT(toprow), NUM2INT(leftcol),
3776
+ NUM2INT(offscreen), NUM2INT(nbuffers));
3777
+ if (fieldp->field == NULL) {
3778
+ check_curses_error(errno);
3779
+ }
3780
+
3781
+ return obj;
3782
+ }
3783
+
3784
+ /*
3785
+ * Document-method: Curses::Field#set_buffer
3786
+ *
3787
+ * call-seq:
3788
+ * set_buffer(buf, value)
3789
+ *
3790
+ * Set the numbered buffer of the field.
3791
+ */
3792
+ static VALUE
3793
+ field_set_buffer(VALUE obj, VALUE buf, VALUE value)
3794
+ {
3795
+ struct fielddata *fieldp;
3796
+
3797
+ GetFIELD(obj, fieldp);
3798
+ value = rb_str_export_to_enc(value, terminal_encoding);
3799
+ set_field_buffer(fieldp->field, NUM2INT(buf), StringValueCStr(value));
3800
+
3801
+ return obj;
3802
+ }
3803
+
3804
+ /*
3805
+ * Document-method: Curses::Field#buffer
3806
+ *
3807
+ * call-seq:
3808
+ * buffer(buf)
3809
+ *
3810
+ * Get the numbered buffer of the field.
3811
+ */
3812
+ static VALUE
3813
+ field_buffer_m(VALUE obj, VALUE buf)
3814
+ {
3815
+ struct fielddata *fieldp;
3816
+ char *s;
3817
+
3818
+ GetFIELD(obj, fieldp);
3819
+ s = field_buffer(fieldp->field, NUM2INT(buf));
3820
+ return rb_external_str_new_with_enc(s, strlen(s), terminal_encoding);
3821
+ }
3822
+
3823
+ /*
3824
+ * Document-method: Curses::Field#set_fore
3825
+ *
3826
+ * call-seq:
3827
+ * set_fore(attr)
3828
+ *
3829
+ * Set the foreground attribute of the field.
3830
+ */
3831
+ static VALUE
3832
+ field_set_fore(VALUE obj, VALUE attr)
3833
+ {
3834
+ struct fielddata *fieldp;
3835
+
3836
+ GetFIELD(obj, fieldp);
3837
+ set_field_fore(fieldp->field, NUM2CHTYPE(attr));
3838
+
3839
+ return attr;
3840
+ }
3841
+
3842
+ /*
3843
+ * Document-method: Curses::Field#fore
3844
+ *
3845
+ * call-seq:
3846
+ * fore
3847
+ *
3848
+ * Get the foreground attribute of the field.
3849
+ */
3850
+ static VALUE
3851
+ field_get_fore(VALUE obj)
3852
+ {
3853
+ struct fielddata *fieldp;
3854
+
3855
+ GetFIELD(obj, fieldp);
3856
+ return CHTYPE2NUM(field_fore(fieldp->field));
3857
+ }
3858
+
3859
+ /*
3860
+ * Document-method: Curses::Field#set_back
3861
+ *
3862
+ * call-seq:
3863
+ * set_back(attr)
3864
+ *
3865
+ * Set the background attribute of the field.
3866
+ */
3867
+ static VALUE
3868
+ field_set_back(VALUE obj, VALUE attr)
3869
+ {
3870
+ struct fielddata *fieldp;
3871
+
3872
+ GetFIELD(obj, fieldp);
3873
+ set_field_back(fieldp->field, NUM2CHTYPE(attr));
3874
+
3875
+ return attr;
3876
+ }
3877
+
3878
+ /*
3879
+ * Document-method: Curses::Field#back
3880
+ *
3881
+ * call-seq:
3882
+ * back
3883
+ *
3884
+ * Get the background attribute of the field.
3885
+ */
3886
+ static VALUE
3887
+ field_get_back(VALUE obj)
3888
+ {
3889
+ struct fielddata *fieldp;
3890
+
3891
+ GetFIELD(obj, fieldp);
3892
+ return CHTYPE2NUM(field_back(fieldp->field));
3893
+ }
3894
+
3895
+ /*
3896
+ * Document-method: Curses::Field#opts_on
3897
+ *
3898
+ * call-seq:
3899
+ * opts_on(opts)
3900
+ *
3901
+ * Turn on the given option bits.
3902
+ */
3903
+ static VALUE
3904
+ field_opts_on_m(VALUE obj, VALUE opts)
3905
+ {
3906
+ struct fielddata *fieldp;
3907
+
3908
+ GetFIELD(obj, fieldp);
3909
+ field_opts_on(fieldp->field, NUM2INT(opts));
3910
+
3911
+ return opts;
3912
+ }
3913
+
3914
+ /*
3915
+ * Document-method: Curses::Field#opts_off
3916
+ *
3917
+ * call-seq:
3918
+ * opts_off(opts)
3919
+ *
3920
+ * Turn off the given option bits.
3921
+ */
3922
+ static VALUE
3923
+ field_opts_off_m(VALUE obj, VALUE opts)
3924
+ {
3925
+ struct fielddata *fieldp;
3926
+
3927
+ GetFIELD(obj, fieldp);
3928
+ field_opts_off(fieldp->field, NUM2INT(opts));
3929
+
3930
+ return opts;
3931
+ }
3932
+
3933
+ /*
3934
+ * Document-method: Curses::Field#opts
3935
+ *
3936
+ * call-seq:
3937
+ * opts
3938
+ *
3939
+ * Get the current option bits.
3940
+ */
3941
+ static VALUE
3942
+ field_opts_m(VALUE obj)
3943
+ {
3944
+ struct fielddata *fieldp;
3945
+
3946
+ GetFIELD(obj, fieldp);
3947
+ return INT2NUM(field_opts(fieldp->field));
3948
+ }
3949
+
3950
+ static VALUE
3951
+ field_height(VALUE obj)
3952
+ {
3953
+ struct fielddata *fieldp;
3954
+ int error, val;
3955
+
3956
+ GetFIELD(obj, fieldp);
3957
+ error = field_info(fieldp->field, &val, NULL, NULL, NULL, NULL, NULL);
3958
+ check_curses_error(error);
3959
+ return INT2NUM(val);
3960
+ }
3961
+
3962
+ static VALUE
3963
+ field_width(VALUE obj)
3964
+ {
3965
+ struct fielddata *fieldp;
3966
+ int error, val;
3967
+
3968
+ GetFIELD(obj, fieldp);
3969
+ error = field_info(fieldp->field, NULL, &val, NULL, NULL, NULL, NULL);
3970
+ check_curses_error(error);
3971
+ return INT2NUM(val);
3972
+ }
3973
+
3974
+ static VALUE
3975
+ field_toprow(VALUE obj)
3976
+ {
3977
+ struct fielddata *fieldp;
3978
+ int error, val;
3979
+
3980
+ GetFIELD(obj, fieldp);
3981
+ error = field_info(fieldp->field, NULL, NULL, &val, NULL, NULL, NULL);
3982
+ check_curses_error(error);
3983
+ return INT2NUM(val);
3984
+ }
3985
+
3986
+ static VALUE
3987
+ field_leftcol(VALUE obj)
3988
+ {
3989
+ struct fielddata *fieldp;
3990
+ int error, val;
3991
+
3992
+ GetFIELD(obj, fieldp);
3993
+ error = field_info(fieldp->field, NULL, NULL, NULL, &val, NULL, NULL);
3994
+ check_curses_error(error);
3995
+ return INT2NUM(val);
3996
+ }
3997
+
3998
+ static VALUE
3999
+ field_offscreen(VALUE obj)
4000
+ {
4001
+ struct fielddata *fieldp;
4002
+ int error, val;
4003
+
4004
+ GetFIELD(obj, fieldp);
4005
+ error = field_info(fieldp->field, NULL, NULL, NULL, NULL, &val, NULL);
4006
+ check_curses_error(error);
4007
+ return INT2NUM(val);
4008
+ }
4009
+
4010
+ static VALUE
4011
+ field_nbuffers(VALUE obj)
4012
+ {
4013
+ struct fielddata *fieldp;
4014
+ int error, val;
4015
+
4016
+ GetFIELD(obj, fieldp);
4017
+ error = field_info(fieldp->field, NULL, NULL, NULL, NULL, NULL, &val);
4018
+ check_curses_error(error);
4019
+ return INT2NUM(val);
4020
+ }
4021
+
4022
+ static VALUE
4023
+ field_dynamic_height(VALUE obj)
4024
+ {
4025
+ struct fielddata *fieldp;
4026
+ int error, val;
4027
+
4028
+ GetFIELD(obj, fieldp);
4029
+ error = dynamic_field_info(fieldp->field, &val, NULL, NULL);
4030
+ check_curses_error(error);
4031
+ return INT2NUM(val);
4032
+ }
4033
+
4034
+ static VALUE
4035
+ field_dynamic_width(VALUE obj)
4036
+ {
4037
+ struct fielddata *fieldp;
4038
+ int error, val;
4039
+
4040
+ GetFIELD(obj, fieldp);
4041
+ error = dynamic_field_info(fieldp->field, NULL, &val, NULL);
4042
+ check_curses_error(error);
4043
+ return INT2NUM(val);
4044
+ }
4045
+
4046
+ static VALUE
4047
+ field_max(VALUE obj)
4048
+ {
4049
+ struct fielddata *fieldp;
4050
+ int error, val;
4051
+
4052
+ GetFIELD(obj, fieldp);
4053
+ error = dynamic_field_info(fieldp->field, NULL, NULL, &val);
4054
+ check_curses_error(error);
4055
+ return INT2NUM(val);
4056
+ }
4057
+
4058
+ static VALUE
4059
+ field_set_max(VALUE obj, VALUE max)
4060
+ {
4061
+ struct fielddata *fieldp;
4062
+ int error;
4063
+
4064
+ GetFIELD(obj, fieldp);
4065
+ error = set_max_field(fieldp->field, NUM2INT(max));
4066
+ check_curses_error(error);
4067
+ return max;
4068
+ }
4069
+
4070
+ #define TYPE_CODE_ALPHA 1
4071
+ #define TYPE_CODE_ALNUM 2
4072
+ #define TYPE_CODE_ENUM 3
4073
+ #define TYPE_CODE_INTEGER 4
4074
+ #define TYPE_CODE_NUMERIC 5
4075
+ #define TYPE_CODE_REGEXP 6
4076
+
4077
+ static VALUE
4078
+ field_set_type(int argc, VALUE *argv, VALUE obj)
4079
+ {
4080
+ struct fielddata *fieldp;
4081
+ VALUE type;
4082
+ int type_code;
4083
+ int error;
4084
+
4085
+ if (argc < 1) {
4086
+ rb_raise(rb_eArgError,
4087
+ "wrong number of arguments (given %d, expected 1)", argc);
4088
+ }
4089
+ type_code = NUM2INT(argv[0]);
4090
+ GetFIELD(obj, fieldp);
4091
+ switch (type_code) {
4092
+ case TYPE_CODE_ALPHA:
4093
+ {
4094
+ VALUE width;
4095
+ rb_scan_args(argc, argv, "11", &type, &width);
4096
+ error = set_field_type(fieldp->field, TYPE_ALPHA,
4097
+ NIL_P(width) ? 0 : NUM2INT(width));
4098
+ }
4099
+ break;
4100
+ case TYPE_CODE_ALNUM:
4101
+ {
4102
+ VALUE width;
4103
+ rb_scan_args(argc, argv, "11", &type, &width);
4104
+ error = set_field_type(fieldp->field, TYPE_ALNUM,
4105
+ NIL_P(width) ? 0 : NUM2INT(width));
4106
+ }
4107
+ break;
4108
+ #if 0
4109
+ case TYPE_CODE_ENUM:
4110
+ {
4111
+ /* TODO: consider how valuelist should be allocated? */
4112
+ }
4113
+ break;
4114
+ #endif
4115
+ case TYPE_CODE_INTEGER:
4116
+ {
4117
+ VALUE padding, vmin, vmax;
4118
+ rb_scan_args(argc, argv, "13", &type, &padding, &vmin, &vmax);
4119
+ error = set_field_type(fieldp->field, TYPE_INTEGER,
4120
+ NIL_P(padding) ? 0 : NUM2INT(padding),
4121
+ NIL_P(vmin) ? INT_MIN : NUM2INT(vmin),
4122
+ NIL_P(vmax) ? INT_MAX : NUM2INT(vmax));
4123
+ }
4124
+ break;
4125
+ case TYPE_CODE_NUMERIC:
4126
+ {
4127
+ VALUE padding, vmin, vmax;
4128
+ rb_scan_args(argc, argv, "13", &type, &padding, &vmin, &vmax);
4129
+ error = set_field_type(fieldp->field, TYPE_INTEGER,
4130
+ NIL_P(padding) ? 0 : NUM2INT(padding),
4131
+ NIL_P(vmin) ? INT_MIN : NUM2INT(vmin),
4132
+ NIL_P(vmax) ? INT_MAX : NUM2INT(vmax));
4133
+ }
4134
+ break;
4135
+ #if 0
4136
+ case TYPE_CODE_REGEXP:
4137
+ {
4138
+ /* TODO: consider how regexp should be allocated? */
4139
+ }
4140
+ break;
4141
+ #endif
4142
+ default:
4143
+ rb_raise(rb_eArgError, "unknwon type: %d", type_code);
4144
+ break;
4145
+ }
4146
+ check_curses_error(error);
4147
+ return obj;
4148
+ }
4149
+
4150
+ struct formdata {
4151
+ FORM *form;
4152
+ VALUE fields;
4153
+ };
4154
+
4155
+ static void
4156
+ no_form(void)
4157
+ {
4158
+ rb_raise(rb_eRuntimeError, "already deleted form");
4159
+ }
4160
+
4161
+ #define GetFORM(obj, formp) do {\
4162
+ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
4163
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted form");\
4164
+ TypedData_Get_Struct((obj), struct formdata, &formdata_type, (formp));\
4165
+ if ((formp)->form == 0) no_form();\
4166
+ } while (0)
4167
+
4168
+ static void
4169
+ form_gc_mark(void *p)
4170
+ {
4171
+ struct formdata *formp = p;
4172
+
4173
+ rb_gc_mark(formp->fields);
4174
+ }
4175
+
4176
+ static void
4177
+ form_free(void *p)
4178
+ {
4179
+ struct formdata *formp = p;
4180
+ FIELD **fields = form_fields(formp->form);
4181
+ if (formp->form) free_form(formp->form);
4182
+ xfree(fields);
4183
+ formp->form = 0;
4184
+ formp->fields = Qnil;
4185
+ xfree(formp);
4186
+ }
4187
+
4188
+ static size_t
4189
+ form_memsize(const void *p)
4190
+ {
4191
+ const struct formdata *formp = p;
4192
+ size_t size = sizeof(*formp);
4193
+ if (!formp) return 0;
4194
+ if (formp->form) size += sizeof(*formp->form);
4195
+ return size;
4196
+ }
4197
+
4198
+ static const rb_data_type_t formdata_type = {
4199
+ "formdata",
4200
+ {form_gc_mark, form_free, form_memsize,}
4201
+ };
4202
+
4203
+ /* returns a Curses::Form object */
4204
+ static VALUE
4205
+ form_s_allocate(VALUE class)
4206
+ {
4207
+ struct formdata *formp;
4208
+
4209
+ return TypedData_Make_Struct(class, struct formdata, &formdata_type, formp);
4210
+ }
4211
+
4212
+ /*
4213
+ * Document-method: Curses::Form.new
4214
+ *
4215
+ * call-seq:
4216
+ * new(fields)
4217
+ *
4218
+ * Construct a new Curses::Form.
4219
+ */
4220
+ static VALUE
4221
+ form_initialize(VALUE obj, VALUE fields)
4222
+ {
4223
+ struct formdata *formp;
4224
+ FIELD **form_fields;
4225
+ int i;
4226
+
4227
+ Check_Type(fields, T_ARRAY);
4228
+ curses_init_screen();
4229
+ TypedData_Get_Struct(obj, struct formdata, &formdata_type, formp);
4230
+ if (formp->form) {
4231
+ rb_raise(rb_eRuntimeError, "already initialized form");
4232
+ }
4233
+ formp->fields = rb_ary_new();
4234
+ form_fields = ALLOC_N(FIELD *, RARRAY_LEN(fields) + 1);
4235
+ for (i = 0; i < RARRAY_LEN(fields); i++) {
4236
+ VALUE field = RARRAY_AREF(fields, i);
4237
+ struct fielddata *fieldp;
4238
+
4239
+ GetFIELD(field, fieldp);
4240
+ form_fields[i] = fieldp->field;
4241
+ rb_ary_push(formp->fields, field);
4242
+ }
4243
+ form_fields[RARRAY_LEN(fields)] = NULL;
4244
+ formp->form = new_form(form_fields);
4245
+ if (formp->form == NULL) {
4246
+ check_curses_error(errno);
4247
+ }
4248
+
4249
+ return obj;
4250
+ }
4251
+
4252
+ /*
4253
+ * Document-method: Curses::Form#post
4254
+ *
4255
+ * call-seq:
4256
+ * post
4257
+ *
4258
+ * Post the form.
4259
+ */
4260
+ static VALUE
4261
+ form_post(VALUE obj)
4262
+ {
4263
+ struct formdata *formp;
4264
+ int error;
4265
+
4266
+ GetFORM(obj, formp);
4267
+ error = post_form(formp->form);
4268
+ check_curses_error(error);
4269
+
4270
+ return obj;
4271
+ }
4272
+
4273
+ /*
4274
+ * Document-method: Curses::Form#unpost
4275
+ *
4276
+ * call-seq:
4277
+ * unpost
4278
+ *
4279
+ * Unpost the form.
4280
+ */
4281
+ static VALUE
4282
+ form_unpost(VALUE obj)
4283
+ {
4284
+ struct formdata *formp;
4285
+ int error;
4286
+
4287
+ GetFORM(obj, formp);
4288
+ error = unpost_form(formp->form);
4289
+ check_curses_error(error);
4290
+
4291
+ return obj;
4292
+ }
4293
+
4294
+ /*
4295
+ * Document-method: Curses::Form#driver
4296
+ *
4297
+ * call-seq:
4298
+ * driver(command)
4299
+ *
4300
+ * Perform the command on the form.
4301
+ */
4302
+ static VALUE
4303
+ form_driver_m(VALUE obj, VALUE command)
4304
+ {
4305
+ struct formdata *formp;
4306
+ int error, c;
4307
+
4308
+ GetFORM(obj, formp);
4309
+ if (FIXNUM_P(command)) {
4310
+ c = NUM2INT(command);
4311
+ }
4312
+ else {
4313
+ ID id_ord;
4314
+
4315
+ StringValue(command);
4316
+ CONST_ID(id_ord, "ord");
4317
+ c = NUM2INT(rb_funcall(command, id_ord, 0));
4318
+ }
4319
+ #ifdef HAVE_FORM_DRIVER_W
4320
+ error = form_driver_w(formp->form,
4321
+ FIXNUM_P(command) ? KEY_CODE_YES : OK,
4322
+ c);
4323
+ #else
4324
+ error = form_driver(formp->form, c);
4325
+ #endif
4326
+ check_curses_error(error);
4327
+
4328
+ return obj;
4329
+ }
4330
+
4331
+ /*
4332
+ * Document-method: Curses::Form#set_win
4333
+ *
4334
+ * call-seq:
4335
+ * set_win=(win)
4336
+ *
4337
+ * Set the window of the form.
4338
+ */
4339
+ static VALUE
4340
+ form_set_win(VALUE obj, VALUE win)
4341
+ {
4342
+ struct formdata *formp;
4343
+ struct windata *winp;
4344
+
4345
+ GetFORM(obj, formp);
4346
+ GetWINDOW(win, winp);
4347
+ set_form_win(formp->form, winp->window);
4348
+ return win;
4349
+ }
4350
+
4351
+ /*
4352
+ * Document-method: Curses::Form#set_sub
4353
+ *
4354
+ * call-seq:
4355
+ * set_sub=(win)
4356
+ *
4357
+ * Set the subwindow of the form.
4358
+ */
4359
+ static VALUE
4360
+ form_set_sub(VALUE obj, VALUE win)
4361
+ {
4362
+ struct formdata *formp;
4363
+ struct windata *winp;
4364
+
4365
+ GetFORM(obj, formp);
4366
+ GetWINDOW(win, winp);
4367
+ set_form_sub(formp->form, winp->window);
4368
+ return win;
4369
+ }
4370
+
4371
+ /*
4372
+ * Document-method: Curses::Form#scale
4373
+ *
4374
+ * call-seq:
4375
+ * scale
4376
+ *
4377
+ * Return the minimum rows and columns required for the subwindow of the form.
4378
+ */
4379
+ static VALUE
4380
+ form_scale(VALUE obj)
4381
+ {
4382
+ struct formdata *formp;
4383
+ int error, rows, columns;
4384
+
4385
+ GetFORM(obj, formp);
4386
+ error = scale_form(formp->form, &rows, &columns);
4387
+ check_curses_error(error);
4388
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(columns));
4389
+ }
4390
+
4391
+ #endif /* HAVE_FORM */
4392
+
4393
+ /*
4394
+ * Document-method: Curses.keyboard_encoding
4395
+ * call-seq: Curses.keyboard_encoding
4396
+ *
4397
+ * Returns the encoding for keyboard input.
4398
+ */
4399
+ static VALUE
4400
+ curses_get_keyboard_encoding(VALUE obj)
4401
+ {
4402
+ return rb_enc_from_encoding(keyboard_encoding);
4403
+ }
4404
+
4405
+ /*
4406
+ * Document-method: Curses.keyboard_encoding=
4407
+ * call-seq: Curses.keyboard_encoding = encoding
4408
+ *
4409
+ * Sets the encoding for keyboard input.
4410
+ */
4411
+ static VALUE
4412
+ curses_set_keyboard_encoding(VALUE obj, VALUE enc)
4413
+ {
4414
+ keyboard_encoding = rb_to_encoding(enc);
4415
+ return enc;
4416
+ }
4417
+
4418
+ /*
4419
+ * Document-method: Curses.terminal_encoding
4420
+ * call-seq: Curses.terminal_encoding
4421
+ *
4422
+ * Returns the encoding for terminal output.
4423
+ */
4424
+ static VALUE
4425
+ curses_get_terminal_encoding(VALUE obj)
4426
+ {
4427
+ return rb_enc_from_encoding(terminal_encoding);
4428
+ }
4429
+
4430
+ /*
4431
+ * Document-method: Curses.terminal_encoding=
4432
+ * call-seq: Curses.terminal_encoding = encoding
4433
+ *
4434
+ * Sets the encoding for terminal output.
4435
+ */
4436
+ static VALUE
4437
+ curses_set_terminal_encoding(VALUE obj, VALUE enc)
4438
+ {
4439
+ terminal_encoding = rb_to_encoding(enc);
4440
+ return enc;
4441
+ }
4442
+
4443
+ /*
4444
+ * Document-method: Curses.unget_char
4445
+ * call-seq: unget_char(ch)
4446
+ *
4447
+ * Places +ch+ back onto the input queue to be returned by
4448
+ * the next call to Curses.get_char etc.
4449
+ *
4450
+ * There is just one input queue for all windows.
4451
+ */
4452
+ static VALUE
4453
+ curses_unget_char(VALUE obj, VALUE ch)
4454
+ {
4455
+ ID id_ord;
4456
+ unsigned int c;
4457
+
4458
+ curses_stdscr();
4459
+ if (FIXNUM_P(ch)) {
4460
+ ungetch(NUM2UINT(ch));
4461
+ }
4462
+ else {
4463
+ StringValue(ch);
4464
+ CONST_ID(id_ord, "ord");
4465
+ c = NUM2UINT(rb_funcall(ch, id_ord, 0));
4466
+ #ifdef HAVE_UNGET_WCH
4467
+ unget_wch(c);
4468
+ #else
4469
+ if (c > 0xff) {
4470
+ rb_raise(rb_eRangeError, "Out of range: %u", c);
4471
+ }
4472
+ ungetch(c);
4473
+ #endif
4474
+ }
4475
+ return Qnil;
4476
+ }
4477
+
4478
+ static VALUE
4479
+ keyboard_uint_chr(unsigned int ch)
4480
+ {
4481
+ return rb_enc_uint_chr(ch, keyboard_encoding);
4482
+ }
4483
+
4484
+ #if defined(HAVE_GET_WCH) || defined(HAVE_WGET_WCH)
4485
+ static VALUE
4486
+ key_code_value(unsigned int ch)
4487
+ {
4488
+ #ifdef CTL_FSLASH
4489
+ if (ch == CTL_FSLASH) {
4490
+ return keyboard_uint_chr(0x1F);
4491
+ }
4492
+ #endif
4493
+ return UINT2NUM(ch);
4494
+ }
4495
+ #endif
4496
+
4497
+ #ifdef HAVE_GET_WCH
4498
+ struct get_wch_arg {
4499
+ int retval;
4500
+ wint_t ch;
4501
+ };
4502
+
4503
+ static void *
4504
+ get_wch_func(void *_arg)
4505
+ {
4506
+ struct get_wch_arg *arg = (struct get_wch_arg *) _arg;
4507
+ arg->retval = get_wch(&arg->ch);
4508
+ return 0;
4509
+ }
4510
+ #endif
4511
+
4512
+ /*
4513
+ * Document-method: Curses.get_char
4514
+ *
4515
+ * Read and returns a character or function key from the window.
4516
+ * A single or multibyte character is represented by a String, and
4517
+ * a function key is represented by an Integer.
4518
+ * Returns nil if no input is ready.
4519
+ *
4520
+ * See Curses::Key to all the function KEY_* available
4521
+ *
4522
+ */
4523
+ static VALUE
4524
+ curses_get_char(VALUE obj)
4525
+ {
4526
+ #ifdef HAVE_GET_WCH
4527
+ struct get_wch_arg arg;
4528
+
4529
+ curses_stdscr();
4530
+ rb_thread_call_without_gvl(get_wch_func, &arg, RUBY_UBF_IO, 0);
4531
+ switch (arg.retval) {
4532
+ case OK:
4533
+ return keyboard_uint_chr(arg.ch);
4534
+ case KEY_CODE_YES:
4535
+ return key_code_value(arg.ch);
4536
+ }
4537
+ return Qnil;
4538
+ #else
4539
+ int c;
4540
+
4541
+ curses_stdscr();
4542
+ rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0);
4543
+ if (c > 0xff) {
4544
+ return INT2NUM(c);
4545
+ }
4546
+ else if (c >= 0) {
4547
+ return keyboard_uint_chr(c);
4548
+ }
4549
+ else {
4550
+ return Qnil;
4551
+ }
4552
+ #endif
4553
+ }
4554
+
4555
+
4556
+ #ifdef HAVE_WGET_WCH
4557
+ struct wget_wch_arg {
4558
+ WINDOW *win;
4559
+ int retval;
4560
+ wint_t ch;
4561
+ };
4562
+
4563
+ static void *
4564
+ wget_wch_func(void *_arg)
4565
+ {
4566
+ struct wget_wch_arg *arg = (struct wget_wch_arg *) _arg;
4567
+ arg->retval = wget_wch(arg->win, &arg->ch);
4568
+ return 0;
4569
+ }
4570
+ #endif
4571
+
4572
+ /*
4573
+ * Document-method: Curses::Window.get_char
4574
+ *
4575
+ * Read and returns a character or function key from the window.
4576
+ * A single or multibyte character is represented by a String, and
4577
+ * a function key is represented by an Integer.
4578
+ * Returns nil if no input is ready.
4579
+ *
4580
+ * See Curses::Key to all the function KEY_* available
4581
+ *
4582
+ */
4583
+ static VALUE
4584
+ window_get_char(VALUE obj)
4585
+ {
4586
+ #ifdef HAVE_WGET_WCH
4587
+ struct windata *winp;
4588
+ struct wget_wch_arg arg;
4589
+
4590
+ GetWINDOW(obj, winp);
4591
+ arg.win = winp->window;
4592
+ rb_thread_call_without_gvl(wget_wch_func, &arg, RUBY_UBF_IO, 0);
4593
+ switch (arg.retval) {
4594
+ case OK:
4595
+ return keyboard_uint_chr(arg.ch);
4596
+ case KEY_CODE_YES:
4597
+ return key_code_value(arg.ch);
3623
4598
  }
3624
4599
  return Qnil;
3625
4600
  #else
@@ -3980,6 +4955,10 @@ Init_curses(void)
3980
4955
  rb_define_method(cItem, "==", item_eq, 1);
3981
4956
  rb_define_method(cItem, "name", item_name_m, 0);
3982
4957
  rb_define_method(cItem, "description", item_description_m, 0);
4958
+ rb_define_method(cItem, "set_opts", item_set_opts, 1);
4959
+ rb_define_method(cItem, "opts_on", item_opts_on_m, 1);
4960
+ rb_define_method(cItem, "opts_off", item_opts_off_m, 1);
4961
+ rb_define_method(cItem, "opts", item_opts_m, 0);
3983
4962
 
3984
4963
  cMenu = rb_define_class_under(mCurses, "Menu", rb_cData);
3985
4964
  rb_define_alloc_func(cMenu, menu_s_allocate);
@@ -3992,6 +4971,54 @@ Init_curses(void)
3992
4971
  rb_define_method(cMenu, "items=", menu_set_items, 1);
3993
4972
  rb_define_method(cMenu, "current_item", menu_get_current_item, 0);
3994
4973
  rb_define_method(cMenu, "current_item=", menu_set_current_item, 1);
4974
+ rb_define_method(cMenu, "set_win", menu_set_win, 1);
4975
+ rb_define_method(cMenu, "set_sub", menu_set_sub, 1);
4976
+ rb_define_method(cMenu, "scale", menu_scale, 0);
4977
+ rb_define_method(cMenu, "set_format", menu_set_format, 2);
4978
+ rb_define_method(cMenu, "format", menu_format_m, 0);
4979
+ rb_define_method(cMenu, "set_opts", menu_set_opts, 1);
4980
+ rb_define_method(cMenu, "opts_on", menu_opts_on_m, 1);
4981
+ rb_define_method(cMenu, "opts_off", menu_opts_off_m, 1);
4982
+ rb_define_method(cMenu, "opts", menu_opts_m, 0);
4983
+ #endif
4984
+
4985
+ #ifdef HAVE_FORM
4986
+ cField = rb_define_class_under(mCurses, "Field", rb_cData);
4987
+ rb_define_alloc_func(cField, field_s_allocate);
4988
+ rb_define_method(cField, "initialize", field_initialize, 6);
4989
+ rb_define_method(cField, "set_buffer", field_set_buffer, 2);
4990
+ rb_define_method(cField, "buffer", field_buffer_m, 1);
4991
+ rb_define_method(cField, "set_fore", field_set_fore, 1);
4992
+ rb_define_method(cField, "fore=", field_set_fore, 1);
4993
+ rb_define_method(cField, "fore", field_get_fore, 0);
4994
+ rb_define_method(cField, "set_back", field_set_back, 1);
4995
+ rb_define_method(cField, "back=", field_set_back, 1);
4996
+ rb_define_method(cField, "back", field_get_back, 0);
4997
+ rb_define_method(cField, "opts_on", field_opts_on_m, 1);
4998
+ rb_define_method(cField, "opts_off", field_opts_off_m, 1);
4999
+ rb_define_method(cField, "opts", field_opts_m, 0);
5000
+ rb_define_method(cField, "height", field_height, 0);
5001
+ rb_define_method(cField, "width", field_width, 0);
5002
+ rb_define_method(cField, "toprow", field_toprow, 0);
5003
+ rb_define_method(cField, "leftcol", field_leftcol, 0);
5004
+ rb_define_method(cField, "offscreen", field_offscreen, 0);
5005
+ rb_define_method(cField, "nbuffers", field_nbuffers, 0);
5006
+ rb_define_method(cField, "dynamic_height", field_dynamic_height, 0);
5007
+ rb_define_method(cField, "dynamic_width", field_dynamic_width, 0);
5008
+ rb_define_method(cField, "max", field_max, 0);
5009
+ rb_define_method(cField, "set_max", field_set_max, 1);
5010
+ rb_define_method(cField, "max=", field_set_max, 1);
5011
+ rb_define_method(cField, "set_type", field_set_type, -1);
5012
+
5013
+ cForm = rb_define_class_under(mCurses, "Form", rb_cData);
5014
+ rb_define_alloc_func(cForm, form_s_allocate);
5015
+ rb_define_method(cForm, "initialize", form_initialize, 1);
5016
+ rb_define_method(cForm, "post", form_post, 0);
5017
+ rb_define_method(cForm, "unpost", form_unpost, 0);
5018
+ rb_define_method(cForm, "driver", form_driver_m, 1);
5019
+ rb_define_method(cForm, "set_win", form_set_win, 1);
5020
+ rb_define_method(cForm, "set_sub", form_set_sub, 1);
5021
+ rb_define_method(cForm, "scale", form_scale, 0);
3995
5022
  #endif
3996
5023
 
3997
5024
  #define rb_curses_define_error(c) do { \
@@ -5482,6 +6509,17 @@ Init_curses(void)
5482
6509
  #endif
5483
6510
 
5484
6511
  #ifdef HAVE_MENU
6512
+ rb_curses_define_const(O_ONEVALUE);
6513
+ rb_curses_define_const(O_SHOWDESC);
6514
+ rb_curses_define_const(O_ROWMAJOR);
6515
+ rb_curses_define_const(O_IGNORECASE);
6516
+ rb_curses_define_const(O_SHOWMATCH);
6517
+ rb_curses_define_const(O_NONCYCLIC);
6518
+ #ifdef O_MOUSE_MENU
6519
+ rb_curses_define_const(O_MOUSE_MENU);
6520
+ #endif
6521
+ rb_curses_define_const(O_SELECTABLE);
6522
+
5485
6523
  rb_curses_define_const(REQ_LEFT_ITEM);
5486
6524
  rb_curses_define_const(REQ_RIGHT_ITEM);
5487
6525
  rb_curses_define_const(REQ_UP_ITEM);
@@ -5500,5 +6538,93 @@ Init_curses(void)
5500
6538
  rb_curses_define_const(REQ_NEXT_MATCH);
5501
6539
  rb_curses_define_const(REQ_PREV_MATCH);
5502
6540
  #endif
6541
+
6542
+ #ifdef HAVE_FORM
6543
+ rb_curses_define_const(O_VISIBLE);
6544
+ rb_curses_define_const(O_ACTIVE);
6545
+ rb_curses_define_const(O_PUBLIC);
6546
+ rb_curses_define_const(O_EDIT);
6547
+ rb_curses_define_const(O_WRAP);
6548
+ rb_curses_define_const(O_BLANK);
6549
+ rb_curses_define_const(O_AUTOSKIP);
6550
+ rb_curses_define_const(O_NULLOK);
6551
+ rb_curses_define_const(O_PASSOK);
6552
+ rb_curses_define_const(O_STATIC);
6553
+ #ifdef O_DYNAMIC_JUSTIFY
6554
+ rb_curses_define_const(O_DYNAMIC_JUSTIFY);
6555
+ #endif
6556
+ #ifdef O_NO_LEFT_STRIP
6557
+ rb_curses_define_const(O_NO_LEFT_STRIP);
6558
+ #endif
6559
+
6560
+ rb_define_const(mCurses, "TYPE_ALPHA", INT2NUM(TYPE_CODE_ALPHA));
6561
+ rb_define_const(mCurses, "TYPE_ALNUM", INT2NUM(TYPE_CODE_ALNUM));
6562
+ rb_define_const(mCurses, "TYPE_ENUM", INT2NUM(TYPE_CODE_ENUM));
6563
+ rb_define_const(mCurses, "TYPE_INTEGER", INT2NUM(TYPE_CODE_INTEGER));
6564
+ rb_define_const(mCurses, "TYPE_NUMERIC", INT2NUM(TYPE_CODE_NUMERIC));
6565
+ rb_define_const(mCurses, "TYPE_REGEXP", INT2NUM(TYPE_CODE_REGEXP));
6566
+
6567
+ rb_curses_define_const(REQ_NEXT_PAGE);
6568
+ rb_curses_define_const(REQ_PREV_PAGE);
6569
+ rb_curses_define_const(REQ_FIRST_PAGE);
6570
+ rb_curses_define_const(REQ_LAST_PAGE);
6571
+
6572
+ rb_curses_define_const(REQ_NEXT_FIELD);
6573
+ rb_curses_define_const(REQ_PREV_FIELD);
6574
+ rb_curses_define_const(REQ_FIRST_FIELD);
6575
+ rb_curses_define_const(REQ_LAST_FIELD);
6576
+ rb_curses_define_const(REQ_SNEXT_FIELD);
6577
+ rb_curses_define_const(REQ_SPREV_FIELD);
6578
+ rb_curses_define_const(REQ_SFIRST_FIELD);
6579
+ rb_curses_define_const(REQ_SLAST_FIELD);
6580
+ rb_curses_define_const(REQ_LEFT_FIELD);
6581
+ rb_curses_define_const(REQ_RIGHT_FIELD);
6582
+ rb_curses_define_const(REQ_UP_FIELD);
6583
+ rb_curses_define_const(REQ_DOWN_FIELD);
6584
+
6585
+ rb_curses_define_const(REQ_NEXT_CHAR);
6586
+ rb_curses_define_const(REQ_PREV_CHAR);
6587
+ rb_curses_define_const(REQ_NEXT_LINE);
6588
+ rb_curses_define_const(REQ_PREV_LINE);
6589
+ rb_curses_define_const(REQ_NEXT_WORD);
6590
+ rb_curses_define_const(REQ_PREV_WORD);
6591
+ rb_curses_define_const(REQ_BEG_FIELD);
6592
+ rb_curses_define_const(REQ_END_FIELD);
6593
+ rb_curses_define_const(REQ_BEG_LINE);
6594
+ rb_curses_define_const(REQ_END_LINE);
6595
+ rb_curses_define_const(REQ_LEFT_CHAR);
6596
+ rb_curses_define_const(REQ_RIGHT_CHAR);
6597
+ rb_curses_define_const(REQ_UP_CHAR);
6598
+ rb_curses_define_const(REQ_DOWN_CHAR);
6599
+
6600
+ rb_curses_define_const(REQ_NEW_LINE);
6601
+ rb_curses_define_const(REQ_INS_CHAR);
6602
+ rb_curses_define_const(REQ_INS_LINE);
6603
+ rb_curses_define_const(REQ_DEL_CHAR);
6604
+ rb_curses_define_const(REQ_DEL_PREV);
6605
+ rb_curses_define_const(REQ_DEL_LINE);
6606
+ rb_curses_define_const(REQ_DEL_WORD);
6607
+ rb_curses_define_const(REQ_CLR_EOL);
6608
+ rb_curses_define_const(REQ_CLR_EOF);
6609
+ rb_curses_define_const(REQ_CLR_FIELD);
6610
+ rb_curses_define_const(REQ_OVL_MODE);
6611
+ rb_curses_define_const(REQ_INS_MODE);
6612
+ rb_curses_define_const(REQ_SCR_FLINE);
6613
+ rb_curses_define_const(REQ_SCR_BLINE);
6614
+ rb_curses_define_const(REQ_SCR_FPAGE);
6615
+ rb_curses_define_const(REQ_SCR_BPAGE);
6616
+ rb_curses_define_const(REQ_SCR_FHPAGE);
6617
+ rb_curses_define_const(REQ_SCR_BHPAGE);
6618
+ rb_curses_define_const(REQ_SCR_FCHAR);
6619
+ rb_curses_define_const(REQ_SCR_BCHAR);
6620
+ rb_curses_define_const(REQ_SCR_HFLINE);
6621
+ rb_curses_define_const(REQ_SCR_HBLINE);
6622
+ rb_curses_define_const(REQ_SCR_HFHALF);
6623
+ rb_curses_define_const(REQ_SCR_HBHALF);
6624
+
6625
+ rb_curses_define_const(REQ_VALIDATION);
6626
+ rb_curses_define_const(REQ_NEXT_CHOICE);
6627
+ rb_curses_define_const(REQ_PREV_CHOICE);
6628
+ #endif
5503
6629
  #undef rb_curses_define_const
5504
6630
  }