curses-1.2.4/0000755000004100000410000000000013267647262013071 5ustar www-datawww-datacurses-1.2.4/COPYING0000644000004100000410000000471013267647262014126 0ustar www-datawww-dataRuby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. curses-1.2.4/.travis.yml0000644000004100000410000000027213267647262015203 0ustar www-datawww-data--- language: ruby notifications: email: recipients: - drbrain@segment7.net - shugo@ruby-lang.org rvm: - 2.2.7 - 2.3.4 - 2.4.1 - ruby-head script: rake compile curses-1.2.4/README.md0000644000004100000410000000535713267647262014362 0ustar www-datawww-data# curses [![Gem Version](https://badge.fury.io/rb/curses.svg)](https://badge.fury.io/rb/curses) [![Build Status](https://travis-ci.org/ruby/curses.svg?branch=master)](https://travis-ci.org/ruby/curses) [![Build status](https://ci.appveyor.com/api/projects/status/kdvksgjo4fyd3c4m/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/curses/branch/master) * https://github.com/ruby/curses * https://github.com/ruby/curses/issues ## Description 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]) ## Install $ gem install curses Requires ncurses or ncursesw (with wide character support). On Debian based distributions, you can install it with apt: $ apt install libncurses5-dev Or $ apt install libncursesw5-dev ## Developers After checking out the repo, run `bundle install` to install dependencies. To compile the extension library, run `bundle exec rake compile`. 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). ### Cross compilation for Windows on Debian GNU/Linux based platforms 1. Install development environment fo 32- and 64-bit Windows. ``` $ sudo apt-get install mingw-w64 ``` 2. Install rake-compiler. ``` $ gem install rake-compiler ``` 3. Compile multiple versions of Ruby. ``` $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.2.6 $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.3.3 $ rake-compiler cross-ruby HOST=i686-w64-mingw32 VERSION=2.4.0 $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.2.6 $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.3.3 $ rake-compiler cross-ruby HOST=x86_64-w64-mingw32 VERSION=2.4.0 ``` 3. Compile PDCurses. ``` $ rake build:pdcurses ``` 5. Compile curses.gem. ``` $ rake RUBY_CC_VERSION=2.3.3:2.4.0 cross clean compile native gem ``` Binary gems are generated in pkg/. ## License curses is released under the Ruby and 2-clause BSD licenses. See COPYING for details. Binary gems for mingw32 include a forked version of PDCurses, which is in the public domain: https://github.com/Bill-Gray/PDCurses The version for Win32 console mode in the win32 subdirectory is used. [1]: https://bugs.ruby-lang.org/issues/8584 [2]: https://github.com/ruby/ruby/commit/9c5b2fd8aa0fd343ad094d47a638cfd3f6ae0a81 curses-1.2.4/.gitignore0000644000004100000410000000030113267647262015053 0ustar www-datawww-data*.rbc *.swp /TAGS /doc /lib/curses.bundle /lib/curses.so /lib/curses.dll /pkg /tmp /Gemfile.lock /vendor/x86-mingw32 /vendor/x64-mingw32 /vendor/x64-mswin64* /ext/curses/Makefile .ruby-version curses-1.2.4/Rakefile0000644000004100000410000000520413267647262014537 0ustar www-datawww-datarequire "bundler" Bundler::GemHelper.install_tasks begin require 'rake/extensiontask' rescue LoadError => e warn "\nmissing #{e.path} (for rake-compiler)" if e.respond_to? :path warn "run: bundle install\n\n" end $mswin = /mswin/ =~ RUBY_PLATFORM CLOBBER.include("vendor/#{RUBY_PLATFORM}") if $mswin CLOBBER.include("vendor/x86-mingw32") CLOBBER.include("vendor/x64-mingw32") CLOBBER.include("lib/2.*") CLOBBER.include("pkg") namespace :build do desc "Build PDCurses" task :pdcurses do mkdir_p "vendor/#{RUBY_PLATFORM}/PDCurses" if $mswin mkdir_p "vendor/x86-mingw32/PDCurses" mkdir_p "vendor/x64-mingw32/PDCurses" chdir "vendor/PDCurses/win32" do if $mswin sh "nmake -f vcwin32.mak clean all WIDE=Y DLL=Y" cp %w[pdcurses.dll pdcurses.lib], "../../#{RUBY_PLATFORM}/PDCurses" else sh "make -f mingwin32.mak clean all WIDE=Y DLL=Y" cp "pdcurses.dll", "../../x86-mingw32/PDCurses" sh "make -f mingwin32.mak clean all _w64=1 WIDE=Y DLL=Y" cp "pdcurses.dll", "../../x64-mingw32/PDCurses" end end end end namespace :clean do desc "Clean PDCurses" task :pdcurses do chdir "vendor/PDCurses/win32" do sh "nmake -f vcwin32.mak clean" if $mswin sh "make -f mingwin32.mak clean _linux_w64=1" end end end spec = eval(File.read(File.expand_path("curses.gemspec", __dir__))) Rake::ExtensionTask.new(spec.name, spec) do |ext| if $mswin ext.config_options << '--with-curses-include=' + File.expand_path("vendor/PDCurses", __dir__) + ' --with-curses-version=function --enable-pdcurses-wide' + ' --enable-pdcurses-dll' + ' --with-curses-lib=' + File.expand_path("vendor/#{RUBY_PLATFORM}/PDCurses", __dir__) spec.files += ["vendor/#{RUBY_PLATFORM}/PDCurses/pdcurses.dll"] end ext.cross_compile = true ext.cross_platform = ["x86-mingw32", "x64-mingw32"] ext.cross_config_options << '--with-curses-include=' + File.expand_path("vendor/PDCurses", __dir__) + ' --with-curses-version=function --enable-pdcurses-wide' ext.cross_config_options << { 'x86-mingw32' => '--with-curses-lib=' + File.expand_path("vendor/x86-mingw32/PDCurses", __dir__), 'x64-mingw32' => '--with-curses-lib=' + File.expand_path("vendor/x64-mingw32/PDCurses", __dir__) } ext.cross_compiling do |_spec| bin_file = "vendor/#{_spec.platform}/PDCurses/pdcurses.dll" _spec.files += [bin_file] stage_file = "#{ext.tmp_dir}/#{_spec.platform}/stage/#{bin_file}" stage_dir = File.dirname(stage_file) directory stage_dir file stage_file => [stage_dir, bin_file] do cp bin_file, stage_file end end end curses-1.2.4/lib/0000755000004100000410000000000013267647262013637 5ustar www-datawww-datacurses-1.2.4/lib/curses.rb0000644000004100000410000000117613267647262015475 0ustar www-datawww-dataplatform = RUBY_PLATFORM.sub(/i[3-7]86/, "x86") pdcurses_path = File.expand_path("../vendor/#{platform}/PDCurses", __dir__) pdcurses_bundled = File.directory?(pdcurses_path) if pdcurses_bundled path = ENV["PATH"] dir = File::ALT_SEPARATOR ? pdcurses_path.tr("/", File::ALT_SEPARATOR) : dir dirs = path.split(File::PATH_SEPARATOR) if !dirs.include?(dir) ENV["PATH"] = [dir, *dirs].join(File::PATH_SEPARATOR) end end begin major, minor, _ = RUBY_VERSION.split(/\./) require "#{major}.#{minor}/curses.so" rescue LoadError require "curses.so" end if pdcurses_bundled Curses.keyboard_encoding = Encoding::UTF_8 end curses-1.2.4/Gemfile0000644000004100000410000000010513267647262014360 0ustar www-datawww-data# frozen_string_literal: true source "https://rubygems.org" gemspec curses-1.2.4/.gitmodules0000644000004100000410000000014713267647262015250 0ustar www-datawww-data[submodule "vendor/PDCurses"] path = vendor/PDCurses url = https://github.com/Bill-Gray/PDCurses.git curses-1.2.4/appveyor.yml0000644000004100000410000000076013267647262015464 0ustar www-datawww-data--- clone_depth: 10 install: - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% - appveyor DownloadFile http://dl.bintray.com/oneclick/OpenKnapsack/x64/pdcurses-3.4-x64-windows.tar.lzma - 7z e pdcurses-3.4-x64-windows.tar.lzma - 7z x -y -oC:\Ruby%ruby_version% pdcurses-3.4-x64-windows.tar - bundle install build_script: - rake -rdevkit compile -- --with-curses-dir=C:\Ruby%ruby_version% test: off deploy: off environment: matrix: - ruby_version: "22-x64" - ruby_version: "23-x64" curses-1.2.4/History.md0000644000004100000410000000437213267647262015062 0ustar www-datawww-data### 1.2.4 / 2017-09-13 New features: * Update PDCurses. Bug fixes: * Fix the path of pdcurses.dll for i386-mingw. (Issue #36) Documentation: * Include reference to ncurses dependency. Pull request #34 by qume. ### 1.2.3 / 2017-07-03 Bug fixes: * Fixes for mswin. Pull requests #30, #31, #32 and #33 by unak. ### 1.2.2 / 2017-04-22 New features: * Add Curses.get_key_modifiers, Curses.return_key_modifiers, and Curses.save_key_modifiers. * Support mswin native build. Pull request #29 by usa. ### 1.2.1 / 2017-03-27 New features: * Add touch, untouch, touched?, touch_line, and line_touched?. Bug fixes: * Fix Pad#subpad to use subpad(3). (Issue #23) * Fix build issues on macOS. Pull requests #24, #25, #26, #27 and #28 by nobu. ### 1.2.0 / 2017-02-19 New features: * Add Curses.assume_default_colors. Bug fixes: * Curses.unget_char should use String#ord even if unget_wch() is not available. * The default value of keyboard_encoding should be ASCII-8BIT if get_wch() is not available. * NUM2ULONG() should be used in Window#bkgd etc. ### 1.1.3 / 2017-02-08 Bug fixes: * Update PDCurses to handle extended keys. ### 1.1.2 / 2017-02-06 Bug fixes: * Use the left-alt-fix branch of https://github.com/shugo/PDCurses.git to get ALT + < etc. ### 1.1.1 / 2017-01-25 Bug fixes: * Add -DPDC_WIDE to CPPFLAGS when compiling with PDCurses. ### 1.1.0 / 2017-01-24 New features: * Use bundler instead of hoe. Pull request #18 by hsbt. * Enable appveyor. Pull request #19 by hsbt. * Add badges for build status to README.md. Pull request #20 by hsbt. * Add Curses.erase and Curses::Window.erase. * Add Curses::Window.redraw. * Add Curses.unget_char, Curses.get_char, and Curses::Window.get_char for multibyte characters. * Add Curses.keyboard_encoding and Curses.terminal_encoding. * Support cross compilation for mingw32. Bug fixes: * Fix error in attron/attroff documentation. Pull request #14 by stomar. * Improve code samples. Pull request #15 by stomar. ### 1.0.2 / 2016-03-15 Bug fixes: * Fix ncursesw support. Pull request #16 by peter50216, patch by eTM. Issue #6 by Jean Lazarou. ### 1.0.1 / 2014-03-26 Bug fixes: * Curses install is a no-op on ruby with bundled curses. Pull request #4 tiredpixel. ### 1.0.0 / 2013-12-10 Birthday! curses-1.2.4/BSDL0000644000004100000410000000240213267647262013536 0ustar www-datawww-dataCopyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. curses-1.2.4/ext/0000755000004100000410000000000013267647262013671 5ustar www-datawww-datacurses-1.2.4/ext/curses/0000755000004100000410000000000013267647262015175 5ustar www-datawww-datacurses-1.2.4/ext/curses/depend0000644000004100000410000000022213267647262016353 0ustar www-datawww-data$(OBJS): $(HDRS) $(ruby_headers) \ $(hdrdir)/ruby/io.h \ $(hdrdir)/ruby/encoding.h \ $(hdrdir)/ruby/oniguruma.h \ $(hdrdir)/ruby/thread.h curses-1.2.4/ext/curses/curses.c0000644000004100000410000033571513267647262016663 0ustar www-datawww-data/* -*- C -*- * $Id$ * * ext/curses/curses.c * * by MAEDA Shugo (ender@pic-internet.or.jp) * modified by Yukihiro Matsumoto (matz@netlab.co.jp), * Toki Yoshinori, * Hitoshi Takahashi, * and Takaaki Tateishi (ttate@kt.jaist.ac.jp) * * maintainers: * - Takaaki Tateishi (ttate@kt.jaist.ac.jp) * * documentation: * - Vincent Batts (vbatts@hashbangbash.com) */ #include "ruby.h" #include "ruby/io.h" #include "ruby/thread.h" #if defined(HAVE_NCURSES_H) # include #elif defined(HAVE_NCURSESW_CURSES_H) # include #elif defined(HAVE_NCURSES_CURSES_H) # include #elif defined(HAVE_CURSES_COLR_CURSES_H) # ifdef HAVE_STDARG_PROTOTYPES # include # else # include # endif # include #else # include # if defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__) # if !defined(_maxx) # define _maxx maxx # endif # if !defined(_maxy) # define _maxy maxy # endif # if !defined(_begx) # define _begx begx # endif # if !defined(_begy) # define _begy begy # endif # endif #endif #ifdef HAVE_INIT_COLOR # define USE_COLOR 1 #endif /* supports only ncurses mouse routines */ #ifdef NCURSES_MOUSE_VERSION # define USE_MOUSE 1 #endif #define NUM2CH NUM2CHR #define CH2FIX CHR2FIX static VALUE mCurses; static VALUE mKey; static VALUE cWindow; static VALUE cPad; #ifdef USE_MOUSE static VALUE cMouseEvent; #endif static VALUE rb_stdscr; static rb_encoding *keyboard_encoding; static rb_encoding *terminal_encoding; struct windata { WINDOW *window; }; static VALUE window_attroff(VALUE obj, VALUE attrs); static VALUE window_attron(VALUE obj, VALUE attrs); static VALUE window_attrset(VALUE obj, VALUE attrs); static void no_window(void) { rb_raise(rb_eRuntimeError, "already closed window"); } #define GetWINDOW(obj, winp) do {\ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\ rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\ TypedData_Get_Struct((obj), struct windata, &windata_type, (winp));\ if ((winp)->window == 0) no_window();\ } while (0) static void window_free(void *p) { struct windata *winp = p; if (winp->window && winp->window != stdscr) delwin(winp->window); winp->window = 0; xfree(winp); } static size_t window_memsize(const void *p) { const struct windata *winp = p; size_t size = sizeof(*winp); if (!winp) return 0; if (winp->window && winp->window != stdscr) size += sizeof(winp->window); return size; } static const rb_data_type_t windata_type = { "windata", {0, window_free, window_memsize,} }; static VALUE prep_window(VALUE class, WINDOW *window) { VALUE obj; struct windata *winp; if (window == NULL) { rb_raise(rb_eRuntimeError, "failed to create window"); } obj = rb_obj_alloc(class); TypedData_Get_Struct(obj, struct windata, &windata_type, winp); winp->window = window; return obj; } #if (defined(HAVE_ADDNWSTR) || defined(HAVE_WADDNWSTR)) && defined(_WIN32) static inline rb_encoding * get_wide_encoding(void) { static rb_encoding *utf16le = NULL; if (!utf16le) { utf16le = rb_enc_find("utf-16le"); } return utf16le; } #endif /*-------------------------- module Curses --------------------------*/ static void curses_finalize(VALUE); /* * Document-method: Curses.init_screen * * Initialize a standard screen * * see also Curses.stdscr */ static VALUE curses_init_screen(void) { if (rb_stdscr) return rb_stdscr; initscr(); if (stdscr == 0) { rb_raise(rb_eRuntimeError, "can't initialize curses"); } rb_set_end_proc(curses_finalize, 0); clear(); rb_stdscr = prep_window(cWindow, stdscr); return rb_stdscr; } /* * Document-method: Curses.stdscr * * The Standard Screen. * * Upon initializing curses, a default window called stdscr, * which is the size of the terminal screen, is created. * * Many curses functions use this window. */ #define curses_stdscr curses_init_screen /* * Document-method: Curses.close_screen * * A program should always call Curses.close_screen before exiting or * escaping from curses mode temporarily. This routine * restores tty modes, moves the cursor to the lower * left-hand corner of the screen and resets the terminal * into the proper non-visual mode. * * Calling Curses.refresh or Curses.doupdate after a temporary * escape causes the program to resume visual mode. * */ static VALUE curses_close_screen(void) { curses_stdscr(); #ifdef HAVE_ISENDWIN if (!isendwin()) #endif endwin(); rb_stdscr = 0; return Qnil; } /* * This is no runtime method, * but a function called before the proc ends * * Similar to Curses.close_screen, except that it also * garbage collects/unregisters the Curses.stdscr */ static void curses_finalize(VALUE dummy) { if (stdscr #ifdef HAVE_ISENDWIN && !isendwin() #endif ) endwin(); rb_stdscr = 0; rb_gc_unregister_address(&rb_stdscr); } #ifdef HAVE_ISENDWIN /* * Document-method: Curses.closed? * * Returns +true+ if the window/screen has been closed, * without any subsequent Curses.refresh calls, * returns +false+ otherwise. */ static VALUE curses_closed(void) { curses_stdscr(); if (isendwin()) { return Qtrue; } return Qfalse; } #else #define curses_closed rb_f_notimplement #endif /* * Document-method: Curses.clear * * Clears every position on the screen completely, * so that a subsequent call by Curses.refresh for the screen/window * will be repainted from scratch. */ static VALUE curses_clear(VALUE obj) { curses_stdscr(); wclear(stdscr); return Qnil; } #ifdef HAVE_WERASE /* * Document-method: Curses.erase * * Erase the screen. */ static VALUE curses_erase(VALUE obj) { curses_stdscr(); werase(stdscr); return Qnil; } #else #define curses_erase rb_f_notimplement #endif /* * Document-method: Curses.clrtoeol * * Clears to the end of line, that the cursor is currently on. */ static VALUE curses_clrtoeol(void) { curses_stdscr(); clrtoeol(); return Qnil; } /* * Document-method: Curses.refresh * * Refreshes the windows and lines. * */ static VALUE curses_refresh(VALUE obj) { curses_stdscr(); refresh(); return Qnil; } /* * Document-method: Curses.doupdate * * Refreshes the windows and lines. * * Curses.doupdate allows multiple updates with * more efficiency than Curses.refresh alone. */ static VALUE curses_doupdate(VALUE obj) { curses_stdscr(); #ifdef HAVE_DOUPDATE doupdate(); #else refresh(); #endif return Qnil; } /* * Document-method: Curses.echo * * Enables characters typed by the user * to be echoed by Curses.getch as they are typed. */ static VALUE curses_echo(VALUE obj) { curses_stdscr(); echo(); return Qnil; } /* * Document-method: Curses.noecho * * Disables characters typed by the user * to be echoed by Curses.getch as they are typed. */ static VALUE curses_noecho(VALUE obj) { curses_stdscr(); noecho(); return Qnil; } /* * Document-method: Curses.raw * * Put the terminal into raw mode. * * Raw mode is similar to Curses.cbreak mode, in that characters typed * are immediately passed through to the user program. * * The differences are that in raw mode, the interrupt, quit, * suspend, and flow control characters are all passed through * uninterpreted, instead of generating a signal. The behavior * of the BREAK key depends on other bits in the tty driver * that are not set by curses. */ static VALUE curses_raw(VALUE obj) { curses_stdscr(); raw(); return Qnil; } /* * Document-method: Curses.noraw * * Put the terminal out of raw mode. * * see Curses.raw for more detail */ static VALUE curses_noraw(VALUE obj) { curses_stdscr(); noraw(); return Qnil; } /* * Document-method: Curses.cbreak * * Put the terminal into cbreak mode. * * Normally, the tty driver buffers typed characters until * a newline or carriage return is typed. The Curses.cbreak * routine disables line buffering and erase/kill * character-processing (interrupt and flow control characters * are unaffected), making characters typed by the user * immediately available to the program. * * The Curses.nocbreak routine returns the terminal to normal (cooked) mode. * * Initially the terminal may or may not be in cbreak mode, * as the mode is inherited; therefore, a program should * call Curses.cbreak or Curses.nocbreak explicitly. * Most interactive programs using curses set the cbreak mode. * Note that Curses.cbreak overrides Curses.raw. * * see also Curses.raw */ static VALUE curses_cbreak(VALUE obj) { curses_stdscr(); cbreak(); return Qnil; } /* * Document-method: Curses.nocbreak * * Put the terminal into normal mode (out of cbreak mode). * * See Curses.cbreak for more detail. */ static VALUE curses_nocbreak(VALUE obj) { curses_stdscr(); nocbreak(); return Qnil; } /* * Document-method: Curses.nl * * Enable the underlying display device to translate * the return key into newline on input, and whether it * translates newline into return and line-feed on output * (in either case, the call Curses.addch('\n') does the * equivalent of return and line feed on the virtual screen). * * Initially, these translations do occur. If you disable * them using Curses.nonl, curses will be able to make better use * of the line-feed capability, resulting in faster cursor * motion. Also, curses will then be able to detect the return key. */ static VALUE curses_nl(VALUE obj) { curses_stdscr(); nl(); return Qnil; } /* * Document-method: Curses.nl * * Disable the underlying display device to translate * the return key into newline on input * * See Curses.nl for more detail */ static VALUE curses_nonl(VALUE obj) { curses_stdscr(); nonl(); return Qnil; } /* * Document-method: Curses.beep * * Sounds an audible alarm on the terminal, if possible; * otherwise it flashes the screen (visual bell). * * see also Curses.flash */ static VALUE curses_beep(VALUE obj) { #ifdef HAVE_BEEP curses_stdscr(); beep(); #endif return Qnil; } /* * Document-method: Curses.flash * * Flashes the screen, for visual alarm on the terminal, if possible; * otherwise it sounds the alert. * * see also Curses.beep */ static VALUE curses_flash(VALUE obj) { #ifdef HAVE_FLASH curses_stdscr(); flash(); #endif return Qnil; } static int curses_char(VALUE c) { if (FIXNUM_P(c)) { return NUM2INT(c); } else { int cc; StringValue(c); if (RSTRING_LEN(c) == 0 || RSTRING_LEN(c) > 1) { rb_raise(rb_eArgError, "string not corresponding a character"); } cc = RSTRING_PTR(c)[0]; if (cc > 0x7f) { rb_raise(rb_eArgError, "no multibyte string supported (yet)"); } return cc; } } #ifdef HAVE_UNGETCH /* * Document-method: Curses.ungetch * call-seq: ungetch(ch) * * Places +ch+ back onto the input queue to be returned by * the next call to Curses.getch. * * There is just one input queue for all windows. */ static VALUE curses_ungetch(VALUE obj, VALUE ch) { int c = curses_char(ch); curses_stdscr(); ungetch(c); return Qnil; } #else #define curses_ungetch rb_f_notimplement #endif /* * Document-method: Curses.setpos * call-seq: setpos(y, x) * * A setter for the position of the cursor, * using coordinates +x+ and +y+ * */ static VALUE curses_setpos(VALUE obj, VALUE y, VALUE x) { curses_stdscr(); move(NUM2INT(y), NUM2INT(x)); return Qnil; } /* * Document-method: Curses.standout * * Enables the best highlighting mode of the terminal. * * This is equivalent to Curses:Window.attron(A_STANDOUT) * * see also Curses::Window.attrset additional information */ static VALUE curses_standout(VALUE obj) { curses_stdscr(); standout(); return Qnil; } /* * Document-method: Curses.standend * * Enables the Normal display (no highlight) * * This is equivalent to Curses.attron(A_NORMAL) * * see also Curses::Window.attrset for additional information. */ static VALUE curses_standend(VALUE obj) { curses_stdscr(); standend(); return Qnil; } /* * Document-method: Curses.inch * * Returns the character at the current position. */ static VALUE curses_inch(VALUE obj) { curses_stdscr(); return CH2FIX(inch()); } /* * Document-method: Curses.addch * call-seq: addch(ch) * * Add a character +ch+, with attributes, then advance the cursor. * * see also the system manual for curs_addch(3) */ static VALUE curses_addch(VALUE obj, VALUE ch) { curses_stdscr(); addch(NUM2CH(ch)); return Qnil; } /* * Document-method: Curses.insch * call-seq: insch(ch) * * Insert a character +ch+, before the cursor. * */ static VALUE curses_insch(VALUE obj, VALUE ch) { curses_stdscr(); insch(NUM2CH(ch)); return Qnil; } /* * Document-method: Curses.addstr * call-seq: addstr(str) * * add a string of characters +str+, to the window and advance cursor * */ static VALUE curses_addstr(VALUE obj, VALUE str) { StringValue(str); #if defined(HAVE_ADDNWSTR) && defined(_WIN32) str = rb_str_export_to_enc(str, get_wide_encoding()); curses_stdscr(); if (!NIL_P(str)) { addnwstr((wchar_t *)RSTRING_PTR(str), RSTRING_LEN(str) / sizeof(wchar_t)); } #else str = rb_str_export_to_enc(str, terminal_encoding); curses_stdscr(); if (!NIL_P(str)) { addstr(StringValueCStr(str)); } #endif return Qnil; } static void * getch_func(void *arg) { int *ip = (int *)arg; *ip = getch(); return 0; } /* * Document-method: Curses.getch * * Read and returns a character from the window. * * See Curses::Key to all the function KEY_* available * */ static VALUE curses_getch(VALUE obj) { int c; curses_stdscr(); rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0); if (c == EOF) return Qnil; if (rb_isprint(c)) { char ch = (char)c; return rb_external_str_new_with_enc(&ch, 1, keyboard_encoding); } return UINT2NUM(c); } /* This should be big enough.. I hope */ #define GETSTR_BUF_SIZE 1024 static void * getstr_func(void *arg) { char *rtn = (char *)arg; #if defined(HAVE_GETNSTR) getnstr(rtn,GETSTR_BUF_SIZE-1); #else getstr(rtn); #endif return 0; } /* * Document-method: Curses.getstr * * This is equivalent to a series f Curses::Window.getch calls * */ static VALUE curses_getstr(VALUE obj) { char rtn[GETSTR_BUF_SIZE]; curses_stdscr(); rb_thread_call_without_gvl(getstr_func, rtn, RUBY_UBF_IO, 0); return rb_external_str_new_with_enc(rtn, strlen(rtn), keyboard_encoding); } /* * Document-method: Curses.delch * * Delete the character under the cursor * */ static VALUE curses_delch(VALUE obj) { curses_stdscr(); delch(); return Qnil; } /* * Document-method: Curses.deleteln * * Delete the line under the cursor. * */ static VALUE curses_deleteln(VALUE obj) { curses_stdscr(); #if defined(HAVE_DELETELN) || defined(deleteln) deleteln(); #endif return Qnil; } /* * Document-method: Curses.insertln * * Inserts a line above the cursor, and the bottom line is lost * */ static VALUE curses_insertln(VALUE obj) { curses_stdscr(); #if defined(HAVE_INSERTLN) || defined(insertln) insertln(); #endif return Qnil; } /* * Document-method: Curses.keyname * call-seq: keyname(c) * * Returns the character string corresponding to key +c+ */ static VALUE curses_keyname(VALUE obj, VALUE c) { #ifdef HAVE_KEYNAME int cc = curses_char(c); const char *name; curses_stdscr(); name = keyname(cc); if (name) { return rb_str_new_cstr(name); } else { return Qnil; } #else return Qnil; #endif } /* * Document-method: Curses.lines * * Returns the number of lines on the screen */ static VALUE curses_lines(void) { return INT2FIX(LINES); } /* * Document-method: Curses.cols * * Returns the number of columns on the screen */ static VALUE curses_cols(void) { return INT2FIX(COLS); } /* * Document-method: Curses.curs_set * call-seq: curs_set(visibility) * * Sets Cursor Visibility. * 0: invisible * 1: visible * 2: very visible */ static VALUE curses_curs_set(VALUE obj, VALUE visibility) { #ifdef HAVE_CURS_SET int n; curses_stdscr(); return (n = curs_set(NUM2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil; #else return Qnil; #endif } /* * Document-method: Curses.scrl * call-seq: scrl(num) * * Scrolls the current window Fixnum +num+ lines. * The current cursor position is not changed. * * For positive +num+, it scrolls up. * * For negative +num+, it scrolls down. * */ static VALUE curses_scrl(VALUE obj, VALUE n) { /* may have to raise exception on ERR */ #ifdef HAVE_SCRL curses_stdscr(); return (scrl(NUM2INT(n)) == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } /* * Document-method: Curses.setscrreg * * call-seq: * setscrreg(top, bottom) * * Set a software scrolling region in a window. * +top+ and +bottom+ are lines numbers of the margin. * * If this option and Curses.scrollok are enabled, an attempt to move off * the bottom margin line causes all lines in the scrolling region * to scroll one line in the direction of the first line. * Only the text of the window is scrolled. * */ static VALUE curses_setscrreg(VALUE obj, VALUE top, VALUE bottom) { /* may have to raise exception on ERR */ #ifdef HAVE_SETSCRREG curses_stdscr(); return (setscrreg(NUM2INT(top), NUM2INT(bottom)) == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } /* * Document-method: Curses.attroff * call-seq: attroff(attrs) * * Turns off the named attributes +attrs+ * without affecting any others. * * See also Curses::Window.attrset for additional information. */ static VALUE curses_attroff(VALUE obj, VALUE attrs) { curses_stdscr(); return window_attroff(rb_stdscr,attrs); /* return INT2FIX(attroff(NUM2INT(attrs))); */ } /* * Document-method: Curses.attron * call-seq: attron(attrs) * * Turns on the named attributes +attrs+ * without turning any other attributes on or off. * * See also Curses::Window.attrset for additional information. */ static VALUE curses_attron(VALUE obj, VALUE attrs) { curses_stdscr(); return window_attron(rb_stdscr,attrs); /* return INT2FIX(attroff(NUM2INT(attrs))); */ } /* * Document-method: Curses.attrset * call-seq: attrset(attrs) * * Sets the current attributes of the given window to +attrs+. * * see also Curses::Window.attrset * */ static VALUE curses_attrset(VALUE obj, VALUE attrs) { curses_stdscr(); return window_attrset(rb_stdscr,attrs); /* return INT2FIX(attroff(NUM2INT(attrs))); */ } /* * Document-method: Curses.bkgdset * call-seq: bkgdset(ch) * * Manipulate the background of the named window * with character Integer +ch+ * * The background becomes a property of the character * and moves with the character through any scrolling * and insert/delete line/character operations. * * see also the system manual for curs_bkgd(3) */ static VALUE curses_bkgdset(VALUE obj, VALUE ch) { #ifdef HAVE_BKGDSET curses_stdscr(); bkgdset(NUM2CHTYPE(ch)); #endif return Qnil; } /* * call-seq: bkgd(ch) * * Window background manipulation routines. * * Set the background property of the current * and then apply the character Integer +ch+ setting * to every character position in that window. * * see also the system manual for curs_bkgd(3) */ static VALUE curses_bkgd(VALUE obj, VALUE ch) { #ifdef HAVE_BKGD curses_stdscr(); return (bkgd(NUM2CHTYPE(ch)) == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } #if defined(HAVE_USE_DEFAULT_COLORS) /* * tells the curses library to use terminal's default colors. * * see also the system manual for default_colors(3) */ static VALUE curses_use_default_colors(VALUE obj) { curses_stdscr(); use_default_colors(); return Qnil; } #else #define curses_use_default_colors rb_f_notimplement #endif #if defined(HAVE_ASSUME_DEFAULT_COLORS) /* * tells which colors to paint for color pair 0. * * see also the system manual for default_colors(3) */ static VALUE curses_assume_default_colors(VALUE obj, VALUE fg, VALUE bg) { curses_stdscr(); assume_default_colors(NUM2INT(fg), NUM2INT(bg)); return Qnil; } #else #define curses_assume_default_colors rb_f_notimplement #endif #if defined(HAVE_TABSIZE) /* * Document-method: Curses.TABSIZE= * call-seq: TABSIZE=(value) * * Sets the TABSIZE to Integer +value+ */ static VALUE curses_tabsize_set(VALUE obj, VALUE val) { TABSIZE = NUM2INT(val); return INT2NUM(TABSIZE); } #else #define curses_tabsize_set rb_f_notimplement #endif #if defined(HAVE_TABSIZE) /* * Returns the number of positions in a tab. */ static VALUE curses_tabsize_get(VALUE ojb) { return INT2NUM(TABSIZE); } #else #define curses_tabsize_get rb_f_notimplement #endif #if defined(HAVE_ESCDELAY) /* * call-seq: Curses.ESCDELAY=(value) * * Sets the ESCDELAY to Integer +value+ */ static VALUE curses_escdelay_set(VALUE obj, VALUE val) { ESCDELAY = NUM2INT(val); return INT2NUM(ESCDELAY); } #else #define curses_escdelay_set rb_f_notimplement #endif #if defined(HAVE_ESCDELAY) /* * Returns the total time, in milliseconds, for which * curses will await a character sequence, e.g., a function key */ static VALUE curses_escdelay_get(VALUE obj) { return INT2NUM(ESCDELAY); } #else #define curses_escdelay_get rb_f_notimplement #endif /* * Document-method: Curses.resize * call-seq: resize(lines, cols) * * alias for Curses.resizeterm * */ /* * Document-method: Curses.resizeterm * call-seq: resizeterm(lines, cols) * * Resize the current term to Fixnum +lines+ and Fixnum +cols+ * */ static VALUE curses_resizeterm(VALUE obj, VALUE lin, VALUE col) { #if defined(HAVE_RESIZETERM) curses_stdscr(); return (resizeterm(NUM2INT(lin),NUM2INT(col)) == OK) ? Qtrue : Qfalse; #else return Qnil; #endif } #ifdef USE_COLOR /* * Document-method: Curses.start_color * * Initializes the color attributes, for terminals that support it. * * This must be called, in order to use color attributes. * It is good practice to call it just after Curses.init_screen */ static VALUE curses_start_color(VALUE obj) { /* may have to raise exception on ERR */ curses_stdscr(); return (start_color() == OK) ? Qtrue : Qfalse; } /* * Document-method: Curses.init_pair * call-seq: init_pair(pair, f, b) * * Changes the definition of a color-pair. * * It takes three arguments: the number of the color-pair to be changed +pair+, * the foreground color number +f+, and the background color number +b+. * * If the color-pair was previously initialized, the screen is * refreshed and all occurrences of that color-pair are changed * to the new definition. * */ static VALUE curses_init_pair(VALUE obj, VALUE pair, VALUE f, VALUE b) { /* may have to raise exception on ERR */ curses_stdscr(); return (init_pair(NUM2INT(pair),NUM2INT(f),NUM2INT(b)) == OK) ? Qtrue : Qfalse; } /* * Document-method: Curses.init_color * call-seq: init_color(color, r, g, b) * * Changes the definition of a color. It takes four arguments: * * the number of the color to be changed, +color+ * * the amount of red, +r+ * * the amount of green, +g+ * * the amount of blue, +b+ * * The value of the first argument must be between 0 and COLORS. * (See the section Colors for the default color index.) Each * of the last three arguments must be a value between 0 and 1000. * When Curses.init_color is used, all occurrences of that color * on the screen immediately change to the new definition. */ static VALUE curses_init_color(VALUE obj, VALUE color, VALUE r, VALUE g, VALUE b) { /* may have to raise exception on ERR */ curses_stdscr(); return (init_color(NUM2INT(color),NUM2INT(r), NUM2INT(g),NUM2INT(b)) == OK) ? Qtrue : Qfalse; } /* * Document-method: Curses.has_colors? * * Returns +true+ or +false+ depending on whether the terminal has color capabilities. */ static VALUE curses_has_colors(VALUE obj) { curses_stdscr(); return has_colors() ? Qtrue : Qfalse; } /* * Document-method: Curses.can_change_color? * * Returns +true+ or +false+ depending on whether the terminal can change color attributes */ static VALUE curses_can_change_color(VALUE obj) { curses_stdscr(); return can_change_color() ? Qtrue : Qfalse; } #if defined(HAVE_COLORS) /* * Document-method: Curses.color * * returns COLORS */ static VALUE curses_colors(VALUE obj) { return INT2FIX(COLORS); } #else #define curses_colors rb_f_notimplement #endif /* * Document-method: Curses.color_content * call-seq: color_content(color) * * Returns an 3 item Array of the RGB values in +color+ */ static VALUE curses_color_content(VALUE obj, VALUE color) { short r,g,b; curses_stdscr(); color_content(NUM2INT(color),&r,&g,&b); return rb_ary_new3(3,INT2FIX(r),INT2FIX(g),INT2FIX(b)); } #if defined(HAVE_COLOR_PAIRS) /* * Document-method: Curses.color_pairs * * Returns the COLOR_PAIRS available, if the curses library supports it. */ static VALUE curses_color_pairs(VALUE obj) { return INT2FIX(COLOR_PAIRS); } #else #define curses_color_pairs rb_f_notimplement #endif /* * Document-method: Curses.pair_content * call-seq: pair_content(pair) * * Returns a 2 item Array, with the foreground and * background color, in +pair+ */ static VALUE curses_pair_content(VALUE obj, VALUE pair) { short f,b; curses_stdscr(); pair_content(NUM2INT(pair),&f,&b); return rb_ary_new3(2,INT2FIX(f),INT2FIX(b)); } /* * Document-method: Curses.color_pair * call-seq: color_pair(attrs) * * Sets the color pair attributes to +attrs+. * * This should be equivalent to Curses.attrset(COLOR_PAIR(+attrs+)) * * TODO: validate that equivalency */ static VALUE curses_color_pair(VALUE obj, VALUE attrs) { return INT2FIX(COLOR_PAIR(NUM2INT(attrs))); } /* * Document-method: Curses.pair_number * call-seq: pair_number(attrs) * * Returns the Fixnum color pair number of attributes +attrs+. */ static VALUE curses_pair_number(VALUE obj, VALUE attrs) { curses_stdscr(); return INT2FIX(PAIR_NUMBER(NUM2LONG(attrs))); } #endif /* USE_COLOR */ #ifdef USE_MOUSE struct mousedata { MEVENT *mevent; }; static void no_mevent(void) { rb_raise(rb_eRuntimeError, "no such mouse event"); } #define GetMOUSE(obj, data) do {\ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\ rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\ TypedData_Get_Struct((obj), struct mousedata, &mousedata_type, (data));\ if ((data)->mevent == 0) no_mevent();\ } while (0) static void curses_mousedata_free(void *p) { struct mousedata *mdata = p; if (mdata->mevent) xfree(mdata->mevent); } static size_t curses_mousedata_memsize(const void *p) { const struct mousedata *mdata = p; size_t size = sizeof(*mdata); if (!mdata) return 0; if (mdata->mevent) size += sizeof(mdata->mevent); return size; } static const rb_data_type_t mousedata_type = { "mousedata", {0, curses_mousedata_free, curses_mousedata_memsize,} }; /* * Document-method: Curses.getmouse * * Returns coordinates of the mouse. * * This will read and pop the mouse event data off the queue * * See the BUTTON*, ALL_MOUSE_EVENTS and REPORT_MOUSE_POSITION constants, to examine the mask of the event */ static VALUE curses_getmouse(VALUE obj) { struct mousedata *mdata; VALUE val; curses_stdscr(); val = TypedData_Make_Struct(cMouseEvent,struct mousedata, &mousedata_type,mdata); mdata->mevent = (MEVENT*)xmalloc(sizeof(MEVENT)); return (getmouse(mdata->mevent) == OK) ? val : Qnil; } /* * Document-method: Curses.ungetmouse * * It pushes a KEY_MOUSE event onto the input queue, and associates with that * event the given state data and screen-relative character-cell coordinates. * * The Curses.ungetmouse function behaves analogously to Curses.ungetch. */ static VALUE curses_ungetmouse(VALUE obj, VALUE mevent) { struct mousedata *mdata; curses_stdscr(); GetMOUSE(mevent,mdata); return (ungetmouse(mdata->mevent) == OK) ? Qtrue : Qfalse; } /* * Document-method: Curses.mouseinterval * call-seq: mouseinterval(interval) * * The Curses.mouseinterval function sets the maximum time * (in thousands of a second) that can elapse between press * and release events for them to be recognized as a click. * * Use Curses.mouseinterval(0) to disable click resolution. * This function returns the previous interval value. * * Use Curses.mouseinterval(-1) to obtain the interval without * altering it. * * The default is one sixth of a second. */ static VALUE curses_mouseinterval(VALUE obj, VALUE interval) { curses_stdscr(); return mouseinterval(NUM2INT(interval)) ? Qtrue : Qfalse; } /* * Document-method: Curses.mousemask * call-seq: mousemask(mask) * * Returns the +mask+ of the reportable events */ static VALUE curses_mousemask(VALUE obj, VALUE mask) { curses_stdscr(); return INT2NUM(mousemask(NUM2UINT(mask),NULL)); } #define DEFINE_MOUSE_GET_MEMBER(func_name,mem) \ static VALUE func_name (VALUE mouse) \ { \ struct mousedata *mdata; \ GetMOUSE(mouse, mdata); \ return (UINT2NUM(mdata->mevent -> mem)); \ } /* * Document-method: Curses::MouseEvent.eid * * Returns the current mouse id */ DEFINE_MOUSE_GET_MEMBER(curs_mouse_id, id) /* * Document-method: Curses::MouseEvent.x * * Returns the current mouse's X coordinate */ DEFINE_MOUSE_GET_MEMBER(curs_mouse_x, x) /* * Document-method: Curses::MouseEvent.y * * Returns the current mouse's Y coordinate */ DEFINE_MOUSE_GET_MEMBER(curs_mouse_y, y) /* * Document-method: Curses::MouseEvent.z * * Returns the current mouse's Z coordinate */ DEFINE_MOUSE_GET_MEMBER(curs_mouse_z, z) /* * Document-method: Curses::MouseEvent.bstate * * Returns the current mouse's button state. Use this with the button state * constants to determine which buttons were pressed. */ DEFINE_MOUSE_GET_MEMBER(curs_mouse_bstate, bstate) #undef define_curs_mouse_member #endif /* USE_MOUSE */ #ifdef HAVE_TIMEOUT /* * Document-method: Curses.timeout= * call-seq: timeout=(delay) * * Sets block and non-blocking reads for the window. * - If delay is negative, blocking read is used (i.e., waits indefinitely for input). * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting). * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input. * */ static VALUE curses_timeout(VALUE obj, VALUE delay) { curses_stdscr(); timeout(NUM2INT(delay)); return Qnil; } #else #define curses_timeout rb_f_notimplement #endif #ifdef HAVE_DEF_PROG_MODE /* * Document-method: Curses.def_prog_mode * * Save the current terminal modes as the "program" * state for use by the Curses.reset_prog_mode * * This is done automatically by Curses.init_screen */ static VALUE curses_def_prog_mode(VALUE obj) { curses_stdscr(); return def_prog_mode() == OK ? Qtrue : Qfalse; } #else #define curses_def_prog_mode rb_f_notimplement #endif #ifdef HAVE_RESET_PROG_MODE /* * Document-method: Curses.reset_prog_mode * * Reset the current terminal modes to the saved state * by the Curses.def_prog_mode * * This is done automatically by Curses.close_screen */ static VALUE curses_reset_prog_mode(VALUE obj) { curses_stdscr(); return reset_prog_mode() == OK ? Qtrue : Qfalse; } #else #define curses_reset_prog_mode rb_f_notimplement #endif /*-------------------------- class Window --------------------------*/ /* returns a Curses::Window object */ static VALUE window_s_allocate(VALUE class) { struct windata *winp; return TypedData_Make_Struct(class, struct windata, &windata_type, winp); } /* * Document-method: Curses::Window.new * call-seq: new(height, width, top, left) * * Construct a new Curses::Window with constraints of * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column. * * A new window using full screen is called as * Curses::Window.new(0,0,0,0) * */ static VALUE window_initialize(VALUE obj, VALUE h, VALUE w, VALUE top, VALUE left) { struct windata *winp; WINDOW *window; curses_init_screen(); TypedData_Get_Struct(obj, struct windata, &windata_type, winp); if (winp->window) delwin(winp->window); window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left)); wclear(window); winp->window = window; return obj; } /* * Document-method: Curses::Window.subwin * call-seq: subwin(height, width, top, left) * * Construct a new subwindow with constraints of * +height+ lines, +width+ columns, begin at +top+ line, and begin +left+ most column. * */ static VALUE window_subwin(VALUE obj, VALUE height, VALUE width, VALUE top, VALUE left) { struct windata *winp; WINDOW *window; VALUE win; int h, w, t, l; h = NUM2INT(height); w = NUM2INT(width); t = NUM2INT(top); l = NUM2INT(left); GetWINDOW(obj, winp); window = subwin(winp->window, h, w, t, l); win = prep_window(rb_obj_class(obj), window); return win; } /* * Document-method: Curses::Window.close * * Deletes the window, and frees the memory */ static VALUE window_close(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); delwin(winp->window); winp->window = 0; return Qnil; } /* * Document-method: Curses::Window.clear * * Clear the window. */ static VALUE window_clear(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wclear(winp->window); return Qnil; } #ifdef HAVE_WERASE /* * Document-method: Curses::Window.erase * * Erase the window. */ static VALUE window_erase(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); werase(winp->window); return Qnil; } #else #define curses_erase rb_f_notimplement #endif /* * Document-method: Curses::Window.clrtoeol * * Clear the window to the end of line, that the cursor is currently on. */ static VALUE window_clrtoeol(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wclrtoeol(winp->window); return Qnil; } /* * Document-method: Curses::Window.refresh * * Refreshes the windows and lines. * */ static VALUE window_refresh(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wrefresh(winp->window); return Qnil; } /* * Document-method: Curses::Window.noutrefresh * * Refreshes the windows and lines. * * Curses::Window.noutrefresh allows multiple updates with * more efficiency than Curses::Window.refresh alone. */ static VALUE window_noutrefresh(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); #ifdef HAVE_DOUPDATE wnoutrefresh(winp->window); #else wrefresh(winp->window); #endif return Qnil; } #ifdef HAVE_REDRAWWIN /* * Document-method: Curses::Window.redraw * * Redraws the entire window. */ static VALUE window_redraw(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); redrawwin(winp->window); return Qnil; } #else #define window_redraw rb_f_notimplement #endif #ifdef HAVE_TOUCHWIN /* * Document-method: Curses::Window.touch * * Treat the window as if it has been modified since the last call of refresh. */ static VALUE window_touch(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); touchwin(winp->window); return Qnil; } #else #define window_touch rb_f_notimplement #endif #ifdef HAVE_UNTOUCHWIN /* * Document-method: Curses::Window.untouch * * Treat the window as if it has not been modified since the last call of * refresh. */ static VALUE window_untouch(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); untouchwin(winp->window); return Qnil; } #else #define window_touch rb_f_notimplement #endif #ifdef HAVE_IS_WINTOUCHED /* * Document-method: Curses::Window.touched? * * Return true if the window has been modified since the last call of refresh. */ static VALUE window_touched(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); return is_wintouched(winp->window) ? Qtrue : Qfalse; } #else #define window_touched rb_f_notimplement #endif #ifdef HAVE_WTOUCHLN /* * Document-method: Curses::Window.touch_line * call-seq: touch_line(y, n, changed = true) * * Make n lines from line y look as if they have (changed = true) or have not * (changed = false) been modified since the last call of refresh. */ static VALUE window_touch_line(int argc, VALUE *argv, VALUE obj) { struct windata *winp; VALUE y, n, changed; int result; rb_scan_args(argc, argv, "12", &y, &n, &changed); if (argc < 2) { n = INT2NUM(1); } if (argc < 3) { changed = Qtrue; } GetWINDOW(obj, winp); result = wtouchln(winp->window, NUM2INT(y), NUM2INT(n), RTEST(changed)); if (result == ERR) { rb_raise(rb_eRangeError, "Out of window"); } return Qnil; } #else #define window_touch_line rb_f_notimplement #endif #ifdef HAVE_IS_LINETOUCHED /* * Document-method: Curses::Window.line_touched? * call-seq: line_touched?(line) * * Return true if the specified line has been modified since the last call of * refresh. */ static VALUE window_line_touched(VALUE obj, VALUE line) { struct windata *winp; int result, n; GetWINDOW(obj, winp); n = NUM2INT(line); result = is_linetouched(winp->window, n); if (result == ERR) { rb_raise(rb_eArgError, "Invalid line %d", n); } return result ? Qtrue : Qfalse; } #else #define window_line_touched rb_f_notimplement #endif /* * Document-method: Curses::Window.move * call-seq: move(y,x) * * Moves the window so that the upper left-hand corner is at position (+y+, +x+) */ static VALUE window_move(VALUE obj, VALUE y, VALUE x) { struct windata *winp; GetWINDOW(obj, winp); mvwin(winp->window, NUM2INT(y), NUM2INT(x)); return Qnil; } /* * Document-method: Curses::Window.setpos * call-seq: setpos(y, x) * * A setter for the position of the cursor * in the current window, * using coordinates +x+ and +y+ * */ static VALUE window_setpos(VALUE obj, VALUE y, VALUE x) { struct windata *winp; GetWINDOW(obj, winp); wmove(winp->window, NUM2INT(y), NUM2INT(x)); return Qnil; } /* * Document-method: Curses::Window.cury * * A getter for the current line (Y coord) of the window */ static VALUE window_cury(VALUE obj) { struct windata *winp; int RB_UNUSED_VAR(x), y; GetWINDOW(obj, winp); getyx(winp->window, y, x); return INT2FIX(y); } /* * Document-method: Curses::Window.curx * * A getter for the current column (X coord) of the window */ static VALUE window_curx(VALUE obj) { struct windata *winp; int x, RB_UNUSED_VAR(y); GetWINDOW(obj, winp); getyx(winp->window, y, x); return INT2FIX(x); } /* * Document-method: Curses::Window.maxy * * A getter for the maximum lines for the window */ static VALUE window_maxy(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); #if defined(getmaxy) return INT2FIX(getmaxy(winp->window)); #elif defined(getmaxyx) { int RB_UNUSED_VAR(x), y; getmaxyx(winp->window, y, x); return INT2FIX(y); } #else return INT2FIX(winp->window->_maxy+1); #endif } /* * Document-method: Curses::Window.maxx * * A getter for the maximum columns for the window */ static VALUE window_maxx(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); #if defined(getmaxx) return INT2FIX(getmaxx(winp->window)); #elif defined(getmaxyx) { int x, RB_UNUSED_VAR(y); getmaxyx(winp->window, y, x); return INT2FIX(x); } #else return INT2FIX(winp->window->_maxx+1); #endif } /* * Document-method: Curses::Window.begy * * A getter for the beginning line (Y coord) of the window */ static VALUE window_begy(VALUE obj) { struct windata *winp; int RB_UNUSED_VAR(x), y; GetWINDOW(obj, winp); #ifdef getbegyx getbegyx(winp->window, y, x); #else y = winp->window->_begy; #endif return INT2FIX(y); } /* * Document-method: Curses::Window.begx * * A getter for the beginning column (X coord) of the window */ static VALUE window_begx(VALUE obj) { struct windata *winp; int x, RB_UNUSED_VAR(y); GetWINDOW(obj, winp); #ifdef getbegyx getbegyx(winp->window, y, x); #else x = winp->window->_begx; #endif return INT2FIX(x); } /* * Document-method: Curses::Window.box * call-seq: box(vert, hor) * * set the characters to frame the window in. * The vertical +vert+ and horizontal +hor+ character. * * win = Curses::Window.new(5,5,5,5) * win.box(?|, ?-) * */ static VALUE window_box(int argc, VALUE *argv, VALUE self) { struct windata *winp; VALUE vert, hor, corn; rb_scan_args(argc, argv, "21", &vert, &hor, &corn); GetWINDOW(self, winp); box(winp->window, NUM2CH(vert), NUM2CH(hor)); if (!NIL_P(corn)) { int cur_x, cur_y, x, y; chtype c; c = NUM2CH(corn); getyx(winp->window, cur_y, cur_x); x = NUM2INT(window_maxx(self)) - 1; y = NUM2INT(window_maxy(self)) - 1; wmove(winp->window, 0, 0); waddch(winp->window, c); wmove(winp->window, y, 0); waddch(winp->window, c); wmove(winp->window, y, x); waddch(winp->window, c); wmove(winp->window, 0, x); waddch(winp->window, c); wmove(winp->window, cur_y, cur_x); } return Qnil; } /* * Document-method: Curses::Window.standout * * Enables the best highlighting mode of the terminal. * * This is equivalent to Curses::Window.attron(A_STANDOUT) * * see also Curses::Window.attrset */ static VALUE window_standout(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wstandout(winp->window); return Qnil; } /* * Document-method: Curses::Window.standend * * Enables the Normal display (no highlight) * * This is equivalent to Curses::Window.attron(A_NORMAL) * * see also Curses::Window.attrset */ static VALUE window_standend(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wstandend(winp->window); return Qnil; } /* * Document-method: Curses::Window.inch * * Returns the character at the current position of the window. */ static VALUE window_inch(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); return CH2FIX(winch(winp->window)); } /* * Document-method: Curses::Window.addch * call-seq: addch(ch) * * Add a character +ch+, with attributes, to the window, then advance the cursor. * * see also the system manual for curs_addch(3) */ static VALUE window_addch(VALUE obj, VALUE ch) { struct windata *winp; GetWINDOW(obj, winp); waddch(winp->window, NUM2CH(ch)); return Qnil; } /* * Document-method: Curses::Window.insch * call-seq: insch(ch) * * Insert a character +ch+, before the cursor, in the current window * */ static VALUE window_insch(VALUE obj, VALUE ch) { struct windata *winp; GetWINDOW(obj, winp); winsch(winp->window, NUM2CH(ch)); return Qnil; } /* * Document-method: Curses::Window.addstr * call-seq: addstr(str) * * add a string of characters +str+, to the window and advance cursor * */ static VALUE window_addstr(VALUE obj, VALUE str) { if (!NIL_P(str)) { struct windata *winp; StringValue(str); #if defined(HAVE_WADDNWSTR) && defined(_WIN32) str = rb_str_export_to_enc(str, get_wide_encoding()); GetWINDOW(obj, winp); waddnwstr(winp->window, (wchar_t *)RSTRING_PTR(str), RSTRING_LEN(str) / sizeof(wchar_t)); #else str = rb_str_export_to_enc(str, terminal_encoding); GetWINDOW(obj, winp); waddstr(winp->window, StringValueCStr(str)); #endif } return Qnil; } /* * Document-method: Curses::Window.<< * * call-seq: * <<(str) * * Add String +str+ to the current string. * * See also Curses::Window.addstr */ static VALUE window_addstr2(VALUE obj, VALUE str) { window_addstr(obj, str); return obj; } struct wgetch_arg { WINDOW *win; int c; }; static void * wgetch_func(void *_arg) { struct wgetch_arg *arg = (struct wgetch_arg *)_arg; arg->c = wgetch(arg->win); return 0; } /* * Document-method: Curses::Window.getch * * Read and returns a character from the window. * * See Curses::Key to all the function KEY_* available * */ static VALUE window_getch(VALUE obj) { struct windata *winp; struct wgetch_arg arg; int c; GetWINDOW(obj, winp); arg.win = winp->window; rb_thread_call_without_gvl(wgetch_func, (void *)&arg, RUBY_UBF_IO, 0); c = arg.c; if (c == EOF) return Qnil; if (rb_isprint(c)) { char ch = (char)c; return rb_external_str_new_with_enc(&ch, 1, keyboard_encoding); } return UINT2NUM(c); } struct wgetstr_arg { WINDOW *win; char rtn[GETSTR_BUF_SIZE]; }; static void * wgetstr_func(void *_arg) { struct wgetstr_arg *arg = (struct wgetstr_arg *)_arg; #if defined(HAVE_WGETNSTR) wgetnstr(arg->win, arg->rtn, GETSTR_BUF_SIZE-1); #else wgetstr(arg->win, arg->rtn); #endif return 0; } /* * Document-method: Curses::Window.getstr * * This is equivalent to a series f Curses::Window.getch calls * */ static VALUE window_getstr(VALUE obj) { struct windata *winp; struct wgetstr_arg arg; GetWINDOW(obj, winp); arg.win = winp->window; rb_thread_call_without_gvl(wgetstr_func, (void *)&arg, RUBY_UBF_IO, 0); return rb_external_str_new_with_enc(arg.rtn, strlen(arg.rtn), keyboard_encoding); } /* * Document-method: Curses::Window.delch * * Delete the character under the cursor * */ static VALUE window_delch(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); wdelch(winp->window); return Qnil; } /* * Document-method: Curses::Window.deleteln * * Delete the line under the cursor. * */ static VALUE window_deleteln(VALUE obj) { #if defined(HAVE_WDELETELN) || defined(wdeleteln) struct windata *winp; GetWINDOW(obj, winp); wdeleteln(winp->window); #endif return Qnil; } /* * Document-method: Curses::Window.insertln * * Inserts a line above the cursor, and the bottom line is lost * */ static VALUE window_insertln(VALUE obj) { #if defined(HAVE_WINSERTLN) || defined(winsertln) struct windata *winp; GetWINDOW(obj, winp); winsertln(winp->window); #endif return Qnil; } /* * Document-method: Curses::Window.scrollok * call-seq: scrollok(bool) * * Controls what happens when the cursor of a window * is moved off the edge of the window or scrolling region, * either as a result of a newline action on the bottom line, * or typing the last character of the last line. * * If disabled, (+bool+ is false), the cursor is left on the bottom line. * * If enabled, (+bool+ is true), the window is scrolled up one line * (Note that to get the physical scrolling effect on the terminal, * it is also necessary to call Curses::Window.idlok) */ static VALUE window_scrollok(VALUE obj, VALUE bf) { struct windata *winp; GetWINDOW(obj, winp); scrollok(winp->window, RTEST(bf) ? TRUE : FALSE); return Qnil; } /* * Document-method: Curses::Window.idlok * call-seq: idlok(bool) * * If +bool+ is +true+ curses considers using the hardware insert/delete * line feature of terminals so equipped. * * If +bool+ is +false+, disables use of line insertion and deletion. * This option should be enabled only if the application needs insert/delete * line, for example, for a screen editor. * * It is disabled by default because insert/delete line tends to be visually * annoying when used in applications where it is not really needed. * If insert/delete line cannot be used, curses redraws the changed portions of all lines. * */ static VALUE window_idlok(VALUE obj, VALUE bf) { struct windata *winp; GetWINDOW(obj, winp); idlok(winp->window, RTEST(bf) ? TRUE : FALSE); return Qnil; } /* * Document-method: Curses::Window.setscrreg * call-seq: * setscrreg(top, bottom) * * Set a software scrolling region in a window. * +top+ and +bottom+ are lines numbers of the margin. * * If this option and Curses::Window.scrollok are enabled, an attempt to move * off the bottom margin line causes all lines in the scrolling region to * scroll one line in the direction of the first line. Only the text of the * window is scrolled. * */ static VALUE window_setscrreg(VALUE obj, VALUE top, VALUE bottom) { #ifdef HAVE_WSETSCRREG struct windata *winp; int res; GetWINDOW(obj, winp); res = wsetscrreg(winp->window, NUM2INT(top), NUM2INT(bottom)); /* may have to raise exception on ERR */ return (res == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET) /* * Document-method: Curses::Window.color_set * call-seq: color_set(col) * * Sets the current color of the given window to the * foreground/background combination described by the Fixnum +col+. */ static VALUE window_color_set(VALUE obj, VALUE col) { struct windata *winp; int res; GetWINDOW(obj, winp); res = wcolor_set(winp->window, NUM2INT(col), NULL); return (res == OK) ? Qtrue : Qfalse; } #endif /* defined(USE_COLOR) && defined(HAVE_WCOLOR_SET) */ /* * Document-method: Curses::Window.scroll * * Scrolls the current window up one line. */ static VALUE window_scroll(VALUE obj) { struct windata *winp; GetWINDOW(obj, winp); /* may have to raise exception on ERR */ return (scroll(winp->window) == OK) ? Qtrue : Qfalse; } /* * Document-method: Curses::Window.scrl * call-seq: scrl(num) * * Scrolls the current window Fixnum +num+ lines. * The current cursor position is not changed. * * For positive +num+, it scrolls up. * * For negative +num+, it scrolls down. * */ static VALUE window_scrl(VALUE obj, VALUE n) { #ifdef HAVE_WSCRL struct windata *winp; GetWINDOW(obj, winp); /* may have to raise exception on ERR */ return (wscrl(winp->window,NUM2INT(n)) == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } /* * Document-method: Curses::Window.attroff * call-seq: attroff(attrs) * * Turns off the named attributes +attrs+ * without affecting any others. * * See also Curses::Window.attrset */ static VALUE window_attroff(VALUE obj, VALUE attrs) { #ifdef HAVE_WATTROFF struct windata *winp; GetWINDOW(obj,winp); return INT2FIX(wattroff(winp->window,NUM2INT(attrs))); #else return Qtrue; #endif } /* * Document-method: Curses::Window.attron * call-seq: attron(attrs) * * Turns on the named attributes +attrs+ * without turning any other attributes on or off. * * See also Curses::Window.attrset */ static VALUE window_attron(VALUE obj, VALUE attrs) { #ifdef HAVE_WATTRON struct windata *winp; VALUE val; GetWINDOW(obj,winp); val = INT2FIX(wattron(winp->window,NUM2INT(attrs))); if (rb_block_given_p()) { rb_yield(val); wattroff(winp->window,NUM2INT(attrs)); return val; } else{ return val; } #else return Qtrue; #endif } /* * Document-method: Curses::Window.attrset * call-seq: attrset(attrs) * * Sets the current attributes of the given window to +attrs+. * * The following video attributes, defined in , can * be passed to the routines Curses::Window.attron, Curses::Window.attroff, * and Curses::Window.attrset, or OR'd with the characters passed to addch. * A_NORMAL Normal display (no highlight) * A_STANDOUT Best highlighting mode of the terminal. * A_UNDERLINE Underlining * A_REVERSE Reverse video * A_BLINK Blinking * A_DIM Half bright * A_BOLD Extra bright or bold * A_PROTECT Protected mode * A_INVIS Invisible or blank mode * A_ALTCHARSET Alternate character set * A_CHARTEXT Bit-mask to extract a character * COLOR_PAIR(n) Color-pair number n * * TODO: provide some examples here. * * see also system manual curs_attr(3) */ static VALUE window_attrset(VALUE obj, VALUE attrs) { #ifdef HAVE_WATTRSET struct windata *winp; GetWINDOW(obj,winp); return INT2FIX(wattrset(winp->window,NUM2INT(attrs))); #else return Qtrue; #endif } /* * Document-method: Curses::Window.bkgdset * call-seq: bkgdset(ch) * * Manipulate the background of the current window * with character Integer +ch+ * * see also Curses.bkgdset */ static VALUE window_bkgdset(VALUE obj, VALUE ch) { #ifdef HAVE_WBKGDSET struct windata *winp; GetWINDOW(obj,winp); wbkgdset(winp->window, NUM2CHTYPE(ch)); #endif return Qnil; } /* * Document-method: Curses::Window.bkgd * call-seq: bkgd(ch) * * Set the background of the current window * and apply character Integer +ch+ to every character. * * see also Curses.bkgd */ static VALUE window_bkgd(VALUE obj, VALUE ch) { #ifdef HAVE_WBKGD struct windata *winp; GetWINDOW(obj,winp); return (wbkgd(winp->window, NUM2CHTYPE(ch)) == OK) ? Qtrue : Qfalse; #else return Qfalse; #endif } /* * Document-method: Curses::Window.getbkgd * * Returns an Integer (+ch+) for the character property in the current window. */ static VALUE window_getbkgd(VALUE obj) { #ifdef HAVE_WGETBKGD chtype c; struct windata *winp; GetWINDOW(obj,winp); return (c = getbkgd(winp->window) != ERR) ? ULONG2NUM(c) : Qnil; #else return Qnil; #endif } /* * Document-method: Curses::Window.resize * call-seq: resize(lines, cols) * * Resize the current window to Fixnum +lines+ and Fixnum +cols+ * */ static VALUE window_resize(VALUE obj, VALUE lin, VALUE col) { #if defined(HAVE_WRESIZE) struct windata *winp; GetWINDOW(obj,winp); return wresize(winp->window, NUM2INT(lin), NUM2INT(col)) == OK ? Qtrue : Qfalse; #else return Qnil; #endif } #ifdef HAVE_KEYPAD /* * Document-method: Curses::Window.keypad= * call-seq: * keypad=(bool) * * See Curses::Window.keypad */ /* * Document-method: Curses::Window.keypad * call-seq: * keypad(bool) * * Enables the keypad of the user's terminal. * * If enabled (+bool+ is +true+), the user can press a function key * (such as an arrow key) and wgetch returns a single value representing * the function key, as in KEY_LEFT. If disabled (+bool+ is +false+), * curses does not treat function keys specially and the program has to * interpret the escape sequences itself. If the keypad in the terminal * can be turned on (made to transmit) and off (made to work locally), * turning on this option causes the terminal keypad to be turned on when * Curses::Window.getch is called. * * The default value for keypad is false. * */ static VALUE window_keypad(VALUE obj, VALUE val) { struct windata *winp; GetWINDOW(obj,winp); /* keypad() of NetBSD's libcurses returns no value */ #if defined(__NetBSD__) && !defined(NCURSES_VERSION) keypad(winp->window,(RTEST(val) ? TRUE : FALSE)); return Qnil; #else /* may have to raise exception on ERR */ return (keypad(winp->window,RTEST(val) ? TRUE : FALSE)) == OK ? Qtrue : Qfalse; #endif } #else #define window_keypad rb_f_notimplement #endif #ifdef HAVE_NODELAY /* * Document-method: Curses::Window.nodelay * call-seq: * window.nodelay = bool * * When in no-delay mode Curses::Window#getch is a non-blocking call. If no * input is ready #getch returns ERR. * * When in delay mode (+bool+ is +false+ which is the default), * Curses::Window#getch blocks until a key is pressed. * */ static VALUE window_nodelay(VALUE obj, VALUE val) { struct windata *winp; GetWINDOW(obj,winp); /* nodelay() of NetBSD's libcurses returns no value */ #if defined(__NetBSD__) && !defined(NCURSES_VERSION) nodelay(winp->window, RTEST(val) ? TRUE : FALSE); return Qnil; #else return nodelay(winp->window,RTEST(val) ? TRUE : FALSE) == OK ? Qtrue : Qfalse; #endif } #else #define window_nodelay rb_f_notimplement #endif #ifdef HAVE_WTIMEOUT /* * Document-method: Curses::Window.timeout= * call-seq: timeout=(delay) * * Sets block and non-blocking reads for the window. * - If delay is negative, blocking read is used (i.e., waits indefinitely for input). * - If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting). * - If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input. * */ static VALUE window_timeout(VALUE obj, VALUE delay) { struct windata *winp; GetWINDOW(obj,winp); wtimeout(winp->window,NUM2INT(delay)); return Qnil; } #else #define window_timeout rb_f_notimplement #endif /*--------------------------- class Pad ----------------------------*/ #ifdef HAVE_NEWPAD /* * Document-method: Curses::Pad.new * * call-seq: * new(height, width) * * Construct a new Curses::Pad with constraints of +height+ lines, +width+ * columns * */ static VALUE pad_initialize(VALUE obj, VALUE h, VALUE w) { struct windata *padp; WINDOW *window; curses_init_screen(); TypedData_Get_Struct(obj, struct windata, &windata_type, padp); if (padp->window) delwin(padp->window); window = newpad(NUM2INT(h), NUM2INT(w)); wclear(window); padp->window = window; return obj; } /* * Document-method: Curses::Pad.subpad * call-seq: * subpad(height, width, begin_x, begin_y) * * Construct a new subpad with constraints of +height+ lines, +width+ columns, * begin at +begin_x+ line, and +begin_y+ columns on the pad. * */ static VALUE pad_subpad(VALUE obj, VALUE height, VALUE width, VALUE begin_x, VALUE begin_y) { struct windata *padp; WINDOW *sub_pad; VALUE pad; int h, w, x, y; h = NUM2INT(height); w = NUM2INT(width); x = NUM2INT(begin_x); y = NUM2INT(begin_y); GetWINDOW(obj, padp); sub_pad = subpad(padp->window, h, w, x, y); pad = prep_window(rb_obj_class(obj), sub_pad); return pad; } /* * Document-method: Curses::Pad.refresh * * call-seq: * pad.refresh(pad_minrow, pad_mincol, screen_minrow, screen_mincol, screen_maxrow, screen_maxcol) * * Refreshes the pad. +pad_minrow+ and pad_mincol+ define the upper-left * corner of the rectangle to be displayed. +screen_minrow+, +screen_mincol+, * +screen_maxrow+, +screen_maxcol+ define the edges of the rectangle to be * displayed on the screen. * */ static VALUE pad_refresh(VALUE obj, VALUE pminrow, VALUE pmincol, VALUE sminrow, VALUE smincol, VALUE smaxrow, VALUE smaxcol) { struct windata *padp; int pmr, pmc, smr, smc, sxr, sxc; pmr = NUM2INT(pminrow); pmc = NUM2INT(pmincol); smr = NUM2INT(sminrow); smc = NUM2INT(smincol); sxr = NUM2INT(smaxrow); sxc = NUM2INT(smaxcol); GetWINDOW(obj, padp); prefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc); return Qnil; } /* * Document-method: Curses::Pad.noutrefresh * * call-seq: * pad.noutrefresh(pad_minrow, pad_mincol, screen_minrow, screen_mincol, screen_maxrow, screen_maxcol) * * Refreshes the pad. +pad_minrow+ and pad_mincol+ define the upper-left * corner of the rectangle to be displayed. +screen_minrow+, +screen_mincol+, * +screen_maxrow+, +screen_maxcol+ define the edges of the rectangle to be * displayed on the screen. * */ static VALUE pad_noutrefresh(VALUE obj, VALUE pminrow, VALUE pmincol, VALUE sminrow, VALUE smincol, VALUE smaxrow, VALUE smaxcol) { struct windata *padp; int pmr, pmc, smr, smc, sxr, sxc; pmr = NUM2INT(pminrow); pmc = NUM2INT(pmincol); smr = NUM2INT(sminrow); smc = NUM2INT(smincol); sxr = NUM2INT(smaxrow); sxc = NUM2INT(smaxcol); GetWINDOW(obj, padp); #ifdef HAVE_DOUPDATE pnoutrefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc); #else prefresh(padp->window, pmr, pmc, smr, smc, sxr, sxc); #endif return Qnil; } #endif /* HAVE_NEWPAD */ /* * Document-method: Curses.keyboard_encoding * call-seq: Curses.keyboard_encoding * * Returns the encoding for keyboard input. */ static VALUE curses_get_keyboard_encoding(VALUE obj) { return rb_enc_from_encoding(keyboard_encoding); } /* * Document-method: Curses.keyboard_encoding= * call-seq: Curses.keyboard_encoding = encoding * * Sets the encoding for keyboard input. */ static VALUE curses_set_keyboard_encoding(VALUE obj, VALUE enc) { keyboard_encoding = rb_to_encoding(enc); return enc; } /* * Document-method: Curses.terminal_encoding * call-seq: Curses.terminal_encoding * * Returns the encoding for terminal output. */ static VALUE curses_get_terminal_encoding(VALUE obj) { return rb_enc_from_encoding(terminal_encoding); } /* * Document-method: Curses.terminal_encoding= * call-seq: Curses.terminal_encoding = encoding * * Sets the encoding for terminal output. */ static VALUE curses_set_terminal_encoding(VALUE obj, VALUE enc) { terminal_encoding = rb_to_encoding(enc); return enc; } /* * Document-method: Curses.unget_char * call-seq: unget_char(ch) * * Places +ch+ back onto the input queue to be returned by * the next call to Curses.get_char etc. * * There is just one input queue for all windows. */ static VALUE curses_unget_char(VALUE obj, VALUE ch) { ID id_ord; unsigned int c; curses_stdscr(); if (FIXNUM_P(ch)) { ungetch(NUM2UINT(ch)); } else { StringValue(ch); CONST_ID(id_ord, "ord"); c = NUM2UINT(rb_funcall(ch, id_ord, 0)); #ifdef HAVE_UNGET_WCH unget_wch(c); #else if (c > 0xff) { rb_raise(rb_eRangeError, "Out of range: %u", c); } ungetch(c); #endif } return Qnil; } static VALUE keyboard_uint_chr(unsigned int ch) { return rb_enc_uint_chr(ch, keyboard_encoding); } #ifdef HAVE_GET_WCH struct get_wch_arg { int retval; wint_t ch; }; static void * get_wch_func(void *_arg) { struct get_wch_arg *arg = (struct get_wch_arg *) _arg; arg->retval = get_wch(&arg->ch); return 0; } #endif /* * Document-method: Curses.get_char * * Read and returns a character or function key from the window. * A single or multibyte character is represented by a String, and * a function key is represented by an Integer. * Returns nil if no input is ready. * * See Curses::Key to all the function KEY_* available * */ static VALUE curses_get_char(VALUE obj) { #ifdef HAVE_GET_WCH struct get_wch_arg arg; curses_stdscr(); rb_thread_call_without_gvl(get_wch_func, &arg, RUBY_UBF_IO, 0); switch (arg.retval) { case OK: return keyboard_uint_chr(arg.ch); case KEY_CODE_YES: return UINT2NUM(arg.ch); } return Qnil; #else int c; curses_stdscr(); rb_thread_call_without_gvl(getch_func, &c, RUBY_UBF_IO, 0); if (c > 0xff) { return INT2NUM(c); } else if (c >= 0) { return keyboard_uint_chr(c); } else { return Qnil; } #endif } #ifdef HAVE_WGET_WCH struct wget_wch_arg { WINDOW *win; int retval; wint_t ch; }; static void * wget_wch_func(void *_arg) { struct wget_wch_arg *arg = (struct wget_wch_arg *) _arg; arg->retval = wget_wch(arg->win, &arg->ch); return 0; } #endif /* * Document-method: Curses::Window.get_char * * Read and returns a character or function key from the window. * A single or multibyte character is represented by a String, and * a function key is represented by an Integer. * Returns nil if no input is ready. * * See Curses::Key to all the function KEY_* available * */ static VALUE window_get_char(VALUE obj) { #ifdef HAVE_WGET_WCH struct windata *winp; struct wget_wch_arg arg; GetWINDOW(obj, winp); arg.win = winp->window; rb_thread_call_without_gvl(wget_wch_func, &arg, RUBY_UBF_IO, 0); switch (arg.retval) { case OK: return keyboard_uint_chr(arg.ch); case KEY_CODE_YES: return UINT2NUM(arg.ch); } return Qnil; #else struct windata *winp; struct wgetch_arg arg; GetWINDOW(obj, winp); arg.win = winp->window; rb_thread_call_without_gvl(wgetch_func, (void *)&arg, RUBY_UBF_IO, 0); if (arg.c > 0xff) { return INT2NUM(arg.c); } else if (arg.c >= 0) { return keyboard_uint_chr(arg.c); } else { return Qnil; } #endif } #ifdef HAVE_PDC_GET_KEY_MODIFIERS static VALUE curses_get_key_modifiers(VALUE obj) { return ULONG2NUM(PDC_get_key_modifiers()); } static VALUE curses_return_key_modifiers(VALUE obj, VALUE flag) { return INT2NUM(PDC_return_key_modifiers(RTEST(flag))); } static VALUE curses_save_key_modifiers(VALUE obj, VALUE flag) { return INT2NUM(PDC_save_key_modifiers(RTEST(flag))); } #endif /*------------------------- Initialization -------------------------*/ /* * Document-module: Curses * * == Description * An implementation of the CRT screen handling and optimization library. * * == Structures and such * * === Classes * * * Curses::Window - class with the means to draw a window or box * * Curses::MouseEvent - class for collecting mouse events * * === Modules * * Curses:: The curses implementation * Curses::Key:: Collection of constants for keypress events * * == Examples * * * hello.rb * :include: sample/hello.rb * * * * rain.rb * :include: sample/rain.rb * * */ void Init_curses(void) { #ifdef HAVE_GET_WCH keyboard_encoding = rb_locale_encoding(); #else keyboard_encoding = rb_ascii8bit_encoding(); #endif terminal_encoding = rb_locale_encoding(); mCurses = rb_define_module("Curses"); /* * Document-module: Curses::Key * * * a container for the KEY_* values. * * See also system manual for getch(3) * */ mKey = rb_define_module_under(mCurses, "Key"); rb_gc_register_address(&rb_stdscr); #ifdef USE_MOUSE /* * Document-class: Curses::MouseEvent * * == Description * * Curses::MouseEvent * * == Example * * * mouse.rb * :include: sample/mouse.rb * */ cMouseEvent = rb_define_class_under(mCurses,"MouseEvent",rb_cObject); rb_undef_method(CLASS_OF(cMouseEvent),"new"); rb_define_method(cMouseEvent, "eid", curs_mouse_id, 0); rb_define_method(cMouseEvent, "x", curs_mouse_x, 0); rb_define_method(cMouseEvent, "y", curs_mouse_y, 0); rb_define_method(cMouseEvent, "z", curs_mouse_z, 0); rb_define_method(cMouseEvent, "bstate", curs_mouse_bstate, 0); #endif /* USE_MOUSE */ rb_define_module_function(mCurses, "ESCDELAY=", curses_escdelay_set, 1); rb_define_module_function(mCurses, "ESCDELAY", curses_escdelay_get, 0); rb_define_module_function(mCurses, "TABSIZE", curses_tabsize_get, 0); rb_define_module_function(mCurses, "TABSIZE=", curses_tabsize_set, 1); rb_define_module_function(mCurses, "use_default_colors", curses_use_default_colors, 0); rb_define_module_function(mCurses, "assume_default_colors", curses_assume_default_colors, 2); rb_define_module_function(mCurses, "init_screen", curses_init_screen, 0); rb_define_module_function(mCurses, "close_screen", curses_close_screen, 0); rb_define_module_function(mCurses, "closed?", curses_closed, 0); rb_define_module_function(mCurses, "stdscr", curses_stdscr, 0); rb_define_module_function(mCurses, "refresh", curses_refresh, 0); rb_define_module_function(mCurses, "doupdate", curses_doupdate, 0); rb_define_module_function(mCurses, "clear", curses_clear, 0); rb_define_module_function(mCurses, "erase", curses_erase, 0); rb_define_module_function(mCurses, "clrtoeol", curses_clrtoeol, 0); rb_define_module_function(mCurses, "echo", curses_echo, 0); rb_define_module_function(mCurses, "noecho", curses_noecho, 0); rb_define_module_function(mCurses, "raw", curses_raw, 0); rb_define_module_function(mCurses, "noraw", curses_noraw, 0); rb_define_module_function(mCurses, "cbreak", curses_cbreak, 0); rb_define_module_function(mCurses, "nocbreak", curses_nocbreak, 0); rb_define_module_function(mCurses, "crmode", curses_cbreak, 0); rb_define_module_function(mCurses, "nocrmode", curses_nocbreak, 0); rb_define_module_function(mCurses, "nl", curses_nl, 0); rb_define_module_function(mCurses, "nonl", curses_nonl, 0); rb_define_module_function(mCurses, "beep", curses_beep, 0); rb_define_module_function(mCurses, "flash", curses_flash, 0); rb_define_module_function(mCurses, "ungetch", curses_ungetch, 1); rb_define_module_function(mCurses, "setpos", curses_setpos, 2); rb_define_module_function(mCurses, "standout", curses_standout, 0); rb_define_module_function(mCurses, "standend", curses_standend, 0); rb_define_module_function(mCurses, "inch", curses_inch, 0); rb_define_module_function(mCurses, "addch", curses_addch, 1); rb_define_module_function(mCurses, "insch", curses_insch, 1); rb_define_module_function(mCurses, "addstr", curses_addstr, 1); rb_define_module_function(mCurses, "getch", curses_getch, 0); rb_define_module_function(mCurses, "getstr", curses_getstr, 0); rb_define_module_function(mCurses, "delch", curses_delch, 0); rb_define_module_function(mCurses, "deleteln", curses_deleteln, 0); rb_define_module_function(mCurses, "insertln", curses_insertln, 0); rb_define_module_function(mCurses, "keyname", curses_keyname, 1); rb_define_module_function(mCurses, "lines", curses_lines, 0); rb_define_module_function(mCurses, "cols", curses_cols, 0); rb_define_module_function(mCurses, "curs_set", curses_curs_set, 1); rb_define_module_function(mCurses, "scrl", curses_scrl, 1); rb_define_module_function(mCurses, "setscrreg", curses_setscrreg, 2); rb_define_module_function(mCurses, "attroff", curses_attroff, 1); rb_define_module_function(mCurses, "attron", curses_attron, 1); rb_define_module_function(mCurses, "attrset", curses_attrset, 1); rb_define_module_function(mCurses, "bkgdset", curses_bkgdset, 1); rb_define_module_function(mCurses, "bkgd", curses_bkgd, 1); rb_define_module_function(mCurses, "resizeterm", curses_resizeterm, 2); rb_define_module_function(mCurses, "resize", curses_resizeterm, 2); #ifdef USE_COLOR rb_define_module_function(mCurses, "start_color", curses_start_color, 0); rb_define_module_function(mCurses, "init_pair", curses_init_pair, 3); rb_define_module_function(mCurses, "init_color", curses_init_color, 4); rb_define_module_function(mCurses, "has_colors?", curses_has_colors, 0); rb_define_module_function(mCurses, "can_change_color?", curses_can_change_color, 0); rb_define_module_function(mCurses, "colors", curses_colors, 0); rb_define_module_function(mCurses, "color_content", curses_color_content, 1); rb_define_module_function(mCurses, "color_pairs", curses_color_pairs, 0); rb_define_module_function(mCurses, "pair_content", curses_pair_content, 1); rb_define_module_function(mCurses, "color_pair", curses_color_pair, 1); rb_define_module_function(mCurses, "pair_number", curses_pair_number, 1); #endif /* USE_COLOR */ #ifdef USE_MOUSE rb_define_module_function(mCurses, "getmouse", curses_getmouse, 0); rb_define_module_function(mCurses, "ungetmouse", curses_ungetmouse, 1); rb_define_module_function(mCurses, "mouseinterval", curses_mouseinterval, 1); rb_define_module_function(mCurses, "mousemask", curses_mousemask, 1); #endif /* USE_MOUSE */ rb_define_module_function(mCurses, "timeout=", curses_timeout, 1); rb_define_module_function(mCurses, "def_prog_mode", curses_def_prog_mode, 0); rb_define_module_function(mCurses, "reset_prog_mode", curses_reset_prog_mode, 0); rb_define_module_function(mCurses, "keyboard_encoding", curses_get_keyboard_encoding, 0); rb_define_module_function(mCurses, "keyboard_encoding=", curses_set_keyboard_encoding, 1); rb_define_module_function(mCurses, "terminal_encoding", curses_get_terminal_encoding, 0); rb_define_module_function(mCurses, "terminal_encoding=", curses_set_terminal_encoding, 1); rb_define_module_function(mCurses, "unget_char", curses_unget_char, 1); rb_define_module_function(mCurses, "get_char", curses_get_char, 0); #ifdef HAVE_PDC_GET_KEY_MODIFIERS rb_define_module_function(mCurses, "get_key_modifiers", curses_get_key_modifiers, 0); rb_define_module_function(mCurses, "return_key_modifiers", curses_return_key_modifiers, 1); rb_define_module_function(mCurses, "save_key_modifiers", curses_save_key_modifiers, 1); #endif { VALUE version; #if defined(HAVE_FUNC_CURSES_VERSION) /* ncurses and PDcurses */ version = rb_str_new2(curses_version()); #elif defined(HAVE_VAR_CURSES_VERSION) /* SVR4 curses has an undocumented and undeclared variable, curses_version. * It contains a string, "SVR4". */ RUBY_EXTERN char *curses_version; version = rb_sprintf("curses (%s)", curses_version); #else /* BSD curses, perhaps. NetBSD 5 still use it. */ version = rb_str_new2("curses (unknown)"); #endif /* * Identifies curses library version. * * - "ncurses 5.9.20110404" * - "PDCurses 3.4 - Public Domain 2008" * - "curses (SVR4)" (System V curses) * - "curses (unknown)" (The original BSD curses? NetBSD maybe.) * */ rb_define_const(mCurses, "VERSION", version); } /* * Document-class: Curses::Window * * == Description * * The means by which to create and manage frames or windows. * While there may be more than one window at a time, only one window * will receive input. * * == Usage * * require "curses" * * Curses.init_screen * * my_str = "LOOK! PONIES!" * * height, width = 12, my_str.length + 10 * top, left = (Curses.lines - height) / 2, (Curses.cols - width) / 2 * bwin = Curses::Window.new(height, width, top, left) * bwin.box("\\", "/") * bwin.refresh * * win = bwin.subwin(height - 4, width - 4, top + 2, left + 2) * win.setpos(2, 3) * win.addstr(my_str) * # or even * win << "\nOH REALLY?" * win << "\nYES!! " + my_str * win.refresh * win.getch * win.close * */ cWindow = rb_define_class_under(mCurses, "Window", rb_cData); rb_define_alloc_func(cWindow, window_s_allocate); rb_define_method(cWindow, "initialize", window_initialize, 4); rb_define_method(cWindow, "subwin", window_subwin, 4); rb_define_method(cWindow, "close", window_close, 0); rb_define_method(cWindow, "clear", window_clear, 0); rb_define_method(cWindow, "erase", window_erase, 0); rb_define_method(cWindow, "clrtoeol", window_clrtoeol, 0); rb_define_method(cWindow, "refresh", window_refresh, 0); rb_define_method(cWindow, "noutrefresh", window_noutrefresh, 0); rb_define_method(cWindow, "redraw", window_redraw, 0); rb_define_method(cWindow, "touch", window_touch, 0); rb_define_method(cWindow, "untouch", window_untouch, 0); rb_define_method(cWindow, "touched?", window_touched, 0); rb_define_method(cWindow, "touch_line", window_touch_line, -1); rb_define_method(cWindow, "line_touched?", window_line_touched, 1); rb_define_method(cWindow, "box", window_box, -1); rb_define_method(cWindow, "move", window_move, 2); rb_define_method(cWindow, "setpos", window_setpos, 2); #if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET) rb_define_method(cWindow, "color_set", window_color_set, 1); #endif /* USE_COLOR && HAVE_WCOLOR_SET */ rb_define_method(cWindow, "cury", window_cury, 0); rb_define_method(cWindow, "curx", window_curx, 0); rb_define_method(cWindow, "maxy", window_maxy, 0); rb_define_method(cWindow, "maxx", window_maxx, 0); rb_define_method(cWindow, "begy", window_begy, 0); rb_define_method(cWindow, "begx", window_begx, 0); rb_define_method(cWindow, "standout", window_standout, 0); rb_define_method(cWindow, "standend", window_standend, 0); rb_define_method(cWindow, "inch", window_inch, 0); rb_define_method(cWindow, "addch", window_addch, 1); rb_define_method(cWindow, "insch", window_insch, 1); rb_define_method(cWindow, "addstr", window_addstr, 1); rb_define_method(cWindow, "<<", window_addstr2, 1); rb_define_method(cWindow, "getch", window_getch, 0); rb_define_method(cWindow, "getstr", window_getstr, 0); rb_define_method(cWindow, "delch", window_delch, 0); rb_define_method(cWindow, "deleteln", window_deleteln, 0); rb_define_method(cWindow, "insertln", window_insertln, 0); rb_define_method(cWindow, "scroll", window_scroll, 0); rb_define_method(cWindow, "scrollok", window_scrollok, 1); rb_define_method(cWindow, "idlok", window_idlok, 1); rb_define_method(cWindow, "setscrreg", window_setscrreg, 2); rb_define_method(cWindow, "scrl", window_scrl, 1); rb_define_method(cWindow, "resize", window_resize, 2); rb_define_method(cWindow, "keypad", window_keypad, 1); rb_define_method(cWindow, "keypad=", window_keypad, 1); rb_define_method(cWindow, "attroff", window_attroff, 1); rb_define_method(cWindow, "attron", window_attron, 1); rb_define_method(cWindow, "attrset", window_attrset, 1); rb_define_method(cWindow, "bkgdset", window_bkgdset, 1); rb_define_method(cWindow, "bkgd", window_bkgd, 1); rb_define_method(cWindow, "getbkgd", window_getbkgd, 0); rb_define_method(cWindow, "nodelay=", window_nodelay, 1); rb_define_method(cWindow, "timeout=", window_timeout, 1); rb_define_method(cWindow, "get_char", window_get_char, 0); #ifdef HAVE_NEWPAD /* * Document-class: Curses::Pad * * == Description * * A Pad is like a Window but allows for scrolling of contents that cannot * fit on the screen. Pads do not refresh automatically, use Pad#refresh * or Pad#noutrefresh instead. * */ cPad = rb_define_class_under(mCurses, "Pad", cWindow); /* inherits alloc_func from cWindow */ rb_define_method(cPad, "initialize", pad_initialize, 2); rb_define_method(cPad, "subpad", pad_subpad, 4); rb_define_method(cPad, "refresh", pad_refresh, 6); rb_define_method(cPad, "noutrefresh", pad_noutrefresh, 6); rb_undef_method(cPad, "subwin"); #endif #define rb_curses_define_const(c) rb_define_const(mCurses,#c,CHTYPE2NUM(c)) #ifdef USE_COLOR /* Document-const: A_ATTRIBUTES * * Character attribute mask: * Bit-mask to extract attributes * * See Curses.inch or Curses::Window.inch */ rb_curses_define_const(A_ATTRIBUTES); #ifdef A_NORMAL /* Document-const: A_NORMAL * * Attribute mask: * Normal display (no highlight) * * See Curses.attrset */ rb_curses_define_const(A_NORMAL); #endif /* Document-const: A_STANDOUT * * Attribute mask: * Best highlighting mode of the terminal. * * See Curses.attrset */ rb_curses_define_const(A_STANDOUT); /* Document-const: A_UNDERLINE * * Attribute mask: * Underlining * * See Curses.attrset */ rb_curses_define_const(A_UNDERLINE); /* Document-const: A_REVERSE * * Attribute mask: * Reverse video * * See Curses.attrset */ rb_curses_define_const(A_REVERSE); /* Document-const: A_BLINK * * Attribute mask: * Blinking * * See Curses.attrset */ rb_curses_define_const(A_BLINK); /* Document-const: A_DIM * * Attribute mask: * Half bright * * See Curses.attrset */ rb_curses_define_const(A_DIM); /* Document-const: A_BOLD * * Attribute mask: * Extra bright or bold * * See Curses.attrset */ rb_curses_define_const(A_BOLD); /* Document-const: A_PROTECT * * Attribute mask: * Protected mode * * See Curses.attrset */ rb_curses_define_const(A_PROTECT); #ifdef A_INVIS /* for NetBSD */ /* Document-const: A_INVIS * * Attribute mask: * Invisible or blank mode * * See Curses.attrset */ rb_curses_define_const(A_INVIS); #endif /* Document-const: A_ALTCHARSET * * Attribute mask: * Alternate character set * * See Curses.attrset */ rb_curses_define_const(A_ALTCHARSET); /* Document-const: A_CHARTEXT * * Attribute mask: * Bit-mask to extract a character * * See Curses.attrset */ rb_curses_define_const(A_CHARTEXT); #ifdef A_HORIZONTAL /* Document-const: A_HORIZONTAL * * Attribute mask: * horizontal highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_HORIZONTAL); #endif #ifdef A_LEFT /* Document-const: A_LEFT * * Attribute mask: * left highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_LEFT); #endif #ifdef A_LOW /* Document-const: A_LOW * * Attribute mask: * low highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_LOW); #endif #ifdef A_RIGHT /* Document-const: A_RIGHT * * Attribute mask: * right highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_RIGHT); #endif #ifdef A_TOP /* Document-const: A_TOP * * Attribute mask: * top highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_TOP); #endif #ifdef A_VERTICAL /* Document-const: A_VERTICAL * * Attribute mask: * vertical highlight * * Check system curs_attr(3x) for support */ rb_curses_define_const(A_VERTICAL); #endif /* Document-const: A_COLOR * * Character attribute mask: * Bit-mask to extract color-pair field information * * See Curses.inch or Curses::Window.inch */ rb_curses_define_const(A_COLOR); #ifdef COLORS /* * Document-const: Curses::COLORS * * Number of the colors available */ rb_curses_define_const(COLORS); #endif /* * Document-const: Curses::COLOR_BLACK * * Value of the color black */ rb_curses_define_const(COLOR_BLACK); /* * Document-const: COLOR_RED * * Value of the color red */ rb_curses_define_const(COLOR_RED); /* * Document-const: COLOR_GREEN * * Value of the color green */ rb_curses_define_const(COLOR_GREEN); /* * Document-const: COLOR_YELLOW * * Value of the color yellow */ rb_curses_define_const(COLOR_YELLOW); /* * Document-const: COLOR_BLUE * * Value of the color blue */ rb_curses_define_const(COLOR_BLUE); /* * Document-const: COLOR_MAGENTA * * Value of the color magenta */ rb_curses_define_const(COLOR_MAGENTA); /* * Document-const: COLOR_CYAN * * Value of the color cyan */ rb_curses_define_const(COLOR_CYAN); /* * Document-const: COLOR_WHITE * * Value of the color white */ rb_curses_define_const(COLOR_WHITE); #endif /* USE_COLOR */ #ifdef USE_MOUSE #ifdef BUTTON1_PRESSED /* Document-const: BUTTON1_PRESSED * * Mouse event mask: * mouse button 1 down * * See Curses.getmouse */ rb_curses_define_const(BUTTON1_PRESSED); #endif #ifdef BUTTON1_RELEASED /* Document-const: BUTTON1_RELEASED * * Mouse event mask: * mouse button 1 up * * See Curses.getmouse */ rb_curses_define_const(BUTTON1_RELEASED); #endif #ifdef BUTTON1_CLICKED /* Document-const: BUTTON1_CLICKED * * Mouse event mask: * mouse button 1 clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON1_CLICKED); #endif #ifdef BUTTON1_DOUBLE_CLICKED /* Document-const: BUTTON1_DOUBLE_CLICKED * * Mouse event mask: * mouse button 1 double clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON1_DOUBLE_CLICKED); #endif #ifdef BUTTON1_TRIPLE_CLICKED /* Document-const: BUTTON1_TRIPLE_CLICKED * * Mouse event mask: * mouse button 1 triple clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON1_TRIPLE_CLICKED); #endif #ifdef BUTTON2_PRESSED /* Document-const: BUTTON2_PRESSED * * Mouse event mask: * mouse button 2 down * * See Curses.getmouse */ rb_curses_define_const(BUTTON2_PRESSED); #endif #ifdef BUTTON2_RELEASED /* Document-const: BUTTON2_RELEASED * * Mouse event mask: * mouse button 2 up * * See Curses.getmouse */ rb_curses_define_const(BUTTON2_RELEASED); #endif #ifdef BUTTON2_CLICKED /* Document-const: BUTTON2_CLICKED * * Mouse event mask: * mouse button 2 clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON2_CLICKED); #endif #ifdef BUTTON2_DOUBLE_CLICKED /* Document-const: BUTTON2_DOUBLE_CLICKED * * Mouse event mask: * mouse button 2 double clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON2_DOUBLE_CLICKED); #endif #ifdef BUTTON2_TRIPLE_CLICKED /* Document-const: BUTTON2_TRIPLE_CLICKED * * Mouse event mask: * mouse button 2 triple clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON2_TRIPLE_CLICKED); #endif #ifdef BUTTON3_PRESSED /* Document-const: BUTTON3_PRESSED * * Mouse event mask: * mouse button 3 down * * See Curses.getmouse */ rb_curses_define_const(BUTTON3_PRESSED); #endif #ifdef BUTTON3_RELEASED /* Document-const: BUTTON3_RELEASED * * Mouse event mask: * mouse button 3 up * * See Curses.getmouse */ rb_curses_define_const(BUTTON3_RELEASED); #endif #ifdef BUTTON3_CLICKED /* Document-const: BUTTON3_CLICKED * * Mouse event mask: * mouse button 3 clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON3_CLICKED); #endif #ifdef BUTTON3_DOUBLE_CLICKED /* Document-const: BUTTON3_DOUBLE_CLICKED * * Mouse event mask: * mouse button 3 double clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON3_DOUBLE_CLICKED); #endif #ifdef BUTTON3_TRIPLE_CLICKED /* Document-const: BUTTON3_TRIPLE_CLICKED * * Mouse event mask: * mouse button 3 triple clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON3_TRIPLE_CLICKED); #endif #ifdef BUTTON4_PRESSED /* Document-const: BUTTON4_PRESSED * * Mouse event mask: * mouse button 4 down * * See Curses.getmouse */ rb_curses_define_const(BUTTON4_PRESSED); #endif #ifdef BUTTON4_RELEASED /* Document-const: BUTTON4_RELEASED * * Mouse event mask: * mouse button 4 up * * See Curses.getmouse */ rb_curses_define_const(BUTTON4_RELEASED); #endif #ifdef BUTTON4_CLICKED /* Document-const: BUTTON4_CLICKED * * Mouse event mask: * mouse button 4 clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON4_CLICKED); #endif #ifdef BUTTON4_DOUBLE_CLICKED /* Document-const: BUTTON4_DOUBLE_CLICKED * * Mouse event mask: * mouse button 4 double clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON4_DOUBLE_CLICKED); #endif #ifdef BUTTON4_TRIPLE_CLICKED /* Document-const: BUTTON4_TRIPLE_CLICKED * * Mouse event mask: * mouse button 4 triple clicked * * See Curses.getmouse */ rb_curses_define_const(BUTTON4_TRIPLE_CLICKED); #endif #ifdef BUTTON_SHIFT /* Document-const: BUTTON_SHIFT * * Mouse event mask: * shift was down during button state change * * See Curses.getmouse */ rb_curses_define_const(BUTTON_SHIFT); #endif #ifdef BUTTON_CTRL /* Document-const: BUTTON_CTRL * * Mouse event mask: * control was down during button state change * * See Curses.getmouse */ rb_curses_define_const(BUTTON_CTRL); #endif #ifdef BUTTON_ALT /* Document-const: BUTTON_ALT * * Mouse event mask: * alt was down during button state change * * See Curses.getmouse */ rb_curses_define_const(BUTTON_ALT); #endif #ifdef ALL_MOUSE_EVENTS /* Document-const: ALL_MOUSE_EVENTS * * Mouse event mask: * report all button state changes * * See Curses.getmouse */ rb_curses_define_const(ALL_MOUSE_EVENTS); #endif #ifdef REPORT_MOUSE_POSITION /* Document-const: REPORT_MOUSE_POSITION * * Mouse event mask: * report mouse movement * * See Curses.getmouse */ rb_curses_define_const(REPORT_MOUSE_POSITION); #endif #endif /* USE_MOUSE */ #if defined(KEY_MOUSE) && defined(USE_MOUSE) /* Document-const: KEY_MOUSE * Mouse event read */ /* Document-const: MOUSE * Mouse event read */ rb_curses_define_const(KEY_MOUSE); rb_define_const(mKey, "MOUSE", INT2NUM(KEY_MOUSE)); #endif #ifdef KEY_MIN /* Document-const: KEY_MIN * The minimum allowed curses key value. */ /* Document-const: MIN * The minimum allowed curses key value. */ rb_curses_define_const(KEY_MIN); rb_define_const(mKey, "MIN", INT2NUM(KEY_MIN)); #endif #ifdef KEY_BREAK /* Document-const: KEY_BREAK * Break key */ /* Document-const: BREAK * Break key */ rb_curses_define_const(KEY_BREAK); rb_define_const(mKey, "BREAK", INT2NUM(KEY_BREAK)); #endif #ifdef KEY_DOWN /* Document-const: KEY_DOWN * the down arrow key */ /* Document-const: DOWN * the down arrow key */ rb_curses_define_const(KEY_DOWN); rb_define_const(mKey, "DOWN", INT2NUM(KEY_DOWN)); #endif #ifdef KEY_UP /* Document-const: KEY_UP * the up arrow key */ /* Document-const: UP * the up arrow key */ rb_curses_define_const(KEY_UP); rb_define_const(mKey, "UP", INT2NUM(KEY_UP)); #endif #ifdef KEY_LEFT /* Document-const: KEY_LEFT * the left arrow key */ /* Document-const: LEFT * the left arrow key */ rb_curses_define_const(KEY_LEFT); rb_define_const(mKey, "LEFT", INT2NUM(KEY_LEFT)); #endif #ifdef KEY_RIGHT /* Document-const: KEY_RIGHT * the right arrow key */ /* Document-const: RIGHT * the right arrow key */ rb_curses_define_const(KEY_RIGHT); rb_define_const(mKey, "RIGHT", INT2NUM(KEY_RIGHT)); #endif #ifdef KEY_HOME /* Document-const: KEY_HOME * Home key (upward+left arrow) */ /* Document-const: HOME * Home key (upward+left arrow) */ rb_curses_define_const(KEY_HOME); rb_define_const(mKey, "HOME", INT2NUM(KEY_HOME)); #endif #ifdef KEY_BACKSPACE /* Document-const: KEY_BACKSPACE * Backspace */ /* Document-const: BACKSPACE * Backspace */ rb_curses_define_const(KEY_BACKSPACE); rb_define_const(mKey, "BACKSPACE", INT2NUM(KEY_BACKSPACE)); #endif #ifdef KEY_F /* KEY_F(n) : 0 <= n <= 63 */ { int i; char c[8]; for (i=0; i<64; i++) { sprintf(c, "KEY_F%d", i); rb_define_const(mCurses, c, INT2NUM(KEY_F(i))); sprintf(c, "F%d", i); rb_define_const(mKey, c, INT2NUM(KEY_F(i))); } } #endif #ifdef KEY_DL /* Document-const: KEY_DL * Delete line */ /* Document-const: DL * Delete line */ rb_curses_define_const(KEY_DL); rb_define_const(mKey, "DL", INT2NUM(KEY_DL)); #endif #ifdef KEY_IL /* Document-const: KEY_IL * Insert line */ /* Document-const: IL * Insert line */ rb_curses_define_const(KEY_IL); rb_define_const(mKey, "IL", INT2NUM(KEY_IL)); #endif #ifdef KEY_DC /* Document-const: KEY_DC * Delete character */ /* Document-const: DC * Delete character */ rb_curses_define_const(KEY_DC); rb_define_const(mKey, "DC", INT2NUM(KEY_DC)); #endif #ifdef KEY_IC /* Document-const: KEY_IC * Insert char or enter insert mode */ /* Document-const: IC * Insert char or enter insert mode */ rb_curses_define_const(KEY_IC); rb_define_const(mKey, "IC", INT2NUM(KEY_IC)); #endif #ifdef KEY_EIC /* Document-const: KEY_EIC * Enter insert char mode */ /* Document-const: EIC * Enter insert char mode */ rb_curses_define_const(KEY_EIC); rb_define_const(mKey, "EIC", INT2NUM(KEY_EIC)); #endif #ifdef KEY_CLEAR /* Document-const: KEY_CLEAR * Clear Screen */ /* Document-const: CLEAR * Clear Screen */ rb_curses_define_const(KEY_CLEAR); rb_define_const(mKey, "CLEAR", INT2NUM(KEY_CLEAR)); #endif #ifdef KEY_EOS /* Document-const: KEY_EOS * Clear to end of screen */ /* Document-const: EOS * Clear to end of screen */ rb_curses_define_const(KEY_EOS); rb_define_const(mKey, "EOS", INT2NUM(KEY_EOS)); #endif #ifdef KEY_EOL /* Document-const: KEY_EOL * Clear to end of line */ /* Document-const: EOL * Clear to end of line */ rb_curses_define_const(KEY_EOL); rb_define_const(mKey, "EOL", INT2NUM(KEY_EOL)); #endif #ifdef KEY_SF /* Document-const: KEY_SF * Scroll 1 line forward */ /* Document-const: SF * Scroll 1 line forward */ rb_curses_define_const(KEY_SF); rb_define_const(mKey, "SF", INT2NUM(KEY_SF)); #endif #ifdef KEY_SR /* Document-const: KEY_SR * Scroll 1 line backward (reverse) */ /* Document-const: SR * Scroll 1 line backward (reverse) */ rb_curses_define_const(KEY_SR); rb_define_const(mKey, "SR", INT2NUM(KEY_SR)); #endif #ifdef KEY_NPAGE /* Document-const: KEY_NPAGE * Next page */ /* Document-const: NPAGE * Next page */ rb_curses_define_const(KEY_NPAGE); rb_define_const(mKey, "NPAGE", INT2NUM(KEY_NPAGE)); #endif #ifdef KEY_PPAGE /* Document-const: KEY_PPAGE * Previous page */ /* Document-const: PPAGE * Previous page */ rb_curses_define_const(KEY_PPAGE); rb_define_const(mKey, "PPAGE", INT2NUM(KEY_PPAGE)); #endif #ifdef KEY_STAB /* Document-const: KEY_STAB * Set tab */ /* Document-const: STAB * Set tab */ rb_curses_define_const(KEY_STAB); rb_define_const(mKey, "STAB", INT2NUM(KEY_STAB)); #endif #ifdef KEY_CTAB /* Document-const: KEY_CTAB * Clear tab */ /* Document-const: CTAB * Clear tab */ rb_curses_define_const(KEY_CTAB); rb_define_const(mKey, "CTAB", INT2NUM(KEY_CTAB)); #endif #ifdef KEY_CATAB /* Document-const: KEY_CATAB * Clear all tabs */ /* Document-const: CATAB * Clear all tabs */ rb_curses_define_const(KEY_CATAB); rb_define_const(mKey, "CATAB", INT2NUM(KEY_CATAB)); #endif #ifdef KEY_ENTER /* Document-const: KEY_ENTER * Enter or send */ /* Document-const: ENTER * Enter or send */ rb_curses_define_const(KEY_ENTER); rb_define_const(mKey, "ENTER", INT2NUM(KEY_ENTER)); #endif #ifdef KEY_SRESET /* Document-const: KEY_SRESET * Soft (partial) reset */ /* Document-const: SRESET * Soft (partial) reset */ rb_curses_define_const(KEY_SRESET); rb_define_const(mKey, "SRESET", INT2NUM(KEY_SRESET)); #endif #ifdef KEY_RESET /* Document-const: KEY_RESET * Reset or hard reset */ /* Document-const: RESET * Reset or hard reset */ rb_curses_define_const(KEY_RESET); rb_define_const(mKey, "RESET", INT2NUM(KEY_RESET)); #endif #ifdef KEY_PRINT /* Document-const: KEY_PRINT * Print or copy */ /* Document-const: PRINT * Print or copy */ rb_curses_define_const(KEY_PRINT); rb_define_const(mKey, "PRINT", INT2NUM(KEY_PRINT)); #endif #ifdef KEY_LL /* Document-const: KEY_LL * Home down or bottom (lower left) */ /* Document-const: LL * Home down or bottom (lower left) */ rb_curses_define_const(KEY_LL); rb_define_const(mKey, "LL", INT2NUM(KEY_LL)); #endif #ifdef KEY_A1 /* Document-const: KEY_A1 * Upper left of keypad */ /* Document-const: A1 * Upper left of keypad */ rb_curses_define_const(KEY_A1); rb_define_const(mKey, "A1", INT2NUM(KEY_A1)); #endif #ifdef KEY_A3 /* Document-const: KEY_A3 * Upper right of keypad */ /* Document-const: A3 * Upper right of keypad */ rb_curses_define_const(KEY_A3); rb_define_const(mKey, "A3", INT2NUM(KEY_A3)); #endif #ifdef KEY_B2 /* Document-const: KEY_B2 * Center of keypad */ /* Document-const: B2 * Center of keypad */ rb_curses_define_const(KEY_B2); rb_define_const(mKey, "B2", INT2NUM(KEY_B2)); #endif #ifdef KEY_C1 /* Document-const: KEY_C1 * Lower left of keypad */ /* Document-const: C1 * Lower left of keypad */ rb_curses_define_const(KEY_C1); rb_define_const(mKey, "C1", INT2NUM(KEY_C1)); #endif #ifdef KEY_C3 /* Document-const: KEY_C3 * Lower right of keypad */ /* Document-const: C3 * Lower right of keypad */ rb_curses_define_const(KEY_C3); rb_define_const(mKey, "C3", INT2NUM(KEY_C3)); #endif #ifdef KEY_BTAB /* Document-const: BTAB * Back tab key */ /* Document-const: KEY_BTAB * Back tab key */ rb_curses_define_const(KEY_BTAB); rb_define_const(mKey, "BTAB", INT2NUM(KEY_BTAB)); #endif #ifdef KEY_BEG /* Document-const: KEY_BEG * Beginning key */ /* Document-const: BEG * Beginning key */ rb_curses_define_const(KEY_BEG); rb_define_const(mKey, "BEG", INT2NUM(KEY_BEG)); #endif #ifdef KEY_CANCEL /* Document-const: KEY_CANCEL * Cancel key */ /* Document-const: CANCEL * Cancel key */ rb_curses_define_const(KEY_CANCEL); rb_define_const(mKey, "CANCEL", INT2NUM(KEY_CANCEL)); #endif #ifdef KEY_CLOSE /* Document-const: KEY_CLOSE * Close key */ /* Document-const: CLOSE * Close key */ rb_curses_define_const(KEY_CLOSE); rb_define_const(mKey, "CLOSE", INT2NUM(KEY_CLOSE)); #endif #ifdef KEY_COMMAND /* Document-const: KEY_COMMAND * Cmd (command) key */ /* Document-const: COMMAND * Cmd (command) key */ rb_curses_define_const(KEY_COMMAND); rb_define_const(mKey, "COMMAND", INT2NUM(KEY_COMMAND)); #endif #ifdef KEY_COPY /* Document-const: KEY_COPY * Copy key */ /* Document-const: COPY * Copy key */ rb_curses_define_const(KEY_COPY); rb_define_const(mKey, "COPY", INT2NUM(KEY_COPY)); #endif #ifdef KEY_CREATE /* Document-const: KEY_CREATE * Create key */ /* Document-const: CREATE * Create key */ rb_curses_define_const(KEY_CREATE); rb_define_const(mKey, "CREATE", INT2NUM(KEY_CREATE)); #endif #ifdef KEY_END /* Document-const: KEY_END * End key */ /* Document-const: END * End key */ rb_curses_define_const(KEY_END); rb_define_const(mKey, "END", INT2NUM(KEY_END)); #endif #ifdef KEY_EXIT /* Document-const: KEY_EXIT * Exit key */ /* Document-const: EXIT * Exit key */ rb_curses_define_const(KEY_EXIT); rb_define_const(mKey, "EXIT", INT2NUM(KEY_EXIT)); #endif #ifdef KEY_FIND /* Document-const: KEY_FIND * Find key */ /* Document-const: FIND * Find key */ rb_curses_define_const(KEY_FIND); rb_define_const(mKey, "FIND", INT2NUM(KEY_FIND)); #endif #ifdef KEY_HELP /* Document-const: KEY_HELP * Help key */ /* Document-const: HELP * Help key */ rb_curses_define_const(KEY_HELP); rb_define_const(mKey, "HELP", INT2NUM(KEY_HELP)); #endif #ifdef KEY_MARK /* Document-const: KEY_MARK * Mark key */ /* Document-const: MARK * Mark key */ rb_curses_define_const(KEY_MARK); rb_define_const(mKey, "MARK", INT2NUM(KEY_MARK)); #endif #ifdef KEY_MESSAGE /* Document-const: KEY_MESSAGE * Message key */ /* Document-const: MESSAGE * Message key */ rb_curses_define_const(KEY_MESSAGE); rb_define_const(mKey, "MESSAGE", INT2NUM(KEY_MESSAGE)); #endif #ifdef KEY_MOVE /* Document-const: KEY_MOVE * Move key */ /* Document-const: MOVE * Move key */ rb_curses_define_const(KEY_MOVE); rb_define_const(mKey, "MOVE", INT2NUM(KEY_MOVE)); #endif #ifdef KEY_NEXT /* Document-const: KEY_NEXT * Next object key */ /* Document-const: NEXT * Next object key */ rb_curses_define_const(KEY_NEXT); rb_define_const(mKey, "NEXT", INT2NUM(KEY_NEXT)); #endif #ifdef KEY_OPEN /* Document-const: KEY_OPEN * Open key */ /* Document-const: OPEN * Open key */ rb_curses_define_const(KEY_OPEN); rb_define_const(mKey, "OPEN", INT2NUM(KEY_OPEN)); #endif #ifdef KEY_OPTIONS /* Document-const: KEY_OPTIONS * Options key */ /* Document-const: OPTIONS * Options key */ rb_curses_define_const(KEY_OPTIONS); rb_define_const(mKey, "OPTIONS", INT2NUM(KEY_OPTIONS)); #endif #ifdef KEY_PREVIOUS /* Document-const: KEY_PREVIOUS * Previous object key */ /* Document-const: PREVIOUS * Previous object key */ rb_curses_define_const(KEY_PREVIOUS); rb_define_const(mKey, "PREVIOUS", INT2NUM(KEY_PREVIOUS)); #endif #ifdef KEY_REDO /* Document-const: KEY_REDO * Redo key */ /* Document-const: REDO * Redo key */ rb_curses_define_const(KEY_REDO); rb_define_const(mKey, "REDO", INT2NUM(KEY_REDO)); #endif #ifdef KEY_REFERENCE /* Document-const: KEY_REFERENCE * Reference key */ /* Document-const: REFERENCE * Reference key */ rb_curses_define_const(KEY_REFERENCE); rb_define_const(mKey, "REFERENCE", INT2NUM(KEY_REFERENCE)); #endif #ifdef KEY_REFRESH /* Document-const: KEY_REFRESH * Refresh key */ /* Document-const: REFRESH * Refresh key */ rb_curses_define_const(KEY_REFRESH); rb_define_const(mKey, "REFRESH", INT2NUM(KEY_REFRESH)); #endif #ifdef KEY_REPLACE /* Document-const: KEY_REPLACE * Replace key */ /* Document-const: REPLACE * Replace key */ rb_curses_define_const(KEY_REPLACE); rb_define_const(mKey, "REPLACE", INT2NUM(KEY_REPLACE)); #endif #ifdef KEY_RESTART /* Document-const: KEY_RESTART * Restart key */ /* Document-const: RESTART * Restart key */ rb_curses_define_const(KEY_RESTART); rb_define_const(mKey, "RESTART", INT2NUM(KEY_RESTART)); #endif #ifdef KEY_RESUME /* Document-const: KEY_RESUME * Resume key */ /* Document-const: RESUME * Resume key */ rb_curses_define_const(KEY_RESUME); rb_define_const(mKey, "RESUME", INT2NUM(KEY_RESUME)); #endif #ifdef KEY_SAVE /* Document-const: KEY_SAVE * Save key */ /* Document-const: SAVE * Save key */ rb_curses_define_const(KEY_SAVE); rb_define_const(mKey, "SAVE", INT2NUM(KEY_SAVE)); #endif #ifdef KEY_SBEG /* Document-const: KEY_SBEG * Shifted beginning key */ /* Document-const: SBEG * Shifted beginning key */ rb_curses_define_const(KEY_SBEG); rb_define_const(mKey, "SBEG", INT2NUM(KEY_SBEG)); #endif #ifdef KEY_SCANCEL /* Document-const: KEY_SCANCEL * Shifted cancel key */ /* Document-const: SCANCEL * Shifted cancel key */ rb_curses_define_const(KEY_SCANCEL); rb_define_const(mKey, "SCANCEL", INT2NUM(KEY_SCANCEL)); #endif #ifdef KEY_SCOMMAND /* Document-const: KEY_SCOMMAND * Shifted command key */ /* Document-const: SCOMMAND * Shifted command key */ rb_curses_define_const(KEY_SCOMMAND); rb_define_const(mKey, "SCOMMAND", INT2NUM(KEY_SCOMMAND)); #endif #ifdef KEY_SCOPY /* Document-const: KEY_SCOPY * Shifted copy key */ /* Document-const: SCOPY * Shifted copy key */ rb_curses_define_const(KEY_SCOPY); rb_define_const(mKey, "SCOPY", INT2NUM(KEY_SCOPY)); #endif #ifdef KEY_SCREATE /* Document-const: KEY_SCREATE * Shifted create key */ /* Document-const: SCREATE * Shifted create key */ rb_curses_define_const(KEY_SCREATE); rb_define_const(mKey, "SCREATE", INT2NUM(KEY_SCREATE)); #endif #ifdef KEY_SDC /* Document-const: KEY_SDC * Shifted delete char key */ /* Document-const: SDC * Shifted delete char key */ rb_curses_define_const(KEY_SDC); rb_define_const(mKey, "SDC", INT2NUM(KEY_SDC)); #endif #ifdef KEY_SDL /* Document-const: KEY_SDL * Shifted delete line key */ /* Document-const: SDL * Shifted delete line key */ rb_curses_define_const(KEY_SDL); rb_define_const(mKey, "SDL", INT2NUM(KEY_SDL)); #endif #ifdef KEY_SELECT /* Document-const: KEY_SELECT * Select key */ /* Document-const: SELECT * Select key */ rb_curses_define_const(KEY_SELECT); rb_define_const(mKey, "SELECT", INT2NUM(KEY_SELECT)); #endif #ifdef KEY_SEND /* Document-const: KEY_SEND * Shifted end key */ /* Document-const: SEND * Shifted end key */ rb_curses_define_const(KEY_SEND); rb_define_const(mKey, "SEND", INT2NUM(KEY_SEND)); #endif #ifdef KEY_SEOL /* Document-const: KEY_SEOL * Shifted clear line key */ /* Document-const: SEOL * Shifted clear line key */ rb_curses_define_const(KEY_SEOL); rb_define_const(mKey, "SEOL", INT2NUM(KEY_SEOL)); #endif #ifdef KEY_SEXIT /* Document-const: KEY_SEXIT * Shifted exit key */ /* Document-const: SEXIT * Shifted exit key */ rb_curses_define_const(KEY_SEXIT); rb_define_const(mKey, "SEXIT", INT2NUM(KEY_SEXIT)); #endif #ifdef KEY_SFIND /* Document-const: KEY_SFIND * Shifted find key */ /* Document-const: SFIND * Shifted find key */ rb_curses_define_const(KEY_SFIND); rb_define_const(mKey, "SFIND", INT2NUM(KEY_SFIND)); #endif #ifdef KEY_SHELP /* Document-const: KEY_SHELP * Shifted help key */ /* Document-const: SHELP * Shifted help key */ rb_curses_define_const(KEY_SHELP); rb_define_const(mKey, "SHELP", INT2NUM(KEY_SHELP)); #endif #ifdef KEY_SHOME /* Document-const: KEY_SHOME * Shifted home key */ /* Document-const: SHOME * Shifted home key */ rb_curses_define_const(KEY_SHOME); rb_define_const(mKey, "SHOME", INT2NUM(KEY_SHOME)); #endif #ifdef KEY_SIC /* Document-const: KEY_SIC * Shifted input key */ /* Document-const: SIC * Shifted input key */ rb_curses_define_const(KEY_SIC); rb_define_const(mKey, "SIC", INT2NUM(KEY_SIC)); #endif #ifdef KEY_SLEFT /* Document-const: KEY_SLEFT * Shifted left arrow key */ /* Document-const: SLEFT * Shifted left arrow key */ rb_curses_define_const(KEY_SLEFT); rb_define_const(mKey, "SLEFT", INT2NUM(KEY_SLEFT)); #endif #ifdef KEY_SMESSAGE /* Document-const: KEY_SMESSAGE * Shifted message key */ /* Document-const: SMESSAGE * Shifted message key */ rb_curses_define_const(KEY_SMESSAGE); rb_define_const(mKey, "SMESSAGE", INT2NUM(KEY_SMESSAGE)); #endif #ifdef KEY_SMOVE /* Document-const: KEY_SMOVE * Shifted move key */ /* Document-const: SMOVE * Shifted move key */ rb_curses_define_const(KEY_SMOVE); rb_define_const(mKey, "SMOVE", INT2NUM(KEY_SMOVE)); #endif #ifdef KEY_SNEXT /* Document-const: KEY_SNEXT * Shifted next key */ /* Document-const: SNEXT * Shifted next key */ rb_curses_define_const(KEY_SNEXT); rb_define_const(mKey, "SNEXT", INT2NUM(KEY_SNEXT)); #endif #ifdef KEY_SOPTIONS /* Document-const: KEY_SOPTIONS * Shifted options key */ /* Document-const: SOPTIONS * Shifted options key */ rb_curses_define_const(KEY_SOPTIONS); rb_define_const(mKey, "SOPTIONS", INT2NUM(KEY_SOPTIONS)); #endif #ifdef KEY_SPREVIOUS /* Document-const: KEY_SPREVIOUS * Shifted previous key */ /* Document-const: SPREVIOUS * Shifted previous key */ rb_curses_define_const(KEY_SPREVIOUS); rb_define_const(mKey, "SPREVIOUS", INT2NUM(KEY_SPREVIOUS)); #endif #ifdef KEY_SPRINT /* Document-const: KEY_SPRINT * Shifted print key */ /* Document-const: SPRINT * Shifted print key */ rb_curses_define_const(KEY_SPRINT); rb_define_const(mKey, "SPRINT", INT2NUM(KEY_SPRINT)); #endif #ifdef KEY_SREDO /* Document-const: KEY_SREDO * Shifted redo key */ /* Document-const: SREDO * Shifted redo key */ rb_curses_define_const(KEY_SREDO); rb_define_const(mKey, "SREDO", INT2NUM(KEY_SREDO)); #endif #ifdef KEY_SREPLACE /* Document-const: KEY_SREPLACE * Shifted replace key */ /* Document-const: SREPLACE * Shifted replace key */ rb_curses_define_const(KEY_SREPLACE); rb_define_const(mKey, "SREPLACE", INT2NUM(KEY_SREPLACE)); #endif #ifdef KEY_SRIGHT /* Document-const: KEY_SRIGHT * Shifted right arrow key */ /* Document-const: SRIGHT * Shifted right arrow key */ rb_curses_define_const(KEY_SRIGHT); rb_define_const(mKey, "SRIGHT", INT2NUM(KEY_SRIGHT)); #endif #ifdef KEY_SRSUME /* Document-const: KEY_SRSUME * Shifted resume key */ /* Document-const: SRSUME * Shifted resume key */ rb_curses_define_const(KEY_SRSUME); rb_define_const(mKey, "SRSUME", INT2NUM(KEY_SRSUME)); #endif #ifdef KEY_SSAVE /* Document-const: KEY_SSAVE * Shifted save key */ /* Document-const: SSAVE * Shifted save key */ rb_curses_define_const(KEY_SSAVE); rb_define_const(mKey, "SSAVE", INT2NUM(KEY_SSAVE)); #endif #ifdef KEY_SSUSPEND /* Document-const: KEY_SSUSPEND * Shifted suspend key */ /* Document-const: SSUSPEND * Shifted suspend key */ rb_curses_define_const(KEY_SSUSPEND); rb_define_const(mKey, "SSUSPEND", INT2NUM(KEY_SSUSPEND)); #endif #ifdef KEY_SUNDO /* Document-const: KEY_SUNDO * Shifted undo key */ /* Document-const: SUNDO * Shifted undo key */ rb_curses_define_const(KEY_SUNDO); rb_define_const(mKey, "SUNDO", INT2NUM(KEY_SUNDO)); #endif #ifdef KEY_SUSPEND /* Document-const: KEY_SUSPEND * Suspend key */ /* Document-const: SUSPEND * Suspend key */ rb_curses_define_const(KEY_SUSPEND); rb_define_const(mKey, "SUSPEND", INT2NUM(KEY_SUSPEND)); #endif #ifdef KEY_UNDO /* Document-const: KEY_UNDO * Undo key */ /* Document-const: UNDO * Undo key */ rb_curses_define_const(KEY_UNDO); rb_define_const(mKey, "UNDO", INT2NUM(KEY_UNDO)); #endif #ifdef KEY_RESIZE /* Document-const: KEY_RESIZE * Screen Resized */ /* Document-const: RESIZE * Screen Resized */ rb_curses_define_const(KEY_RESIZE); rb_define_const(mKey, "RESIZE", INT2NUM(KEY_RESIZE)); #endif #ifdef KEY_MAX /* Document-const: KEY_MAX * The maximum allowed curses key value. */ /* Document-const: MAX * The maximum allowed curses key value. */ rb_curses_define_const(KEY_MAX); rb_define_const(mKey, "MAX", INT2NUM(KEY_MAX)); #endif { int c; char name[] = "KEY_CTRL_x"; for (c = 'A'; c <= 'Z'; c++) { name[sizeof(name) - 2] = c; rb_define_const(mCurses, name, INT2FIX(c - 'A' + 1)); } } #ifdef PDC_KEY_MODIFIER_SHIFT /* PDCurses-specific keys */ rb_curses_define_const(ALT_0); rb_curses_define_const(ALT_1); rb_curses_define_const(ALT_2); rb_curses_define_const(ALT_3); rb_curses_define_const(ALT_4); rb_curses_define_const(ALT_5); rb_curses_define_const(ALT_6); rb_curses_define_const(ALT_7); rb_curses_define_const(ALT_8); rb_curses_define_const(ALT_9); rb_curses_define_const(ALT_A); rb_curses_define_const(ALT_B); rb_curses_define_const(ALT_C); rb_curses_define_const(ALT_D); rb_curses_define_const(ALT_E); rb_curses_define_const(ALT_F); rb_curses_define_const(ALT_G); rb_curses_define_const(ALT_H); rb_curses_define_const(ALT_I); rb_curses_define_const(ALT_J); rb_curses_define_const(ALT_K); rb_curses_define_const(ALT_L); rb_curses_define_const(ALT_M); rb_curses_define_const(ALT_N); rb_curses_define_const(ALT_O); rb_curses_define_const(ALT_P); rb_curses_define_const(ALT_Q); rb_curses_define_const(ALT_R); rb_curses_define_const(ALT_S); rb_curses_define_const(ALT_T); rb_curses_define_const(ALT_U); rb_curses_define_const(ALT_V); rb_curses_define_const(ALT_W); rb_curses_define_const(ALT_X); rb_curses_define_const(ALT_Y); rb_curses_define_const(ALT_Z); rb_curses_define_const(PDC_KEY_MODIFIER_SHIFT); rb_curses_define_const(PDC_KEY_MODIFIER_CONTROL); rb_curses_define_const(PDC_KEY_MODIFIER_ALT); rb_curses_define_const(PDC_KEY_MODIFIER_NUMLOCK); #endif #undef rb_curses_define_const } curses-1.2.4/ext/curses/extconf.rb0000644000004100000410000001145413267647262017175 0ustar www-datawww-datarequire 'mkmf' def have_all(*args) old_libs = $libs.dup old_defs = $defs.dup result = [] begin args.each {|arg| r = arg.call(*result) if !r return nil end result << r } result ensure if result.length != args.length $libs = old_libs $defs = old_defs end end end dir_config('curses') dir_config('ncurses') dir_config('termcap') have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM have_library("tinfo", "tgetent") or have_library("termcap", "tgetent") header_library = nil [ ["ncursesw/curses.h", ["ncursesw"]], ["ncurses.h", ["ncursesw", "ncurses"]], ["ncurses/curses.h", ["ncurses"]], ["curses_colr/curses.h", ["cur_colr"]], ["curses.h", ["curses", "pdcurses"]], # ["xcurses.h", ["XCurses"]], # XCurses (PDCurses for X11) ].each {|hdr, libs| header_library = have_all( lambda { have_header(hdr) && hdr }, lambda {|h| libs.find {|lib| have_library(lib, "initscr", h) } }) if header_library break; end } if header_library header, library = header_library puts "header: #{header}" puts "library: #{library}" curses = [header] if header == 'curses_colr/curses.h' curses.unshift("varargs.h") end for f in %w(beep bkgd bkgdset curs_set deleteln doupdate flash getbkgd getnstr init isendwin keyname keypad resizeterm scrl set setscrreg ungetch addnwstr wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr wresize wscrl wsetscrreg werase redrawwin waddnwstr touchwin untouchwin wtouchln is_linetouched is_wintouched def_prog_mode reset_prog_mode timeout wtimeout nodelay init_color wcolor_set use_default_colors assume_default_colors newpad unget_wch get_wch wget_wch PDC_get_key_modifiers) have_func(f) || (have_macro(f, curses) && $defs.push(format("-DHAVE_%s", f.upcase))) end convertible_int('chtype', [["#undef MOUSE_MOVED\n"]]+curses) or abort flag = "-D_XOPEN_SOURCE_EXTENDED" if checking_for("_XOPEN_SOURCE_EXTENDED") { try_compile(cpp_include(%w[stdio.h stdlib.h]+curses), flag, :werror => true) } $defs << flag end have_var("ESCDELAY", curses) have_var("TABSIZE", curses) have_var("COLORS", curses) have_var("COLOR_PAIRS", curses) # SVR4 curses has a (undocumented) variable char *curses_version. # ncurses and PDcurses has a function char *curses_version(). # Note that the original BSD curses doesn't provide version information. # # configure option: # --with-curses-version=function for SVR4 # --with-curses-version=variable for ncurses and PDcurses # (not given) automatically determined case with_curses_version = with_config("curses-version") when "function" $defs << '-DHAVE_FUNC_CURSES_VERSION' when "variable" $defs << '-DHAVE_VAR_CURSES_VERSION' when nil func_test_program = cpp_include(curses) + <<-"End" int main(int argc, char *argv[]) { curses_version(); return EXIT_SUCCESS; } End var_test_program = cpp_include(curses) + <<-"End" extern char *curses_version; int main(int argc, char *argv[]) { int i = 0; for (i = 0; i < 100; i++) { if (curses_version[i] == 0) return 0 < i ? EXIT_SUCCESS : EXIT_FAILURE; if (curses_version[i] & 0x80) return EXIT_FAILURE; } return EXIT_FAILURE; } End try = method(CROSS_COMPILING ? :try_link : :try_run) function_p = checking_for(checking_message('function curses_version', curses)) { try[func_test_program] } variable_p = checking_for(checking_message('variable curses_version', curses)) { try[var_test_program] } if function_p and variable_p if [header, library].grep(/ncurses|pdcurses|xcurses/i) variable_p = false else warn "found curses_version but cannot determine whether it is a" warn "function or a variable, so assume a variable in old SVR4" warn "ncurses." function_p = false end end $defs << '-DHAVE_FUNC_CURSES_VERSION' if function_p $defs << '-DHAVE_VAR_CURSES_VERSION' if variable_p else warn "unexpected value for --with-curses-version: #{with_curses_version}" end if enable_config("pdcurses-wide") $defs << '-DPDC_WIDE' end if enable_config("pdcurses-dll") $defs << '-DPDC_DLL_BUILD' end if RUBY_VERSION >= '2.1' create_header create_makefile("curses") else # curses is part of ruby-core pre-2.1.0, so this gem is not required. But # make pre-2.1.0 a no-op rather than failing or listing as unsupported, to # aid gems offering multi-version Ruby support. File.open("Makefile", 'w') do |f| f.puts dummy_makefile("curses").join end end end curses-1.2.4/sample/0000755000004100000410000000000013267647262014352 5ustar www-datawww-datacurses-1.2.4/sample/hello.rb0000755000004100000410000000107613267647262016011 0ustar www-datawww-data#!/usr/bin/env ruby require "curses" def show_message(message) height = 5 width = message.length + 6 top = (Curses.lines - height) / 2 left = (Curses.cols - width) / 2 win = Curses::Window.new(height, width, top, left) win.box("|", "-") win.setpos(2, 3) win.addstr(message) win.refresh win.getch win.close end Curses.init_screen begin Curses.crmode Curses.setpos((Curses.lines - 1) / 2, (Curses.cols - 11) / 2) Curses.addstr("Hit any key") Curses.refresh Curses.getch show_message("Hello, World!") ensure Curses.close_screen end curses-1.2.4/sample/mouse.rb0000755000004100000410000000210113267647262016024 0ustar www-datawww-data#!/usr/bin/env ruby require "curses" include Curses def show_message(*msgs) message = msgs.join height, width = 5, message.length + 6 top, left = (lines - height) / 2, (cols - width) / 2 win = Window.new(height, width, top, left) win.keypad = true win.attron(color_pair(COLOR_RED)) do win.box("|", "-", "+") end win.setpos(2, 3) win.addstr(message) win.refresh win.getch win.close end init_screen start_color init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_WHITE) init_pair(COLOR_RED, COLOR_RED, COLOR_WHITE) crmode noecho stdscr.keypad(true) begin mousemask(BUTTON1_CLICKED|BUTTON2_CLICKED|BUTTON3_CLICKED|BUTTON4_CLICKED) setpos((lines - 1) / 2, (cols - 5) / 2) attron(color_pair(COLOR_BLUE)|A_BOLD) do addstr("click") end refresh loop do c = getch case c when KEY_MOUSE m = getmouse if m show_message("getch = #{c.inspect}, ", "mouse event = #{'0x%x' % m.bstate}, ", "axis = (#{m.x},#{m.y},#{m.z})") end break end end refresh ensure close_screen end curses-1.2.4/sample/rain.rb0000755000004100000410000000276613267647262015646 0ustar www-datawww-data#!/usr/bin/env ruby require "curses" def onsig(signal) Curses.close_screen exit signal end def place_string(y, x, string) Curses.setpos(y, x) Curses.addstr(string) end def cycle_index(index) (index + 1) % 5 end %w[HUP INT QUIT TERM].each do |sig| unless trap(sig, "IGNORE") == "IGNORE" # previous handler trap(sig) {|s| onsig(s) } end end Curses.init_screen Curses.nl Curses.noecho Curses.curs_set 0 srand xpos, ypos = {}, {} x_range = 2..(Curses.cols - 3) y_range = 2..(Curses.lines - 3) (0..4).each do |i| xpos[i], ypos[i] = rand(x_range), rand(y_range) end i = 0 loop do x, y = rand(x_range), rand(y_range) place_string(y, x, ".") place_string(ypos[i], xpos[i], "o") i = cycle_index(i) place_string(ypos[i], xpos[i], "O") i = cycle_index(i) place_string(ypos[i] - 1, xpos[i], "-") place_string(ypos[i], xpos[i] - 1, "|.|") place_string(ypos[i] + 1, xpos[i], "-") i = cycle_index(i) place_string(ypos[i] - 2, xpos[i], "-") place_string(ypos[i] - 1, xpos[i] - 1, "/ \\") place_string(ypos[i], xpos[i] - 2, "| O |") place_string(ypos[i] + 1, xpos[i] - 1, "\\ /") place_string(ypos[i] + 2, xpos[i], "-") i = cycle_index(i) place_string(ypos[i] - 2, xpos[i], " ") place_string(ypos[i] - 1, xpos[i] - 1, " ") place_string(ypos[i], xpos[i] - 2, " ") place_string(ypos[i] + 1, xpos[i] - 1, " ") place_string(ypos[i] + 2, xpos[i], " ") xpos[i], ypos[i] = x, y Curses.refresh sleep(0.5) end curses-1.2.4/sample/view.rb0000755000004100000410000000175213267647262015661 0ustar www-datawww-data#!/usr/bin/env ruby require "curses" include Curses unless ARGV.size == 1 puts "usage: #{$0} file" exit end begin data_lines = File.readlines(ARGV[0]) rescue raise "cannot open file: #{ARGV[0]}" end init_screen #keypad(stdscr, true) nonl cbreak noecho #scrollok(stdscr, true) lptr = 0 loop do lines.times do |i| setpos(i, 0) #clrtoeol addstr(data_lines[lptr + i] || "") end refresh explicit = false n = 0 c = nil loop do c = getch if c =~ /[0-9]/ n = 10 * n + c.to_i explicit = true else break end end n = 1 if !explicit && n == 0 case c when "n" #when KEY_DOWN i = 0 n.times do if lptr + lines < data_lines.size lptr += 1 else break end i += 1 end #wscrl(i) when "p" #when KEY_UP i = 0 n.times do if lptr > 0 lptr -= 1 else break end i += 1 end #wscrl(-i) when "q" break end end close_screen curses-1.2.4/sample/view2.rb0000755000004100000410000000564113267647262015744 0ustar www-datawww-data#!/usr/bin/env ruby require "curses" # A curses based file viewer. class FileViewer # Create a new FileViewer and view the file. def initialize(filename) @data_lines = [] @screen = nil @top = nil init_curses load_file(filename) interact end # Perform the curses setup. def init_curses Curses.init_screen Curses.nonl Curses.cbreak Curses.noecho @screen = Curses.stdscr @screen.scrollok(true) #@screen.keypad(true) end # Load the file into memory and # put the first part on the curses display. def load_file(filename) @data_lines = File.readlines(filename).map(&:chomp) @top = 0 @data_lines[0..@screen.maxy-1].each_with_index do |line, idx| @screen.setpos(idx, 0) @screen.addstr(line) end @screen.setpos(0, 0) @screen.refresh rescue raise "cannot open file '#{filename}' for reading" end # Scroll the display up by one line. def scroll_up if @top > 0 @screen.scrl(-1) @top -= 1 str = @data_lines[@top] if str @screen.setpos(0, 0) @screen.addstr(str) end return true else return false end end # Scroll the display down by one line. def scroll_down if @top + @screen.maxy < @data_lines.length @screen.scrl(1) @top += 1 str = @data_lines[@top + @screen.maxy - 1] if str @screen.setpos(@screen.maxy - 1, 0) @screen.addstr(str) end return true else return false end end # Allow the user to interact with the display. # This uses Emacs-like keybindings, and also # vi-like keybindings as well, except that left # and right move to the beginning and end of the # file, respectively. def interact loop do result = true c = Curses.getch case c when Curses::KEY_DOWN, Curses::KEY_CTRL_N, "j" result = scroll_down when Curses::KEY_UP, Curses::KEY_CTRL_P, "k" result = scroll_up when Curses::KEY_NPAGE, " " (@screen.maxy - 1).times do |i| if !scroll_down && i == 0 result = false break end end when Curses::KEY_PPAGE (@screen.maxy - 1).times do |i| if !scroll_up && i == 0 result = false break end end when Curses::KEY_LEFT, Curses::KEY_CTRL_T, "h" while scroll_up end when Curses::KEY_RIGHT, Curses::KEY_CTRL_B, "l" while scroll_down end when "q" break else @screen.setpos(0, 0) @screen.addstr("[unknown key `#{Curses.keyname(c)}'=#{c}] ") end if !result Curses.beep end @screen.setpos(0, 0) end Curses.close_screen end end # If we are being run as a main program... if __FILE__ == $0 unless ARGV.size == 1 puts "usage: #{$0} file" exit end viewer = FileViewer.new(ARGV[0]) end curses-1.2.4/curses.gemspec0000644000004100000410000000161713267647262015747 0ustar www-datawww-dataGem::Specification.new { |s| s.name = "curses" s.version = "1.2.4" s.author = ["Shugo Maeda", 'Eric Hodel'] s.email = ["shugo@ruby-lang.org", 'drbrain@segment7.net'] s.homepage = "https://github.com/ruby/curses" s.platform = Gem::Platform::RUBY 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])" s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(vendor)/}) } s.extensions = ["ext/curses/extconf.rb"] s.require_path = "lib" s.required_ruby_version = Gem::Requirement.new('>= 2.1.0') s.licenses = ['Ruby', 'BSD-2-Clause'] s.add_development_dependency 'bundler' s.add_development_dependency 'rake' s.add_development_dependency 'rake-compiler' }