├── EXPERIMENTAL ├── CREDITS ├── tests ├── 004.phpt ├── 001.phpt ├── 006.phpt ├── 005.phpt ├── 002.phpt └── 003.phpt ├── config.w32 ├── README.md ├── config.m4 ├── package.xml ├── php_termbox.h ├── constants.h ├── LICENSE ├── termbox.c └── examples └── termbox.php /EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | termbox 2 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for defined constants 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 5 | --FILE-- 6 | 5 | --FILE-- 6 | 5 | --FILE-- 6 | 5 | --FILE-- 6 | 8 | --FILE-- 9 | 19 | --EXPECT-- 20 | string(1) "A" 21 | string(1) "0" 22 | string(1) " " 23 | string(0) "" 24 | bool(true) 25 | int(1) 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | termbox-php 2 | =========== 3 | 4 | termbox-php is a termbox wrapper for PHP. Termbox is a robust, minimal 5 | alternative to ncurses. See https://github.com/nsf/termbox 6 | 7 | To install: 8 | 9 | $ # Follow installation instructions for termbox 10 | $ 11 | $ # Clone repo 12 | $ git clone https://github.com/adsr/termbox-php.git 13 | $ cd termbox-php 14 | $ 15 | $ # Build extension 16 | $ phpize && ./configure && make 17 | $ 18 | $ # Run keyboard demo 19 | $ php -denable_dl=on -dextension=`pwd`/modules/termbox.so examples/termbox.php 20 | $ 21 | $ # Optionally install 22 | $ sudo make install 23 | 24 | Screenshot of termbox-php in action: 25 | 26 | ![termbox-php in action](http://i.imgur.com/vI52dsl.png) 27 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(termbox, for termbox support, 2 | [ --with-termbox Include termbox support]) 3 | 4 | if test "$PHP_TERMBOX" != "no"; then 5 | dnl 6 | dnl Find header files 7 | dnl 8 | SEARCH_PATH="/usr/local /usr" 9 | SEARCH_FOR="/include/termbox.h" 10 | if test -r $PHP_TERMBOX/$SEARCH_FOR; then 11 | TERMBOX_DIR=$PHP_TERMBOX 12 | else 13 | AC_MSG_CHECKING([for termbox files in default path]) 14 | for i in $SEARCH_PATH ; do 15 | if test -r $i/$SEARCH_FOR; then 16 | TERMBOX_DIR=$i 17 | AC_MSG_RESULT(found in $i) 18 | fi 19 | done 20 | fi 21 | if test -z "$TERMBOX_DIR"; then 22 | AC_MSG_RESULT([not found]) 23 | AC_MSG_ERROR([Please install termbox development files]) 24 | fi 25 | PHP_ADD_INCLUDE($TERMBOX_DIR/include) 26 | 27 | dnl 28 | dnl Check library 29 | dnl 30 | LIBNAME=termbox 31 | LIBSYMBOL=tb_init 32 | PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 33 | [ 34 | PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $TERMBOX_DIR/$PHP_LIBDIR, TERMBOX_SHARED_LIBADD) 35 | AC_DEFINE(HAVE_TERMBOXLIB,1,[ ]) 36 | ],[ 37 | AC_MSG_ERROR([wrong termbox lib version or lib not found]) 38 | ],[ 39 | -L$TERMBOX_DIR/$PHP_LIBDIR -lm 40 | ]) 41 | PHP_SUBST(TERMBOX_SHARED_LIBADD) 42 | 43 | PHP_NEW_EXTENSION(termbox, termbox.c, $ext_shared) 44 | fi 45 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | termbox 4 | pecl.php.net 5 | a termbox wrapper for PHP 6 | termbox is a robust, minimal alternative to ncurses. termbox-php is a wrapper 7 | extension that provides termbox functionality in PHP land. 8 | 9 | See https://github.com/adsr/termbox-php for the source distribution. 10 | See https://github.com/nsf/termbox for the underlying library. 11 | 12 | Adam Saponara 13 | as 14 | as@php.net 15 | yes 16 | 17 | 2014-11-20 18 | 19 | 20 | 0.1.2 21 | 0.1.0 22 | 23 | 24 | beta 25 | beta 26 | 27 | Apache 28 | fix termbox_peek_event return value 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 5 63 | 64 | 65 | 1.4.8 66 | 67 | 68 | 69 | termbox 70 | 71 | 72 | 73 | 74 | 0.1.2 75 | 0.1.0 76 | 77 | 78 | beta 79 | beta 80 | 81 | 2014-11-20 82 | Apache 83 | fix termbox_peek_event return value 84 | 85 | 86 | 87 | 0.1.1 88 | 0.1.1 89 | 90 | 91 | beta 92 | beta 93 | 94 | 2014-09-13 95 | Apache 96 | build fixes; arginfo 97 | 98 | 99 | 100 | 0.1.0 101 | 0.1.0 102 | 103 | 104 | beta 105 | beta 106 | 107 | 2014-09-11 108 | Apache 109 | initial release 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /php_termbox.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | termbox | 4 | +----------------------------------------------------------------------+ 5 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 6 | | may not use this file except in compliance with the License. You may | 7 | | obtain a copy of the License at | 8 | | http://www.apache.org/licenses/LICENSE-2.0 | 9 | | | 10 | | Unless required by applicable law or agreed to in writing, software | 11 | | distributed under the License is distributed on an "AS IS" BASIS, | 12 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 13 | | implied. See the License for the specific language governing | 14 | | permissions and limitations under the License. | 15 | +----------------------------------------------------------------------+ 16 | | Author: Adam Saponara | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifndef PHP_TERMBOX_H 23 | #define PHP_TERMBOX_H 24 | 25 | extern zend_module_entry termbox_module_entry; 26 | #define phpext_termbox_ptr &termbox_module_entry 27 | 28 | #ifdef PHP_WIN32 29 | # define PHP_TERMBOX_API __declspec(dllexport) 30 | #elif defined(__GNUC__) && __GNUC__ >= 4 31 | # define PHP_TERMBOX_API __attribute__ ((visibility("default"))) 32 | #else 33 | # define PHP_TERMBOX_API 34 | #endif 35 | 36 | #ifdef ZTS 37 | #include "TSRM.h" 38 | #endif 39 | 40 | #define PHP_TERMBOX_VERSION "0.1.2" 41 | 42 | #include 43 | 44 | #define TB_ERROR_NONE 0 45 | #define TB_ERROR_NOT_INITIALIZED -100 46 | #define TB_ERROR_ALREADY_INITIALIZED -101 47 | #define TB_ERROR_COULD_NOT_READ_INPUT -102 48 | #define TB_ERROR_INVALID_MODE -103 49 | 50 | #define PHP_TERMBOX_ENSURE_INITIALIZED() do { \ 51 | if (TERMBOX_G(is_initialized) != 1) { \ 52 | TERMBOX_G(last_error) = TB_ERROR_NOT_INITIALIZED; \ 53 | RETURN_FALSE; \ 54 | } \ 55 | } while (0) 56 | 57 | ZEND_BEGIN_MODULE_GLOBALS(termbox) 58 | int is_initialized; 59 | int last_error; 60 | ZEND_END_MODULE_GLOBALS(termbox) 61 | 62 | PHP_MINIT_FUNCTION(termbox); 63 | PHP_MSHUTDOWN_FUNCTION(termbox); 64 | PHP_MINFO_FUNCTION(termbox); 65 | 66 | PHP_FUNCTION(termbox_init); 67 | PHP_FUNCTION(termbox_shutdown); 68 | PHP_FUNCTION(termbox_width); 69 | PHP_FUNCTION(termbox_height); 70 | PHP_FUNCTION(termbox_clear); 71 | PHP_FUNCTION(termbox_set_clear_attributes); 72 | PHP_FUNCTION(termbox_present); 73 | PHP_FUNCTION(termbox_set_cursor); 74 | PHP_FUNCTION(termbox_change_cell); 75 | PHP_FUNCTION(termbox_set_input_mode); 76 | PHP_FUNCTION(termbox_get_input_mode); 77 | PHP_FUNCTION(termbox_set_output_mode); 78 | PHP_FUNCTION(termbox_get_output_mode); 79 | PHP_FUNCTION(termbox_peek_event); 80 | PHP_FUNCTION(termbox_poll_event); 81 | PHP_FUNCTION(termbox_utf8_char_to_unicode); 82 | PHP_FUNCTION(termbox_utf8_unicode_to_char); 83 | PHP_FUNCTION(termbox_print); 84 | PHP_FUNCTION(termbox_last_error); 85 | 86 | #ifdef ZTS 87 | #define TERMBOX_G(v) TSRMG(termbox_globals_id, zend_termbox_globals *, v) 88 | #else 89 | #define TERMBOX_G(v) (termbox_globals.v) 90 | #endif 91 | 92 | #if PHP_MAJOR_VERSION < 7 93 | typedef long zend_long; 94 | typedef int strsize; 95 | #define TERMBOX_RETSTRL(a,l) RETURN_STRINGL(a,l,1) 96 | #else 97 | typedef size_t strsize; 98 | #define TSRMLS_CC 99 | #define TERMBOX_RETSTRL(a,l) RETURN_STRINGL(a,l) 100 | #endif 101 | 102 | #endif /* PHP_TERMBOX_H */ 103 | 104 | /* 105 | * Local variables: 106 | * tab-width: 4 107 | * c-basic-offset: 4 108 | * End: 109 | * vim600: noet sw=4 ts=4 fdm=marker 110 | * vim<600: noet sw=4 ts=4 111 | */ 112 | -------------------------------------------------------------------------------- /constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | termbox | 4 | +----------------------------------------------------------------------+ 5 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 6 | | may not use this file except in compliance with the License. You may | 7 | | obtain a copy of the License at | 8 | | http://www.apache.org/licenses/LICENSE-2.0 | 9 | | | 10 | | Unless required by applicable law or agreed to in writing, software | 11 | | distributed under the License is distributed on an "AS IS" BASIS, | 12 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 13 | | implied. See the License for the specific language governing | 14 | | permissions and limitations under the License. | 15 | +----------------------------------------------------------------------+ 16 | | Author: Adam Saponara | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | #ifndef PHP_TERMBOX_CONSTANTS_H 21 | #define PHP_TERMBOX_CONSTANTS_H 22 | 23 | /** termbox constants */ 24 | PHP_TERMBOX_CONSTANT(TB_KEY_F1) 25 | PHP_TERMBOX_CONSTANT(TB_KEY_F2) 26 | PHP_TERMBOX_CONSTANT(TB_KEY_F3) 27 | PHP_TERMBOX_CONSTANT(TB_KEY_F4) 28 | PHP_TERMBOX_CONSTANT(TB_KEY_F5) 29 | PHP_TERMBOX_CONSTANT(TB_KEY_F6) 30 | PHP_TERMBOX_CONSTANT(TB_KEY_F7) 31 | PHP_TERMBOX_CONSTANT(TB_KEY_F8) 32 | PHP_TERMBOX_CONSTANT(TB_KEY_F9) 33 | PHP_TERMBOX_CONSTANT(TB_KEY_F10) 34 | PHP_TERMBOX_CONSTANT(TB_KEY_F11) 35 | PHP_TERMBOX_CONSTANT(TB_KEY_F12) 36 | PHP_TERMBOX_CONSTANT(TB_KEY_INSERT) 37 | PHP_TERMBOX_CONSTANT(TB_KEY_DELETE) 38 | PHP_TERMBOX_CONSTANT(TB_KEY_HOME) 39 | PHP_TERMBOX_CONSTANT(TB_KEY_END) 40 | PHP_TERMBOX_CONSTANT(TB_KEY_PGUP) 41 | PHP_TERMBOX_CONSTANT(TB_KEY_PGDN) 42 | PHP_TERMBOX_CONSTANT(TB_KEY_ARROW_UP) 43 | PHP_TERMBOX_CONSTANT(TB_KEY_ARROW_DOWN) 44 | PHP_TERMBOX_CONSTANT(TB_KEY_ARROW_LEFT) 45 | PHP_TERMBOX_CONSTANT(TB_KEY_ARROW_RIGHT) 46 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_TILDE) 47 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_2) 48 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_A) 49 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_B) 50 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_C) 51 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_D) 52 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_E) 53 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_F) 54 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_G) 55 | PHP_TERMBOX_CONSTANT(TB_KEY_BACKSPACE) 56 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_H) 57 | PHP_TERMBOX_CONSTANT(TB_KEY_TAB) 58 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_I) 59 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_J) 60 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_K) 61 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_L) 62 | PHP_TERMBOX_CONSTANT(TB_KEY_ENTER) 63 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_M) 64 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_N) 65 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_O) 66 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_P) 67 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_Q) 68 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_R) 69 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_S) 70 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_T) 71 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_U) 72 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_V) 73 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_W) 74 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_X) 75 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_Y) 76 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_Z) 77 | PHP_TERMBOX_CONSTANT(TB_KEY_ESC) 78 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_LSQ_BRACKET) 79 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_3) 80 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_4) 81 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_BACKSLASH) 82 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_5) 83 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_RSQ_BRACKET) 84 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_6) 85 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_7) 86 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_SLASH) 87 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_UNDERSCORE) 88 | PHP_TERMBOX_CONSTANT(TB_KEY_SPACE) 89 | PHP_TERMBOX_CONSTANT(TB_KEY_BACKSPACE2) 90 | PHP_TERMBOX_CONSTANT(TB_KEY_CTRL_8) 91 | PHP_TERMBOX_CONSTANT(TB_MOD_ALT) 92 | PHP_TERMBOX_CONSTANT(TB_DEFAULT) 93 | PHP_TERMBOX_CONSTANT(TB_BLACK) 94 | PHP_TERMBOX_CONSTANT(TB_RED) 95 | PHP_TERMBOX_CONSTANT(TB_GREEN) 96 | PHP_TERMBOX_CONSTANT(TB_YELLOW) 97 | PHP_TERMBOX_CONSTANT(TB_BLUE) 98 | PHP_TERMBOX_CONSTANT(TB_MAGENTA) 99 | PHP_TERMBOX_CONSTANT(TB_CYAN) 100 | PHP_TERMBOX_CONSTANT(TB_WHITE) 101 | PHP_TERMBOX_CONSTANT(TB_BOLD) 102 | PHP_TERMBOX_CONSTANT(TB_UNDERLINE) 103 | PHP_TERMBOX_CONSTANT(TB_REVERSE) 104 | PHP_TERMBOX_CONSTANT(TB_EVENT_KEY) 105 | PHP_TERMBOX_CONSTANT(TB_EVENT_RESIZE) 106 | PHP_TERMBOX_CONSTANT(TB_EUNSUPPORTED_TERMINAL) 107 | PHP_TERMBOX_CONSTANT(TB_EFAILED_TO_OPEN_TTY) 108 | PHP_TERMBOX_CONSTANT(TB_EPIPE_TRAP_ERROR) 109 | PHP_TERMBOX_CONSTANT(TB_HIDE_CURSOR) 110 | PHP_TERMBOX_CONSTANT(TB_INPUT_CURRENT) 111 | PHP_TERMBOX_CONSTANT(TB_INPUT_ESC) 112 | PHP_TERMBOX_CONSTANT(TB_INPUT_ALT) 113 | PHP_TERMBOX_CONSTANT(TB_OUTPUT_CURRENT) 114 | PHP_TERMBOX_CONSTANT(TB_OUTPUT_NORMAL) 115 | PHP_TERMBOX_CONSTANT(TB_OUTPUT_256) 116 | PHP_TERMBOX_CONSTANT(TB_OUTPUT_216) 117 | PHP_TERMBOX_CONSTANT(TB_OUTPUT_GRAYSCALE) 118 | PHP_TERMBOX_CONSTANT(TB_EOF) 119 | 120 | /** termbox-php constants */ 121 | PHP_TERMBOX_CONSTANT(TB_ERROR_NONE) 122 | PHP_TERMBOX_CONSTANT(TB_ERROR_NOT_INITIALIZED) 123 | PHP_TERMBOX_CONSTANT(TB_ERROR_ALREADY_INITIALIZED) 124 | PHP_TERMBOX_CONSTANT(TB_ERROR_COULD_NOT_READ_INPUT) 125 | PHP_TERMBOX_CONSTANT(TB_ERROR_INVALID_MODE) 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /termbox.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | termbox | 4 | +----------------------------------------------------------------------+ 5 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 6 | | may not use this file except in compliance with the License. You may | 7 | | obtain a copy of the License at | 8 | | http://www.apache.org/licenses/LICENSE-2.0 | 9 | | | 10 | | Unless required by applicable law or agreed to in writing, software | 11 | | distributed under the License is distributed on an "AS IS" BASIS, | 12 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 13 | | implied. See the License for the specific language governing | 14 | | permissions and limitations under the License. | 15 | +----------------------------------------------------------------------+ 16 | | Author: Adam Saponara | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_ini.h" 28 | #include "ext/standard/info.h" 29 | #include "php_termbox.h" 30 | 31 | #include 32 | 33 | ZEND_DECLARE_MODULE_GLOBALS(termbox) 34 | 35 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_none, 0, 0, 0) 36 | ZEND_END_ARG_INFO() 37 | 38 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_set_clear_attributes, 0, 0, 2) 39 | ZEND_ARG_INFO(0, fg) 40 | ZEND_ARG_INFO(0, bg) 41 | ZEND_END_ARG_INFO() 42 | 43 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_set_cursor, 0, 0, 2) 44 | ZEND_ARG_INFO(0, x) 45 | ZEND_ARG_INFO(0, y) 46 | ZEND_END_ARG_INFO() 47 | 48 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_change_cell, 0, 0, 5) 49 | ZEND_ARG_INFO(0, x) 50 | ZEND_ARG_INFO(0, y) 51 | ZEND_ARG_INFO(0, ch) 52 | ZEND_ARG_INFO(0, fg) 53 | ZEND_ARG_INFO(0, bg) 54 | ZEND_END_ARG_INFO() 55 | 56 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_mode, 0, 0, 1) 57 | ZEND_ARG_INFO(0, mode) 58 | ZEND_END_ARG_INFO() 59 | 60 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_peek_event, 0, 0, 1) 61 | ZEND_ARG_INFO(0, timeout_ms) 62 | ZEND_END_ARG_INFO() 63 | 64 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_utf8_char_to_unicode, 0, 0, 1) 65 | ZEND_ARG_INFO(0, char) 66 | ZEND_END_ARG_INFO() 67 | 68 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_utf8_unicode_to_char, 0, 0, 1) 69 | ZEND_ARG_INFO(0, unicode) 70 | ZEND_END_ARG_INFO() 71 | 72 | ZEND_BEGIN_ARG_INFO_EX(arginfo_termbox_print, 0, 0, 5) 73 | ZEND_ARG_INFO(0, str) 74 | ZEND_ARG_INFO(0, x) 75 | ZEND_ARG_INFO(0, y) 76 | ZEND_ARG_INFO(0, fg) 77 | ZEND_ARG_INFO(0, bg) 78 | ZEND_END_ARG_INFO() 79 | 80 | /* {{{ termbox_functions[] 81 | * 82 | * Every user visible function must have an entry in termbox_functions[]. 83 | */ 84 | const zend_function_entry termbox_functions[] = { 85 | PHP_FE(termbox_init, arginfo_termbox_none) 86 | PHP_FE(termbox_shutdown, arginfo_termbox_none) 87 | PHP_FE(termbox_width, arginfo_termbox_none) 88 | PHP_FE(termbox_height, arginfo_termbox_none) 89 | PHP_FE(termbox_clear, arginfo_termbox_none) 90 | PHP_FE(termbox_set_clear_attributes, arginfo_termbox_set_clear_attributes) 91 | PHP_FE(termbox_present, arginfo_termbox_none) 92 | PHP_FE(termbox_set_cursor, arginfo_termbox_set_cursor) 93 | PHP_FE(termbox_change_cell, arginfo_termbox_change_cell) 94 | PHP_FE(termbox_set_input_mode, arginfo_termbox_mode) 95 | PHP_FE(termbox_get_input_mode, arginfo_termbox_none) 96 | PHP_FE(termbox_set_output_mode, arginfo_termbox_mode) 97 | PHP_FE(termbox_get_output_mode, arginfo_termbox_none) 98 | PHP_FE(termbox_peek_event, arginfo_termbox_peek_event) 99 | PHP_FE(termbox_poll_event, arginfo_termbox_none) 100 | PHP_FE(termbox_utf8_char_to_unicode, arginfo_termbox_utf8_char_to_unicode) 101 | PHP_FE(termbox_utf8_unicode_to_char, arginfo_termbox_utf8_unicode_to_char) 102 | PHP_FE(termbox_print, arginfo_termbox_print) 103 | PHP_FE(termbox_last_error, arginfo_termbox_none) 104 | #ifdef PHP_FE_END 105 | PHP_FE_END /* Must be the last line in termbox_functions[] */ 106 | #else 107 | {NULL, NULL, NULL} 108 | #endif 109 | }; 110 | /* }}} */ 111 | 112 | /* {{{ termbox_module_entry 113 | */ 114 | zend_module_entry termbox_module_entry = { 115 | #if ZEND_MODULE_API_NO >= 20010901 116 | STANDARD_MODULE_HEADER, 117 | #endif 118 | "termbox", 119 | termbox_functions, 120 | PHP_MINIT(termbox), 121 | PHP_MSHUTDOWN(termbox), 122 | NULL, 123 | NULL, 124 | PHP_MINFO(termbox), 125 | #if ZEND_MODULE_API_NO >= 20010901 126 | PHP_TERMBOX_VERSION, 127 | #endif 128 | STANDARD_MODULE_PROPERTIES 129 | }; 130 | /* }}} */ 131 | 132 | #ifdef COMPILE_DL_TERMBOX 133 | ZEND_GET_MODULE(termbox) 134 | #endif 135 | 136 | /* {{{ 137 | * Initialize module globals */ 138 | static void _termbox_init_globals(zend_termbox_globals *g) 139 | { 140 | memset(g, 0, sizeof(zend_termbox_globals)); 141 | } 142 | /* }}} */ 143 | 144 | /* {{{ PHP_MINIT_FUNCTION 145 | */ 146 | PHP_MINIT_FUNCTION(termbox) 147 | { 148 | /** Init globals */ 149 | ZEND_INIT_MODULE_GLOBALS(termbox, _termbox_init_globals, NULL); 150 | 151 | /** Register constants */ 152 | #define PHP_TERMBOX_CONSTANT(NAME) REGISTER_LONG_CONSTANT(#NAME, NAME, CONST_CS | CONST_PERSISTENT); 153 | #include "constants.h" 154 | #undef PHP_TERMBOX_CONSTANT 155 | return SUCCESS; 156 | } 157 | /* }}} */ 158 | 159 | /* {{{ PHP_MSHUTDOWN_FUNCTION 160 | */ 161 | PHP_MSHUTDOWN_FUNCTION(termbox) 162 | { 163 | return SUCCESS; 164 | } 165 | /* }}} */ 166 | 167 | /* {{{ PHP_MINFO_FUNCTION 168 | */ 169 | PHP_MINFO_FUNCTION(termbox) 170 | { 171 | php_info_print_table_start(); 172 | php_info_print_table_header(2, "termbox support", "enabled"); 173 | php_info_print_table_header(2, "extension version", PHP_TERMBOX_VERSION); 174 | /** TODO libtermbox version? */ 175 | php_info_print_table_end(); 176 | } 177 | /* }}} */ 178 | 179 | /* {{{ proto bool termbox_init(void) 180 | Initializes the termbox library. This function should be called before any 181 | other functions. Return FALSE if an error occurs. */ 182 | PHP_FUNCTION(termbox_init) 183 | { 184 | int retval; 185 | if (zend_parse_parameters_none() == FAILURE) { 186 | return; 187 | } 188 | if (TERMBOX_G(is_initialized) == 0) { 189 | /** Attempt to initialize */ 190 | if ((retval = tb_init()) == 0) { 191 | /** Success! Set is_initialized to 1 */ 192 | TERMBOX_G(is_initialized) = 1; 193 | } else { 194 | /** Failure. Set last_error */ 195 | TERMBOX_G(last_error) = retval; 196 | RETURN_FALSE; 197 | } 198 | } else { 199 | /** Already initialized. Set last_error */ 200 | TERMBOX_G(last_error) = TB_ERROR_ALREADY_INITIALIZED; 201 | RETURN_FALSE; 202 | } 203 | RETURN_TRUE; 204 | } 205 | /* }}} */ 206 | 207 | /* {{{ proto bool termbox_shutdown(void) 208 | After successful initialization, the library must be finalized using this 209 | function. Return FALSE if not initialized yet. */ 210 | PHP_FUNCTION(termbox_shutdown) 211 | { 212 | if (zend_parse_parameters_none() == FAILURE) { 213 | return; 214 | } 215 | PHP_TERMBOX_ENSURE_INITIALIZED(); 216 | tb_shutdown(); 217 | RETURN_TRUE; 218 | } 219 | /* }}} */ 220 | 221 | /* {{{ proto mixed termbox_width(void) 222 | Returns the width of the buffer. Return FALSE if not initialized yet. */ 223 | PHP_FUNCTION(termbox_width) 224 | { 225 | if (zend_parse_parameters_none() == FAILURE) { 226 | return; 227 | } 228 | PHP_TERMBOX_ENSURE_INITIALIZED(); 229 | RETURN_LONG(tb_width()); 230 | } 231 | /* }}} */ 232 | 233 | /* {{{ proto mixed termbox_height(void) 234 | Returns the height of the buffer. Return FALSE if not initialized yet. */ 235 | PHP_FUNCTION(termbox_height) 236 | { 237 | if (zend_parse_parameters_none() == FAILURE) { 238 | return; 239 | } 240 | PHP_TERMBOX_ENSURE_INITIALIZED(); 241 | RETURN_LONG(tb_height()); 242 | } 243 | /* }}} */ 244 | 245 | /* {{{ proto bool termbox_clear(void) 246 | Clears the buffer using TB_DEFAULT color or the color/attributes set by 247 | termbox_set_clear_attributes(). Return FALSE if not initialized yet. */ 248 | PHP_FUNCTION(termbox_clear) 249 | { 250 | if (zend_parse_parameters_none() == FAILURE) { 251 | return; 252 | } 253 | PHP_TERMBOX_ENSURE_INITIALIZED(); 254 | tb_clear(); 255 | RETURN_TRUE; 256 | } 257 | /* }}} */ 258 | 259 | /* {{{ proto bool termbox_set_clear_attributes(int fg, int bg) 260 | Sets the default foreground and background attributes. Return FALSE if not 261 | initialized yet. */ 262 | PHP_FUNCTION(termbox_set_clear_attributes) 263 | { 264 | zend_long fg, bg; 265 | 266 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &fg, &bg) == FAILURE) { 267 | return; 268 | } 269 | PHP_TERMBOX_ENSURE_INITIALIZED(); 270 | tb_set_clear_attributes((uint16_t)fg, (uint16_t)bg); 271 | RETURN_TRUE; 272 | } 273 | /* }}} */ 274 | 275 | /* {{{ proto bool termbox_present() 276 | Syncronizes the internal back buffer with the terminal. Return FALSE if not 277 | initialized yet. */ 278 | PHP_FUNCTION(termbox_present) 279 | { 280 | if (zend_parse_parameters_none() == FAILURE) { 281 | return; 282 | } 283 | PHP_TERMBOX_ENSURE_INITIALIZED(); 284 | tb_present(); 285 | RETURN_TRUE; 286 | } 287 | /* }}} */ 288 | 289 | /* {{{ proto bool termbox_set_cursor(int x, int y) 290 | Sets the position of the cursor. Upper-left character is (0, 0). If you 291 | pass TB_HIDE_CURSOR as both coordinates, then the cursor will be hidden. 292 | Cursor is hidden by default. Return FALSE if not initialized yet. */ 293 | PHP_FUNCTION(termbox_set_cursor) 294 | { 295 | zend_long x, y; 296 | 297 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &x, &y) == FAILURE) { 298 | return; 299 | } 300 | PHP_TERMBOX_ENSURE_INITIALIZED(); 301 | tb_set_clear_attributes((int)x, (int)y); 302 | RETURN_TRUE; 303 | } 304 | /* }}} */ 305 | 306 | /* {{{ proto bool termbox_change_cell(int x, int y, int ch, int fg, int bg) 307 | Changes cell's parameters in the internal back buffer at the specified 308 | position. Return FALSE if not initialized yet. */ 309 | PHP_FUNCTION(termbox_change_cell) 310 | { 311 | zend_long x, y, ch, fg, bg; 312 | 313 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllll", &x, &y, &ch, &fg, &bg) == FAILURE) { 314 | return; 315 | } 316 | PHP_TERMBOX_ENSURE_INITIALIZED(); 317 | tb_change_cell((int)x, (int)y, (uint32_t)ch, (uint16_t)fg, (uint16_t)bg); 318 | RETURN_TRUE; 319 | } 320 | /* }}} */ 321 | 322 | /* {{{ proto bool termbox_set_input_mode(int mode) 323 | Sets the termbox input mode: TB_INPUT_ESC or TB_INPUT_ALT. Return FALSE 324 | if not yet initialized. */ 325 | PHP_FUNCTION(termbox_set_input_mode) 326 | { 327 | zend_long mode; 328 | 329 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) { 330 | return; 331 | } 332 | PHP_TERMBOX_ENSURE_INITIALIZED(); 333 | if (mode != TB_INPUT_ESC && mode != TB_INPUT_ALT) { 334 | TERMBOX_G(last_error) = TB_ERROR_INVALID_MODE; 335 | RETURN_FALSE; 336 | } 337 | tb_select_input_mode((int)mode); 338 | RETURN_TRUE; 339 | } 340 | /* }}} */ 341 | 342 | /* {{{ proto mixed termbox_get_input_mode() 343 | Return the current termbox input mode: TB_INPUT_ESC or TB_INPUT_ALT. 344 | Return FALSE if not yet initialized. */ 345 | PHP_FUNCTION(termbox_get_input_mode) { 346 | if (zend_parse_parameters_none() == FAILURE) { 347 | return; 348 | } 349 | PHP_TERMBOX_ENSURE_INITIALIZED(); 350 | RETURN_LONG(tb_select_input_mode(TB_INPUT_CURRENT)); 351 | } 352 | /* }}} */ 353 | 354 | /* {{{ proto bool termbox_set_output_mode(int mode) 355 | Sets the termbox output mode. Termbox has three output options: 356 | TB_OUTPUT_256, TB_OUTPUT_216, or TB_OUTPUT_GRAYSCALE. Return FALSE if not 357 | yet initialized. */ 358 | PHP_FUNCTION(termbox_set_output_mode) 359 | { 360 | zend_long mode; 361 | 362 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) { 363 | return; 364 | } 365 | PHP_TERMBOX_ENSURE_INITIALIZED(); 366 | if (mode != TB_OUTPUT_256 && mode != TB_OUTPUT_216 && mode != TB_OUTPUT_GRAYSCALE) { 367 | TERMBOX_G(last_error) = TB_ERROR_INVALID_MODE; 368 | RETURN_FALSE; 369 | } 370 | tb_select_output_mode((int)mode); 371 | RETURN_TRUE; 372 | } 373 | /* }}} */ 374 | 375 | /* {{{ proto mixed termbox_get_output_mode() 376 | Return the current termbox output mode: TB_OUTPUT_256, TB_OUTPUT_216, or 377 | TB_OUTPUT_GRAYSCALE. Return FALSE if not yet initialized. */ 378 | PHP_FUNCTION(termbox_get_output_mode) { 379 | if (zend_parse_parameters_none() == FAILURE) { 380 | return; 381 | } 382 | PHP_TERMBOX_ENSURE_INITIALIZED(); 383 | RETURN_LONG(tb_select_output_mode(TB_OUTPUT_CURRENT)); 384 | } 385 | /* }}} */ 386 | 387 | /* {{{ Convert a termbox event to a PHP array 388 | */ 389 | static void _termbox_event_to_php_array(struct tb_event *event, zval *event_arr) { 390 | add_assoc_long_ex(event_arr, "type", sizeof("type"), (long)event->type); 391 | add_assoc_long_ex(event_arr, "mod", sizeof("mod"), (long)event->mod); 392 | add_assoc_long_ex(event_arr, "key", sizeof("key"), (long)event->key); 393 | add_assoc_long_ex(event_arr, "ch", sizeof("ch"), (long)event->ch); 394 | add_assoc_long_ex(event_arr, "w", sizeof("w"), (long)event->w); 395 | add_assoc_long_ex(event_arr, "h", sizeof("h"), (long)event->h); 396 | } 397 | /* }}} */ 398 | 399 | /* {{{ proto mixed termbox_peek_event(int timeout_ms) 400 | Wait for an event up to 'timeout' milliseconds. If an event was available, 401 | return an array containing event info. If no event was available, return 402 | NULL. If an error occurrs, return FALSE. */ 403 | PHP_FUNCTION(termbox_peek_event) 404 | { 405 | zend_long timeout_ms; 406 | struct tb_event event; 407 | int rc; 408 | 409 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &timeout_ms) == FAILURE) { 410 | return; 411 | } 412 | 413 | PHP_TERMBOX_ENSURE_INITIALIZED(); 414 | 415 | rc = tb_peek_event(&event, (int)timeout_ms); 416 | if (rc == -1) { 417 | TERMBOX_G(last_error) = TB_ERROR_COULD_NOT_READ_INPUT; 418 | RETURN_FALSE; 419 | } else if (rc == 0) { 420 | RETURN_NULL(); 421 | } 422 | 423 | array_init(return_value); 424 | _termbox_event_to_php_array(&event, return_value); 425 | } 426 | /* }}} */ 427 | 428 | /* {{{ proto mixed termbox_poll_event() 429 | Wait for an event forever and return an array containing event info. If an 430 | error occurs, return FALSE. */ 431 | PHP_FUNCTION(termbox_poll_event) 432 | { 433 | struct tb_event event; 434 | 435 | if (zend_parse_parameters_none() == FAILURE) { 436 | return; 437 | } 438 | 439 | PHP_TERMBOX_ENSURE_INITIALIZED(); 440 | 441 | if (tb_poll_event(&event) == -1) { 442 | TERMBOX_G(last_error) = TB_ERROR_COULD_NOT_READ_INPUT; 443 | RETURN_FALSE; 444 | } 445 | 446 | array_init(return_value); 447 | _termbox_event_to_php_array(&event, return_value); 448 | } 449 | /* }}} */ 450 | 451 | /* {{{ proto mixed termbox_utf8_char_to_unicode(string char) 452 | Return the 32-bit unicode value of 'char' or FALSE if 'char' is empty. */ 453 | PHP_FUNCTION(termbox_utf8_char_to_unicode) 454 | { 455 | char *str; 456 | strsize str_len; 457 | uint32_t unicode_int; 458 | 459 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { 460 | return; 461 | } 462 | 463 | unicode_int = 0; 464 | if (str_len < 1 || tb_utf8_char_to_unicode(&unicode_int, str) == TB_EOF) { 465 | RETURN_FALSE; 466 | } 467 | RETURN_LONG(unicode_int); 468 | } 469 | /* }}} */ 470 | 471 | /* {{{ proto string termbox_utf8_unicode_to_char(int char) 472 | Return the UTF8 string version of the 32-bit unicode value 'char'. */ 473 | PHP_FUNCTION(termbox_utf8_unicode_to_char) 474 | { 475 | char str[7]; 476 | int str_len; 477 | zend_long unicode; 478 | 479 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &unicode) == FAILURE) { 480 | return; 481 | } 482 | 483 | if (unicode > 0) { 484 | str_len = tb_utf8_unicode_to_char((char*)&str, (uint32_t)unicode); 485 | } else { 486 | str[0] = '\0'; 487 | str_len = 0; 488 | } 489 | 490 | TERMBOX_RETSTRL(str, str_len); 491 | } 492 | /* }}} */ 493 | 494 | /* {{{ proto bool termbox_print(string str, int x, int y, int fg, int bg) 495 | Print str at coordinate x, y with attributes fg, bg. If an error occurs, 496 | return FALSE. */ 497 | PHP_FUNCTION(termbox_print) 498 | { 499 | char *str; 500 | strsize str_len; 501 | zend_long x, y, fg, bg; 502 | uint32_t unicode; 503 | 504 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &str, &str_len, &x, &y, &fg, &bg) == FAILURE) { 505 | return; 506 | } 507 | 508 | PHP_TERMBOX_ENSURE_INITIALIZED(); 509 | 510 | if (str_len > 0) { 511 | while (*str) { 512 | str += tb_utf8_char_to_unicode(&unicode, str); 513 | tb_change_cell(x, y, unicode, fg, bg); 514 | x += 1; 515 | } 516 | } 517 | 518 | RETURN_TRUE; 519 | } 520 | 521 | /* {{{ proto int termbox_last_error(void) 522 | Returns the last error code. */ 523 | PHP_FUNCTION(termbox_last_error) 524 | { 525 | if (zend_parse_parameters_none() == FAILURE) { 526 | return; 527 | } 528 | RETURN_LONG(TERMBOX_G(last_error)); 529 | } 530 | /* }}} */ 531 | 532 | /* 533 | * Local variables: 534 | * tab-width: 4 535 | * c-basic-offset: 4 536 | * End: 537 | * vim600: noet sw=4 ts=4 fdm=marker 538 | * vim<600: noet sw=4 ts=4 539 | */ 540 | -------------------------------------------------------------------------------- /examples/termbox.php: -------------------------------------------------------------------------------- 1 | ']]; 198 | $K_SLASH = [[36,10,'/']]; 199 | $K_QUESTION = [[36,10,'?']]; 200 | $K_RSHIFT = [[42,10,'S'],[43,10,'H'],[44,10,'I'],[45,10,'F'],[46,10,'T']]; 201 | $K_ARROW_UP = [[54,10,'('],[55,10,0x2191],[56,10,')']]; 202 | $K_K_1 = [[65,10,'1']]; 203 | $K_K_2 = [[68,10,'2']]; 204 | $K_K_3 = [[71,10,'3']]; 205 | $K_K_ENTER = [[74,10,0x2591],[74,11,0x2591],[74,12,0x2591]]; 206 | 207 | $K_LCTRL = [[1,12,'C'],[2,12,'T'],[3,12,'R'],[4,12,'L']]; 208 | $K_LWIN = [[6,12,'W'],[7,12,'I'],[8,12,'N']]; 209 | $K_LALT = [[10,12,'A'],[11,12,'L'],[12,12,'T']]; 210 | $K_SPACE = [ 211 | [14,12,' '],[15,12,' '],[16,12,' '],[17,12,' '],[18,12,' '], 212 | [19,12,'S'],[20,12,'P'],[21,12,'A'],[22,12,'C'],[23,12,'E'], 213 | [24,12,' '],[25,12,' '],[26,12,' '],[27,12,' '],[28,12,' '], 214 | ]; 215 | $K_RALT = [[30,12,'A'],[31,12,'L'],[32,12,'T']]; 216 | $K_RWIN = [[34,12,'W'],[35,12,'I'],[36,12,'N']]; 217 | $K_RPROP = [[38,12,'P'],[39,12,'R'],[40,12,'O'],[41,12,'P']]; 218 | $K_RCTRL = [[43,12,'C'],[44,12,'T'],[45,12,'R'],[46,12,'L']]; 219 | $K_ARROW_LEFT = [[50,12,'('],[51,12,0x2190],[52,12,')']]; 220 | $K_ARROW_DOWN = [[54,12,'('],[55,12,0x2193],[56,12,')']]; 221 | $K_ARROW_RIGHT = [[58,12,'('],[59,12,0x2192],[60,12,')']]; 222 | $K_K_0 = [[65,12,' '],[66,12,'0'],[67,12,' '],[68,12,' ']]; 223 | $K_K_PERIOD = [[71,12,'.']]; 224 | 225 | $combos = [ 226 | [$K_TILDE, $K_2, $K_LCTRL, $K_RCTRL], 227 | [$K_A, $K_LCTRL, $K_RCTRL], 228 | [$K_B, $K_LCTRL, $K_RCTRL], 229 | [$K_C, $K_LCTRL, $K_RCTRL], 230 | [$K_D, $K_LCTRL, $K_RCTRL], 231 | [$K_E, $K_LCTRL, $K_RCTRL], 232 | [$K_F, $K_LCTRL, $K_RCTRL], 233 | [$K_G, $K_LCTRL, $K_RCTRL], 234 | [$K_H, $K_BACKSPACE, $K_LCTRL, $K_RCTRL], 235 | [$K_I, $K_TAB, $K_LCTRL, $K_RCTRL], 236 | [$K_J, $K_LCTRL, $K_RCTRL], 237 | [$K_K, $K_LCTRL, $K_RCTRL], 238 | [$K_L, $K_LCTRL, $K_RCTRL], 239 | [$K_M, $K_ENTER, $K_K_ENTER, $K_LCTRL, $K_RCTRL], 240 | [$K_N, $K_LCTRL, $K_RCTRL], 241 | [$K_O, $K_LCTRL, $K_RCTRL], 242 | [$K_P, $K_LCTRL, $K_RCTRL], 243 | [$K_Q, $K_LCTRL, $K_RCTRL], 244 | [$K_R, $K_LCTRL, $K_RCTRL], 245 | [$K_S, $K_LCTRL, $K_RCTRL], 246 | [$K_T, $K_LCTRL, $K_RCTRL], 247 | [$K_U, $K_LCTRL, $K_RCTRL], 248 | [$K_V, $K_LCTRL, $K_RCTRL], 249 | [$K_W, $K_LCTRL, $K_RCTRL], 250 | [$K_X, $K_LCTRL, $K_RCTRL], 251 | [$K_Y, $K_LCTRL, $K_RCTRL], 252 | [$K_Z, $K_LCTRL, $K_RCTRL], 253 | [$K_LSQB, $K_ESC, $K_3, $K_LCTRL, $K_RCTRL], 254 | [$K_4, $K_BACKSLASH, $K_LCTRL, $K_RCTRL], 255 | [$K_RSQB, $K_5, $K_LCTRL, $K_RCTRL], 256 | [$K_6, $K_LCTRL, $K_RCTRL], 257 | [$K_7, $K_SLASH, $K_MINUS_SHIFT, $K_LCTRL, $K_RCTRL], 258 | [$K_SPACE], 259 | [$K_1_SHIFT,$K_LSHIFT,$K_RSHIFT], 260 | [$K_DOUBLEQUOTE,$K_LSHIFT,$K_RSHIFT], 261 | [$K_3_SHIFT,$K_LSHIFT,$K_RSHIFT], 262 | [$K_4_SHIFT,$K_LSHIFT,$K_RSHIFT], 263 | [$K_5_SHIFT,$K_LSHIFT,$K_RSHIFT], 264 | [$K_7_SHIFT,$K_LSHIFT,$K_RSHIFT], 265 | [$K_QUOTE], 266 | [$K_9_SHIFT,$K_LSHIFT,$K_RSHIFT], 267 | [$K_0_SHIFT,$K_LSHIFT,$K_RSHIFT], 268 | [$K_8_SHIFT,$K_K_STAR,$K_LSHIFT,$K_RSHIFT], 269 | [$K_EQUALS_SHIFT,$K_K_PLUS,$K_LSHIFT,$K_RSHIFT], 270 | [$K_COMMA], 271 | [$K_MINUS,$K_K_MINUS], 272 | [$K_PERIOD,$K_K_PERIOD], 273 | [$K_SLASH,$K_K_SLASH], 274 | [$K_0,$K_K_0], 275 | [$K_1,$K_K_1], 276 | [$K_2,$K_K_2], 277 | [$K_3,$K_K_3], 278 | [$K_4,$K_K_4], 279 | [$K_5,$K_K_5], 280 | [$K_6,$K_K_6], 281 | [$K_7,$K_K_7], 282 | [$K_8,$K_K_8], 283 | [$K_9,$K_K_9], 284 | [$K_PARENTHESIS,$K_LSHIFT,$K_RSHIFT], 285 | [$K_SEMICOLON], 286 | [$K_LANB,$K_LSHIFT,$K_RSHIFT], 287 | [$K_EQUALS], 288 | [$K_RANB,$K_LSHIFT,$K_RSHIFT], 289 | [$K_QUESTION,$K_LSHIFT,$K_RSHIFT], 290 | [$K_2_SHIFT,$K_LSHIFT,$K_RSHIFT], 291 | [$K_A,$K_LSHIFT,$K_RSHIFT], 292 | [$K_B,$K_LSHIFT,$K_RSHIFT], 293 | [$K_C,$K_LSHIFT,$K_RSHIFT], 294 | [$K_D,$K_LSHIFT,$K_RSHIFT], 295 | [$K_E,$K_LSHIFT,$K_RSHIFT], 296 | [$K_F,$K_LSHIFT,$K_RSHIFT], 297 | [$K_G,$K_LSHIFT,$K_RSHIFT], 298 | [$K_H,$K_LSHIFT,$K_RSHIFT], 299 | [$K_I,$K_LSHIFT,$K_RSHIFT], 300 | [$K_J,$K_LSHIFT,$K_RSHIFT], 301 | [$K_K,$K_LSHIFT,$K_RSHIFT], 302 | [$K_L,$K_LSHIFT,$K_RSHIFT], 303 | [$K_M,$K_LSHIFT,$K_RSHIFT], 304 | [$K_N,$K_LSHIFT,$K_RSHIFT], 305 | [$K_O,$K_LSHIFT,$K_RSHIFT], 306 | [$K_P,$K_LSHIFT,$K_RSHIFT], 307 | [$K_Q,$K_LSHIFT,$K_RSHIFT], 308 | [$K_R,$K_LSHIFT,$K_RSHIFT], 309 | [$K_S,$K_LSHIFT,$K_RSHIFT], 310 | [$K_T,$K_LSHIFT,$K_RSHIFT], 311 | [$K_U,$K_LSHIFT,$K_RSHIFT], 312 | [$K_V,$K_LSHIFT,$K_RSHIFT], 313 | [$K_W,$K_LSHIFT,$K_RSHIFT], 314 | [$K_X,$K_LSHIFT,$K_RSHIFT], 315 | [$K_Y,$K_LSHIFT,$K_RSHIFT], 316 | [$K_Z,$K_LSHIFT,$K_RSHIFT], 317 | [$K_LSQB], 318 | [$K_BACKSLASH], 319 | [$K_RSQB], 320 | [$K_6_SHIFT,$K_LSHIFT,$K_RSHIFT], 321 | [$K_MINUS_SHIFT,$K_LSHIFT,$K_RSHIFT], 322 | [$K_TILDE], 323 | [$K_a], 324 | [$K_b], 325 | [$K_c], 326 | [$K_d], 327 | [$K_e], 328 | [$K_f], 329 | [$K_g], 330 | [$K_h], 331 | [$K_i], 332 | [$K_j], 333 | [$K_k], 334 | [$K_l], 335 | [$K_m], 336 | [$K_n], 337 | [$K_o], 338 | [$K_p], 339 | [$K_q], 340 | [$K_r], 341 | [$K_s], 342 | [$K_t], 343 | [$K_u], 344 | [$K_v], 345 | [$K_w], 346 | [$K_x], 347 | [$K_y], 348 | [$K_z], 349 | [$K_LCUB,$K_LSHIFT,$K_RSHIFT], 350 | [$K_BACKSLASH_SHIFT,$K_LSHIFT,$K_RSHIFT], 351 | [$K_RCUB,$K_LSHIFT,$K_RSHIFT], 352 | [$K_TILDE_SHIFT,$K_LSHIFT,$K_RSHIFT], 353 | [$K_8, $K_BACKSPACE, $K_LCTRL, $K_RCTRL] 354 | ]; 355 | 356 | $func_combos = [ 357 | [$K_F1], 358 | [$K_F2], 359 | [$K_F3], 360 | [$K_F4], 361 | [$K_F5], 362 | [$K_F6], 363 | [$K_F7], 364 | [$K_F8], 365 | [$K_F9], 366 | [$K_F10], 367 | [$K_F11], 368 | [$K_F12], 369 | [$K_INS], 370 | [$K_DEL], 371 | [$K_HOM], 372 | [$K_END], 373 | [$K_PGU], 374 | [$K_PGD], 375 | [$K_ARROW_UP], 376 | [$K_ARROW_DOWN], 377 | [$K_ARROW_LEFT], 378 | [$K_ARROW_RIGHT] 379 | ]; 380 | 381 | function printf_tb($x, $y, $fg, $bg, $fmt) { 382 | $buf = vsprintf($fmt, array_slice(func_get_args(), 5)); 383 | termbox_print($buf, $x, $y, $fg, $bg); 384 | } 385 | 386 | function draw_key($ks, $fg, $bg) { 387 | foreach ($ks as $k) { 388 | termbox_change_cell($k[0]+2, $k[1]+4, is_int($k[2]) ? $k[2] : ord($k[2]), $fg, $bg); 389 | } 390 | } 391 | 392 | function draw_keyboard() { 393 | extract($GLOBALS); 394 | termbox_change_cell(0, 0, 0x250C, TB_WHITE, TB_DEFAULT); 395 | termbox_change_cell(79, 0, 0x2510, TB_WHITE, TB_DEFAULT); 396 | termbox_change_cell(0, 23, 0x2514, TB_WHITE, TB_DEFAULT); 397 | termbox_change_cell(79, 23, 0x2518, TB_WHITE, TB_DEFAULT); 398 | 399 | for ($i = 1; $i < 79; ++$i) { 400 | termbox_change_cell($i, 0, 0x2500, TB_WHITE, TB_DEFAULT); 401 | termbox_change_cell($i, 23, 0x2500, TB_WHITE, TB_DEFAULT); 402 | termbox_change_cell($i, 17, 0x2500, TB_WHITE, TB_DEFAULT); 403 | termbox_change_cell($i, 4, 0x2500, TB_WHITE, TB_DEFAULT); 404 | } 405 | for ($i = 1; $i < 23; ++$i) { 406 | termbox_change_cell(0, $i, 0x2502, TB_WHITE, TB_DEFAULT); 407 | termbox_change_cell(79, $i, 0x2502, TB_WHITE, TB_DEFAULT); 408 | } 409 | termbox_change_cell(0, 17, 0x251C, TB_WHITE, TB_DEFAULT); 410 | termbox_change_cell(79, 17, 0x2524, TB_WHITE, TB_DEFAULT); 411 | termbox_change_cell(0, 4, 0x251C, TB_WHITE, TB_DEFAULT); 412 | termbox_change_cell(79, 4, 0x2524, TB_WHITE, TB_DEFAULT); 413 | for ($i = 5; $i < 17; ++$i) { 414 | termbox_change_cell(1, $i, 0x2588, TB_YELLOW, TB_YELLOW); 415 | termbox_change_cell(78, $i, 0x2588, TB_YELLOW, TB_YELLOW); 416 | } 417 | 418 | draw_key($K_ESC, TB_WHITE, TB_BLUE); 419 | draw_key($K_F1, TB_WHITE, TB_BLUE); 420 | draw_key($K_F2, TB_WHITE, TB_BLUE); 421 | draw_key($K_F3, TB_WHITE, TB_BLUE); 422 | draw_key($K_F4, TB_WHITE, TB_BLUE); 423 | draw_key($K_F5, TB_WHITE, TB_BLUE); 424 | draw_key($K_F6, TB_WHITE, TB_BLUE); 425 | draw_key($K_F7, TB_WHITE, TB_BLUE); 426 | draw_key($K_F8, TB_WHITE, TB_BLUE); 427 | draw_key($K_F9, TB_WHITE, TB_BLUE); 428 | draw_key($K_F10, TB_WHITE, TB_BLUE); 429 | draw_key($K_F11, TB_WHITE, TB_BLUE); 430 | draw_key($K_F12, TB_WHITE, TB_BLUE); 431 | draw_key($K_PRN, TB_WHITE, TB_BLUE); 432 | draw_key($K_SCR, TB_WHITE, TB_BLUE); 433 | draw_key($K_BRK, TB_WHITE, TB_BLUE); 434 | draw_key($K_LED1, TB_WHITE, TB_BLUE); 435 | draw_key($K_LED2, TB_WHITE, TB_BLUE); 436 | draw_key($K_LED3, TB_WHITE, TB_BLUE); 437 | 438 | draw_key($K_TILDE, TB_WHITE, TB_BLUE); 439 | draw_key($K_1, TB_WHITE, TB_BLUE); 440 | draw_key($K_2, TB_WHITE, TB_BLUE); 441 | draw_key($K_3, TB_WHITE, TB_BLUE); 442 | draw_key($K_4, TB_WHITE, TB_BLUE); 443 | draw_key($K_5, TB_WHITE, TB_BLUE); 444 | draw_key($K_6, TB_WHITE, TB_BLUE); 445 | draw_key($K_7, TB_WHITE, TB_BLUE); 446 | draw_key($K_8, TB_WHITE, TB_BLUE); 447 | draw_key($K_9, TB_WHITE, TB_BLUE); 448 | draw_key($K_0, TB_WHITE, TB_BLUE); 449 | draw_key($K_MINUS, TB_WHITE, TB_BLUE); 450 | draw_key($K_EQUALS, TB_WHITE, TB_BLUE); 451 | draw_key($K_BACKSLASH, TB_WHITE, TB_BLUE); 452 | draw_key($K_BACKSPACE, TB_WHITE, TB_BLUE); 453 | draw_key($K_INS, TB_WHITE, TB_BLUE); 454 | draw_key($K_HOM, TB_WHITE, TB_BLUE); 455 | draw_key($K_PGU, TB_WHITE, TB_BLUE); 456 | draw_key($K_K_NUMLOCK, TB_WHITE, TB_BLUE); 457 | draw_key($K_K_SLASH, TB_WHITE, TB_BLUE); 458 | draw_key($K_K_STAR, TB_WHITE, TB_BLUE); 459 | draw_key($K_K_MINUS, TB_WHITE, TB_BLUE); 460 | 461 | draw_key($K_TAB, TB_WHITE, TB_BLUE); 462 | draw_key($K_q, TB_WHITE, TB_BLUE); 463 | draw_key($K_w, TB_WHITE, TB_BLUE); 464 | draw_key($K_e, TB_WHITE, TB_BLUE); 465 | draw_key($K_r, TB_WHITE, TB_BLUE); 466 | draw_key($K_t, TB_WHITE, TB_BLUE); 467 | draw_key($K_y, TB_WHITE, TB_BLUE); 468 | draw_key($K_u, TB_WHITE, TB_BLUE); 469 | draw_key($K_i, TB_WHITE, TB_BLUE); 470 | draw_key($K_o, TB_WHITE, TB_BLUE); 471 | draw_key($K_p, TB_WHITE, TB_BLUE); 472 | draw_key($K_LSQB, TB_WHITE, TB_BLUE); 473 | draw_key($K_RSQB, TB_WHITE, TB_BLUE); 474 | draw_key($K_ENTER, TB_WHITE, TB_BLUE); 475 | draw_key($K_DEL, TB_WHITE, TB_BLUE); 476 | draw_key($K_END, TB_WHITE, TB_BLUE); 477 | draw_key($K_PGD, TB_WHITE, TB_BLUE); 478 | draw_key($K_K_7, TB_WHITE, TB_BLUE); 479 | draw_key($K_K_8, TB_WHITE, TB_BLUE); 480 | draw_key($K_K_9, TB_WHITE, TB_BLUE); 481 | draw_key($K_K_PLUS, TB_WHITE, TB_BLUE); 482 | 483 | draw_key($K_CAPS, TB_WHITE, TB_BLUE); 484 | draw_key($K_a, TB_WHITE, TB_BLUE); 485 | draw_key($K_s, TB_WHITE, TB_BLUE); 486 | draw_key($K_d, TB_WHITE, TB_BLUE); 487 | draw_key($K_f, TB_WHITE, TB_BLUE); 488 | draw_key($K_g, TB_WHITE, TB_BLUE); 489 | draw_key($K_h, TB_WHITE, TB_BLUE); 490 | draw_key($K_j, TB_WHITE, TB_BLUE); 491 | draw_key($K_k, TB_WHITE, TB_BLUE); 492 | draw_key($K_l, TB_WHITE, TB_BLUE); 493 | draw_key($K_SEMICOLON, TB_WHITE, TB_BLUE); 494 | draw_key($K_QUOTE, TB_WHITE, TB_BLUE); 495 | draw_key($K_K_4, TB_WHITE, TB_BLUE); 496 | draw_key($K_K_5, TB_WHITE, TB_BLUE); 497 | draw_key($K_K_6, TB_WHITE, TB_BLUE); 498 | 499 | draw_key($K_LSHIFT, TB_WHITE, TB_BLUE); 500 | draw_key($K_z, TB_WHITE, TB_BLUE); 501 | draw_key($K_x, TB_WHITE, TB_BLUE); 502 | draw_key($K_c, TB_WHITE, TB_BLUE); 503 | draw_key($K_v, TB_WHITE, TB_BLUE); 504 | draw_key($K_b, TB_WHITE, TB_BLUE); 505 | draw_key($K_n, TB_WHITE, TB_BLUE); 506 | draw_key($K_m, TB_WHITE, TB_BLUE); 507 | draw_key($K_COMMA, TB_WHITE, TB_BLUE); 508 | draw_key($K_PERIOD, TB_WHITE, TB_BLUE); 509 | draw_key($K_SLASH, TB_WHITE, TB_BLUE); 510 | draw_key($K_RSHIFT, TB_WHITE, TB_BLUE); 511 | draw_key($K_ARROW_UP, TB_WHITE, TB_BLUE); 512 | draw_key($K_K_1, TB_WHITE, TB_BLUE); 513 | draw_key($K_K_2, TB_WHITE, TB_BLUE); 514 | draw_key($K_K_3, TB_WHITE, TB_BLUE); 515 | draw_key($K_K_ENTER, TB_WHITE, TB_BLUE); 516 | 517 | draw_key($K_LCTRL, TB_WHITE, TB_BLUE); 518 | draw_key($K_LWIN, TB_WHITE, TB_BLUE); 519 | draw_key($K_LALT, TB_WHITE, TB_BLUE); 520 | draw_key($K_SPACE, TB_WHITE, TB_BLUE); 521 | draw_key($K_RCTRL, TB_WHITE, TB_BLUE); 522 | draw_key($K_RPROP, TB_WHITE, TB_BLUE); 523 | draw_key($K_RWIN, TB_WHITE, TB_BLUE); 524 | draw_key($K_RALT, TB_WHITE, TB_BLUE); 525 | draw_key($K_ARROW_LEFT, TB_WHITE, TB_BLUE); 526 | draw_key($K_ARROW_DOWN, TB_WHITE, TB_BLUE); 527 | draw_key($K_ARROW_RIGHT, TB_WHITE, TB_BLUE); 528 | draw_key($K_K_0, TB_WHITE, TB_BLUE); 529 | draw_key($K_K_PERIOD, TB_WHITE, TB_BLUE); 530 | 531 | printf_tb(33, 1, TB_MAGENTA | TB_BOLD, TB_DEFAULT, "Keyboard demo!"); 532 | printf_tb(21, 2, TB_MAGENTA, TB_DEFAULT, "(press CTRL+X and then CTRL+Q to exit)"); 533 | printf_tb(15, 3, TB_MAGENTA, TB_DEFAULT, "(press CTRL+X and then CTRL+C to change input mode)"); 534 | 535 | $inputmodemap = [ 536 | '0', 537 | "TB_INPUT_ESC", 538 | "TB_INPUT_ALT" 539 | ]; 540 | printf_tb(3, 18, TB_WHITE, TB_DEFAULT, "Input mode: %s", 541 | $inputmodemap[termbox_get_input_mode()]); 542 | } 543 | 544 | function funckeymap($k) { 545 | $fcmap = [ 546 | "CTRL+2, CTRL+~", 547 | "CTRL+A", 548 | "CTRL+B", 549 | "CTRL+C", 550 | "CTRL+D", 551 | "CTRL+E", 552 | "CTRL+F", 553 | "CTRL+G", 554 | "CTRL+H, BACKSPACE", 555 | "CTRL+I, TAB", 556 | "CTRL+J", 557 | "CTRL+K", 558 | "CTRL+L", 559 | "CTRL+M, ENTER", 560 | "CTRL+N", 561 | "CTRL+O", 562 | "CTRL+P", 563 | "CTRL+Q", 564 | "CTRL+R", 565 | "CTRL+S", 566 | "CTRL+T", 567 | "CTRL+U", 568 | "CTRL+V", 569 | "CTRL+W", 570 | "CTRL+X", 571 | "CTRL+Y", 572 | "CTRL+Z", 573 | "CTRL+3, ESC, CTRL+[", 574 | "CTRL+4, CTRL+\\", 575 | "CTRL+5, CTRL+]", 576 | "CTRL+6", 577 | "CTRL+7, CTRL+/, CTRL+_", 578 | "SPACE" 579 | ]; 580 | $fkmap = [ 581 | "F1", 582 | "F2", 583 | "F3", 584 | "F4", 585 | "F5", 586 | "F6", 587 | "F7", 588 | "F8", 589 | "F9", 590 | "F10", 591 | "F11", 592 | "F12", 593 | "INSERT", 594 | "DELETE", 595 | "HOME", 596 | "END", 597 | "PGUP", 598 | "PGDN", 599 | "ARROW UP", 600 | "ARROW DOWN", 601 | "ARROW LEFT", 602 | "ARROW RIGHT" 603 | ]; 604 | 605 | if ($k == TB_KEY_CTRL_8) 606 | return "CTRL+8, BACKSPACE 2"; /* 0x7F */ 607 | else if ($k >= TB_KEY_ARROW_RIGHT && $k <= 0xFFFF) 608 | return $fkmap[0xFFFF-$k]; 609 | else if ($k <= TB_KEY_SPACE) 610 | return $fcmap[$k]; 611 | return "UNKNOWN"; 612 | } 613 | 614 | function pretty_print_press($ev) { 615 | $buf = termbox_utf8_unicode_to_char($ev['ch']); 616 | 617 | printf_tb(3, 19, TB_WHITE , TB_DEFAULT, "Key: "); 618 | printf_tb(8, 19, TB_YELLOW, TB_DEFAULT, "decimal: %d", $ev['key']); 619 | printf_tb(8, 20, TB_GREEN , TB_DEFAULT, "hex: 0x%X", $ev['key']); 620 | printf_tb(8, 21, TB_CYAN , TB_DEFAULT, "octal: 0%o", $ev['key']); 621 | printf_tb(8, 22, TB_RED , TB_DEFAULT, "string: %s", funckeymap($ev['key'])); 622 | 623 | printf_tb(43, 19, TB_WHITE , TB_DEFAULT, "Char: "); 624 | printf_tb(49, 19, TB_YELLOW, TB_DEFAULT, "decimal: %d", $ev['ch']); 625 | printf_tb(49, 20, TB_GREEN , TB_DEFAULT, "hex: 0x%X", $ev['ch']); 626 | printf_tb(49, 21, TB_CYAN , TB_DEFAULT, "octal: 0%o", $ev['ch']); 627 | printf_tb(49, 22, TB_RED , TB_DEFAULT, "string: %s", $buf); 628 | 629 | printf_tb(43, 18, TB_WHITE, TB_DEFAULT, "Modifier: %s", 630 | ($ev['mod']) ? "TB_MOD_ALT" : "none"); 631 | } 632 | 633 | function pretty_print_resize($ev) { 634 | printf_tb(3, 19, TB_WHITE, TB_DEFAULT, "Resize event: %d x %d", $ev['w'], $ev['h']); 635 | } 636 | 637 | function dispatch_press($ev) { 638 | extract($GLOBALS); 639 | if ($ev['mod'] & TB_MOD_ALT) { 640 | draw_key($K_LALT, TB_WHITE, TB_RED); 641 | draw_key($K_RALT, TB_WHITE, TB_RED); 642 | } 643 | $k = null; 644 | if ($ev['key'] >= TB_KEY_ARROW_RIGHT) { 645 | $k = $func_combos[0xFFFF - $ev['key']]; 646 | } else if ($ev['ch'] < 128) { 647 | if ($ev['ch'] == 0 && $ev['key'] < 128) { 648 | $k = $combos[$ev['key']]; 649 | } else { 650 | $k = $combos[$ev['ch']]; 651 | } 652 | } 653 | if (!$k) { 654 | return; 655 | } 656 | foreach ($k as $key) { 657 | draw_key($key, TB_WHITE, TB_RED); 658 | } 659 | } 660 | 661 | main(); 662 | --------------------------------------------------------------------------------