curses 1.2.7 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +19 -0
  3. data/.github/workflows/ubuntu.yml +26 -0
  4. data/.github/workflows/windows.yml +25 -0
  5. data/.gitmodules +1 -1
  6. data/History.md +41 -0
  7. data/README.md +14 -46
  8. data/Rakefile +0 -83
  9. data/curses.gemspec +2 -3
  10. data/ext/curses/curses.c +1314 -176
  11. data/ext/curses/extconf.rb +140 -17
  12. data/lib/curses.rb +5 -12
  13. data/sample/form.rb +52 -0
  14. data/sample/menu.rb +1 -1
  15. data/vendor/PDCurses/.gitignore +47 -0
  16. data/vendor/PDCurses/.travis.yml +49 -0
  17. data/vendor/PDCurses/CMakeLists.txt +68 -0
  18. data/vendor/PDCurses/HISTORY.md +2036 -0
  19. data/vendor/PDCurses/IMPLEMNT.md +327 -0
  20. data/vendor/PDCurses/README.md +77 -0
  21. data/vendor/PDCurses/acs_defs.h +265 -0
  22. data/vendor/PDCurses/appveyor.yml +218 -0
  23. data/vendor/PDCurses/cmake/README.md +71 -0
  24. data/vendor/PDCurses/cmake/build_dependencies.cmake +178 -0
  25. data/vendor/PDCurses/cmake/build_options.cmake +25 -0
  26. data/vendor/PDCurses/cmake/dll_version.cmake +26 -0
  27. data/vendor/PDCurses/cmake/gen_config_header.cmake +43 -0
  28. data/vendor/PDCurses/cmake/get_version.cmake +17 -0
  29. data/vendor/PDCurses/cmake/make_uninstall.cmake +19 -0
  30. data/vendor/PDCurses/cmake/project_common.cmake +121 -0
  31. data/vendor/PDCurses/cmake/resource.in.cmake +52 -0
  32. data/vendor/PDCurses/cmake/sdl2_ttf/CMakeLists.txt +83 -0
  33. data/vendor/PDCurses/cmake/target_arch.cmake +36 -0
  34. data/vendor/PDCurses/cmake/version.in.cmake +73 -0
  35. data/vendor/PDCurses/cmake/watcom_open_dos16_toolchain.cmake +96 -0
  36. data/vendor/PDCurses/cmake/watcom_open_dos32_toolchain.cmake +106 -0
  37. data/vendor/PDCurses/cmake/watcom_open_os2v2_toolchain.cmake +105 -0
  38. data/vendor/PDCurses/curses.h +1846 -0
  39. data/vendor/PDCurses/curspriv.h +134 -0
  40. data/vendor/PDCurses/demos/README.md +25 -0
  41. data/vendor/PDCurses/demos/firework.c +144 -0
  42. data/vendor/PDCurses/demos/newtest.c +581 -0
  43. data/vendor/PDCurses/demos/ozdemo.c +447 -0
  44. data/vendor/PDCurses/demos/ptest.c +283 -0
  45. data/vendor/PDCurses/demos/rain.c +157 -0
  46. data/vendor/PDCurses/demos/testcurs.c +1607 -0
  47. data/vendor/PDCurses/demos/tui.c +1048 -0
  48. data/vendor/PDCurses/demos/tui.h +65 -0
  49. data/vendor/PDCurses/demos/tuidemo.c +233 -0
  50. data/vendor/PDCurses/demos/version.c +61 -0
  51. data/vendor/PDCurses/demos/worm.c +432 -0
  52. data/vendor/PDCurses/demos/xmas.c +955 -0
  53. data/vendor/PDCurses/dos/CMakeLists.txt +47 -0
  54. data/vendor/PDCurses/dos/Makefile.bcc +83 -0
  55. data/vendor/PDCurses/dos/Makefile.dmc +257 -0
  56. data/vendor/PDCurses/dos/Makefile.msc +113 -0
  57. data/vendor/PDCurses/dos/Makefile.wcc +107 -0
  58. data/vendor/PDCurses/dos/README.md +51 -0
  59. data/vendor/PDCurses/dos/bccdos.lrf +9 -0
  60. data/vendor/PDCurses/dos/mscdos.lrf +50 -0
  61. data/vendor/PDCurses/dos/pdcclip.c +132 -0
  62. data/vendor/PDCurses/dos/pdcdisp.c +135 -0
  63. data/vendor/PDCurses/dos/pdcdos.h +194 -0
  64. data/vendor/PDCurses/dos/pdcgetsc.c +98 -0
  65. data/vendor/PDCurses/dos/pdckbd.c +513 -0
  66. data/vendor/PDCurses/dos/pdcscrn.c +785 -0
  67. data/vendor/PDCurses/dos/pdcsetsc.c +101 -0
  68. data/vendor/PDCurses/dos/pdcutil.c +212 -0
  69. data/vendor/PDCurses/libobjs.mif +26 -0
  70. data/vendor/PDCurses/makedist.mif +20 -0
  71. data/vendor/PDCurses/man/README.md +21 -0
  72. data/vendor/PDCurses/man/intro.md +361 -0
  73. data/vendor/PDCurses/man/manext.c +119 -0
  74. data/vendor/PDCurses/man/sdl.md +152 -0
  75. data/vendor/PDCurses/man/sdl2.md +58 -0
  76. data/vendor/PDCurses/man/x11.md +407 -0
  77. data/vendor/PDCurses/ncurses/CMakeLists.txt +66 -0
  78. data/vendor/PDCurses/ncurses/README.md +26 -0
  79. data/vendor/PDCurses/ncurses/makefile +29 -0
  80. data/vendor/PDCurses/os2/CMakeLists.txt +41 -0
  81. data/vendor/PDCurses/os2/Makefile.bcc +90 -0
  82. data/vendor/PDCurses/os2/Makefile.wcc +43 -0
  83. data/vendor/PDCurses/os2/README.md +43 -0
  84. data/vendor/PDCurses/os2/iccos2.lrf +50 -0
  85. data/vendor/PDCurses/os2/iccos2.mak +256 -0
  86. data/vendor/PDCurses/os2/pdcclip.c +188 -0
  87. data/vendor/PDCurses/os2/pdcdisp.c +93 -0
  88. data/vendor/PDCurses/os2/pdcgetsc.c +89 -0
  89. data/vendor/PDCurses/os2/pdckbd.c +521 -0
  90. data/vendor/PDCurses/os2/pdcos2.h +55 -0
  91. data/vendor/PDCurses/os2/pdcscrn.c +449 -0
  92. data/vendor/PDCurses/os2/pdcsetsc.c +112 -0
  93. data/vendor/PDCurses/os2/pdcutil.c +52 -0
  94. data/vendor/PDCurses/panel.h +56 -0
  95. data/vendor/PDCurses/pdcurses/README.md +25 -0
  96. data/vendor/PDCurses/pdcurses/addch.c +693 -0
  97. data/vendor/PDCurses/pdcurses/addchstr.c +245 -0
  98. data/vendor/PDCurses/pdcurses/addstr.c +240 -0
  99. data/vendor/PDCurses/pdcurses/attr.c +359 -0
  100. data/vendor/PDCurses/pdcurses/beep.c +68 -0
  101. data/vendor/PDCurses/pdcurses/bkgd.c +223 -0
  102. data/vendor/PDCurses/pdcurses/border.c +411 -0
  103. data/vendor/PDCurses/pdcurses/clear.c +159 -0
  104. data/vendor/PDCurses/pdcurses/color.c +298 -0
  105. data/vendor/PDCurses/pdcurses/debug.c +109 -0
  106. data/vendor/PDCurses/pdcurses/delch.c +96 -0
  107. data/vendor/PDCurses/pdcurses/deleteln.c +211 -0
  108. data/vendor/PDCurses/pdcurses/deprec.c +27 -0
  109. data/vendor/PDCurses/pdcurses/getch.c +417 -0
  110. data/vendor/PDCurses/pdcurses/getstr.c +474 -0
  111. data/vendor/PDCurses/pdcurses/getyx.c +139 -0
  112. data/vendor/PDCurses/pdcurses/inch.c +127 -0
  113. data/vendor/PDCurses/pdcurses/inchstr.c +214 -0
  114. data/vendor/PDCurses/pdcurses/initscr.c +367 -0
  115. data/vendor/PDCurses/pdcurses/inopts.c +324 -0
  116. data/vendor/PDCurses/pdcurses/insch.c +271 -0
  117. data/vendor/PDCurses/pdcurses/insstr.c +264 -0
  118. data/vendor/PDCurses/pdcurses/instr.c +246 -0
  119. data/vendor/PDCurses/pdcurses/kernel.c +259 -0
  120. data/vendor/PDCurses/pdcurses/keyname.c +157 -0
  121. data/vendor/PDCurses/pdcurses/mouse.c +438 -0
  122. data/vendor/PDCurses/pdcurses/move.c +57 -0
  123. data/vendor/PDCurses/pdcurses/outopts.c +159 -0
  124. data/vendor/PDCurses/pdcurses/overlay.c +214 -0
  125. data/vendor/PDCurses/pdcurses/pad.c +260 -0
  126. data/vendor/PDCurses/pdcurses/panel.c +633 -0
  127. data/vendor/PDCurses/pdcurses/printw.c +126 -0
  128. data/vendor/PDCurses/pdcurses/refresh.c +279 -0
  129. data/vendor/PDCurses/pdcurses/scanw.c +578 -0
  130. data/vendor/PDCurses/pdcurses/scr_dump.c +213 -0
  131. data/vendor/PDCurses/pdcurses/scroll.c +101 -0
  132. data/vendor/PDCurses/pdcurses/slk.c +591 -0
  133. data/vendor/PDCurses/pdcurses/termattr.c +182 -0
  134. data/vendor/PDCurses/pdcurses/terminfo.c +217 -0
  135. data/vendor/PDCurses/pdcurses/touch.c +163 -0
  136. data/vendor/PDCurses/pdcurses/util.c +312 -0
  137. data/vendor/PDCurses/pdcurses/window.c +569 -0
  138. data/vendor/PDCurses/sdl1/Makefile.mng +110 -0
  139. data/vendor/PDCurses/sdl1/README.md +31 -0
  140. data/vendor/PDCurses/sdl1/deffont.h +385 -0
  141. data/vendor/PDCurses/sdl1/deficon.h +23 -0
  142. data/vendor/PDCurses/sdl1/pdcclip.c +131 -0
  143. data/vendor/PDCurses/sdl1/pdcdisp.c +373 -0
  144. data/vendor/PDCurses/sdl1/pdcgetsc.c +30 -0
  145. data/vendor/PDCurses/sdl1/pdckbd.c +405 -0
  146. data/vendor/PDCurses/sdl1/pdcscrn.c +414 -0
  147. data/vendor/PDCurses/sdl1/pdcsdl.h +31 -0
  148. data/vendor/PDCurses/sdl1/pdcsetsc.c +64 -0
  149. data/vendor/PDCurses/sdl1/pdcutil.c +40 -0
  150. data/vendor/PDCurses/sdl1/sdltest.c +79 -0
  151. data/vendor/PDCurses/sdl2/CMakeLists.txt +76 -0
  152. data/vendor/PDCurses/sdl2/Makefile.vc +164 -0
  153. data/vendor/PDCurses/sdl2/README.md +34 -0
  154. data/vendor/PDCurses/sdl2/deffont.h +385 -0
  155. data/vendor/PDCurses/sdl2/deficon.h +23 -0
  156. data/vendor/PDCurses/sdl2/pdcclip.c +93 -0
  157. data/vendor/PDCurses/sdl2/pdcdisp.c +534 -0
  158. data/vendor/PDCurses/sdl2/pdcgetsc.c +30 -0
  159. data/vendor/PDCurses/sdl2/pdckbd.c +480 -0
  160. data/vendor/PDCurses/sdl2/pdcscrn.c +443 -0
  161. data/vendor/PDCurses/sdl2/pdcsdl.h +33 -0
  162. data/vendor/PDCurses/sdl2/pdcsetsc.c +67 -0
  163. data/vendor/PDCurses/sdl2/pdcutil.c +39 -0
  164. data/vendor/PDCurses/sdl2/sdltest.c +81 -0
  165. data/vendor/PDCurses/term.h +48 -0
  166. data/vendor/PDCurses/version.mif +7 -0
  167. data/vendor/PDCurses/vt/CMakeLists.txt +28 -0
  168. data/vendor/PDCurses/vt/Makefile.bcc +111 -0
  169. data/vendor/PDCurses/vt/Makefile.dmc +258 -0
  170. data/vendor/PDCurses/vt/Makefile.vc +144 -0
  171. data/vendor/PDCurses/vt/Makefile.wcc +107 -0
  172. data/vendor/PDCurses/vt/README.md +64 -0
  173. data/vendor/PDCurses/vt/pdcclip.c +20 -0
  174. data/vendor/PDCurses/vt/pdcdisp.c +284 -0
  175. data/vendor/PDCurses/vt/pdcgetsc.c +27 -0
  176. data/vendor/PDCurses/vt/pdckbd.c +394 -0
  177. data/vendor/PDCurses/vt/pdcscrn.c +434 -0
  178. data/vendor/PDCurses/vt/pdcsetsc.c +45 -0
  179. data/vendor/PDCurses/vt/pdcutil.c +43 -0
  180. data/vendor/PDCurses/vt/pdcvt.h +16 -0
  181. data/vendor/PDCurses/watcom.mif +68 -0
  182. data/vendor/PDCurses/wincon/CMakeLists.txt +27 -0
  183. data/vendor/PDCurses/wincon/Makefile.bcc +88 -0
  184. data/vendor/PDCurses/wincon/Makefile.dmc +256 -0
  185. data/vendor/PDCurses/wincon/Makefile.lcc +273 -0
  186. data/vendor/PDCurses/wincon/Makefile.mng +176 -0
  187. data/vendor/PDCurses/wincon/Makefile.vc +144 -0
  188. data/vendor/PDCurses/wincon/Makefile.wcc +51 -0
  189. data/vendor/PDCurses/wincon/README.md +85 -0
  190. data/vendor/PDCurses/wincon/pdcclip.c +174 -0
  191. data/vendor/PDCurses/wincon/pdcdisp.c +143 -0
  192. data/vendor/PDCurses/wincon/pdcgetsc.c +55 -0
  193. data/vendor/PDCurses/wincon/pdckbd.c +786 -0
  194. data/vendor/PDCurses/wincon/pdcscrn.c +717 -0
  195. data/vendor/PDCurses/wincon/pdcsetsc.c +91 -0
  196. data/vendor/PDCurses/wincon/pdcurses.ico +0 -0
  197. data/vendor/PDCurses/wincon/pdcurses.rc +28 -0
  198. data/vendor/PDCurses/wincon/pdcutil.c +41 -0
  199. data/vendor/PDCurses/wincon/pdcwin.h +31 -0
  200. data/vendor/PDCurses/wingui/CMakeLists.txt +27 -0
  201. data/vendor/PDCurses/wingui/Makefile.bcc +85 -0
  202. data/vendor/PDCurses/wingui/Makefile.dmc +259 -0
  203. data/vendor/PDCurses/wingui/Makefile.lcc +273 -0
  204. data/vendor/PDCurses/wingui/Makefile.mng +171 -0
  205. data/vendor/PDCurses/wingui/Makefile.vc +144 -0
  206. data/vendor/PDCurses/wingui/Makefile.wcc +51 -0
  207. data/vendor/PDCurses/wingui/README.md +93 -0
  208. data/vendor/PDCurses/wingui/pdcclip.c +174 -0
  209. data/vendor/PDCurses/wingui/pdcdisp.c +718 -0
  210. data/vendor/PDCurses/wingui/pdcgetsc.c +30 -0
  211. data/vendor/PDCurses/wingui/pdckbd.c +143 -0
  212. data/vendor/PDCurses/wingui/pdcscrn.c +2797 -0
  213. data/vendor/PDCurses/wingui/pdcsetsc.c +89 -0
  214. data/vendor/PDCurses/wingui/pdcurses.ico +0 -0
  215. data/vendor/PDCurses/wingui/pdcurses.rc +28 -0
  216. data/vendor/PDCurses/wingui/pdcutil.c +61 -0
  217. data/vendor/PDCurses/wingui/pdcwin.h +122 -0
  218. data/vendor/PDCurses/x11/Makefile.in +754 -0
  219. data/vendor/PDCurses/x11/PDCurses.spec +82 -0
  220. data/vendor/PDCurses/x11/README.md +62 -0
  221. data/vendor/PDCurses/x11/ScrollBox.c +319 -0
  222. data/vendor/PDCurses/x11/ScrollBox.h +51 -0
  223. data/vendor/PDCurses/x11/ScrollBoxP.h +70 -0
  224. data/vendor/PDCurses/x11/aclocal.m4 +994 -0
  225. data/vendor/PDCurses/x11/big_icon.xbm +46 -0
  226. data/vendor/PDCurses/x11/compose.h +201 -0
  227. data/vendor/PDCurses/x11/config.guess +1500 -0
  228. data/vendor/PDCurses/x11/config.h.in +100 -0
  229. data/vendor/PDCurses/x11/config.sub +1616 -0
  230. data/vendor/PDCurses/x11/configure +6700 -0
  231. data/vendor/PDCurses/x11/configure.ac +295 -0
  232. data/vendor/PDCurses/x11/debian/changelog +6 -0
  233. data/vendor/PDCurses/x11/debian/compat +1 -0
  234. data/vendor/PDCurses/x11/debian/control +11 -0
  235. data/vendor/PDCurses/x11/debian/copyright +27 -0
  236. data/vendor/PDCurses/x11/debian/rules +98 -0
  237. data/vendor/PDCurses/x11/install-sh +253 -0
  238. data/vendor/PDCurses/x11/little_icon.xbm +14 -0
  239. data/vendor/PDCurses/x11/ncurses_cfg.h +45 -0
  240. data/vendor/PDCurses/x11/pdcclip.c +173 -0
  241. data/vendor/PDCurses/x11/pdcdisp.c +85 -0
  242. data/vendor/PDCurses/x11/pdcgetsc.c +28 -0
  243. data/vendor/PDCurses/x11/pdckbd.c +104 -0
  244. data/vendor/PDCurses/x11/pdcscrn.c +258 -0
  245. data/vendor/PDCurses/x11/pdcsetsc.c +95 -0
  246. data/vendor/PDCurses/x11/pdcutil.c +52 -0
  247. data/vendor/PDCurses/x11/pdcx11.c +316 -0
  248. data/vendor/PDCurses/x11/pdcx11.h +191 -0
  249. data/vendor/PDCurses/x11/sb.c +155 -0
  250. data/vendor/PDCurses/x11/x11.c +3686 -0
  251. data/vendor/PDCurses/x11/xcurses-config.in +81 -0
  252. metadata +255 -24
  253. data/.travis.yml +0 -13
  254. data/appveyor.yml +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfa821d182e0a62293a794d22c2b09a0167be3c839a5ac67ea596e98fd5b1f55
4
- data.tar.gz: 1249a4e26714cfdb8ac20394e5c1333b3136b9d5275fac18b3618165cdd1d286
3
+ metadata.gz: 857d0a003f909b9e148855feb1d7b5eca2487aab1d22c544e0fdf560a92293b5
4
+ data.tar.gz: 49329a8c35c0e157c5cba591eb317bf9acf2672af16c8e826aa22ab0ada59cda
5
5
  SHA512:
6
- metadata.gz: e11281a03551d1104a38e2c9b48c0fa1dc8313c8777f2c8e25c97b7833a75c4ea4d44c6d5b0e6b7e2008f7ee012ae9e0e2719df74adbfb85ca731858b3bc2cae
7
- data.tar.gz: 98b90ee805453cb60ec62f698a7477279631e712b6f83ba1ce4edb5488a06d38694e4d0ac5de4eb00e098d47ce9b77c12b4c988afc42d9b1f123705d3cb2ab18
6
+ metadata.gz: 7330fdebb60f3871c10d74685ea5c7ed0194ba7630d0def5cd65de72a3e32e48df343b290ed7e718a116eae1eeab52b5f32d58a4e16e64db6210da9fea19d99e
7
+ data.tar.gz: 77d3c8bcc7183642917311d0cbde1d14f55771b133adb2b7953a052a02672053a5bdc3dd0fc0ab78963383d1e114c9b4534df643be05cb17c2adfdcfca8d7c1a
@@ -0,0 +1,19 @@
1
+ name: macos
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: macos-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Install dependencies
11
+ run: |
12
+ gem install bundler --no-document
13
+ bundle install
14
+ - name: Build package
15
+ run: bundle exec rake build
16
+ - name: Install package
17
+ run: |
18
+ gem install pkg/curses-*.gem
19
+ ruby -r curses -e 'puts Curses::VERSION'
@@ -0,0 +1,26 @@
1
+ name: ubuntu
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ matrix:
9
+ ruby: [ head, 2.7, 2.6, 2.5 ]
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - uses: ruby/setup-ruby@v1
14
+ with:
15
+ ruby-version: ${{ matrix.ruby }}
16
+ - name: Install dependencies
17
+ run: |
18
+ sudo apt install libncursesw5-dev
19
+ gem install bundler --no-document
20
+ bundle install
21
+ - name: Build package
22
+ run: bundle exec rake build
23
+ - name: Install package
24
+ run: |
25
+ gem install pkg/curses-*.gem
26
+ ruby -r curses -e 'puts Curses::VERSION'
@@ -0,0 +1,25 @@
1
+ name: windows
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: windows-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 'mingw', 'mswin', '2.7', '2.6', '2.5' ]
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ with:
14
+ submodules: true
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+ bundler-cache: true
20
+ - name: Build package
21
+ run: bundle exec rake build
22
+ - name: Install package
23
+ run: |
24
+ gem install pkg/curses-*.gem
25
+ ruby -r curses -e 'puts Curses::VERSION'
data/.gitmodules CHANGED
@@ -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
data/History.md CHANGED
@@ -1,3 +1,44 @@
1
+ ### 1.4.1 / 2021-05-22
2
+
3
+ Bug fixes:
4
+
5
+ * Use chtype instead of char to support attributes
6
+ * Fixes for Ruby 3.1.
7
+
8
+ ### 1.4.0 / 2020-12-10
9
+
10
+ New features:
11
+
12
+ * Remove fat binary support for newer versions of Ruby
13
+
14
+ ### 1.3.2 / 2019-12-20
15
+
16
+ Bug fixes:
17
+
18
+ * Drop rb_safe_level check for Ruby 2.7 by Eric Wong.
19
+ * Try libtinfow first. Issue #52 by Marco Sirabella.
20
+
21
+ ### 1.3.1 / 2019-04-21
22
+
23
+ Bug fixes:
24
+
25
+ * Check whether sizeof(WINDOW) is available to avoid build failures on macOS.
26
+ Issue #48 reported by chdiza.
27
+
28
+ ### 1.3.0 / 2019-04-16
29
+
30
+ New features:
31
+
32
+ * Add Curses::Form and Curses::Field.
33
+
34
+ Bug fixes:
35
+
36
+ * Fix TravisCI issues by amatsuda and znz.
37
+ * Fix typo in sample/menu.rb by binford2k.
38
+ * Ctrl-/ should return ^_ on Windows.
39
+ * Workaround for new Windows console.
40
+ https://github.com/Bill-Gray/PDCurses/pull/108
41
+
1
42
  ### 1.2.7 / 2019-01-10
2
43
 
3
44
  Bug fixes:
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # curses
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/curses.svg)](https://badge.fury.io/rb/curses)
4
- [![Build Status](https://travis-ci.org/ruby/curses.svg?branch=master)](https://travis-ci.org/ruby/curses)
5
- [![Build status](https://ci.appveyor.com/api/projects/status/kdvksgjo4fyd3c4m/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/curses/branch/master)
4
+ [![ubuntu](https://github.com/ruby/curses/workflows/ubuntu/badge.svg)](https://github.com/ruby/curses/actions?query=workflow%3Aubuntu)
5
+ [![windows](https://github.com/ruby/curses/workflows/windows/badge.svg)](https://github.com/ruby/curses/actions?query=workflow%3Awindows)
6
+ [![macos](https://github.com/ruby/curses/workflows/macos/badge.svg)](https://github.com/ruby/curses/actions?query=workflow%3Amacos)
6
7
 
7
8
  * https://github.com/ruby/curses
8
9
  * https://github.com/ruby/curses/issues
@@ -18,7 +19,7 @@ with the release of Ruby 2.1.0. (see [ruby/ruby@9c5b2fd][2])
18
19
  ## Install
19
20
 
20
21
  $ gem install curses
21
-
22
+
22
23
  Requires ncurses or ncursesw (with wide character support).
23
24
  On Debian based distributions, you can install it with apt:
24
25
 
@@ -28,6 +29,14 @@ Or
28
29
 
29
30
  $ apt install libncursesw5-dev
30
31
 
32
+ On Windows, `gem install curses` will build bundled PDCurses, so you
33
+ don't need to install extra libraries.
34
+ However, if you prefer ncurses to PDCurses, specify the following option:
35
+
36
+ > gem install curses -- --use-system-libraries
37
+
38
+ On mingw, you need DevKit to compile the extension library.
39
+
31
40
  ## Documentation
32
41
 
33
42
  See [https://www.rubydoc.info/gems/curses](https://www.rubydoc.info/gems/curses).
@@ -39,57 +48,16 @@ After checking out the repo, run `bundle install` to install dependencies.
39
48
  To compile the extension library, run `bundle exec rake compile`.
40
49
 
41
50
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `curses.gemspec`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
-
43
- ### Cross compilation for Windows on Debian GNU/Linux based platforms
44
-
45
- 1. Install development environment fo 32- and 64-bit Windows.
46
-
47
- ```
48
- $ sudo apt-get install mingw-w64
49
- ```
50
-
51
- 2. Install rake-compiler.
52
-
53
- ```
54
- $ gem install rake-compiler
55
- ```
56
-
57
- 3. Compile multiple versions of Ruby.
58
-
59
- ```
60
- $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.2.6
61
- $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.3.3
62
- $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.4.0
63
- $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.2.6
64
- $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.3.3
65
- $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.4.0
66
- ```
67
-
68
- 3. Compile PDCurses.
69
-
70
- ```
71
- $ rake build:pdcurses
72
- ```
73
-
74
- 5. Compile curses.gem.
75
-
76
- ```
77
- $ rake RUBY_CC_VERSION=2.3.3:2.4.0 cross clean compile native gem
78
- ```
79
-
80
- Binary gems are generated in pkg/.
81
-
82
51
  ## License
83
52
 
84
53
  curses is released under the Ruby and 2-clause BSD licenses. See COPYING for
85
54
  details.
86
55
 
87
- Binary gems for mingw32 include a forked version of PDCurses, which is in
88
- the public domain:
56
+ It includes a forked version of PDCurses, which is in the public domain:
89
57
 
90
58
  https://github.com/Bill-Gray/PDCurses
91
59
 
92
- The version for Win32 console mode in the win32 subdirectory is used.
60
+ The version for Win32 console mode in the wincon subdirectory is used.
93
61
 
94
62
  [1]: https://bugs.ruby-lang.org/issues/8584
95
63
  [2]: https://github.com/ruby/ruby/commit/9c5b2fd8aa0fd343ad094d47a638cfd3f6ae0a81
data/Rakefile CHANGED
@@ -1,86 +1,3 @@
1
1
  require "bundler"
2
2
 
3
3
  Bundler::GemHelper.install_tasks
4
-
5
- begin
6
- require 'rake/extensiontask'
7
- rescue LoadError => e
8
- warn "\nmissing #{e.path} (for rake-compiler)" if e.respond_to? :path
9
- warn "run: bundle install\n\n"
10
- end
11
-
12
- $mswin = /mswin/ =~ RUBY_PLATFORM
13
-
14
- CLOBBER.include("vendor/#{RUBY_PLATFORM}") if $mswin
15
- CLOBBER.include("vendor/x86-mingw32")
16
- CLOBBER.include("vendor/x64-mingw32")
17
- CLOBBER.include("lib/2.*")
18
- CLOBBER.include("pkg")
19
-
20
- namespace :build do
21
- desc "Build PDCurses"
22
- task :pdcurses do
23
- mkdir_p "vendor/#{RUBY_PLATFORM}/PDCurses" if $mswin
24
- mkdir_p "vendor/x86-mingw32/PDCurses"
25
- mkdir_p "vendor/x64-mingw32/PDCurses"
26
- chdir "vendor/PDCurses/win32" do
27
- if $mswin
28
- sh "nmake -f vcwin32.mak clean all WIDE=Y DLL=Y"
29
- cp %w[pdcurses.dll pdcurses.lib], "../../#{RUBY_PLATFORM}/PDCurses"
30
- else
31
- sh "make -f mingwin32.mak clean all WIDE=Y DLL=N"
32
- cp "pdcurses.a", "../../x86-mingw32/PDCurses/libpdcurses.a"
33
-
34
- sh "make -f mingwin32.mak clean all _w64=1 WIDE=Y DLL=N"
35
- cp "pdcurses.a", "../../x64-mingw32/PDCurses/libpdcurses.a"
36
- end
37
- end
38
- end
39
- end
40
-
41
- namespace :clean do
42
- desc "Clean PDCurses"
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"
47
- end
48
- end
49
- end
50
-
51
- spec = eval(File.read(File.expand_path("curses.gemspec", __dir__)))
52
- Rake::ExtensionTask.new(spec.name, spec) do |ext|
53
- if $mswin
54
- ext.config_options << '--with-curses-include=' +
55
- File.expand_path("vendor/PDCurses", __dir__) +
56
- ' --with-curses-version=function --enable-pdcurses-wide' +
57
- ' --enable-pdcurses-dll' +
58
- ' --with-curses-lib=' +
59
- File.expand_path("vendor/#{RUBY_PLATFORM}/PDCurses", __dir__)
60
- spec.files += ["vendor/#{RUBY_PLATFORM}/PDCurses/pdcurses.dll"]
61
- end
62
-
63
- ext.cross_compile = true
64
- ext.cross_platform = ["x86-mingw32", "x64-mingw32"]
65
- ext.cross_config_options << '--with-curses-include=' +
66
- File.expand_path("vendor/PDCurses", __dir__) +
67
- ' --with-curses-version=function --enable-pdcurses-wide'
68
- ext.cross_config_options << {
69
- 'x86-mingw32' => '--with-curses-lib=' +
70
- File.expand_path("vendor/x86-mingw32/PDCurses", __dir__),
71
- 'x64-mingw32' => '--with-curses-lib=' +
72
- File.expand_path("vendor/x64-mingw32/PDCurses", __dir__)
73
- }
74
- if $mswin
75
- ext.cross_compiling do |_spec|
76
- bin_file = "vendor/#{_spec.platform}/PDCurses/pdcurses.dll"
77
- _spec.files += [bin_file]
78
- stage_file = "#{ext.tmp_dir}/#{_spec.platform}/stage/#{bin_file}"
79
- stage_dir = File.dirname(stage_file)
80
- directory stage_dir
81
- file stage_file => [stage_dir, bin_file] do
82
- cp bin_file, stage_file
83
- end
84
- end
85
- end
86
- end
data/curses.gemspec CHANGED
@@ -1,17 +1,16 @@
1
1
  Gem::Specification.new { |s|
2
2
  s.name = "curses"
3
- s.version = "1.2.7"
3
+ s.version = "1.4.1"
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"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.summary = "A Ruby binding for curses, ncurses, and PDCurses. curses is an extension library for text UI applications. Formerly part of the Ruby standard library, [curses was removed and placed in this gem][1] with the release of Ruby 2.1.0. (see [ruby/ruby@9c5b2fd][2])"
9
- s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(vendor)/}) }
9
+ s.files = `git ls-files --recurse-submodules -z`.split("\x0")
10
10
  s.extensions = ["ext/curses/extconf.rb"]
11
11
  s.require_path = "lib"
12
12
  s.required_ruby_version = Gem::Requirement.new('>= 2.1.0')
13
13
  s.licenses = ['Ruby', 'BSD-2-Clause']
14
14
  s.add_development_dependency 'bundler'
15
15
  s.add_development_dependency 'rake'
16
- s.add_development_dependency 'rake-compiler'
17
16
  }
data/ext/curses/curses.c CHANGED
@@ -20,7 +20,9 @@
20
20
  #include "ruby/io.h"
21
21
  #include "ruby/thread.h"
22
22
 
23
- #if defined(HAVE_NCURSESW_CURSES_H)
23
+ #if defined(HAVE_PDCURSES_H)
24
+ # include <pdcurses.h>
25
+ #elif defined(HAVE_NCURSESW_CURSES_H)
24
26
  # include <ncursesw/curses.h>
25
27
  #elif defined(HAVE_NCURSES_CURSES_H)
26
28
  # include <ncurses/curses.h>
@@ -61,6 +63,16 @@
61
63
  # include <menu.h>
62
64
  #endif
63
65
 
66
+ #if defined(HAVE_NCURSESW_FORM_H)
67
+ # include <ncursesw/form.h>
68
+ #elif defined(HAVE_NCURSES_FORM_H)
69
+ # include <ncurses/form.h>
70
+ #elif defined(HAVE_CURSES_FORM_H)
71
+ # include <curses/form.h>
72
+ #elif defined(HAVE_FORM_H)
73
+ # include <form.h>
74
+ #endif
75
+
64
76
  #ifdef HAVE_INIT_COLOR
65
77
  # define USE_COLOR 1
66
78
  #endif
@@ -70,8 +82,19 @@
70
82
  # define USE_MOUSE 1
71
83
  #endif
72
84
 
73
- #define NUM2CH NUM2CHR
74
- #define CH2FIX CHR2FIX
85
+ #define OBJ2CHTYPE rb_obj2chtype_inline
86
+
87
+ static inline chtype
88
+ rb_obj2chtype_inline(VALUE x)
89
+ {
90
+ if (RB_TYPE_P(x, RUBY_T_STRING)) {
91
+ ID id_ord;
92
+
93
+ CONST_ID(id_ord, "ord");
94
+ x = rb_funcall(x, id_ord, 0);
95
+ }
96
+ return NUM2CHTYPE(x);
97
+ }
75
98
 
76
99
  static VALUE mCurses;
77
100
  static VALUE mKey;
@@ -84,6 +107,10 @@ static VALUE cMouseEvent;
84
107
  static VALUE cItem;
85
108
  static VALUE cMenu;
86
109
  #endif
110
+ #ifdef HAVE_FORM
111
+ static VALUE cField;
112
+ static VALUE cForm;
113
+ #endif
87
114
  static VALUE eError;
88
115
  static VALUE eSystemError;
89
116
  static VALUE eBadArgumentError;
@@ -199,6 +226,7 @@ static VALUE window_attroff(VALUE obj, VALUE attrs);
199
226
  static VALUE window_attron(VALUE obj, VALUE attrs);
200
227
  static VALUE window_attrset(VALUE obj, VALUE attrs);
201
228
 
229
+ NORETURN(static void no_window(void));
202
230
  static void
203
231
  no_window(void)
204
232
  {
@@ -206,8 +234,6 @@ no_window(void)
206
234
  }
207
235
 
208
236
  #define GetWINDOW(obj, winp) do {\
209
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
210
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\
211
237
  TypedData_Get_Struct((obj), struct windata, &windata_type, (winp));\
212
238
  if ((winp)->window == 0) no_window();\
213
239
  } while (0)
@@ -227,7 +253,7 @@ window_memsize(const void *p)
227
253
  const struct windata *winp = p;
228
254
  size_t size = sizeof(*winp);
229
255
  if (!winp) return 0;
230
- if (winp->window && winp->window != stdscr) size += sizeof(winp->window);
256
+ if (winp->window && winp->window != stdscr) size += CURSES_SIZEOF_WINDOW;
231
257
  return size;
232
258
  }
233
259
 
@@ -276,7 +302,7 @@ static void curses_finalize(VALUE);
276
302
  * see also Curses.stdscr
277
303
  */
278
304
  static VALUE
279
- curses_init_screen(void)
305
+ curses_init_screen(VALUE self)
280
306
  {
281
307
  if (rb_stdscr) return rb_stdscr;
282
308
  initscr();
@@ -299,7 +325,7 @@ curses_init_screen(void)
299
325
  *
300
326
  * Many curses functions use this window.
301
327
  */
302
- #define curses_stdscr curses_init_screen
328
+ #define curses_stdscr() curses_init_screen(Qnil)
303
329
 
304
330
  /*
305
331
  * Document-method: Curses.close_screen
@@ -315,7 +341,7 @@ curses_init_screen(void)
315
341
  *
316
342
  */
317
343
  static VALUE
318
- curses_close_screen(void)
344
+ curses_close_screen(VALUE self)
319
345
  {
320
346
  curses_stdscr();
321
347
  #ifdef HAVE_ISENDWIN
@@ -355,7 +381,7 @@ curses_finalize(VALUE dummy)
355
381
  * returns +false+ otherwise.
356
382
  */
357
383
  static VALUE
358
- curses_closed(void)
384
+ curses_closed(VALUE self)
359
385
  {
360
386
  curses_stdscr();
361
387
  if (isendwin()) {
@@ -405,7 +431,7 @@ curses_erase(VALUE obj)
405
431
  * Clears to the end of line, that the cursor is currently on.
406
432
  */
407
433
  static VALUE
408
- curses_clrtoeol(void)
434
+ curses_clrtoeol(VALUE self)
409
435
  {
410
436
  curses_stdscr();
411
437
  clrtoeol();
@@ -732,7 +758,7 @@ static VALUE
732
758
  curses_inch(VALUE obj)
733
759
  {
734
760
  curses_stdscr();
735
- return CH2FIX(inch());
761
+ return CHTYPE2NUM(inch());
736
762
  }
737
763
 
738
764
  /*
@@ -747,7 +773,7 @@ static VALUE
747
773
  curses_addch(VALUE obj, VALUE ch)
748
774
  {
749
775
  curses_stdscr();
750
- addch(NUM2CH(ch));
776
+ addch(OBJ2CHTYPE(ch));
751
777
  return Qnil;
752
778
  }
753
779
 
@@ -762,7 +788,7 @@ static VALUE
762
788
  curses_insch(VALUE obj, VALUE ch)
763
789
  {
764
790
  curses_stdscr();
765
- insch(NUM2CH(ch));
791
+ insch(OBJ2CHTYPE(ch));
766
792
  return Qnil;
767
793
  }
768
794
 
@@ -843,7 +869,7 @@ getstr_func(void *arg)
843
869
  /*
844
870
  * Document-method: Curses.getstr
845
871
  *
846
- * This is equivalent to a series f Curses::Window.getch calls
872
+ * This is equivalent to a series of Curses::Window.getch calls
847
873
  *
848
874
  */
849
875
  static VALUE
@@ -934,7 +960,7 @@ curses_keyname(VALUE obj, VALUE c)
934
960
  * Returns the number of lines on the screen
935
961
  */
936
962
  static VALUE
937
- curses_lines(void)
963
+ curses_lines(VALUE self)
938
964
  {
939
965
  return INT2FIX(LINES);
940
966
  }
@@ -945,7 +971,7 @@ curses_lines(void)
945
971
  * Returns the number of columns on the screen
946
972
  */
947
973
  static VALUE
948
- curses_cols(void)
974
+ curses_cols(VALUE self)
949
975
  {
950
976
  return INT2FIX(COLS);
951
977
  }
@@ -1091,7 +1117,7 @@ curses_bkgdset(VALUE obj, VALUE ch)
1091
1117
  {
1092
1118
  #ifdef HAVE_BKGDSET
1093
1119
  curses_stdscr();
1094
- bkgdset(NUM2CHTYPE(ch));
1120
+ bkgdset(OBJ2CHTYPE(ch));
1095
1121
  #endif
1096
1122
  return Qnil;
1097
1123
  }
@@ -1112,7 +1138,7 @@ curses_bkgd(VALUE obj, VALUE ch)
1112
1138
  {
1113
1139
  #ifdef HAVE_BKGD
1114
1140
  curses_stdscr();
1115
- return (bkgd(NUM2CHTYPE(ch)) == OK) ? Qtrue : Qfalse;
1141
+ return (bkgd(OBJ2CHTYPE(ch)) == OK) ? Qtrue : Qfalse;
1116
1142
  #else
1117
1143
  return Qfalse;
1118
1144
  #endif
@@ -1425,6 +1451,7 @@ struct mousedata {
1425
1451
  MEVENT *mevent;
1426
1452
  };
1427
1453
 
1454
+ NORETURN(static void no_mevent(void));
1428
1455
  static void
1429
1456
  no_mevent(void)
1430
1457
  {
@@ -1432,8 +1459,6 @@ no_mevent(void)
1432
1459
  }
1433
1460
 
1434
1461
  #define GetMOUSE(obj, data) do {\
1435
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
1436
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\
1437
1462
  TypedData_Get_Struct((obj), struct mousedata, &mousedata_type, (data));\
1438
1463
  if ((data)->mevent == 0) no_mevent();\
1439
1464
  } while (0)
@@ -1452,7 +1477,7 @@ curses_mousedata_memsize(const void *p)
1452
1477
  const struct mousedata *mdata = p;
1453
1478
  size_t size = sizeof(*mdata);
1454
1479
  if (!mdata) return 0;
1455
- if (mdata->mevent) size += sizeof(mdata->mevent);
1480
+ if (mdata->mevent) size += CURSES_SIZEOF_MEVENT;
1456
1481
  return size;
1457
1482
  }
1458
1483
 
@@ -1534,7 +1559,7 @@ static VALUE
1534
1559
  curses_mousemask(VALUE obj, VALUE mask)
1535
1560
  {
1536
1561
  curses_stdscr();
1537
- return INT2NUM(mousemask(NUM2UINT(mask),NULL));
1562
+ return ULONG2NUM(mousemask(NUM2UINT(mask),NULL));
1538
1563
  }
1539
1564
 
1540
1565
  #define DEFINE_MOUSE_GET_MEMBER(func_name,mem) \
@@ -1575,7 +1600,12 @@ DEFINE_MOUSE_GET_MEMBER(curs_mouse_z, z)
1575
1600
  * Returns the current mouse's button state. Use this with the button state
1576
1601
  * constants to determine which buttons were pressed.
1577
1602
  */
1578
- DEFINE_MOUSE_GET_MEMBER(curs_mouse_bstate, bstate)
1603
+ static VALUE curs_mouse_bstate(VALUE mouse)
1604
+ {
1605
+ struct mousedata *mdata;
1606
+ GetMOUSE(mouse, mdata);
1607
+ return ULONG2NUM(mdata->mevent->bstate);
1608
+ }
1579
1609
  #undef define_curs_mouse_member
1580
1610
  #endif /* USE_MOUSE */
1581
1611
 
@@ -1667,7 +1697,7 @@ window_initialize(VALUE obj, VALUE h, VALUE w, VALUE top, VALUE left)
1667
1697
  struct windata *winp;
1668
1698
  WINDOW *window;
1669
1699
 
1670
- curses_init_screen();
1700
+ curses_init_screen(Qnil);
1671
1701
  TypedData_Get_Struct(obj, struct windata, &windata_type, winp);
1672
1702
  if (winp->window) delwin(winp->window);
1673
1703
  window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left));
@@ -2164,7 +2194,7 @@ window_begx(VALUE obj)
2164
2194
 
2165
2195
  /*
2166
2196
  * Document-method: Curses::Window.box
2167
- * call-seq: box(vert, hor)
2197
+ * call-seq: box(vert = nil, hor = nil, corn = nil)
2168
2198
  *
2169
2199
  * set the characters to frame the window in.
2170
2200
  * The vertical +vert+ and horizontal +hor+ character.
@@ -2179,16 +2209,18 @@ window_box(int argc, VALUE *argv, VALUE self)
2179
2209
  struct windata *winp;
2180
2210
  VALUE vert, hor, corn;
2181
2211
 
2182
- rb_scan_args(argc, argv, "21", &vert, &hor, &corn);
2212
+ rb_scan_args(argc, argv, "03", &vert, &hor, &corn);
2183
2213
 
2184
2214
  GetWINDOW(self, winp);
2185
- box(winp->window, NUM2CH(vert), NUM2CH(hor));
2215
+ box(winp->window,
2216
+ NIL_P(vert) ? 0 : OBJ2CHTYPE(vert),
2217
+ NIL_P(hor) ? 0 : OBJ2CHTYPE(hor));
2186
2218
 
2187
2219
  if (!NIL_P(corn)) {
2188
2220
  int cur_x, cur_y, x, y;
2189
2221
  chtype c;
2190
2222
 
2191
- c = NUM2CH(corn);
2223
+ c = OBJ2CHTYPE(corn);
2192
2224
  getyx(winp->window, cur_y, cur_x);
2193
2225
  x = NUM2INT(window_maxx(self)) - 1;
2194
2226
  y = NUM2INT(window_maxy(self)) - 1;
@@ -2255,7 +2287,7 @@ window_inch(VALUE obj)
2255
2287
  struct windata *winp;
2256
2288
 
2257
2289
  GetWINDOW(obj, winp);
2258
- return CH2FIX(winch(winp->window));
2290
+ return CHTYPE2NUM(winch(winp->window));
2259
2291
  }
2260
2292
 
2261
2293
  /*
@@ -2272,7 +2304,7 @@ window_addch(VALUE obj, VALUE ch)
2272
2304
  struct windata *winp;
2273
2305
 
2274
2306
  GetWINDOW(obj, winp);
2275
- waddch(winp->window, NUM2CH(ch));
2307
+ waddch(winp->window, OBJ2CHTYPE(ch));
2276
2308
 
2277
2309
  return Qnil;
2278
2310
  }
@@ -2290,7 +2322,7 @@ window_insch(VALUE obj, VALUE ch)
2290
2322
  struct windata *winp;
2291
2323
 
2292
2324
  GetWINDOW(obj, winp);
2293
- winsch(winp->window, NUM2CH(ch));
2325
+ winsch(winp->window, OBJ2CHTYPE(ch));
2294
2326
 
2295
2327
  return Qnil;
2296
2328
  }
@@ -2400,7 +2432,7 @@ wgetstr_func(void *_arg)
2400
2432
  /*
2401
2433
  * Document-method: Curses::Window.getstr
2402
2434
  *
2403
- * This is equivalent to a series f Curses::Window.getch calls
2435
+ * This is equivalent to a series of Curses::Window.getch calls
2404
2436
  *
2405
2437
  */
2406
2438
  static VALUE
@@ -2718,7 +2750,7 @@ window_bkgdset(VALUE obj, VALUE ch)
2718
2750
  struct windata *winp;
2719
2751
 
2720
2752
  GetWINDOW(obj,winp);
2721
- wbkgdset(winp->window, NUM2CHTYPE(ch));
2753
+ wbkgdset(winp->window, OBJ2CHTYPE(ch));
2722
2754
  #endif
2723
2755
  return Qnil;
2724
2756
  }
@@ -2739,7 +2771,7 @@ window_bkgd(VALUE obj, VALUE ch)
2739
2771
  struct windata *winp;
2740
2772
 
2741
2773
  GetWINDOW(obj,winp);
2742
- return (wbkgd(winp->window, NUM2CHTYPE(ch)) == OK) ? Qtrue : Qfalse;
2774
+ return (wbkgd(winp->window, OBJ2CHTYPE(ch)) == OK) ? Qtrue : Qfalse;
2743
2775
  #else
2744
2776
  return Qfalse;
2745
2777
  #endif
@@ -2907,7 +2939,7 @@ pad_initialize(VALUE obj, VALUE h, VALUE w)
2907
2939
  struct windata *padp;
2908
2940
  WINDOW *window;
2909
2941
 
2910
- curses_init_screen();
2942
+ curses_init_screen(Qnil);
2911
2943
  TypedData_Get_Struct(obj, struct windata, &windata_type, padp);
2912
2944
  if (padp->window) delwin(padp->window);
2913
2945
  window = newpad(NUM2INT(h), NUM2INT(w));
@@ -3028,8 +3060,6 @@ no_item(void)
3028
3060
  }
3029
3061
 
3030
3062
  #define GetITEM(obj, itemp) do {\
3031
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
3032
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted item");\
3033
3063
  TypedData_Get_Struct((obj), struct itemdata, &itemdata_type, (itemp));\
3034
3064
  if ((itemp)->item == 0) no_item();\
3035
3065
  } while (0)
@@ -3049,7 +3079,7 @@ item_memsize(const void *p)
3049
3079
  const struct itemdata *itemp = p;
3050
3080
  size_t size = sizeof(*itemp);
3051
3081
  if (!itemp) return 0;
3052
- if (itemp->item) size += sizeof(itemp->item);
3082
+ if (itemp->item) size += CURSES_SIZEOF_ITEM;
3053
3083
  return size;
3054
3084
  }
3055
3085
 
@@ -3080,7 +3110,7 @@ item_initialize(VALUE obj, VALUE name, VALUE description)
3080
3110
  {
3081
3111
  struct itemdata *itemp;
3082
3112
 
3083
- curses_init_screen();
3113
+ curses_init_screen(Qnil);
3084
3114
  TypedData_Get_Struct(obj, struct itemdata, &itemdata_type, itemp);
3085
3115
  if (itemp->item) {
3086
3116
  rb_raise(rb_eRuntimeError, "already initialized item");
@@ -3139,6 +3169,83 @@ item_description_m(VALUE obj)
3139
3169
  return rb_external_str_new_with_enc(desc, strlen(desc), terminal_encoding);
3140
3170
  }
3141
3171
 
3172
+ /*
3173
+ * Document-method: Curses::Item#set_opts
3174
+ *
3175
+ * call-seq:
3176
+ * set_opts(opts)
3177
+ *
3178
+ * Set the option bits of the item.
3179
+ */
3180
+ static VALUE
3181
+ item_set_opts(VALUE obj, VALUE opts)
3182
+ {
3183
+ struct itemdata *itemp;
3184
+ int error;
3185
+
3186
+ GetITEM(obj, itemp);
3187
+ error = set_item_opts(itemp->item, NUM2INT(opts));
3188
+ check_curses_error(error);
3189
+ return obj;
3190
+ }
3191
+
3192
+ /*
3193
+ * Document-method: Curses::Item#opts_on
3194
+ *
3195
+ * call-seq:
3196
+ * opts_on(opts)
3197
+ *
3198
+ * Turn on the option bits of the item.
3199
+ */
3200
+ static VALUE
3201
+ item_opts_on_m(VALUE obj, VALUE opts)
3202
+ {
3203
+ struct itemdata *itemp;
3204
+ int error;
3205
+
3206
+ GetITEM(obj, itemp);
3207
+ error = item_opts_on(itemp->item, NUM2INT(opts));
3208
+ check_curses_error(error);
3209
+ return obj;
3210
+ }
3211
+
3212
+ /*
3213
+ * Document-method: Curses::Item#opts_off
3214
+ *
3215
+ * call-seq:
3216
+ * opts_off(opts)
3217
+ *
3218
+ * Turn off the option bits of the item.
3219
+ */
3220
+ static VALUE
3221
+ item_opts_off_m(VALUE obj, VALUE opts)
3222
+ {
3223
+ struct itemdata *itemp;
3224
+ int error;
3225
+
3226
+ GetITEM(obj, itemp);
3227
+ error = item_opts_off(itemp->item, NUM2INT(opts));
3228
+ check_curses_error(error);
3229
+ return obj;
3230
+ }
3231
+
3232
+ /*
3233
+ * Document-method: Curses::Item#opts
3234
+ *
3235
+ * call-seq:
3236
+ * opts
3237
+ *
3238
+ * Get the current option bits of the item.
3239
+ */
3240
+ static VALUE
3241
+ item_opts_m(VALUE obj, VALUE opts)
3242
+ {
3243
+ struct itemdata *itemp;
3244
+
3245
+ GetITEM(obj, itemp);
3246
+ return INT2NUM(item_opts(itemp->item));
3247
+ }
3248
+
3142
3249
  struct menudata {
3143
3250
  MENU *menu;
3144
3251
  VALUE items;
@@ -3151,8 +3258,6 @@ no_menu(void)
3151
3258
  }
3152
3259
 
3153
3260
  #define GetMENU(obj, menup) do {\
3154
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
3155
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted menu");\
3156
3261
  TypedData_Get_Struct((obj), struct menudata, &menudata_type, (menup));\
3157
3262
  if ((menup)->menu == 0) no_menu();\
3158
3263
  } while (0)
@@ -3183,7 +3288,7 @@ menu_memsize(const void *p)
3183
3288
  const struct menudata *menup = p;
3184
3289
  size_t size = sizeof(*menup);
3185
3290
  if (!menup) return 0;
3186
- if (menup->menu) size += sizeof(menup->menu);
3291
+ if (menup->menu) size += CURSES_SIZEOF_MENU;
3187
3292
  return size;
3188
3293
  }
3189
3294
 
@@ -3205,7 +3310,7 @@ menu_s_allocate(VALUE class)
3205
3310
  * Document-method: Curses::Menu.new
3206
3311
  *
3207
3312
  * call-seq:
3208
- * new(name, description)
3313
+ * new(items)
3209
3314
  *
3210
3315
  * Construct a new Curses::Menu.
3211
3316
  */
@@ -3215,26 +3320,33 @@ menu_initialize(VALUE obj, VALUE items)
3215
3320
  struct menudata *menup;
3216
3321
  ITEM **menu_items;
3217
3322
  int i;
3323
+ ID id_new;
3218
3324
 
3219
3325
  Check_Type(items, T_ARRAY);
3220
- curses_init_screen();
3326
+ curses_init_screen(Qnil);
3221
3327
  TypedData_Get_Struct(obj, struct menudata, &menudata_type, menup);
3222
3328
  if (menup->menu) {
3223
3329
  rb_raise(rb_eRuntimeError, "already initialized menu");
3224
3330
  }
3331
+ menup->items = rb_ary_new();
3225
3332
  menu_items = ALLOC_N(ITEM *, RARRAY_LEN(items) + 1);
3333
+ CONST_ID(id_new, "new");
3226
3334
  for (i = 0; i < RARRAY_LEN(items); i++) {
3335
+ VALUE item = RARRAY_AREF(items, i);
3227
3336
  struct itemdata *itemp;
3228
3337
 
3229
- GetITEM(RARRAY_AREF(items, i), itemp);
3338
+ if (RB_TYPE_P(item, T_ARRAY)) {
3339
+ item = rb_apply(cItem, id_new, item);
3340
+ }
3341
+ GetITEM(item, itemp);
3230
3342
  menu_items[i] = itemp->item;
3343
+ rb_ary_push(menup->items, item);
3231
3344
  }
3232
3345
  menu_items[RARRAY_LEN(items)] = NULL;
3233
3346
  menup->menu = new_menu(menu_items);
3234
3347
  if (menup->menu == NULL) {
3235
3348
  check_curses_error(errno);
3236
3349
  }
3237
- menup->items = rb_ary_dup(items);
3238
3350
 
3239
3351
  return obj;
3240
3352
  }
@@ -3426,190 +3538,1065 @@ menu_set_current_item(VALUE obj, VALUE item)
3426
3538
  return item;
3427
3539
  }
3428
3540
 
3429
- #endif /* HAVE_MENU */
3430
-
3431
3541
  /*
3432
- * Document-method: Curses.keyboard_encoding
3433
- * call-seq: Curses.keyboard_encoding
3542
+ * Document-method: Curses::Menu#set_win
3434
3543
  *
3435
- * Returns the encoding for keyboard input.
3544
+ * call-seq:
3545
+ * set_win=(win)
3546
+ *
3547
+ * Set the window of the menu.
3436
3548
  */
3437
3549
  static VALUE
3438
- curses_get_keyboard_encoding(VALUE obj)
3550
+ menu_set_win(VALUE obj, VALUE win)
3439
3551
  {
3440
- return rb_enc_from_encoding(keyboard_encoding);
3552
+ struct menudata *menup;
3553
+ struct windata *winp;
3554
+
3555
+ GetMENU(obj, menup);
3556
+ GetWINDOW(win, winp);
3557
+ set_menu_win(menup->menu, winp->window);
3558
+ return win;
3441
3559
  }
3442
3560
 
3443
3561
  /*
3444
- * Document-method: Curses.keyboard_encoding=
3445
- * call-seq: Curses.keyboard_encoding = encoding
3562
+ * Document-method: Curses::Menu#set_sub
3446
3563
  *
3447
- * Sets the encoding for keyboard input.
3564
+ * call-seq:
3565
+ * set_sub=(win)
3566
+ *
3567
+ * Set the subwindow of the menu.
3448
3568
  */
3449
3569
  static VALUE
3450
- curses_set_keyboard_encoding(VALUE obj, VALUE enc)
3570
+ menu_set_sub(VALUE obj, VALUE win)
3451
3571
  {
3452
- keyboard_encoding = rb_to_encoding(enc);
3453
- return enc;
3572
+ struct menudata *menup;
3573
+ struct windata *winp;
3574
+
3575
+ GetMENU(obj, menup);
3576
+ GetWINDOW(win, winp);
3577
+ set_menu_sub(menup->menu, winp->window);
3578
+ return win;
3454
3579
  }
3455
3580
 
3456
3581
  /*
3457
- * Document-method: Curses.terminal_encoding
3458
- * call-seq: Curses.terminal_encoding
3582
+ * Document-method: Curses::Menu#scale
3459
3583
  *
3460
- * Returns the encoding for terminal output.
3584
+ * call-seq:
3585
+ * scale
3586
+ *
3587
+ * Return the minimum rows and columns required for the subwindow of the menu.
3461
3588
  */
3462
3589
  static VALUE
3463
- curses_get_terminal_encoding(VALUE obj)
3590
+ menu_scale(VALUE obj)
3464
3591
  {
3465
- return rb_enc_from_encoding(terminal_encoding);
3592
+ struct menudata *menup;
3593
+ int error, rows, columns;
3594
+
3595
+ GetMENU(obj, menup);
3596
+ error = scale_menu(menup->menu, &rows, &columns);
3597
+ check_curses_error(error);
3598
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(columns));
3466
3599
  }
3467
3600
 
3468
3601
  /*
3469
- * Document-method: Curses.terminal_encoding=
3470
- * call-seq: Curses.terminal_encoding = encoding
3602
+ * Document-method: Curses::Menu#set_format
3471
3603
  *
3472
- * Sets the encoding for terminal output.
3604
+ * call-seq:
3605
+ * set_format(rows, cols)
3606
+ *
3607
+ * Set the maximum size of the menu.
3473
3608
  */
3474
3609
  static VALUE
3475
- curses_set_terminal_encoding(VALUE obj, VALUE enc)
3610
+ menu_set_format(VALUE obj, VALUE rows, VALUE cols)
3476
3611
  {
3477
- terminal_encoding = rb_to_encoding(enc);
3478
- return enc;
3612
+ struct menudata *menup;
3613
+ int error;
3614
+
3615
+ GetMENU(obj, menup);
3616
+ error = set_menu_format(menup->menu, NUM2INT(rows), NUM2INT(cols));
3617
+ check_curses_error(error);
3618
+ return obj;
3479
3619
  }
3480
3620
 
3481
3621
  /*
3482
- * Document-method: Curses.unget_char
3483
- * call-seq: unget_char(ch)
3622
+ * Document-method: Curses::Menu#format
3484
3623
  *
3485
- * Places +ch+ back onto the input queue to be returned by
3486
- * the next call to Curses.get_char etc.
3624
+ * call-seq:
3625
+ * format
3487
3626
  *
3488
- * There is just one input queue for all windows.
3627
+ * Get the maximum size of the menu.
3489
3628
  */
3490
3629
  static VALUE
3491
- curses_unget_char(VALUE obj, VALUE ch)
3630
+ menu_format_m(VALUE obj)
3492
3631
  {
3493
- ID id_ord;
3494
- unsigned int c;
3632
+ struct menudata *menup;
3633
+ int rows, cols;
3495
3634
 
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;
3635
+ GetMENU(obj, menup);
3636
+ menu_format(menup->menu, &rows, &cols);
3637
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(cols));
3514
3638
  }
3515
3639
 
3640
+ /*
3641
+ * Document-method: Curses::Menu#set_opts
3642
+ *
3643
+ * call-seq:
3644
+ * set_opts(opts)
3645
+ *
3646
+ * Set the option bits of the menu.
3647
+ */
3516
3648
  static VALUE
3517
- keyboard_uint_chr(unsigned int ch)
3649
+ menu_set_opts(VALUE obj, VALUE opts)
3518
3650
  {
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
- };
3651
+ struct menudata *menup;
3652
+ int error;
3527
3653
 
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;
3654
+ GetMENU(obj, menup);
3655
+ error = set_menu_opts(menup->menu, NUM2INT(opts));
3656
+ check_curses_error(error);
3657
+ return obj;
3534
3658
  }
3535
- #endif
3536
3659
 
3537
3660
  /*
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.
3661
+ * Document-method: Curses::Menu#opts_on
3544
3662
  *
3545
- * See Curses::Key to all the function KEY_* available
3663
+ * call-seq:
3664
+ * opts_on(opts)
3546
3665
  *
3666
+ * Turn on the option bits of the menu.
3547
3667
  */
3548
3668
  static VALUE
3549
- curses_get_char(VALUE obj)
3669
+ menu_opts_on_m(VALUE obj, VALUE opts)
3550
3670
  {
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;
3671
+ struct menudata *menup;
3672
+ int error;
3565
3673
 
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
3674
+ GetMENU(obj, menup);
3675
+ error = menu_opts_on(menup->menu, NUM2INT(opts));
3676
+ check_curses_error(error);
3677
+ return obj;
3578
3678
  }
3579
3679
 
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)
3680
+ /*
3681
+ * Document-method: Curses::Menu#opts_off
3682
+ *
3683
+ * call-seq:
3684
+ * opts_off(opts)
3685
+ *
3686
+ * Turn off the option bits of the menu.
3687
+ */
3688
+ static VALUE
3689
+ menu_opts_off_m(VALUE obj, VALUE opts)
3590
3690
  {
3591
- struct wget_wch_arg *arg = (struct wget_wch_arg *) _arg;
3592
- arg->retval = wget_wch(arg->win, &arg->ch);
3593
- return 0;
3691
+ struct menudata *menup;
3692
+ int error;
3693
+
3694
+ GetMENU(obj, menup);
3695
+ error = menu_opts_off(menup->menu, NUM2INT(opts));
3696
+ check_curses_error(error);
3697
+ return obj;
3594
3698
  }
3595
- #endif
3596
3699
 
3597
3700
  /*
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.
3701
+ * Document-method: Curses::Menu#opts
3604
3702
  *
3605
- * See Curses::Key to all the function KEY_* available
3703
+ * call-seq:
3704
+ * opts
3606
3705
  *
3706
+ * Get the current option bits of the menu.
3607
3707
  */
3608
3708
  static VALUE
3609
- window_get_char(VALUE obj)
3709
+ menu_opts_m(VALUE obj, VALUE opts)
3610
3710
  {
3611
- #ifdef HAVE_WGET_WCH
3612
- struct windata *winp;
3711
+ struct menudata *menup;
3712
+
3713
+ GetMENU(obj, menup);
3714
+ return INT2NUM(menu_opts(menup->menu));
3715
+ }
3716
+ #endif /* HAVE_MENU */
3717
+
3718
+ #ifdef HAVE_FORM
3719
+ struct fielddata {
3720
+ FIELD *field;
3721
+ };
3722
+
3723
+ NORETURN(static void no_field(void));
3724
+ static void
3725
+ no_field(void)
3726
+ {
3727
+ rb_raise(rb_eRuntimeError, "already deleted field");
3728
+ }
3729
+
3730
+ #define GetFIELD(obj, fieldp) do {\
3731
+ TypedData_Get_Struct((obj), struct fielddata, &fielddata_type, (fieldp));\
3732
+ if ((fieldp)->field == 0) no_field();\
3733
+ } while (0)
3734
+
3735
+ static void
3736
+ field_free(void *p)
3737
+ {
3738
+ struct fielddata *fieldp = p;
3739
+ if (fieldp->field) free_field(fieldp->field);
3740
+ fieldp->field = 0;
3741
+ xfree(fieldp);
3742
+ }
3743
+
3744
+ static size_t
3745
+ field_memsize(const void *p)
3746
+ {
3747
+ const struct fielddata *fieldp = p;
3748
+ size_t size = sizeof(*fieldp);
3749
+ if (!fieldp) return 0;
3750
+ if (fieldp->field) size += CURSES_SIZEOF_FIELD;
3751
+ return size;
3752
+ }
3753
+
3754
+ static const rb_data_type_t fielddata_type = {
3755
+ "fielddata",
3756
+ {0, field_free, field_memsize,}
3757
+ };
3758
+
3759
+ /* returns a Curses::Menu object */
3760
+ static VALUE
3761
+ field_s_allocate(VALUE class)
3762
+ {
3763
+ struct fielddata *fieldp;
3764
+
3765
+ return TypedData_Make_Struct(class, struct fielddata, &fielddata_type, fieldp);
3766
+ }
3767
+
3768
+ /*
3769
+ * Document-method: Curses::Field.new
3770
+ *
3771
+ * call-seq:
3772
+ * new(height, width, toprow, leftcol, offscreen, nbuffers)
3773
+ *
3774
+ * Construct a new Curses::Field.
3775
+ */
3776
+ static VALUE
3777
+ field_initialize(VALUE obj, VALUE height, VALUE width,
3778
+ VALUE toprow, VALUE leftcol, VALUE offscreen, VALUE nbuffers)
3779
+ {
3780
+ struct fielddata *fieldp;
3781
+
3782
+ curses_init_screen(Qnil);
3783
+ TypedData_Get_Struct(obj, struct fielddata, &fielddata_type, fieldp);
3784
+ if (fieldp->field) {
3785
+ rb_raise(rb_eRuntimeError, "already initialized field");
3786
+ }
3787
+ fieldp->field = new_field(NUM2INT(height), NUM2INT(width),
3788
+ NUM2INT(toprow), NUM2INT(leftcol),
3789
+ NUM2INT(offscreen), NUM2INT(nbuffers));
3790
+ if (fieldp->field == NULL) {
3791
+ check_curses_error(errno);
3792
+ }
3793
+
3794
+ return obj;
3795
+ }
3796
+
3797
+ /*
3798
+ * Document-method: Curses::Field#set_buffer
3799
+ *
3800
+ * call-seq:
3801
+ * set_buffer(buf, value)
3802
+ *
3803
+ * Set the numbered buffer of the field.
3804
+ */
3805
+ static VALUE
3806
+ field_set_buffer(VALUE obj, VALUE buf, VALUE value)
3807
+ {
3808
+ struct fielddata *fieldp;
3809
+
3810
+ GetFIELD(obj, fieldp);
3811
+ value = rb_str_export_to_enc(value, terminal_encoding);
3812
+ set_field_buffer(fieldp->field, NUM2INT(buf), StringValueCStr(value));
3813
+
3814
+ return obj;
3815
+ }
3816
+
3817
+ /*
3818
+ * Document-method: Curses::Field#buffer
3819
+ *
3820
+ * call-seq:
3821
+ * buffer(buf)
3822
+ *
3823
+ * Get the numbered buffer of the field.
3824
+ */
3825
+ static VALUE
3826
+ field_buffer_m(VALUE obj, VALUE buf)
3827
+ {
3828
+ struct fielddata *fieldp;
3829
+ char *s;
3830
+
3831
+ GetFIELD(obj, fieldp);
3832
+ s = field_buffer(fieldp->field, NUM2INT(buf));
3833
+ return rb_external_str_new_with_enc(s, strlen(s), terminal_encoding);
3834
+ }
3835
+
3836
+ /*
3837
+ * Document-method: Curses::Field#set_fore
3838
+ *
3839
+ * call-seq:
3840
+ * set_fore(attr)
3841
+ *
3842
+ * Set the foreground attribute of the field.
3843
+ */
3844
+ static VALUE
3845
+ field_set_fore(VALUE obj, VALUE attr)
3846
+ {
3847
+ struct fielddata *fieldp;
3848
+
3849
+ GetFIELD(obj, fieldp);
3850
+ set_field_fore(fieldp->field, NUM2CHTYPE(attr));
3851
+
3852
+ return attr;
3853
+ }
3854
+
3855
+ /*
3856
+ * Document-method: Curses::Field#fore
3857
+ *
3858
+ * call-seq:
3859
+ * fore
3860
+ *
3861
+ * Get the foreground attribute of the field.
3862
+ */
3863
+ static VALUE
3864
+ field_get_fore(VALUE obj)
3865
+ {
3866
+ struct fielddata *fieldp;
3867
+
3868
+ GetFIELD(obj, fieldp);
3869
+ return CHTYPE2NUM(field_fore(fieldp->field));
3870
+ }
3871
+
3872
+ /*
3873
+ * Document-method: Curses::Field#set_back
3874
+ *
3875
+ * call-seq:
3876
+ * set_back(attr)
3877
+ *
3878
+ * Set the background attribute of the field.
3879
+ */
3880
+ static VALUE
3881
+ field_set_back(VALUE obj, VALUE attr)
3882
+ {
3883
+ struct fielddata *fieldp;
3884
+
3885
+ GetFIELD(obj, fieldp);
3886
+ set_field_back(fieldp->field, NUM2CHTYPE(attr));
3887
+
3888
+ return attr;
3889
+ }
3890
+
3891
+ /*
3892
+ * Document-method: Curses::Field#back
3893
+ *
3894
+ * call-seq:
3895
+ * back
3896
+ *
3897
+ * Get the background attribute of the field.
3898
+ */
3899
+ static VALUE
3900
+ field_get_back(VALUE obj)
3901
+ {
3902
+ struct fielddata *fieldp;
3903
+
3904
+ GetFIELD(obj, fieldp);
3905
+ return CHTYPE2NUM(field_back(fieldp->field));
3906
+ }
3907
+
3908
+ /*
3909
+ * Document-method: Curses::Field#opts_on
3910
+ *
3911
+ * call-seq:
3912
+ * opts_on(opts)
3913
+ *
3914
+ * Turn on the given option bits.
3915
+ */
3916
+ static VALUE
3917
+ field_opts_on_m(VALUE obj, VALUE opts)
3918
+ {
3919
+ struct fielddata *fieldp;
3920
+
3921
+ GetFIELD(obj, fieldp);
3922
+ field_opts_on(fieldp->field, NUM2INT(opts));
3923
+
3924
+ return opts;
3925
+ }
3926
+
3927
+ /*
3928
+ * Document-method: Curses::Field#opts_off
3929
+ *
3930
+ * call-seq:
3931
+ * opts_off(opts)
3932
+ *
3933
+ * Turn off the given option bits.
3934
+ */
3935
+ static VALUE
3936
+ field_opts_off_m(VALUE obj, VALUE opts)
3937
+ {
3938
+ struct fielddata *fieldp;
3939
+
3940
+ GetFIELD(obj, fieldp);
3941
+ field_opts_off(fieldp->field, NUM2INT(opts));
3942
+
3943
+ return opts;
3944
+ }
3945
+
3946
+ /*
3947
+ * Document-method: Curses::Field#opts
3948
+ *
3949
+ * call-seq:
3950
+ * opts
3951
+ *
3952
+ * Get the current option bits.
3953
+ */
3954
+ static VALUE
3955
+ field_opts_m(VALUE obj)
3956
+ {
3957
+ struct fielddata *fieldp;
3958
+
3959
+ GetFIELD(obj, fieldp);
3960
+ return INT2NUM(field_opts(fieldp->field));
3961
+ }
3962
+
3963
+ static VALUE
3964
+ field_height(VALUE obj)
3965
+ {
3966
+ struct fielddata *fieldp;
3967
+ int error, val;
3968
+
3969
+ GetFIELD(obj, fieldp);
3970
+ error = field_info(fieldp->field, &val, NULL, NULL, NULL, NULL, NULL);
3971
+ check_curses_error(error);
3972
+ return INT2NUM(val);
3973
+ }
3974
+
3975
+ static VALUE
3976
+ field_width(VALUE obj)
3977
+ {
3978
+ struct fielddata *fieldp;
3979
+ int error, val;
3980
+
3981
+ GetFIELD(obj, fieldp);
3982
+ error = field_info(fieldp->field, NULL, &val, NULL, NULL, NULL, NULL);
3983
+ check_curses_error(error);
3984
+ return INT2NUM(val);
3985
+ }
3986
+
3987
+ static VALUE
3988
+ field_toprow(VALUE obj)
3989
+ {
3990
+ struct fielddata *fieldp;
3991
+ int error, val;
3992
+
3993
+ GetFIELD(obj, fieldp);
3994
+ error = field_info(fieldp->field, NULL, NULL, &val, NULL, NULL, NULL);
3995
+ check_curses_error(error);
3996
+ return INT2NUM(val);
3997
+ }
3998
+
3999
+ static VALUE
4000
+ field_leftcol(VALUE obj)
4001
+ {
4002
+ struct fielddata *fieldp;
4003
+ int error, val;
4004
+
4005
+ GetFIELD(obj, fieldp);
4006
+ error = field_info(fieldp->field, NULL, NULL, NULL, &val, NULL, NULL);
4007
+ check_curses_error(error);
4008
+ return INT2NUM(val);
4009
+ }
4010
+
4011
+ static VALUE
4012
+ field_offscreen(VALUE obj)
4013
+ {
4014
+ struct fielddata *fieldp;
4015
+ int error, val;
4016
+
4017
+ GetFIELD(obj, fieldp);
4018
+ error = field_info(fieldp->field, NULL, NULL, NULL, NULL, &val, NULL);
4019
+ check_curses_error(error);
4020
+ return INT2NUM(val);
4021
+ }
4022
+
4023
+ static VALUE
4024
+ field_nbuffers(VALUE obj)
4025
+ {
4026
+ struct fielddata *fieldp;
4027
+ int error, val;
4028
+
4029
+ GetFIELD(obj, fieldp);
4030
+ error = field_info(fieldp->field, NULL, NULL, NULL, NULL, NULL, &val);
4031
+ check_curses_error(error);
4032
+ return INT2NUM(val);
4033
+ }
4034
+
4035
+ static VALUE
4036
+ field_dynamic_height(VALUE obj)
4037
+ {
4038
+ struct fielddata *fieldp;
4039
+ int error, val;
4040
+
4041
+ GetFIELD(obj, fieldp);
4042
+ error = dynamic_field_info(fieldp->field, &val, NULL, NULL);
4043
+ check_curses_error(error);
4044
+ return INT2NUM(val);
4045
+ }
4046
+
4047
+ static VALUE
4048
+ field_dynamic_width(VALUE obj)
4049
+ {
4050
+ struct fielddata *fieldp;
4051
+ int error, val;
4052
+
4053
+ GetFIELD(obj, fieldp);
4054
+ error = dynamic_field_info(fieldp->field, NULL, &val, NULL);
4055
+ check_curses_error(error);
4056
+ return INT2NUM(val);
4057
+ }
4058
+
4059
+ static VALUE
4060
+ field_max(VALUE obj)
4061
+ {
4062
+ struct fielddata *fieldp;
4063
+ int error, val;
4064
+
4065
+ GetFIELD(obj, fieldp);
4066
+ error = dynamic_field_info(fieldp->field, NULL, NULL, &val);
4067
+ check_curses_error(error);
4068
+ return INT2NUM(val);
4069
+ }
4070
+
4071
+ static VALUE
4072
+ field_set_max(VALUE obj, VALUE max)
4073
+ {
4074
+ struct fielddata *fieldp;
4075
+ int error;
4076
+
4077
+ GetFIELD(obj, fieldp);
4078
+ error = set_max_field(fieldp->field, NUM2INT(max));
4079
+ check_curses_error(error);
4080
+ return max;
4081
+ }
4082
+
4083
+ #define TYPE_CODE_ALPHA 1
4084
+ #define TYPE_CODE_ALNUM 2
4085
+ #define TYPE_CODE_ENUM 3
4086
+ #define TYPE_CODE_INTEGER 4
4087
+ #define TYPE_CODE_NUMERIC 5
4088
+ #define TYPE_CODE_REGEXP 6
4089
+
4090
+ static VALUE
4091
+ field_set_type(int argc, VALUE *argv, VALUE obj)
4092
+ {
4093
+ struct fielddata *fieldp;
4094
+ VALUE type;
4095
+ int type_code;
4096
+ int error;
4097
+
4098
+ if (argc < 1) {
4099
+ rb_raise(rb_eArgError,
4100
+ "wrong number of arguments (given %d, expected 1)", argc);
4101
+ }
4102
+ type_code = NUM2INT(argv[0]);
4103
+ GetFIELD(obj, fieldp);
4104
+ switch (type_code) {
4105
+ case TYPE_CODE_ALPHA:
4106
+ {
4107
+ VALUE width;
4108
+ rb_scan_args(argc, argv, "11", &type, &width);
4109
+ error = set_field_type(fieldp->field, TYPE_ALPHA,
4110
+ NIL_P(width) ? 0 : NUM2INT(width));
4111
+ }
4112
+ break;
4113
+ case TYPE_CODE_ALNUM:
4114
+ {
4115
+ VALUE width;
4116
+ rb_scan_args(argc, argv, "11", &type, &width);
4117
+ error = set_field_type(fieldp->field, TYPE_ALNUM,
4118
+ NIL_P(width) ? 0 : NUM2INT(width));
4119
+ }
4120
+ break;
4121
+ #if 0
4122
+ case TYPE_CODE_ENUM:
4123
+ {
4124
+ /* TODO: consider how valuelist should be allocated? */
4125
+ }
4126
+ break;
4127
+ #endif
4128
+ case TYPE_CODE_INTEGER:
4129
+ {
4130
+ VALUE padding, vmin, vmax;
4131
+ rb_scan_args(argc, argv, "13", &type, &padding, &vmin, &vmax);
4132
+ error = set_field_type(fieldp->field, TYPE_INTEGER,
4133
+ NIL_P(padding) ? 0 : NUM2INT(padding),
4134
+ NIL_P(vmin) ? INT_MIN : NUM2INT(vmin),
4135
+ NIL_P(vmax) ? INT_MAX : NUM2INT(vmax));
4136
+ }
4137
+ break;
4138
+ case TYPE_CODE_NUMERIC:
4139
+ {
4140
+ VALUE padding, vmin, vmax;
4141
+ rb_scan_args(argc, argv, "13", &type, &padding, &vmin, &vmax);
4142
+ error = set_field_type(fieldp->field, TYPE_INTEGER,
4143
+ NIL_P(padding) ? 0 : NUM2INT(padding),
4144
+ NIL_P(vmin) ? INT_MIN : NUM2INT(vmin),
4145
+ NIL_P(vmax) ? INT_MAX : NUM2INT(vmax));
4146
+ }
4147
+ break;
4148
+ #if 0
4149
+ case TYPE_CODE_REGEXP:
4150
+ {
4151
+ /* TODO: consider how regexp should be allocated? */
4152
+ }
4153
+ break;
4154
+ #endif
4155
+ default:
4156
+ rb_raise(rb_eArgError, "unknwon type: %d", type_code);
4157
+ break;
4158
+ }
4159
+ check_curses_error(error);
4160
+ return obj;
4161
+ }
4162
+
4163
+ struct formdata {
4164
+ FORM *form;
4165
+ VALUE fields;
4166
+ };
4167
+
4168
+ NORETURN(static void no_form(void));
4169
+ static void
4170
+ no_form(void)
4171
+ {
4172
+ rb_raise(rb_eRuntimeError, "already deleted form");
4173
+ }
4174
+
4175
+ #define GetFORM(obj, formp) do {\
4176
+ TypedData_Get_Struct((obj), struct formdata, &formdata_type, (formp));\
4177
+ if ((formp)->form == 0) no_form();\
4178
+ } while (0)
4179
+
4180
+ static void
4181
+ form_gc_mark(void *p)
4182
+ {
4183
+ struct formdata *formp = p;
4184
+
4185
+ rb_gc_mark(formp->fields);
4186
+ }
4187
+
4188
+ static void
4189
+ form_free(void *p)
4190
+ {
4191
+ struct formdata *formp = p;
4192
+ FIELD **fields = form_fields(formp->form);
4193
+ if (formp->form) free_form(formp->form);
4194
+ xfree(fields);
4195
+ formp->form = 0;
4196
+ formp->fields = Qnil;
4197
+ xfree(formp);
4198
+ }
4199
+
4200
+ static size_t
4201
+ form_memsize(const void *p)
4202
+ {
4203
+ const struct formdata *formp = p;
4204
+ size_t size = sizeof(*formp);
4205
+ if (!formp) return 0;
4206
+ if (formp->form) size += CURSES_SIZEOF_FORM;
4207
+ return size;
4208
+ }
4209
+
4210
+ static const rb_data_type_t formdata_type = {
4211
+ "formdata",
4212
+ {form_gc_mark, form_free, form_memsize,}
4213
+ };
4214
+
4215
+ /* returns a Curses::Form object */
4216
+ static VALUE
4217
+ form_s_allocate(VALUE class)
4218
+ {
4219
+ struct formdata *formp;
4220
+
4221
+ return TypedData_Make_Struct(class, struct formdata, &formdata_type, formp);
4222
+ }
4223
+
4224
+ /*
4225
+ * Document-method: Curses::Form.new
4226
+ *
4227
+ * call-seq:
4228
+ * new(fields)
4229
+ *
4230
+ * Construct a new Curses::Form.
4231
+ */
4232
+ static VALUE
4233
+ form_initialize(VALUE obj, VALUE fields)
4234
+ {
4235
+ struct formdata *formp;
4236
+ FIELD **form_fields;
4237
+ int i;
4238
+
4239
+ Check_Type(fields, T_ARRAY);
4240
+ curses_init_screen(Qnil);
4241
+ TypedData_Get_Struct(obj, struct formdata, &formdata_type, formp);
4242
+ if (formp->form) {
4243
+ rb_raise(rb_eRuntimeError, "already initialized form");
4244
+ }
4245
+ formp->fields = rb_ary_new();
4246
+ form_fields = ALLOC_N(FIELD *, RARRAY_LEN(fields) + 1);
4247
+ for (i = 0; i < RARRAY_LEN(fields); i++) {
4248
+ VALUE field = RARRAY_AREF(fields, i);
4249
+ struct fielddata *fieldp;
4250
+
4251
+ GetFIELD(field, fieldp);
4252
+ form_fields[i] = fieldp->field;
4253
+ rb_ary_push(formp->fields, field);
4254
+ }
4255
+ form_fields[RARRAY_LEN(fields)] = NULL;
4256
+ formp->form = new_form(form_fields);
4257
+ if (formp->form == NULL) {
4258
+ check_curses_error(errno);
4259
+ }
4260
+
4261
+ return obj;
4262
+ }
4263
+
4264
+ /*
4265
+ * Document-method: Curses::Form#post
4266
+ *
4267
+ * call-seq:
4268
+ * post
4269
+ *
4270
+ * Post the form.
4271
+ */
4272
+ static VALUE
4273
+ form_post(VALUE obj)
4274
+ {
4275
+ struct formdata *formp;
4276
+ int error;
4277
+
4278
+ GetFORM(obj, formp);
4279
+ error = post_form(formp->form);
4280
+ check_curses_error(error);
4281
+
4282
+ return obj;
4283
+ }
4284
+
4285
+ /*
4286
+ * Document-method: Curses::Form#unpost
4287
+ *
4288
+ * call-seq:
4289
+ * unpost
4290
+ *
4291
+ * Unpost the form.
4292
+ */
4293
+ static VALUE
4294
+ form_unpost(VALUE obj)
4295
+ {
4296
+ struct formdata *formp;
4297
+ int error;
4298
+
4299
+ GetFORM(obj, formp);
4300
+ error = unpost_form(formp->form);
4301
+ check_curses_error(error);
4302
+
4303
+ return obj;
4304
+ }
4305
+
4306
+ /*
4307
+ * Document-method: Curses::Form#driver
4308
+ *
4309
+ * call-seq:
4310
+ * driver(command)
4311
+ *
4312
+ * Perform the command on the form.
4313
+ */
4314
+ static VALUE
4315
+ form_driver_m(VALUE obj, VALUE command)
4316
+ {
4317
+ struct formdata *formp;
4318
+ int error, c;
4319
+
4320
+ GetFORM(obj, formp);
4321
+ if (FIXNUM_P(command)) {
4322
+ c = NUM2INT(command);
4323
+ }
4324
+ else {
4325
+ ID id_ord;
4326
+
4327
+ StringValue(command);
4328
+ CONST_ID(id_ord, "ord");
4329
+ c = NUM2INT(rb_funcall(command, id_ord, 0));
4330
+ }
4331
+ #ifdef HAVE_FORM_DRIVER_W
4332
+ error = form_driver_w(formp->form,
4333
+ FIXNUM_P(command) ? KEY_CODE_YES : OK,
4334
+ c);
4335
+ #else
4336
+ error = form_driver(formp->form, c);
4337
+ #endif
4338
+ check_curses_error(error);
4339
+
4340
+ return obj;
4341
+ }
4342
+
4343
+ /*
4344
+ * Document-method: Curses::Form#set_win
4345
+ *
4346
+ * call-seq:
4347
+ * set_win=(win)
4348
+ *
4349
+ * Set the window of the form.
4350
+ */
4351
+ static VALUE
4352
+ form_set_win(VALUE obj, VALUE win)
4353
+ {
4354
+ struct formdata *formp;
4355
+ struct windata *winp;
4356
+
4357
+ GetFORM(obj, formp);
4358
+ GetWINDOW(win, winp);
4359
+ set_form_win(formp->form, winp->window);
4360
+ return win;
4361
+ }
4362
+
4363
+ /*
4364
+ * Document-method: Curses::Form#set_sub
4365
+ *
4366
+ * call-seq:
4367
+ * set_sub=(win)
4368
+ *
4369
+ * Set the subwindow of the form.
4370
+ */
4371
+ static VALUE
4372
+ form_set_sub(VALUE obj, VALUE win)
4373
+ {
4374
+ struct formdata *formp;
4375
+ struct windata *winp;
4376
+
4377
+ GetFORM(obj, formp);
4378
+ GetWINDOW(win, winp);
4379
+ set_form_sub(formp->form, winp->window);
4380
+ return win;
4381
+ }
4382
+
4383
+ /*
4384
+ * Document-method: Curses::Form#scale
4385
+ *
4386
+ * call-seq:
4387
+ * scale
4388
+ *
4389
+ * Return the minimum rows and columns required for the subwindow of the form.
4390
+ */
4391
+ static VALUE
4392
+ form_scale(VALUE obj)
4393
+ {
4394
+ struct formdata *formp;
4395
+ int error, rows, columns;
4396
+
4397
+ GetFORM(obj, formp);
4398
+ error = scale_form(formp->form, &rows, &columns);
4399
+ check_curses_error(error);
4400
+ return rb_assoc_new(INT2NUM(rows), INT2NUM(columns));
4401
+ }
4402
+
4403
+ #endif /* HAVE_FORM */
4404
+
4405
+ /*
4406
+ * Document-method: Curses.keyboard_encoding
4407
+ * call-seq: Curses.keyboard_encoding
4408
+ *
4409
+ * Returns the encoding for keyboard input.
4410
+ */
4411
+ static VALUE
4412
+ curses_get_keyboard_encoding(VALUE obj)
4413
+ {
4414
+ return rb_enc_from_encoding(keyboard_encoding);
4415
+ }
4416
+
4417
+ /*
4418
+ * Document-method: Curses.keyboard_encoding=
4419
+ * call-seq: Curses.keyboard_encoding = encoding
4420
+ *
4421
+ * Sets the encoding for keyboard input.
4422
+ */
4423
+ static VALUE
4424
+ curses_set_keyboard_encoding(VALUE obj, VALUE enc)
4425
+ {
4426
+ keyboard_encoding = rb_to_encoding(enc);
4427
+ return enc;
4428
+ }
4429
+
4430
+ /*
4431
+ * Document-method: Curses.terminal_encoding
4432
+ * call-seq: Curses.terminal_encoding
4433
+ *
4434
+ * Returns the encoding for terminal output.
4435
+ */
4436
+ static VALUE
4437
+ curses_get_terminal_encoding(VALUE obj)
4438
+ {
4439
+ return rb_enc_from_encoding(terminal_encoding);
4440
+ }
4441
+
4442
+ /*
4443
+ * Document-method: Curses.terminal_encoding=
4444
+ * call-seq: Curses.terminal_encoding = encoding
4445
+ *
4446
+ * Sets the encoding for terminal output.
4447
+ */
4448
+ static VALUE
4449
+ curses_set_terminal_encoding(VALUE obj, VALUE enc)
4450
+ {
4451
+ terminal_encoding = rb_to_encoding(enc);
4452
+ return enc;
4453
+ }
4454
+
4455
+ /*
4456
+ * Document-method: Curses.unget_char
4457
+ * call-seq: unget_char(ch)
4458
+ *
4459
+ * Places +ch+ back onto the input queue to be returned by
4460
+ * the next call to Curses.get_char etc.
4461
+ *
4462
+ * There is just one input queue for all windows.
4463
+ */
4464
+ static VALUE
4465
+ curses_unget_char(VALUE obj, VALUE ch)
4466
+ {
4467
+ ID id_ord;
4468
+ unsigned int c;
4469
+
4470
+ curses_stdscr();
4471
+ if (FIXNUM_P(ch)) {
4472
+ ungetch(NUM2UINT(ch));
4473
+ }
4474
+ else {
4475
+ StringValue(ch);
4476
+ CONST_ID(id_ord, "ord");
4477
+ c = NUM2UINT(rb_funcall(ch, id_ord, 0));
4478
+ #ifdef HAVE_UNGET_WCH
4479
+ unget_wch(c);
4480
+ #else
4481
+ if (c > 0xff) {
4482
+ rb_raise(rb_eRangeError, "Out of range: %u", c);
4483
+ }
4484
+ ungetch(c);
4485
+ #endif
4486
+ }
4487
+ return Qnil;
4488
+ }
4489
+
4490
+ static VALUE
4491
+ keyboard_uint_chr(unsigned int ch)
4492
+ {
4493
+ return rb_enc_uint_chr(ch, keyboard_encoding);
4494
+ }
4495
+
4496
+ #if defined(HAVE_GET_WCH) || defined(HAVE_WGET_WCH)
4497
+ static VALUE
4498
+ key_code_value(unsigned int ch)
4499
+ {
4500
+ #ifdef CTL_FSLASH
4501
+ if (ch == CTL_FSLASH) {
4502
+ return keyboard_uint_chr(0x1F);
4503
+ }
4504
+ #endif
4505
+ return UINT2NUM(ch);
4506
+ }
4507
+ #endif
4508
+
4509
+ #ifdef HAVE_GET_WCH
4510
+ struct get_wch_arg {
4511
+ int retval;
4512
+ wint_t ch;
4513
+ };
4514
+
4515
+ static void *
4516
+ get_wch_func(void *_arg)
4517
+ {
4518
+ struct get_wch_arg *arg = (struct get_wch_arg *) _arg;
4519
+ arg->retval = get_wch(&arg->ch);
4520
+ return 0;
4521
+ }
4522
+ #endif
4523
+
4524
+ /*
4525
+ * Document-method: Curses.get_char
4526
+ *
4527
+ * Read and returns a character or function key from the window.
4528
+ * A single or multibyte character is represented by a String, and
4529
+ * a function key is represented by an Integer.
4530
+ * Returns nil if no input is ready.
4531
+ *
4532
+ * See Curses::Key to all the function KEY_* available
4533
+ *
4534
+ */
4535
+ static VALUE
4536
+ curses_get_char(VALUE obj)
4537
+ {
4538
+ #ifdef HAVE_GET_WCH
4539
+ struct get_wch_arg arg;
4540
+
4541
+ curses_stdscr();
4542
+ rb_thread_call_without_gvl(get_wch_func, &arg, RUBY_UBF_IO, 0);
4543
+ switch (arg.retval) {
4544
+ case OK:
4545
+ return keyboard_uint_chr(arg.ch);
4546
+ case KEY_CODE_YES:
4547
+ return key_code_value(arg.ch);
4548
+ }
4549
+ return Qnil;
4550
+ #else
4551
+ int c;
4552
+
4553
+ curses_stdscr();
4554
+ rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0);
4555
+ if (c > 0xff) {
4556
+ return INT2NUM(c);
4557
+ }
4558
+ else if (c >= 0) {
4559
+ return keyboard_uint_chr(c);
4560
+ }
4561
+ else {
4562
+ return Qnil;
4563
+ }
4564
+ #endif
4565
+ }
4566
+
4567
+
4568
+ #ifdef HAVE_WGET_WCH
4569
+ struct wget_wch_arg {
4570
+ WINDOW *win;
4571
+ int retval;
4572
+ wint_t ch;
4573
+ };
4574
+
4575
+ static void *
4576
+ wget_wch_func(void *_arg)
4577
+ {
4578
+ struct wget_wch_arg *arg = (struct wget_wch_arg *) _arg;
4579
+ arg->retval = wget_wch(arg->win, &arg->ch);
4580
+ return 0;
4581
+ }
4582
+ #endif
4583
+
4584
+ /*
4585
+ * Document-method: Curses::Window.get_char
4586
+ *
4587
+ * Read and returns a character or function key from the window.
4588
+ * A single or multibyte character is represented by a String, and
4589
+ * a function key is represented by an Integer.
4590
+ * Returns nil if no input is ready.
4591
+ *
4592
+ * See Curses::Key to all the function KEY_* available
4593
+ *
4594
+ */
4595
+ static VALUE
4596
+ window_get_char(VALUE obj)
4597
+ {
4598
+ #ifdef HAVE_WGET_WCH
4599
+ struct windata *winp;
3613
4600
  struct wget_wch_arg arg;
3614
4601
 
3615
4602
  GetWINDOW(obj, winp);
@@ -3619,7 +4606,7 @@ window_get_char(VALUE obj)
3619
4606
  case OK:
3620
4607
  return keyboard_uint_chr(arg.ch);
3621
4608
  case KEY_CODE_YES:
3622
- return UINT2NUM(arg.ch);
4609
+ return key_code_value(arg.ch);
3623
4610
  }
3624
4611
  return Qnil;
3625
4612
  #else
@@ -3750,7 +4737,7 @@ Init_curses(void)
3750
4737
  rb_define_module_function(mCurses, "init_screen", curses_init_screen, 0);
3751
4738
  rb_define_module_function(mCurses, "close_screen", curses_close_screen, 0);
3752
4739
  rb_define_module_function(mCurses, "closed?", curses_closed, 0);
3753
- rb_define_module_function(mCurses, "stdscr", curses_stdscr, 0);
4740
+ rb_define_module_function(mCurses, "stdscr", curses_init_screen, 0);
3754
4741
  rb_define_module_function(mCurses, "refresh", curses_refresh, 0);
3755
4742
  rb_define_module_function(mCurses, "doupdate", curses_doupdate, 0);
3756
4743
  rb_define_module_function(mCurses, "clear", curses_clear, 0);
@@ -3890,7 +4877,7 @@ Init_curses(void)
3890
4877
  * win.close
3891
4878
  *
3892
4879
  */
3893
- cWindow = rb_define_class_under(mCurses, "Window", rb_cData);
4880
+ cWindow = rb_define_class_under(mCurses, "Window", rb_cObject);
3894
4881
  rb_define_alloc_func(cWindow, window_s_allocate);
3895
4882
  rb_define_method(cWindow, "initialize", window_initialize, 4);
3896
4883
  rb_define_method(cWindow, "subwin", window_subwin, 4);
@@ -3974,14 +4961,18 @@ Init_curses(void)
3974
4961
  #endif
3975
4962
 
3976
4963
  #ifdef HAVE_MENU
3977
- cItem = rb_define_class_under(mCurses, "Item", rb_cData);
4964
+ cItem = rb_define_class_under(mCurses, "Item", rb_cObject);
3978
4965
  rb_define_alloc_func(cItem, item_s_allocate);
3979
4966
  rb_define_method(cItem, "initialize", item_initialize, 2);
3980
4967
  rb_define_method(cItem, "==", item_eq, 1);
3981
4968
  rb_define_method(cItem, "name", item_name_m, 0);
3982
4969