PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Window.php

https://github.com/jeremyFreeAgent/Console
PHP | 498 lines | 228 code | 106 blank | 164 comment | 18 complexity | 6c1c583ac2b1ca4b8b1d5c8bb29a75f1 MD5 | raw file
  1. <?php
  2. /**
  3. * Hoa
  4. *
  5. *
  6. * @license
  7. *
  8. * New BSD License
  9. *
  10. * Copyright © 2007-2013, Ivan Enderlin. All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * * Neither the name of the Hoa nor the names of its contributors may be
  20. * used to endorse or promote products derived from this software without
  21. * specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  24. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  27. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  30. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  31. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  32. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. namespace {
  36. from('Hoa')
  37. /**
  38. * \Hoa\Console
  39. */
  40. -> import('Console.~')
  41. /**
  42. * \Hoa\Console\Processus
  43. */
  44. -> import('Console.Processus');
  45. }
  46. namespace Hoa\Console {
  47. /**
  48. * Class \Hoa\Console\Window.
  49. *
  50. * Allow to manipulate the window.
  51. *
  52. * We can listen the event channel hoa://Event/Console/Window:resize to detect
  53. * if the window has been resized. Please, see the constructor documentation to
  54. * get more informations.
  55. *
  56. * Please, see C0 and C1 control codes.
  57. *
  58. * @author Ivan Enderlin <ivan.enderlin@hoa-project.net>
  59. * @copyright Copyright © 2007-2013 Ivan Enderlin.
  60. * @license New BSD License
  61. */
  62. class Window implements \Hoa\Core\Event\Source {
  63. /**
  64. * Singleton (only for events).
  65. *
  66. * @var \Hoa\Console\Window object
  67. */
  68. private static $_instance = null;
  69. /**
  70. * Set the event channel.
  71. * We need to declare(ticks = 1) in the main script to ensure that the event
  72. * is fired. Also, we need the pcntl_signal() function enabled.
  73. *
  74. * @access public
  75. * @return void
  76. */
  77. public function __construct ( ) {
  78. \Hoa\Core\Event::register(
  79. 'hoa://Event/Console/Window:resize',
  80. $this
  81. );
  82. return;
  83. }
  84. /**
  85. * Singleton.
  86. *
  87. * @access public
  88. * @return \Hoa\Console\Window
  89. */
  90. public static function getInstance ( ) {
  91. if(null === static::$_instance)
  92. static::$_instance = new static();
  93. return static::$_instance;
  94. }
  95. /**
  96. * Set size to X lines and Y columns.
  97. *
  98. * @access public
  99. * @param int $x X coordinate.
  100. * @param int $y Y coordinate.
  101. * @return void
  102. */
  103. public static function setSize ( $x, $y ) {
  104. if(OS_WIN)
  105. return;
  106. // DECSLPP.
  107. echo "\033[8;" . $y . ";" . $x . "t";
  108. return;
  109. }
  110. /**
  111. * Get current size (x and y) of the window.
  112. *
  113. * @access public
  114. * @return array
  115. */
  116. public static function getSize ( ) {
  117. if(OS_WIN) {
  118. $modecon = explode("\n", ltrim(Processus::execute('mode con')));
  119. $_y = trim($modecon[2]);
  120. preg_match('#[^:]+:\s*([0-9]+)#', $_y, $matches);
  121. $y = (int) $matches[1];
  122. $_x = trim($modecon[3]);
  123. preg_match('#[^:]+:\s*([0-9]+)#', $_x, $matches);
  124. $x = (int) $matches[1];
  125. return array(
  126. 'x' => $x,
  127. 'y' => $y
  128. );
  129. }
  130. // DECSLPP.
  131. echo "\033[18t";
  132. // Read \033[8;y;xt.
  133. fread(STDIN, 4); // skip \033, [, 8 and ;.
  134. $x = null;
  135. $y = null;
  136. $handle = &$y;
  137. do {
  138. $char = fread(STDIN, 1);
  139. switch($char) {
  140. case ';':
  141. $handle = &$x;
  142. break;
  143. case 't':
  144. break 2;
  145. default:
  146. $handle .= $char;
  147. }
  148. } while(true);
  149. return array(
  150. 'x' => (int) $x,
  151. 'y' => (int) $y
  152. );
  153. }
  154. /**
  155. * Move to X and Y (in pixels).
  156. *
  157. * @access public
  158. * @param int $x X coordinate.
  159. * @param int $y Y coordinate.
  160. * @return void
  161. */
  162. public static function moveTo ( $x, $y ) {
  163. if(OS_WIN)
  164. return;
  165. // DECSLPP.
  166. echo "\033[3;" . $y . ";" . $x . "t";
  167. return;
  168. }
  169. /**
  170. * Get current position (x and y) of the window (in pixels).
  171. *
  172. * @access public
  173. * @return array
  174. */
  175. public static function getPosition ( ) {
  176. if(OS_WIN)
  177. return;
  178. // DECSLPP.
  179. echo "\033[13t";
  180. // Read \033[3;x;yt.
  181. fread(STDIN, 4); // skip \033, [, 3 and ;.
  182. $x = null;
  183. $y = null;
  184. $handle = &$x;
  185. do {
  186. $char = fread(STDIN, 1);
  187. switch($char) {
  188. case ';':
  189. $handle = &$y;
  190. break;
  191. case 't':
  192. break 2;
  193. default:
  194. $handle .= $char;
  195. }
  196. } while(true);
  197. return array(
  198. 'x' => (int) $x,
  199. 'y' => (int) $y
  200. );
  201. }
  202. /**
  203. * Scroll whole page.
  204. * Directions can be:
  205. * • u, up, ↑ : scroll whole page up;
  206. * • d, down, ↓ : scroll whole page down.
  207. * Directions can be concatenated by a single space.
  208. *
  209. * @access public
  210. * @param string $directions Directions.
  211. * @param int $repeat How many times do we scroll?
  212. * @reutrn void
  213. */
  214. public static function scroll ( $directions, $repeat = 1 ) {
  215. if(OS_WIN)
  216. return;
  217. if(1 > $repeat)
  218. return;
  219. elseif(1 === $repeat)
  220. $handle = explode(' ', $directions);
  221. else
  222. $handle = explode(' ', $directions, 1);
  223. $count = array('up' => 0, 'down' => 0);
  224. foreach($handle as $direction)
  225. switch($direction) {
  226. case 'u':
  227. case 'up':
  228. case '↑':
  229. ++$count['up'];
  230. break;
  231. case 'd':
  232. case 'down':
  233. case '↓':
  234. ++$count['down'];
  235. break;
  236. }
  237. if(0 < $count['up']) {
  238. // SU.
  239. $up = $count['up'] * $repeat;
  240. echo "\033[" . $up . "S";
  241. }
  242. if(0 < $count['down']) {
  243. // SD.
  244. $down = $count['down'] * $repeat;
  245. echo "\033[" . $down . "T";
  246. }
  247. return;
  248. }
  249. /**
  250. * Minimize the window.
  251. *
  252. * @access public
  253. * @return void
  254. */
  255. public static function minimize ( ) {
  256. if(OS_WIN)
  257. return;
  258. // DECSLPP.
  259. echo "\033[2t";
  260. return;
  261. }
  262. /**
  263. * Set title.
  264. *
  265. * @access public
  266. * @param string $title Title.
  267. * @return void
  268. */
  269. public static function setTitle ( $title ) {
  270. if(OS_WIN)
  271. return;
  272. // DECSLPP.
  273. echo "\033]0;" . $title . "\033\\";
  274. return;
  275. }
  276. /**
  277. * Get title.
  278. *
  279. * @access public
  280. * @return string
  281. */
  282. public static function getTitle ( ) {
  283. if(OS_WIN)
  284. return;
  285. // DECSLPP.
  286. echo "\033[21t";
  287. // Read \033]l<title>\033\
  288. fread(STDIN, 3); // skip \033, ] and l.
  289. $out = null;
  290. do {
  291. $char = fread(STDIN, 1);
  292. if("\033" === $char) {
  293. $chaar = fread(STDIN, 1);
  294. if('\\' === $chaar)
  295. break;
  296. $char .= $chaar;
  297. }
  298. $out .= $char;
  299. } while(true);
  300. return $out;
  301. }
  302. /**
  303. * Get label.
  304. *
  305. * @access public
  306. * @return string
  307. */
  308. public static function getLabel ( ) {
  309. if(OS_WIN)
  310. return;
  311. // DECSLPP.
  312. echo "\033[20t";
  313. // Read \033]L<label>\033\
  314. fread(STDIN, 3); // skip \033, ] and L.
  315. $out = null;
  316. do {
  317. $char = fread(STDIN, 1);
  318. if("\033" === $char) {
  319. $chaar = fread(STDIN, 1);
  320. if('\\' === $chaar)
  321. break;
  322. $char .= $chaar;
  323. }
  324. $out .= $char;
  325. } while(true);
  326. return $out;
  327. }
  328. /**
  329. * Refresh the window.
  330. *
  331. * @access public
  332. * @return void
  333. */
  334. public static function refresh ( ) {
  335. if(OS_WIN)
  336. return;
  337. // DECSLPP.
  338. echo "\033[7t";
  339. return;
  340. }
  341. /**
  342. * Set clipboard value.
  343. *
  344. * @access public
  345. * @param string $data Data to copy.
  346. * @return void
  347. */
  348. public static function copy ( $data ) {
  349. if(OS_WIN)
  350. return;
  351. echo "\033]52;;" . base64_encode($data) . "\033\\";
  352. return;
  353. }
  354. }
  355. }
  356. namespace {
  357. /**
  358. * Advanced interaction.
  359. */
  360. \Hoa\Console::advancedInteraction();
  361. /**
  362. * Event.
  363. */
  364. if(ƒ('pcntl_signal')) {
  365. \Hoa\Console\Window::getInstance();
  366. pcntl_signal(SIGWINCH, function ( ) {
  367. static $_window = null;
  368. if(null === $_window)
  369. $_window = \Hoa\Console\Window::getInstance();
  370. \Hoa\Core\Event::notify(
  371. 'hoa://Event/Console/Window:resize',
  372. $_window,
  373. new \Hoa\Core\Event\Bucket(array(
  374. 'size' => \Hoa\Console\Window::getSize()
  375. ))
  376. );
  377. });
  378. }
  379. }