asyncengine 0.0.1.testing

Sign up to get free protection for your applications and to get access to all the features.
Files changed (317) hide show
  1. data/README.markdown +0 -0
  2. data/asyncengine.gemspec +26 -0
  3. data/ext/asyncengine_ext/asyncengine_ruby.c +82 -0
  4. data/ext/asyncengine_ext/extconf.rb +47 -0
  5. data/ext/asyncengine_ext/libuv/AUTHORS +45 -0
  6. data/ext/asyncengine_ext/libuv/LICENSE +42 -0
  7. data/ext/asyncengine_ext/libuv/Makefile +119 -0
  8. data/ext/asyncengine_ext/libuv/README.md +88 -0
  9. data/ext/asyncengine_ext/libuv/build/gcc_version.py +20 -0
  10. data/ext/asyncengine_ext/libuv/common.gypi +176 -0
  11. data/ext/asyncengine_ext/libuv/config-mingw.mk +61 -0
  12. data/ext/asyncengine_ext/libuv/config-unix.mk +173 -0
  13. data/ext/asyncengine_ext/libuv/gyp_uv +60 -0
  14. data/ext/asyncengine_ext/libuv/include/ares.h +591 -0
  15. data/ext/asyncengine_ext/libuv/include/ares_version.h +24 -0
  16. data/ext/asyncengine_ext/libuv/include/uv-private/eio.h +403 -0
  17. data/ext/asyncengine_ext/libuv/include/uv-private/ev.h +838 -0
  18. data/ext/asyncengine_ext/libuv/include/uv-private/ngx-queue.h +106 -0
  19. data/ext/asyncengine_ext/libuv/include/uv-private/tree.h +768 -0
  20. data/ext/asyncengine_ext/libuv/include/uv-private/uv-unix.h +256 -0
  21. data/ext/asyncengine_ext/libuv/include/uv-private/uv-win.h +458 -0
  22. data/ext/asyncengine_ext/libuv/include/uv.h +1556 -0
  23. data/ext/asyncengine_ext/libuv/src/ares/AUTHORS +37 -0
  24. data/ext/asyncengine_ext/libuv/src/ares/CHANGES +1218 -0
  25. data/ext/asyncengine_ext/libuv/src/ares/CMakeLists.txt +22 -0
  26. data/ext/asyncengine_ext/libuv/src/ares/NEWS +21 -0
  27. data/ext/asyncengine_ext/libuv/src/ares/README +60 -0
  28. data/ext/asyncengine_ext/libuv/src/ares/README.cares +13 -0
  29. data/ext/asyncengine_ext/libuv/src/ares/README.msvc +142 -0
  30. data/ext/asyncengine_ext/libuv/src/ares/README.node +21 -0
  31. data/ext/asyncengine_ext/libuv/src/ares/RELEASE-NOTES +26 -0
  32. data/ext/asyncengine_ext/libuv/src/ares/TODO +23 -0
  33. data/ext/asyncengine_ext/libuv/src/ares/ares__close_sockets.c +66 -0
  34. data/ext/asyncengine_ext/libuv/src/ares/ares__get_hostent.c +263 -0
  35. data/ext/asyncengine_ext/libuv/src/ares/ares__read_line.c +71 -0
  36. data/ext/asyncengine_ext/libuv/src/ares/ares__timeval.c +111 -0
  37. data/ext/asyncengine_ext/libuv/src/ares/ares_cancel.c +63 -0
  38. data/ext/asyncengine_ext/libuv/src/ares/ares_data.c +190 -0
  39. data/ext/asyncengine_ext/libuv/src/ares/ares_data.h +65 -0
  40. data/ext/asyncengine_ext/libuv/src/ares/ares_destroy.c +105 -0
  41. data/ext/asyncengine_ext/libuv/src/ares/ares_dns.h +90 -0
  42. data/ext/asyncengine_ext/libuv/src/ares/ares_expand_name.c +200 -0
  43. data/ext/asyncengine_ext/libuv/src/ares/ares_expand_string.c +75 -0
  44. data/ext/asyncengine_ext/libuv/src/ares/ares_fds.c +63 -0
  45. data/ext/asyncengine_ext/libuv/src/ares/ares_free_hostent.c +42 -0
  46. data/ext/asyncengine_ext/libuv/src/ares/ares_free_string.c +25 -0
  47. data/ext/asyncengine_ext/libuv/src/ares/ares_getenv.c +30 -0
  48. data/ext/asyncengine_ext/libuv/src/ares/ares_getenv.h +26 -0
  49. data/ext/asyncengine_ext/libuv/src/ares/ares_gethostbyaddr.c +301 -0
  50. data/ext/asyncengine_ext/libuv/src/ares/ares_gethostbyname.c +523 -0
  51. data/ext/asyncengine_ext/libuv/src/ares/ares_getnameinfo.c +427 -0
  52. data/ext/asyncengine_ext/libuv/src/ares/ares_getopt.c +122 -0
  53. data/ext/asyncengine_ext/libuv/src/ares/ares_getopt.h +53 -0
  54. data/ext/asyncengine_ext/libuv/src/ares/ares_getsock.c +72 -0
  55. data/ext/asyncengine_ext/libuv/src/ares/ares_init.c +1809 -0
  56. data/ext/asyncengine_ext/libuv/src/ares/ares_iphlpapi.h +221 -0
  57. data/ext/asyncengine_ext/libuv/src/ares/ares_ipv6.h +78 -0
  58. data/ext/asyncengine_ext/libuv/src/ares/ares_library_init.c +142 -0
  59. data/ext/asyncengine_ext/libuv/src/ares/ares_library_init.h +42 -0
  60. data/ext/asyncengine_ext/libuv/src/ares/ares_llist.c +86 -0
  61. data/ext/asyncengine_ext/libuv/src/ares/ares_llist.h +42 -0
  62. data/ext/asyncengine_ext/libuv/src/ares/ares_mkquery.c +195 -0
  63. data/ext/asyncengine_ext/libuv/src/ares/ares_nowarn.c +181 -0
  64. data/ext/asyncengine_ext/libuv/src/ares/ares_nowarn.h +55 -0
  65. data/ext/asyncengine_ext/libuv/src/ares/ares_options.c +248 -0
  66. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_a_reply.c +263 -0
  67. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_aaaa_reply.c +259 -0
  68. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_mx_reply.c +170 -0
  69. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_ns_reply.c +182 -0
  70. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_ptr_reply.c +217 -0
  71. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_srv_reply.c +179 -0
  72. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_txt_reply.c +201 -0
  73. data/ext/asyncengine_ext/libuv/src/ares/ares_platform.c +11035 -0
  74. data/ext/asyncengine_ext/libuv/src/ares/ares_platform.h +43 -0
  75. data/ext/asyncengine_ext/libuv/src/ares/ares_private.h +355 -0
  76. data/ext/asyncengine_ext/libuv/src/ares/ares_process.c +1295 -0
  77. data/ext/asyncengine_ext/libuv/src/ares/ares_query.c +183 -0
  78. data/ext/asyncengine_ext/libuv/src/ares/ares_rules.h +144 -0
  79. data/ext/asyncengine_ext/libuv/src/ares/ares_search.c +321 -0
  80. data/ext/asyncengine_ext/libuv/src/ares/ares_send.c +134 -0
  81. data/ext/asyncengine_ext/libuv/src/ares/ares_setup.h +199 -0
  82. data/ext/asyncengine_ext/libuv/src/ares/ares_strcasecmp.c +66 -0
  83. data/ext/asyncengine_ext/libuv/src/ares/ares_strcasecmp.h +30 -0
  84. data/ext/asyncengine_ext/libuv/src/ares/ares_strdup.c +42 -0
  85. data/ext/asyncengine_ext/libuv/src/ares/ares_strdup.h +26 -0
  86. data/ext/asyncengine_ext/libuv/src/ares/ares_strerror.c +56 -0
  87. data/ext/asyncengine_ext/libuv/src/ares/ares_timeout.c +80 -0
  88. data/ext/asyncengine_ext/libuv/src/ares/ares_version.c +11 -0
  89. data/ext/asyncengine_ext/libuv/src/ares/ares_writev.c +79 -0
  90. data/ext/asyncengine_ext/libuv/src/ares/ares_writev.h +36 -0
  91. data/ext/asyncengine_ext/libuv/src/ares/bitncmp.c +59 -0
  92. data/ext/asyncengine_ext/libuv/src/ares/bitncmp.h +26 -0
  93. data/ext/asyncengine_ext/libuv/src/ares/config_cygwin/ares_config.h +512 -0
  94. data/ext/asyncengine_ext/libuv/src/ares/config_darwin/ares_config.h +512 -0
  95. data/ext/asyncengine_ext/libuv/src/ares/config_freebsd/ares_config.h +512 -0
  96. data/ext/asyncengine_ext/libuv/src/ares/config_linux/ares_config.h +512 -0
  97. data/ext/asyncengine_ext/libuv/src/ares/config_netbsd/ares_config.h +512 -0
  98. data/ext/asyncengine_ext/libuv/src/ares/config_openbsd/ares_config.h +512 -0
  99. data/ext/asyncengine_ext/libuv/src/ares/config_sunos/ares_config.h +512 -0
  100. data/ext/asyncengine_ext/libuv/src/ares/config_win32/ares_config.h +369 -0
  101. data/ext/asyncengine_ext/libuv/src/ares/get_ver.awk +35 -0
  102. data/ext/asyncengine_ext/libuv/src/ares/inet_net_pton.c +451 -0
  103. data/ext/asyncengine_ext/libuv/src/ares/inet_net_pton.h +31 -0
  104. data/ext/asyncengine_ext/libuv/src/ares/inet_ntop.c +208 -0
  105. data/ext/asyncengine_ext/libuv/src/ares/inet_ntop.h +26 -0
  106. data/ext/asyncengine_ext/libuv/src/ares/nameser.h +203 -0
  107. data/ext/asyncengine_ext/libuv/src/ares/setup_once.h +504 -0
  108. data/ext/asyncengine_ext/libuv/src/ares/windows_port.c +22 -0
  109. data/ext/asyncengine_ext/libuv/src/unix/async.c +58 -0
  110. data/ext/asyncengine_ext/libuv/src/unix/cares.c +194 -0
  111. data/ext/asyncengine_ext/libuv/src/unix/check.c +80 -0
  112. data/ext/asyncengine_ext/libuv/src/unix/core.c +588 -0
  113. data/ext/asyncengine_ext/libuv/src/unix/cygwin.c +84 -0
  114. data/ext/asyncengine_ext/libuv/src/unix/darwin.c +341 -0
  115. data/ext/asyncengine_ext/libuv/src/unix/dl.c +91 -0
  116. data/ext/asyncengine_ext/libuv/src/unix/eio/Changes +63 -0
  117. data/ext/asyncengine_ext/libuv/src/unix/eio/LICENSE +36 -0
  118. data/ext/asyncengine_ext/libuv/src/unix/eio/Makefile.am +15 -0
  119. data/ext/asyncengine_ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
  120. data/ext/asyncengine_ext/libuv/src/unix/eio/autogen.sh +3 -0
  121. data/ext/asyncengine_ext/libuv/src/unix/eio/config.h.in +86 -0
  122. data/ext/asyncengine_ext/libuv/src/unix/eio/config_cygwin.h +80 -0
  123. data/ext/asyncengine_ext/libuv/src/unix/eio/config_darwin.h +141 -0
  124. data/ext/asyncengine_ext/libuv/src/unix/eio/config_freebsd.h +81 -0
  125. data/ext/asyncengine_ext/libuv/src/unix/eio/config_linux.h +94 -0
  126. data/ext/asyncengine_ext/libuv/src/unix/eio/config_netbsd.h +81 -0
  127. data/ext/asyncengine_ext/libuv/src/unix/eio/config_openbsd.h +137 -0
  128. data/ext/asyncengine_ext/libuv/src/unix/eio/config_sunos.h +84 -0
  129. data/ext/asyncengine_ext/libuv/src/unix/eio/configure.ac +22 -0
  130. data/ext/asyncengine_ext/libuv/src/unix/eio/demo.c +194 -0
  131. data/ext/asyncengine_ext/libuv/src/unix/eio/ecb.h +370 -0
  132. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.3 +3428 -0
  133. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.c +2593 -0
  134. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.pod +969 -0
  135. data/ext/asyncengine_ext/libuv/src/unix/eio/libeio.m4 +195 -0
  136. data/ext/asyncengine_ext/libuv/src/unix/eio/xthread.h +164 -0
  137. data/ext/asyncengine_ext/libuv/src/unix/error.c +98 -0
  138. data/ext/asyncengine_ext/libuv/src/unix/ev/Changes +388 -0
  139. data/ext/asyncengine_ext/libuv/src/unix/ev/LICENSE +36 -0
  140. data/ext/asyncengine_ext/libuv/src/unix/ev/Makefile.am +18 -0
  141. data/ext/asyncengine_ext/libuv/src/unix/ev/Makefile.in +771 -0
  142. data/ext/asyncengine_ext/libuv/src/unix/ev/README +58 -0
  143. data/ext/asyncengine_ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
  144. data/ext/asyncengine_ext/libuv/src/unix/ev/autogen.sh +6 -0
  145. data/ext/asyncengine_ext/libuv/src/unix/ev/config.guess +1526 -0
  146. data/ext/asyncengine_ext/libuv/src/unix/ev/config.h.in +125 -0
  147. data/ext/asyncengine_ext/libuv/src/unix/ev/config.sub +1658 -0
  148. data/ext/asyncengine_ext/libuv/src/unix/ev/config_cygwin.h +123 -0
  149. data/ext/asyncengine_ext/libuv/src/unix/ev/config_darwin.h +122 -0
  150. data/ext/asyncengine_ext/libuv/src/unix/ev/config_freebsd.h +120 -0
  151. data/ext/asyncengine_ext/libuv/src/unix/ev/config_linux.h +141 -0
  152. data/ext/asyncengine_ext/libuv/src/unix/ev/config_netbsd.h +120 -0
  153. data/ext/asyncengine_ext/libuv/src/unix/ev/config_openbsd.h +126 -0
  154. data/ext/asyncengine_ext/libuv/src/unix/ev/config_sunos.h +122 -0
  155. data/ext/asyncengine_ext/libuv/src/unix/ev/configure +13037 -0
  156. data/ext/asyncengine_ext/libuv/src/unix/ev/configure.ac +18 -0
  157. data/ext/asyncengine_ext/libuv/src/unix/ev/depcomp +630 -0
  158. data/ext/asyncengine_ext/libuv/src/unix/ev/ev++.h +816 -0
  159. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.3 +5311 -0
  160. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.c +3921 -0
  161. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.pod +5243 -0
  162. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_epoll.c +266 -0
  163. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
  164. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_poll.c +148 -0
  165. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_port.c +179 -0
  166. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_select.c +310 -0
  167. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_vars.h +203 -0
  168. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_win32.c +153 -0
  169. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_wrap.h +196 -0
  170. data/ext/asyncengine_ext/libuv/src/unix/ev/event.c +402 -0
  171. data/ext/asyncengine_ext/libuv/src/unix/ev/event.h +170 -0
  172. data/ext/asyncengine_ext/libuv/src/unix/ev/install-sh +294 -0
  173. data/ext/asyncengine_ext/libuv/src/unix/ev/libev.m4 +39 -0
  174. data/ext/asyncengine_ext/libuv/src/unix/ev/ltmain.sh +8413 -0
  175. data/ext/asyncengine_ext/libuv/src/unix/ev/missing +336 -0
  176. data/ext/asyncengine_ext/libuv/src/unix/ev/mkinstalldirs +111 -0
  177. data/ext/asyncengine_ext/libuv/src/unix/freebsd.c +312 -0
  178. data/ext/asyncengine_ext/libuv/src/unix/fs.c +707 -0
  179. data/ext/asyncengine_ext/libuv/src/unix/idle.c +79 -0
  180. data/ext/asyncengine_ext/libuv/src/unix/internal.h +161 -0
  181. data/ext/asyncengine_ext/libuv/src/unix/kqueue.c +127 -0
  182. data/ext/asyncengine_ext/libuv/src/unix/linux/core.c +474 -0
  183. data/ext/asyncengine_ext/libuv/src/unix/linux/inotify.c +211 -0
  184. data/ext/asyncengine_ext/libuv/src/unix/linux/syscalls.c +230 -0
  185. data/ext/asyncengine_ext/libuv/src/unix/linux/syscalls.h +87 -0
  186. data/ext/asyncengine_ext/libuv/src/unix/loop.c +58 -0
  187. data/ext/asyncengine_ext/libuv/src/unix/netbsd.c +108 -0
  188. data/ext/asyncengine_ext/libuv/src/unix/openbsd.c +295 -0
  189. data/ext/asyncengine_ext/libuv/src/unix/pipe.c +266 -0
  190. data/ext/asyncengine_ext/libuv/src/unix/prepare.c +79 -0
  191. data/ext/asyncengine_ext/libuv/src/unix/process.c +369 -0
  192. data/ext/asyncengine_ext/libuv/src/unix/stream.c +1033 -0
  193. data/ext/asyncengine_ext/libuv/src/unix/sunos.c +466 -0
  194. data/ext/asyncengine_ext/libuv/src/unix/tcp.c +327 -0
  195. data/ext/asyncengine_ext/libuv/src/unix/thread.c +154 -0
  196. data/ext/asyncengine_ext/libuv/src/unix/timer.c +127 -0
  197. data/ext/asyncengine_ext/libuv/src/unix/tty.c +146 -0
  198. data/ext/asyncengine_ext/libuv/src/unix/udp.c +670 -0
  199. data/ext/asyncengine_ext/libuv/src/unix/uv-eio.c +124 -0
  200. data/ext/asyncengine_ext/libuv/src/unix/uv-eio.h +13 -0
  201. data/ext/asyncengine_ext/libuv/src/uv-common.c +354 -0
  202. data/ext/asyncengine_ext/libuv/src/uv-common.h +87 -0
  203. data/ext/asyncengine_ext/libuv/src/win/async.c +127 -0
  204. data/ext/asyncengine_ext/libuv/src/win/cares.c +290 -0
  205. data/ext/asyncengine_ext/libuv/src/win/core.c +270 -0
  206. data/ext/asyncengine_ext/libuv/src/win/dl.c +82 -0
  207. data/ext/asyncengine_ext/libuv/src/win/error.c +132 -0
  208. data/ext/asyncengine_ext/libuv/src/win/fs-event.c +514 -0
  209. data/ext/asyncengine_ext/libuv/src/win/fs.c +1576 -0
  210. data/ext/asyncengine_ext/libuv/src/win/getaddrinfo.c +372 -0
  211. data/ext/asyncengine_ext/libuv/src/win/handle.c +225 -0
  212. data/ext/asyncengine_ext/libuv/src/win/internal.h +352 -0
  213. data/ext/asyncengine_ext/libuv/src/win/loop-watcher.c +131 -0
  214. data/ext/asyncengine_ext/libuv/src/win/pipe.c +1661 -0
  215. data/ext/asyncengine_ext/libuv/src/win/process.c +1140 -0
  216. data/ext/asyncengine_ext/libuv/src/win/req.c +174 -0
  217. data/ext/asyncengine_ext/libuv/src/win/stream.c +201 -0
  218. data/ext/asyncengine_ext/libuv/src/win/tcp.c +1282 -0
  219. data/ext/asyncengine_ext/libuv/src/win/thread.c +332 -0
  220. data/ext/asyncengine_ext/libuv/src/win/threadpool.c +73 -0
  221. data/ext/asyncengine_ext/libuv/src/win/timer.c +276 -0
  222. data/ext/asyncengine_ext/libuv/src/win/tty.c +1795 -0
  223. data/ext/asyncengine_ext/libuv/src/win/udp.c +709 -0
  224. data/ext/asyncengine_ext/libuv/src/win/util.c +719 -0
  225. data/ext/asyncengine_ext/libuv/src/win/winapi.c +117 -0
  226. data/ext/asyncengine_ext/libuv/src/win/winapi.h +4419 -0
  227. data/ext/asyncengine_ext/libuv/src/win/winsock.c +470 -0
  228. data/ext/asyncengine_ext/libuv/src/win/winsock.h +138 -0
  229. data/ext/asyncengine_ext/libuv/test/benchmark-ares.c +118 -0
  230. data/ext/asyncengine_ext/libuv/test/benchmark-getaddrinfo.c +94 -0
  231. data/ext/asyncengine_ext/libuv/test/benchmark-list.h +105 -0
  232. data/ext/asyncengine_ext/libuv/test/benchmark-ping-pongs.c +213 -0
  233. data/ext/asyncengine_ext/libuv/test/benchmark-pound.c +324 -0
  234. data/ext/asyncengine_ext/libuv/test/benchmark-pump.c +462 -0
  235. data/ext/asyncengine_ext/libuv/test/benchmark-sizes.c +40 -0
  236. data/ext/asyncengine_ext/libuv/test/benchmark-spawn.c +156 -0
  237. data/ext/asyncengine_ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
  238. data/ext/asyncengine_ext/libuv/test/benchmark-thread.c +64 -0
  239. data/ext/asyncengine_ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
  240. data/ext/asyncengine_ext/libuv/test/blackhole-server.c +118 -0
  241. data/ext/asyncengine_ext/libuv/test/dns-server.c +321 -0
  242. data/ext/asyncengine_ext/libuv/test/echo-server.c +370 -0
  243. data/ext/asyncengine_ext/libuv/test/fixtures/empty_file +0 -0
  244. data/ext/asyncengine_ext/libuv/test/fixtures/load_error.node +1 -0
  245. data/ext/asyncengine_ext/libuv/test/run-benchmarks.c +64 -0
  246. data/ext/asyncengine_ext/libuv/test/run-tests.c +108 -0
  247. data/ext/asyncengine_ext/libuv/test/runner-unix.c +315 -0
  248. data/ext/asyncengine_ext/libuv/test/runner-unix.h +36 -0
  249. data/ext/asyncengine_ext/libuv/test/runner-win.c +343 -0
  250. data/ext/asyncengine_ext/libuv/test/runner-win.h +42 -0
  251. data/ext/asyncengine_ext/libuv/test/runner.c +317 -0
  252. data/ext/asyncengine_ext/libuv/test/runner.h +159 -0
  253. data/ext/asyncengine_ext/libuv/test/task.h +117 -0
  254. data/ext/asyncengine_ext/libuv/test/test-async.c +216 -0
  255. data/ext/asyncengine_ext/libuv/test/test-callback-stack.c +203 -0
  256. data/ext/asyncengine_ext/libuv/test/test-connection-fail.c +148 -0
  257. data/ext/asyncengine_ext/libuv/test/test-counters-init.c +216 -0
  258. data/ext/asyncengine_ext/libuv/test/test-cwd-and-chdir.c +64 -0
  259. data/ext/asyncengine_ext/libuv/test/test-delayed-accept.c +197 -0
  260. data/ext/asyncengine_ext/libuv/test/test-dlerror.c +49 -0
  261. data/ext/asyncengine_ext/libuv/test/test-eio-overflow.c +90 -0
  262. data/ext/asyncengine_ext/libuv/test/test-error.c +59 -0
  263. data/ext/asyncengine_ext/libuv/test/test-fail-always.c +29 -0
  264. data/ext/asyncengine_ext/libuv/test/test-fs-event.c +442 -0
  265. data/ext/asyncengine_ext/libuv/test/test-fs.c +1731 -0
  266. data/ext/asyncengine_ext/libuv/test/test-get-currentexe.c +63 -0
  267. data/ext/asyncengine_ext/libuv/test/test-get-loadavg.c +36 -0
  268. data/ext/asyncengine_ext/libuv/test/test-get-memory.c +38 -0
  269. data/ext/asyncengine_ext/libuv/test/test-getaddrinfo.c +122 -0
  270. data/ext/asyncengine_ext/libuv/test/test-gethostbyname.c +189 -0
  271. data/ext/asyncengine_ext/libuv/test/test-getsockname.c +342 -0
  272. data/ext/asyncengine_ext/libuv/test/test-hrtime.c +51 -0
  273. data/ext/asyncengine_ext/libuv/test/test-idle.c +81 -0
  274. data/ext/asyncengine_ext/libuv/test/test-ipc-send-recv.c +209 -0
  275. data/ext/asyncengine_ext/libuv/test/test-ipc.c +614 -0
  276. data/ext/asyncengine_ext/libuv/test/test-list.h +371 -0
  277. data/ext/asyncengine_ext/libuv/test/test-loop-handles.c +359 -0
  278. data/ext/asyncengine_ext/libuv/test/test-multiple-listen.c +102 -0
  279. data/ext/asyncengine_ext/libuv/test/test-mutexes.c +63 -0
  280. data/ext/asyncengine_ext/libuv/test/test-pass-always.c +28 -0
  281. data/ext/asyncengine_ext/libuv/test/test-ping-pong.c +253 -0
  282. data/ext/asyncengine_ext/libuv/test/test-pipe-bind-error.c +140 -0
  283. data/ext/asyncengine_ext/libuv/test/test-pipe-connect-error.c +96 -0
  284. data/ext/asyncengine_ext/libuv/test/test-platform-output.c +87 -0
  285. data/ext/asyncengine_ext/libuv/test/test-process-title.c +42 -0
  286. data/ext/asyncengine_ext/libuv/test/test-ref.c +322 -0
  287. data/ext/asyncengine_ext/libuv/test/test-run-once.c +44 -0
  288. data/ext/asyncengine_ext/libuv/test/test-shutdown-close.c +103 -0
  289. data/ext/asyncengine_ext/libuv/test/test-shutdown-eof.c +183 -0
  290. data/ext/asyncengine_ext/libuv/test/test-spawn.c +499 -0
  291. data/ext/asyncengine_ext/libuv/test/test-stdio-over-pipes.c +256 -0
  292. data/ext/asyncengine_ext/libuv/test/test-tcp-bind-error.c +191 -0
  293. data/ext/asyncengine_ext/libuv/test/test-tcp-bind6-error.c +154 -0
  294. data/ext/asyncengine_ext/libuv/test/test-tcp-close.c +129 -0
  295. data/ext/asyncengine_ext/libuv/test/test-tcp-connect-error.c +70 -0
  296. data/ext/asyncengine_ext/libuv/test/test-tcp-connect6-error.c +68 -0
  297. data/ext/asyncengine_ext/libuv/test/test-tcp-flags.c +51 -0
  298. data/ext/asyncengine_ext/libuv/test/test-tcp-write-error.c +168 -0
  299. data/ext/asyncengine_ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
  300. data/ext/asyncengine_ext/libuv/test/test-tcp-writealot.c +195 -0
  301. data/ext/asyncengine_ext/libuv/test/test-thread.c +183 -0
  302. data/ext/asyncengine_ext/libuv/test/test-threadpool.c +57 -0
  303. data/ext/asyncengine_ext/libuv/test/test-timer-again.c +141 -0
  304. data/ext/asyncengine_ext/libuv/test/test-timer.c +130 -0
  305. data/ext/asyncengine_ext/libuv/test/test-tty.c +110 -0
  306. data/ext/asyncengine_ext/libuv/test/test-udp-dgram-too-big.c +86 -0
  307. data/ext/asyncengine_ext/libuv/test/test-udp-ipv6.c +156 -0
  308. data/ext/asyncengine_ext/libuv/test/test-udp-multicast-join.c +139 -0
  309. data/ext/asyncengine_ext/libuv/test/test-udp-multicast-ttl.c +86 -0
  310. data/ext/asyncengine_ext/libuv/test/test-udp-options.c +86 -0
  311. data/ext/asyncengine_ext/libuv/test/test-udp-send-and-recv.c +208 -0
  312. data/ext/asyncengine_ext/libuv/test/test-util.c +97 -0
  313. data/ext/asyncengine_ext/libuv/uv.gyp +435 -0
  314. data/ext/asyncengine_ext/libuv/vcbuild.bat +105 -0
  315. data/lib/asyncengine/version.rb +3 -0
  316. data/lib/asyncengine.rb +41 -0
  317. metadata +384 -0
@@ -0,0 +1,1795 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include <assert.h>
23
+ #include <io.h>
24
+ #include <string.h>
25
+ #include <stdint.h>
26
+
27
+ #include "uv.h"
28
+ #include "../uv-common.h"
29
+ #include "internal.h"
30
+
31
+
32
+ #define UNICODE_REPLACEMENT_CHARACTER (0xfffd)
33
+
34
+ #define ANSI_NORMAL 0x00
35
+ #define ANSI_ESCAPE_SEEN 0x02
36
+ #define ANSI_CSI 0x04
37
+ #define ANSI_ST_CONTROL 0x08
38
+ #define ANSI_IGNORE 0x10
39
+ #define ANSI_IN_ARG 0x20
40
+ #define ANSI_IN_STRING 0x40
41
+ #define ANSI_BACKSLASH_SEEN 0x80
42
+
43
+
44
+ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
45
+
46
+
47
+ /* Null uv_buf_t */
48
+ static const uv_buf_t uv_null_buf_ = { 0, NULL };
49
+
50
+
51
+ /*
52
+ * The console virtual window.
53
+ *
54
+ * Normally cursor movement in windows is relative to the console screen buffer,
55
+ * e.g. the application is allowed to overwrite the 'history'. This is very
56
+ * inconvenient, it makes absolute cursor movement pretty useless. There is
57
+ * also the concept of 'client rect' which is defined by the actual size of
58
+ * the console window and the scroll position of the screen buffer, but it's
59
+ * very volatile because it changes when the user scrolls.
60
+ *
61
+ * To make cursor movement behave sensibly we define a virtual window to which
62
+ * cursor movement is confined. The virtual window is always as wide as the
63
+ * console screen buffer, but it's height is defined by the size of the
64
+ * console window. The top of the virtual window aligns with the position
65
+ * of the caret when the first stdout/err handle is created, unless that would
66
+ * mean that it would extend beyond the bottom of the screen buffer - in that
67
+ * that case it's located as far down as possible.
68
+ *
69
+ * When the user writes a long text or many newlines, such that the output
70
+ * reaches beyond the bottom of the virtual window, the virtual window is
71
+ * shifted downwards, but not resized.
72
+ *
73
+ * Since all tty i/o happens on the same console, this window is shared
74
+ * between all stdout/stderr handles.
75
+ */
76
+
77
+ static int uv_tty_virtual_offset = -1;
78
+ static int uv_tty_virtual_height = -1;
79
+ static int uv_tty_virtual_width = -1;
80
+
81
+ static CRITICAL_SECTION uv_tty_output_lock;
82
+
83
+
84
+ void uv_console_init() {
85
+ InitializeCriticalSection(&uv_tty_output_lock);
86
+ }
87
+
88
+
89
+ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
90
+ HANDLE win_handle;
91
+ CONSOLE_SCREEN_BUFFER_INFO info;
92
+
93
+ loop->counters.tty_init++;
94
+
95
+ win_handle = (HANDLE) _get_osfhandle(fd);
96
+ if (win_handle == INVALID_HANDLE_VALUE) {
97
+ uv__set_sys_error(loop, ERROR_INVALID_HANDLE);
98
+ return -1;
99
+ }
100
+
101
+ if (!GetConsoleMode(win_handle, &tty->original_console_mode)) {
102
+ uv__set_sys_error(loop, GetLastError());
103
+ return -1;
104
+ }
105
+
106
+ /* Initialize virtual window size; if it fails, assume that this is stdin. */
107
+ if (GetConsoleScreenBufferInfo(win_handle, &info)) {
108
+ EnterCriticalSection(&uv_tty_output_lock);
109
+ uv_tty_update_virtual_window(&info);
110
+ LeaveCriticalSection(&uv_tty_output_lock);
111
+ }
112
+
113
+ uv_stream_init(loop, (uv_stream_t*) tty);
114
+ uv_connection_init((uv_stream_t*) tty);
115
+
116
+ tty->type = UV_TTY;
117
+ tty->handle = win_handle;
118
+ tty->read_line_handle = NULL;
119
+ tty->read_line_buffer = uv_null_buf_;
120
+ tty->read_raw_wait = NULL;
121
+ tty->reqs_pending = 0;
122
+ tty->flags |= UV_HANDLE_BOUND;
123
+
124
+ /* Init keycode-to-vt100 mapper state. */
125
+ tty->last_key_len = 0;
126
+ tty->last_key_offset = 0;
127
+ tty->last_utf16_high_surrogate = 0;
128
+ memset(&tty->last_input_record, 0, sizeof tty->last_input_record);
129
+
130
+ /* Init utf8-to-utf16 conversion state. */
131
+ tty->utf8_bytes_left = 0;
132
+ tty->utf8_codepoint = 0;
133
+
134
+ /* Initialize eol conversion state */
135
+ tty->previous_eol = 0;
136
+
137
+ /* Init ANSI parser state. */
138
+ tty->ansi_parser_state = ANSI_NORMAL;
139
+
140
+ return 0;
141
+ }
142
+
143
+
144
+ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
145
+ DWORD flags = 0;
146
+ unsigned char was_reading;
147
+ uv_alloc_cb alloc_cb;
148
+ uv_read_cb read_cb;
149
+
150
+ if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) {
151
+ return 0;
152
+ }
153
+
154
+ if (tty->original_console_mode & ENABLE_QUICK_EDIT_MODE) {
155
+ flags = ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS;
156
+ }
157
+
158
+ if (mode) {
159
+ /* Raw input */
160
+ flags |= ENABLE_WINDOW_INPUT;
161
+ } else {
162
+ /* Line-buffered mode. */
163
+ flags |= ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT |
164
+ ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT;
165
+ }
166
+
167
+ if (!SetConsoleMode(tty->handle, flags)) {
168
+ uv__set_sys_error(tty->loop, GetLastError());
169
+ return -1;
170
+ }
171
+
172
+ /* If currently reading, stop, and restart reading. */
173
+ if (tty->flags & UV_HANDLE_READING) {
174
+ was_reading = 1;
175
+ alloc_cb = tty->alloc_cb;
176
+ read_cb = tty->read_cb;
177
+
178
+ if (was_reading && uv_tty_read_stop(tty) != 0) {
179
+ return -1;
180
+ }
181
+ } else {
182
+ was_reading = 0;
183
+ }
184
+
185
+ /* Update flag. */
186
+ tty->flags &= ~UV_HANDLE_TTY_RAW;
187
+ tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;
188
+
189
+ /* If we just stopped reading, restart. */
190
+ if (was_reading && uv_tty_read_start(tty, alloc_cb, read_cb) != 0) {
191
+ return -1;
192
+ }
193
+
194
+ return 0;
195
+ }
196
+
197
+
198
+ int uv_is_tty(uv_file file) {
199
+ DWORD result;
200
+ return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0;
201
+ }
202
+
203
+
204
+ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
205
+ CONSOLE_SCREEN_BUFFER_INFO info;
206
+
207
+ if (!GetConsoleScreenBufferInfo(tty->handle, &info)) {
208
+ uv__set_sys_error(tty->loop, GetLastError());
209
+ return -1;
210
+ }
211
+
212
+ EnterCriticalSection(&uv_tty_output_lock);
213
+ uv_tty_update_virtual_window(&info);
214
+ LeaveCriticalSection(&uv_tty_output_lock);
215
+
216
+ *width = uv_tty_virtual_width;
217
+ *height = uv_tty_virtual_height;
218
+
219
+ return 0;
220
+ }
221
+
222
+
223
+ static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) {
224
+ uv_loop_t* loop;
225
+ uv_tty_t* handle;
226
+ uv_req_t* req;
227
+
228
+ assert(data);
229
+ assert(!didTimeout);
230
+
231
+ req = (uv_req_t*) data;
232
+ handle = (uv_tty_t*) req->data;
233
+ loop = handle->loop;
234
+
235
+ UnregisterWait(handle->read_raw_wait);
236
+ handle->read_raw_wait = NULL;
237
+
238
+ SET_REQ_SUCCESS(req);
239
+ POST_COMPLETION_FOR_REQ(loop, req);
240
+ }
241
+
242
+
243
+ static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {
244
+ uv_read_t* req;
245
+ BOOL r;
246
+
247
+ assert(handle->flags & UV_HANDLE_READING);
248
+ assert(!(handle->flags & UV_HANDLE_READ_PENDING));
249
+
250
+ assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);
251
+
252
+ handle->read_line_buffer = uv_null_buf_;
253
+
254
+ req = &handle->read_req;
255
+ memset(&req->overlapped, 0, sizeof(req->overlapped));
256
+
257
+ r = RegisterWaitForSingleObject(&handle->read_raw_wait,
258
+ handle->handle,
259
+ uv_tty_post_raw_read,
260
+ (void*) req,
261
+ INFINITE,
262
+ WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
263
+ if (!r) {
264
+ handle->read_raw_wait = NULL;
265
+ SET_REQ_ERROR(req, GetLastError());
266
+ uv_insert_pending_req(loop, (uv_req_t*)req);
267
+ }
268
+
269
+ handle->flags |= UV_HANDLE_READ_PENDING;
270
+ handle->reqs_pending++;
271
+ }
272
+
273
+
274
+ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
275
+ uv_loop_t* loop;
276
+ uv_tty_t* handle;
277
+ uv_req_t* req;
278
+ DWORD bytes, read_bytes;
279
+
280
+ assert(data);
281
+
282
+ req = (uv_req_t*) data;
283
+ handle = (uv_tty_t*) req->data;
284
+ loop = handle->loop;
285
+
286
+ assert(handle->read_line_buffer.base != NULL);
287
+ assert(handle->read_line_buffer.len > 0);
288
+
289
+ /* ReadConsole can't handle big buffers. */
290
+ if (handle->read_line_buffer.len < 8192) {
291
+ bytes = handle->read_line_buffer.len;
292
+ } else {
293
+ bytes = 8192;
294
+ }
295
+
296
+ /* Todo: Unicode */
297
+ if (ReadConsoleA(handle->read_line_handle,
298
+ (void*) handle->read_line_buffer.base,
299
+ bytes,
300
+ &read_bytes,
301
+ NULL)) {
302
+ SET_REQ_SUCCESS(req);
303
+ req->overlapped.InternalHigh = read_bytes;
304
+ } else {
305
+ SET_REQ_ERROR(req, GetLastError());
306
+ }
307
+
308
+ POST_COMPLETION_FOR_REQ(loop, req);
309
+ return 0;
310
+ }
311
+
312
+
313
+ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
314
+ uv_read_t* req;
315
+ BOOL r;
316
+
317
+ assert(handle->flags & UV_HANDLE_READING);
318
+ assert(!(handle->flags & UV_HANDLE_READ_PENDING));
319
+ assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);
320
+
321
+ req = &handle->read_req;
322
+ memset(&req->overlapped, 0, sizeof(req->overlapped));
323
+
324
+ handle->read_line_buffer = handle->alloc_cb((uv_handle_t*) handle, 8192);
325
+ assert(handle->read_line_buffer.base != NULL);
326
+ assert(handle->read_line_buffer.len > 0);
327
+
328
+ /* Duplicate the console handle, so if we want to cancel the read, we can */
329
+ /* just close this handle duplicate. */
330
+ if (handle->read_line_handle == NULL) {
331
+ HANDLE this_process = GetCurrentProcess();
332
+ r = DuplicateHandle(this_process,
333
+ handle->handle,
334
+ this_process,
335
+ &handle->read_line_handle,
336
+ 0,
337
+ 0,
338
+ DUPLICATE_SAME_ACCESS);
339
+ if (!r) {
340
+ handle->read_line_handle = NULL;
341
+ SET_REQ_ERROR(req, GetLastError());
342
+ uv_insert_pending_req(loop, (uv_req_t*)req);
343
+ goto out;
344
+ }
345
+ }
346
+
347
+ r = QueueUserWorkItem(uv_tty_line_read_thread,
348
+ (void*) req,
349
+ WT_EXECUTELONGFUNCTION);
350
+ if (!r) {
351
+ SET_REQ_ERROR(req, GetLastError());
352
+ uv_insert_pending_req(loop, (uv_req_t*)req);
353
+ }
354
+
355
+ out:
356
+ handle->flags |= UV_HANDLE_READ_PENDING;
357
+ handle->reqs_pending++;
358
+ }
359
+
360
+
361
+ static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
362
+ if (handle->flags & UV_HANDLE_TTY_RAW) {
363
+ uv_tty_queue_read_raw(loop, handle);
364
+ } else {
365
+ uv_tty_queue_read_line(loop, handle);
366
+ }
367
+ }
368
+
369
+
370
+ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,
371
+ size_t* len) {
372
+ #define VK_CASE(vk, normal_str, shift_str, ctrl_str, shift_ctrl_str) \
373
+ case (vk): \
374
+ if (shift && ctrl) { \
375
+ *len = sizeof shift_ctrl_str; \
376
+ return "\033" shift_ctrl_str; \
377
+ } else if (shift) { \
378
+ *len = sizeof shift_str ; \
379
+ return "\033" shift_str; \
380
+ } else if (ctrl) { \
381
+ *len = sizeof ctrl_str; \
382
+ return "\033" ctrl_str; \
383
+ } else { \
384
+ *len = sizeof normal_str; \
385
+ return "\033" normal_str; \
386
+ }
387
+
388
+ switch (code) {
389
+ /* These mappings are the same as Cygwin's. Unmodified and alt-modified */
390
+ /* keypad keys comply with linux console, modifiers comply with xterm */
391
+ /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */
392
+ /* f6..f12 with and without modifiers comply with rxvt. */
393
+ VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~")
394
+ VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~")
395
+ VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B")
396
+ VK_CASE(VK_NEXT, "[6~", "[6;2~", "[6;5~", "[6;6~")
397
+ VK_CASE(VK_LEFT, "[D", "[1;2D", "[1;5D", "[1;6D")
398
+ VK_CASE(VK_CLEAR, "[G", "[1;2G", "[1;5G", "[1;6G")
399
+ VK_CASE(VK_RIGHT, "[C", "[1;2C", "[1;5C", "[1;6C")
400
+ VK_CASE(VK_UP, "[A", "[1;2A", "[1;5A", "[1;6A")
401
+ VK_CASE(VK_HOME, "[1~", "[1;2~", "[1;5~", "[1;6~")
402
+ VK_CASE(VK_PRIOR, "[5~", "[5;2~", "[5;5~", "[5;6~")
403
+ VK_CASE(VK_DELETE, "[3~", "[3;2~", "[3;5~", "[3;6~")
404
+ VK_CASE(VK_NUMPAD0, "[2~", "[2;2~", "[2;5~", "[2;6~")
405
+ VK_CASE(VK_NUMPAD1, "[4~", "[4;2~", "[4;5~", "[4;6~")
406
+ VK_CASE(VK_NUMPAD2, "[B", "[1;2B", "[1;5B", "[1;6B")
407
+ VK_CASE(VK_NUMPAD3, "[6~", "[6;2~", "[6;5~", "[6;6~")
408
+ VK_CASE(VK_NUMPAD4, "[D", "[1;2D", "[1;5D", "[1;6D")
409
+ VK_CASE(VK_NUMPAD5, "[G", "[1;2G", "[1;5G", "[1;6G")
410
+ VK_CASE(VK_NUMPAD6, "[C", "[1;2C", "[1;5C", "[1;6C")
411
+ VK_CASE(VK_NUMPAD7, "[A", "[1;2A", "[1;5A", "[1;6A")
412
+ VK_CASE(VK_NUMPAD8, "[1~", "[1;2~", "[1;5~", "[1;6~")
413
+ VK_CASE(VK_NUMPAD9, "[5~", "[5;2~", "[5;5~", "[5;6~")
414
+ VK_CASE(VK_DECIMAL, "[3~", "[3;2~", "[3;5~", "[3;6~")
415
+ VK_CASE(VK_F1, "[[A", "[23~", "[11^", "[23^" )
416
+ VK_CASE(VK_F2, "[[B", "[24~", "[12^", "[24^" )
417
+ VK_CASE(VK_F3, "[[C", "[25~", "[13^", "[25^" )
418
+ VK_CASE(VK_F4, "[[D", "[26~", "[14^", "[26^" )
419
+ VK_CASE(VK_F5, "[[E", "[28~", "[15^", "[28^" )
420
+ VK_CASE(VK_F6, "[17~", "[29~", "[17^", "[29^" )
421
+ VK_CASE(VK_F7, "[18~", "[31~", "[18^", "[31^" )
422
+ VK_CASE(VK_F8, "[19~", "[32~", "[19^", "[32^" )
423
+ VK_CASE(VK_F9, "[20~", "[33~", "[20^", "[33^" )
424
+ VK_CASE(VK_F10, "[21~", "[34~", "[21^", "[34^" )
425
+ VK_CASE(VK_F11, "[23~", "[23$", "[23^", "[23@" )
426
+ VK_CASE(VK_F12, "[24~", "[24$", "[24^", "[24@" )
427
+
428
+ default:
429
+ *len = 0;
430
+ return NULL;
431
+ }
432
+ #undef VK_CASE
433
+ }
434
+
435
+
436
+ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
437
+ uv_req_t* req) {
438
+ /* Shortcut for handle->last_input_record.Event.KeyEvent. */
439
+ #define KEV handle->last_input_record.Event.KeyEvent
440
+
441
+ DWORD records_left, records_read;
442
+ uv_buf_t buf;
443
+ off_t buf_used;
444
+
445
+ assert(handle->type == UV_TTY);
446
+ handle->flags &= ~UV_HANDLE_READ_PENDING;
447
+
448
+ if (!(handle->flags & UV_HANDLE_READING) ||
449
+ !(handle->flags & UV_HANDLE_TTY_RAW)) {
450
+ goto out;
451
+ }
452
+
453
+ if (!REQ_SUCCESS(req)) {
454
+ /* An error occurred while waiting for the event. */
455
+ if ((handle->flags & UV_HANDLE_READING)) {
456
+ handle->flags &= ~UV_HANDLE_READING;
457
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
458
+ handle->read_cb((uv_stream_t*)handle, -1, uv_null_buf_);
459
+ }
460
+ goto out;
461
+ }
462
+
463
+ /* Fetch the number of events */
464
+ if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) {
465
+ handle->flags &= ~UV_HANDLE_READING;
466
+ uv__set_sys_error(loop, GetLastError());
467
+ handle->read_cb((uv_stream_t*)handle, -1, uv_null_buf_);
468
+ goto out;
469
+ }
470
+
471
+ /* Windows sends a lot of events that we're not interested in, so buf */
472
+ /* will be allocated on demand, when there's actually something to emit. */
473
+ buf = uv_null_buf_;
474
+ buf_used = 0;
475
+
476
+ while ((records_left > 0 || handle->last_key_len > 0) &&
477
+ (handle->flags & UV_HANDLE_READING)) {
478
+ if (handle->last_key_len == 0) {
479
+ /* Read the next input record */
480
+ if (!ReadConsoleInputW(handle->handle,
481
+ &handle->last_input_record,
482
+ 1,
483
+ &records_read)) {
484
+ uv__set_sys_error(loop, GetLastError());
485
+ handle->flags &= ~UV_HANDLE_READING;
486
+ handle->read_cb((uv_stream_t*) handle, -1, buf);
487
+ goto out;
488
+ }
489
+ records_left--;
490
+
491
+ /* Ignore events that are not keyboard events */
492
+ if (handle->last_input_record.EventType != KEY_EVENT) {
493
+ continue;
494
+ }
495
+
496
+ /* Ignore keyup events, unless the left alt key was held and a valid */
497
+ /* unicode character was emitted. */
498
+ if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) ||
499
+ KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) {
500
+ continue;
501
+ }
502
+
503
+ /* Ignore keypresses to numpad number keys if the left alt is held */
504
+ /* because the user is composing a character, or windows simulating */
505
+ /* this. */
506
+ if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
507
+ !(KEV.dwControlKeyState & ENHANCED_KEY) &&
508
+ (KEV.wVirtualKeyCode == VK_INSERT ||
509
+ KEV.wVirtualKeyCode == VK_END ||
510
+ KEV.wVirtualKeyCode == VK_DOWN ||
511
+ KEV.wVirtualKeyCode == VK_NEXT ||
512
+ KEV.wVirtualKeyCode == VK_LEFT ||
513
+ KEV.wVirtualKeyCode == VK_CLEAR ||
514
+ KEV.wVirtualKeyCode == VK_RIGHT ||
515
+ KEV.wVirtualKeyCode == VK_HOME ||
516
+ KEV.wVirtualKeyCode == VK_UP ||
517
+ KEV.wVirtualKeyCode == VK_PRIOR ||
518
+ KEV.wVirtualKeyCode == VK_NUMPAD0 ||
519
+ KEV.wVirtualKeyCode == VK_NUMPAD1 ||
520
+ KEV.wVirtualKeyCode == VK_NUMPAD2 ||
521
+ KEV.wVirtualKeyCode == VK_NUMPAD3 ||
522
+ KEV.wVirtualKeyCode == VK_NUMPAD4 ||
523
+ KEV.wVirtualKeyCode == VK_NUMPAD5 ||
524
+ KEV.wVirtualKeyCode == VK_NUMPAD6 ||
525
+ KEV.wVirtualKeyCode == VK_NUMPAD7 ||
526
+ KEV.wVirtualKeyCode == VK_NUMPAD8 ||
527
+ KEV.wVirtualKeyCode == VK_NUMPAD9)) {
528
+ continue;
529
+ }
530
+
531
+ if (KEV.uChar.UnicodeChar != 0) {
532
+ int prefix_len, char_len;
533
+
534
+ /* Character key pressed */
535
+ if (KEV.uChar.UnicodeChar >= 0xD800 &&
536
+ KEV.uChar.UnicodeChar < 0xDC00) {
537
+ /* UTF-16 high surrogate */
538
+ handle->last_utf16_high_surrogate = KEV.uChar.UnicodeChar;
539
+ continue;
540
+ }
541
+
542
+ /* Prefix with \u033 if alt was held, but alt was not used as part */
543
+ /* a compose sequence. */
544
+ if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
545
+ && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
546
+ RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
547
+ handle->last_key[0] = '\033';
548
+ prefix_len = 1;
549
+ } else {
550
+ prefix_len = 0;
551
+ }
552
+
553
+ if (KEV.uChar.UnicodeChar >= 0xDC00 &&
554
+ KEV.uChar.UnicodeChar < 0xE000) {
555
+ /* UTF-16 surrogate pair */
556
+ WCHAR utf16_buffer[2] = { handle->last_utf16_high_surrogate,
557
+ KEV.uChar.UnicodeChar};
558
+ char_len = WideCharToMultiByte(CP_UTF8,
559
+ 0,
560
+ utf16_buffer,
561
+ 2,
562
+ &handle->last_key[prefix_len],
563
+ sizeof handle->last_key,
564
+ NULL,
565
+ NULL);
566
+ } else {
567
+ /* Single UTF-16 character */
568
+ char_len = WideCharToMultiByte(CP_UTF8,
569
+ 0,
570
+ &KEV.uChar.UnicodeChar,
571
+ 1,
572
+ &handle->last_key[prefix_len],
573
+ sizeof handle->last_key,
574
+ NULL,
575
+ NULL);
576
+ }
577
+
578
+ /* Whatever happened, the last character wasn't a high surrogate. */
579
+ handle->last_utf16_high_surrogate = 0;
580
+
581
+ /* If the utf16 character(s) couldn't be converted something must */
582
+ /* be wrong. */
583
+ if (!char_len) {
584
+ uv__set_sys_error(loop, GetLastError());
585
+ handle->flags &= ~UV_HANDLE_READING;
586
+ handle->read_cb((uv_stream_t*) handle, -1, buf);
587
+ goto out;
588
+ }
589
+
590
+ handle->last_key_len = (unsigned char) (prefix_len + char_len);
591
+ handle->last_key_offset = 0;
592
+ continue;
593
+
594
+ } else {
595
+ /* Function key pressed */
596
+ const char* vt100;
597
+ size_t prefix_len, vt100_len;
598
+
599
+ vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode,
600
+ !!(KEV.dwControlKeyState & SHIFT_PRESSED),
601
+ !!(KEV.dwControlKeyState & (
602
+ LEFT_CTRL_PRESSED |
603
+ RIGHT_CTRL_PRESSED)),
604
+ &vt100_len);
605
+
606
+ /* If we were unable to map to a vt100 sequence, just ignore. */
607
+ if (!vt100) {
608
+ continue;
609
+ }
610
+
611
+ /* Prefix with \x033 when the alt key was held. */
612
+ if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
613
+ handle->last_key[0] = '\033';
614
+ prefix_len = 1;
615
+ } else {
616
+ prefix_len = 0;
617
+ }
618
+
619
+ /* Copy the vt100 sequence to the handle buffer. */
620
+ assert(prefix_len + vt100_len < sizeof handle->last_key);
621
+ memcpy(&handle->last_key[prefix_len], vt100, vt100_len);
622
+
623
+ handle->last_key_len = (unsigned char) (prefix_len + vt100_len);
624
+ handle->last_key_offset = 0;
625
+ continue;
626
+ }
627
+ } else {
628
+ /* Copy any bytes left from the last keypress to the user buffer. */
629
+ if (handle->last_key_offset < handle->last_key_len) {
630
+ /* Allocate a buffer if needed */
631
+ if (buf_used == 0) {
632
+ buf = handle->alloc_cb((uv_handle_t*) handle, 1024);
633
+ }
634
+
635
+ buf.base[buf_used++] = handle->last_key[handle->last_key_offset++];
636
+
637
+ /* If the buffer is full, emit it */
638
+ if (buf_used == buf.len) {
639
+ handle->read_cb((uv_stream_t*) handle, buf_used, buf);
640
+ buf = uv_null_buf_;
641
+ buf_used = 0;
642
+ }
643
+
644
+ continue;
645
+ }
646
+
647
+ /* Apply dwRepeat from the last input record. */
648
+ if (--KEV.wRepeatCount > 0) {
649
+ handle->last_key_offset = 0;
650
+ continue;
651
+ }
652
+
653
+ handle->last_key_len = 0;
654
+ continue;
655
+ }
656
+ }
657
+
658
+ /* Send the buffer back to the user */
659
+ if (buf_used > 0) {
660
+ handle->read_cb((uv_stream_t*) handle, buf_used, buf);
661
+ }
662
+
663
+ out:
664
+ /* Wait for more input events. */
665
+ if ((handle->flags & UV_HANDLE_READING) &&
666
+ !(handle->flags & UV_HANDLE_READ_PENDING)) {
667
+ uv_tty_queue_read(loop, handle);
668
+ }
669
+
670
+ DECREASE_PENDING_REQ_COUNT(handle);
671
+
672
+ #undef KEV
673
+ }
674
+
675
+
676
+
677
+ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
678
+ uv_req_t* req) {
679
+ uv_buf_t buf;
680
+
681
+ assert(handle->type == UV_TTY);
682
+
683
+ buf = handle->read_line_buffer;
684
+
685
+ handle->flags &= ~UV_HANDLE_READ_PENDING;
686
+ handle->read_line_buffer = uv_null_buf_;
687
+
688
+ if (!REQ_SUCCESS(req)) {
689
+ /* Read was not successful */
690
+ if ((handle->flags & UV_HANDLE_READING) &&
691
+ !(handle->flags & UV_HANDLE_TTY_RAW)) {
692
+ /* Real error */
693
+ handle->flags &= ~UV_HANDLE_READING;
694
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
695
+ handle->read_cb((uv_stream_t*) handle, -1, buf);
696
+ } else {
697
+ /* The read was cancelled, or whatever we don't care */
698
+ uv__set_sys_error(loop, WSAEWOULDBLOCK); /* maps to UV_EAGAIN */
699
+ handle->read_cb((uv_stream_t*) handle, 0, buf);
700
+ }
701
+
702
+ } else {
703
+ /* Read successful */
704
+ /* TODO: read unicode, convert to utf-8 */
705
+ DWORD bytes = req->overlapped.InternalHigh;
706
+ if (bytes == 0) {
707
+ uv__set_sys_error(loop, WSAEWOULDBLOCK); /* maps to UV_EAGAIN */
708
+ }
709
+ handle->read_cb((uv_stream_t*) handle, bytes, buf);
710
+ }
711
+
712
+ /* Wait for more input events. */
713
+ if ((handle->flags & UV_HANDLE_READING) &&
714
+ !(handle->flags & UV_HANDLE_READ_PENDING)) {
715
+ uv_tty_queue_read(loop, handle);
716
+ }
717
+
718
+ DECREASE_PENDING_REQ_COUNT(handle);
719
+ }
720
+
721
+
722
+ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
723
+ uv_req_t* req) {
724
+
725
+ /* If the read_line_buffer member is zero, it must have been an raw read. */
726
+ /* Otherwise it was a line-buffered read. */
727
+ /* FIXME: This is quite obscure. Use a flag or something. */
728
+ if (handle->read_line_buffer.len == 0) {
729
+ uv_process_tty_read_raw_req(loop, handle, req);
730
+ } else {
731
+ uv_process_tty_read_line_req(loop, handle, req);
732
+ }
733
+ }
734
+
735
+
736
+ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
737
+ uv_read_cb read_cb) {
738
+ uv_loop_t* loop = handle->loop;
739
+
740
+ handle->flags |= UV_HANDLE_READING;
741
+ handle->read_cb = read_cb;
742
+ handle->alloc_cb = alloc_cb;
743
+
744
+ /* If reading was stopped and then started again, there could still be a */
745
+ /* read request pending. */
746
+ if (handle->flags & UV_HANDLE_READ_PENDING) {
747
+ return 0;
748
+ }
749
+
750
+ /* Maybe the user stopped reading half-way while processing key events. */
751
+ /* Short-circuit if this could be the case. */
752
+ if (handle->last_key_len > 0) {
753
+ SET_REQ_SUCCESS(&handle->read_req);
754
+ uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
755
+ return -1;
756
+ }
757
+
758
+ uv_tty_queue_read(loop, handle);
759
+
760
+ return 0;
761
+ }
762
+
763
+
764
+ int uv_tty_read_stop(uv_tty_t* handle) {
765
+ handle->flags &= ~UV_HANDLE_READING;
766
+
767
+ /* Cancel raw read */
768
+ if ((handle->flags & UV_HANDLE_READ_PENDING) &&
769
+ (handle->flags & UV_HANDLE_TTY_RAW)) {
770
+ /* Write some bullshit event to force the console wait to return. */
771
+ INPUT_RECORD record;
772
+ DWORD written;
773
+ memset(&record, 0, sizeof record);
774
+ if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
775
+ uv__set_sys_error(handle->loop, GetLastError());
776
+ return -1;
777
+ }
778
+ }
779
+
780
+ /* Cancel line-buffered read */
781
+ if (handle->read_line_handle != NULL) {
782
+ /* Closing this handle will cancel the ReadConsole operation */
783
+ CloseHandle(handle->read_line_handle);
784
+ handle->read_line_handle = NULL;
785
+ }
786
+
787
+
788
+ return 0;
789
+ }
790
+
791
+
792
+ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
793
+ uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
794
+ uv_tty_virtual_width = info->dwSize.X;
795
+
796
+ /* Recompute virtual window offset row. */
797
+ if (uv_tty_virtual_offset == -1) {
798
+ uv_tty_virtual_offset = info->dwCursorPosition.Y;
799
+ } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
800
+ uv_tty_virtual_height + 1) {
801
+ /* If suddenly find the cursor outside of the virtual window, it must */
802
+ /* have somehow scrolled. Update the virtual window offset. */
803
+ uv_tty_virtual_offset = info->dwCursorPosition.Y -
804
+ uv_tty_virtual_height + 1;
805
+ }
806
+ if (uv_tty_virtual_offset + uv_tty_virtual_height > info->dwSize.Y) {
807
+ uv_tty_virtual_offset = info->dwSize.Y - uv_tty_virtual_height;
808
+ }
809
+ if (uv_tty_virtual_offset < 0) {
810
+ uv_tty_virtual_offset = 0;
811
+ }
812
+ }
813
+
814
+
815
+ static COORD uv_tty_make_real_coord(uv_tty_t* handle,
816
+ CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y,
817
+ unsigned char y_relative) {
818
+ COORD result;
819
+
820
+ uv_tty_update_virtual_window(info);
821
+
822
+ /* Adjust y position */
823
+ if (y_relative) {
824
+ y = info->dwCursorPosition.Y + y;
825
+ } else {
826
+ y = uv_tty_virtual_offset + y;
827
+ }
828
+ /* Clip y to virtual client rectangle */
829
+ if (y < uv_tty_virtual_offset) {
830
+ y = uv_tty_virtual_offset;
831
+ } else if (y >= uv_tty_virtual_offset + uv_tty_virtual_height) {
832
+ y = uv_tty_virtual_offset + uv_tty_virtual_height - 1;
833
+ }
834
+
835
+ /* Adjust x */
836
+ if (x_relative) {
837
+ x = info->dwCursorPosition.X + x;
838
+ }
839
+ /* Clip x */
840
+ if (x < 0) {
841
+ x = 0;
842
+ } else if (x >= uv_tty_virtual_width) {
843
+ x = uv_tty_virtual_width - 1;
844
+ }
845
+
846
+ result.X = (unsigned short) x;
847
+ result.Y = (unsigned short) y;
848
+ return result;
849
+ }
850
+
851
+
852
+ static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,
853
+ DWORD* error) {
854
+ DWORD written;
855
+
856
+ if (*error != ERROR_SUCCESS) {
857
+ return -1;
858
+ }
859
+
860
+ if (!WriteConsoleW(handle->handle,
861
+ (void*) buffer,
862
+ length,
863
+ &written,
864
+ NULL)) {
865
+ *error = GetLastError();
866
+ return -1;
867
+ }
868
+
869
+ return 0;
870
+ }
871
+
872
+
873
+ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
874
+ int y, unsigned char y_relative, DWORD* error) {
875
+ CONSOLE_SCREEN_BUFFER_INFO info;
876
+ COORD pos;
877
+
878
+ if (*error != ERROR_SUCCESS) {
879
+ return -1;
880
+ }
881
+
882
+ retry:
883
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
884
+ *error = GetLastError();
885
+ }
886
+
887
+ pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative);
888
+
889
+ if (!SetConsoleCursorPosition(handle->handle, pos)) {
890
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
891
+ /* The console may be resized - retry */
892
+ goto retry;
893
+ } else {
894
+ *error = GetLastError();
895
+ return -1;
896
+ }
897
+ }
898
+
899
+ return 0;
900
+ }
901
+
902
+
903
+ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
904
+ const COORD origin = {0, 0};
905
+ const WORD char_attrs = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_RED;
906
+ CONSOLE_SCREEN_BUFFER_INFO info;
907
+ DWORD count, written;
908
+
909
+ if (*error != ERROR_SUCCESS) {
910
+ return -1;
911
+ }
912
+
913
+ /* Reset original text attributes. */
914
+ if (!SetConsoleTextAttribute(handle->handle, char_attrs)) {
915
+ *error = GetLastError();
916
+ return -1;
917
+ }
918
+
919
+ /* Move the cursor position to (0, 0). */
920
+ if (!SetConsoleCursorPosition(handle->handle, origin)) {
921
+ *error = GetLastError();
922
+ return -1;
923
+ }
924
+
925
+ /* Clear the screen buffer. */
926
+ retry:
927
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
928
+ *error = GetLastError();
929
+ return -1;
930
+ }
931
+
932
+ count = info.dwSize.X * info.dwSize.Y;
933
+
934
+ if (!(FillConsoleOutputCharacterW(handle->handle,
935
+ L'\x20',
936
+ count,
937
+ origin,
938
+ &written) &&
939
+ FillConsoleOutputAttribute(handle->handle,
940
+ char_attrs,
941
+ written,
942
+ origin,
943
+ &written))) {
944
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
945
+ /* The console may be resized - retry */
946
+ goto retry;
947
+ } else {
948
+ *error = GetLastError();
949
+ return -1;
950
+ }
951
+ }
952
+
953
+ /* Move the virtual window up to the top. */
954
+ uv_tty_virtual_offset = 0;
955
+ uv_tty_update_virtual_window(&info);
956
+
957
+ return 0;
958
+ }
959
+
960
+
961
+ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
962
+ DWORD* error) {
963
+ unsigned short argc = handle->ansi_csi_argc;
964
+ unsigned short* argv = handle->ansi_csi_argv;
965
+
966
+ CONSOLE_SCREEN_BUFFER_INFO info;
967
+ COORD start, end;
968
+ DWORD count, written;
969
+
970
+ int x1, x2, y1, y2;
971
+ int x1r, x2r, y1r, y2r;
972
+
973
+ if (*error != ERROR_SUCCESS) {
974
+ return -1;
975
+ }
976
+
977
+ if (dir == 0) {
978
+ /* Clear from current position */
979
+ x1 = 0;
980
+ x1r = 1;
981
+ } else {
982
+ /* Clear from column 0 */
983
+ x1 = 0;
984
+ x1r = 0;
985
+ }
986
+
987
+ if (dir == 1) {
988
+ /* Clear to current position */
989
+ x2 = 0;
990
+ x2r = 1;
991
+ } else {
992
+ /* Clear to end of row. We pretend the console is 65536 characters wide, */
993
+ /* uv_tty_make_real_coord will clip it to the actual console width. */
994
+ x2 = 0xffff;
995
+ x2r = 0;
996
+ }
997
+
998
+ if (!entire_screen) {
999
+ /* Stay on our own row */
1000
+ y1 = y2 = 0;
1001
+ y1r = y2r = 1;
1002
+ } else {
1003
+ /* Apply columns direction to row */
1004
+ y1 = x1;
1005
+ y1r = x1r;
1006
+ y2 = x2;
1007
+ y2r = x2r;
1008
+ }
1009
+
1010
+ retry:
1011
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
1012
+ *error = GetLastError();
1013
+ return -1;
1014
+ }
1015
+
1016
+ start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r);
1017
+ end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r);
1018
+ count = (end.Y * info.dwSize.X + end.X) -
1019
+ (start.Y * info.dwSize.X + start.X) + 1;
1020
+
1021
+ if (!(FillConsoleOutputCharacterW(handle->handle,
1022
+ L'\x20',
1023
+ count,
1024
+ start,
1025
+ &written) &&
1026
+ FillConsoleOutputAttribute(handle->handle,
1027
+ info.wAttributes,
1028
+ written,
1029
+ start,
1030
+ &written))) {
1031
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
1032
+ /* The console may be resized - retry */
1033
+ goto retry;
1034
+ } else {
1035
+ *error = GetLastError();
1036
+ return -1;
1037
+ }
1038
+ }
1039
+
1040
+ return 0;
1041
+ }
1042
+
1043
+
1044
+ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
1045
+ unsigned short argc = handle->ansi_csi_argc;
1046
+ unsigned short* argv = handle->ansi_csi_argv;
1047
+ int i;
1048
+ CONSOLE_SCREEN_BUFFER_INFO info;
1049
+
1050
+ char fg_color = -1, bg_color = -1;
1051
+ char fg_bright = -1, bg_bright = -1;
1052
+
1053
+ if (argc == 0) {
1054
+ /* Reset mode */
1055
+ fg_color = 7;
1056
+ bg_color = 0;
1057
+ fg_bright = 0;
1058
+ bg_bright = 0;
1059
+ }
1060
+
1061
+ for (i = 0; i < argc; i++) {
1062
+ short arg = argv[i];
1063
+
1064
+ if (arg == 0) {
1065
+ /* Reset mode */
1066
+ fg_color = 7;
1067
+ bg_color = 0;
1068
+ fg_bright = 0;
1069
+ bg_bright = 0;
1070
+
1071
+ } else if (arg == 1) {
1072
+ /* Foreground bright on */
1073
+ fg_bright = 1;
1074
+
1075
+ } else if (arg == 2) {
1076
+ /* Both bright off */
1077
+ fg_bright = 0;
1078
+ bg_bright = 0;
1079
+
1080
+ } else if (arg == 5) {
1081
+ /* Background bright on */
1082
+ bg_bright = 1;
1083
+
1084
+ } else if (arg == 21 || arg == 22) {
1085
+ /* Foreground bright off */
1086
+ fg_bright = 0;
1087
+
1088
+ } else if (arg == 25) {
1089
+ /* Background bright off */
1090
+ bg_bright = 0;
1091
+
1092
+ } else if (arg >= 30 && arg <= 37) {
1093
+ /* Set foreground color */
1094
+ fg_color = arg - 30;
1095
+
1096
+ } else if (arg == 39) {
1097
+ /* Default text color */
1098
+ fg_color = 7;
1099
+ fg_bright = 0;
1100
+
1101
+ } else if (arg >= 40 && arg <= 47) {
1102
+ /* Set background color */
1103
+ bg_color = arg - 40;
1104
+
1105
+ } else if (arg == 49) {
1106
+ /* Default background color */
1107
+ bg_color = 0;
1108
+
1109
+ } else if (arg >= 90 && arg <= 97) {
1110
+ /* Set bold foreground color */
1111
+ fg_bright = 1;
1112
+ fg_color = arg - 90;
1113
+
1114
+ } else if (arg >= 100 && arg <= 107) {
1115
+ /* Set bold background color */
1116
+ bg_bright = 1;
1117
+ bg_color = arg - 100;
1118
+
1119
+ }
1120
+ }
1121
+
1122
+ if (fg_color == -1 && bg_color == -1 && fg_bright == -1 &&
1123
+ bg_bright == -1) {
1124
+ /* Nothing changed */
1125
+ return 0;
1126
+ }
1127
+
1128
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
1129
+ *error = GetLastError();
1130
+ return -1;
1131
+ }
1132
+
1133
+ if (fg_color != -1) {
1134
+ info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
1135
+ if (fg_color & 1) info.wAttributes |= FOREGROUND_RED;
1136
+ if (fg_color & 2) info.wAttributes |= FOREGROUND_GREEN;
1137
+ if (fg_color & 4) info.wAttributes |= FOREGROUND_BLUE;
1138
+ }
1139
+
1140
+ if (fg_bright != -1) {
1141
+ if (fg_bright) {
1142
+ info.wAttributes |= FOREGROUND_INTENSITY;
1143
+ } else {
1144
+ info.wAttributes &= ~FOREGROUND_INTENSITY;
1145
+ }
1146
+ }
1147
+
1148
+ if (bg_color != -1) {
1149
+ info.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
1150
+ if (bg_color & 1) info.wAttributes |= BACKGROUND_RED;
1151
+ if (bg_color & 2) info.wAttributes |= BACKGROUND_GREEN;
1152
+ if (bg_color & 4) info.wAttributes |= BACKGROUND_BLUE;
1153
+ }
1154
+
1155
+ if (bg_bright != -1) {
1156
+ if (bg_bright) {
1157
+ info.wAttributes |= BACKGROUND_INTENSITY;
1158
+ } else {
1159
+ info.wAttributes &= ~BACKGROUND_INTENSITY;
1160
+ }
1161
+ }
1162
+
1163
+ if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) {
1164
+ *error = GetLastError();
1165
+ return -1;
1166
+ }
1167
+
1168
+ return 0;
1169
+ }
1170
+
1171
+
1172
+ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
1173
+ DWORD* error) {
1174
+ CONSOLE_SCREEN_BUFFER_INFO info;
1175
+
1176
+ if (*error != ERROR_SUCCESS) {
1177
+ return -1;
1178
+ }
1179
+
1180
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
1181
+ *error = GetLastError();
1182
+ return -1;
1183
+ }
1184
+
1185
+ uv_tty_update_virtual_window(&info);
1186
+
1187
+ handle->saved_position.X = info.dwCursorPosition.X;
1188
+ handle->saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset;
1189
+ handle->flags |= UV_HANDLE_TTY_SAVED_POSITION;
1190
+
1191
+ if (save_attributes) {
1192
+ handle->saved_attributes = info.wAttributes &
1193
+ (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
1194
+ handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES;
1195
+ }
1196
+
1197
+ return 0;
1198
+ }
1199
+
1200
+
1201
+ static int uv_tty_restore_state(uv_tty_t* handle,
1202
+ unsigned char restore_attributes, DWORD* error) {
1203
+ CONSOLE_SCREEN_BUFFER_INFO info;
1204
+ WORD new_attributes;
1205
+
1206
+ if (*error != ERROR_SUCCESS) {
1207
+ return -1;
1208
+ }
1209
+
1210
+ if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) {
1211
+ if (uv_tty_move_caret(handle,
1212
+ handle->saved_position.X,
1213
+ 0,
1214
+ handle->saved_position.Y,
1215
+ 0,
1216
+ error) != 0) {
1217
+ return -1;
1218
+ }
1219
+ }
1220
+
1221
+ if (restore_attributes &&
1222
+ (handle->flags & UV_HANDLE_TTY_SAVED_ATTRIBUTES)) {
1223
+ if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
1224
+ *error = GetLastError();
1225
+ return -1;
1226
+ }
1227
+
1228
+ new_attributes = info.wAttributes;
1229
+ new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
1230
+ new_attributes |= handle->saved_attributes;
1231
+
1232
+ if (!SetConsoleTextAttribute(handle->handle, new_attributes)) {
1233
+ *error = GetLastError();
1234
+ return -1;
1235
+ }
1236
+ }
1237
+
1238
+ return 0;
1239
+ }
1240
+
1241
+
1242
+ static int uv_tty_write_bufs(uv_tty_t* handle, uv_buf_t bufs[], int bufcnt,
1243
+ DWORD* error) {
1244
+ /* We can only write 8k characters at a time. Windows can't handle */
1245
+ /* much more characters in a single console write anyway. */
1246
+ WCHAR utf16_buf[8192];
1247
+ DWORD utf16_buf_used = 0;
1248
+ int i;
1249
+
1250
+ #define FLUSH_TEXT() \
1251
+ do { \
1252
+ if (utf16_buf_used > 0) { \
1253
+ uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
1254
+ utf16_buf_used = 0; \
1255
+ } \
1256
+ } while (0)
1257
+
1258
+ /* Cache for fast access */
1259
+ unsigned char utf8_bytes_left = handle->utf8_bytes_left;
1260
+ unsigned int utf8_codepoint = handle->utf8_codepoint;
1261
+ unsigned char previous_eol = handle->previous_eol;
1262
+ unsigned char ansi_parser_state = handle->ansi_parser_state;
1263
+
1264
+ /* Store the error here. If we encounter an error, stop trying to do i/o */
1265
+ /* but keep parsing the buffer so we leave the parser in a consistent */
1266
+ /* state. */
1267
+ *error = ERROR_SUCCESS;
1268
+
1269
+ EnterCriticalSection(&uv_tty_output_lock);
1270
+
1271
+ for (i = 0; i < bufcnt; i++) {
1272
+ uv_buf_t buf = bufs[i];
1273
+ unsigned int j;
1274
+
1275
+ for (j = 0; j < buf.len; j++) {
1276
+ unsigned char c = buf.base[j];
1277
+
1278
+ /* Run the character through the utf8 decoder We happily accept non */
1279
+ /* shortest form encodings and invalid code points - there's no real */
1280
+ /* harm that can be done. */
1281
+ if (utf8_bytes_left == 0) {
1282
+ /* Read utf-8 start byte */
1283
+ DWORD first_zero_bit;
1284
+ unsigned char not_c = ~c;
1285
+ #ifdef _MSC_VER /* msvc */
1286
+ if (_BitScanReverse(&first_zero_bit, not_c)) {
1287
+ #else /* assume gcc */
1288
+ if (c != 0) {
1289
+ first_zero_bit = (sizeof(int) * 8) - 1 - __builtin_clz(not_c);
1290
+ #endif
1291
+ if (first_zero_bit == 7) {
1292
+ /* Ascii - pass right through */
1293
+ utf8_codepoint = (unsigned int) c;
1294
+
1295
+ } else if (first_zero_bit <= 5) {
1296
+ /* Multibyte sequence */
1297
+ utf8_codepoint = (0xff >> (8 - first_zero_bit)) & c;
1298
+ utf8_bytes_left = (char) (6 - first_zero_bit);
1299
+
1300
+ } else {
1301
+ /* Invalid continuation */
1302
+ utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
1303
+ }
1304
+
1305
+ } else {
1306
+ /* 0xff -- invalid */
1307
+ utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
1308
+ }
1309
+
1310
+ } else if ((c & 0xc0) == 0x80) {
1311
+ /* Valid continuation of utf-8 multibyte sequence */
1312
+ utf8_bytes_left--;
1313
+ utf8_codepoint <<= 6;
1314
+ utf8_codepoint |= ((unsigned int) c & 0x3f);
1315
+
1316
+ } else {
1317
+ /* Start byte where continuation was expected. */
1318
+ utf8_bytes_left = 0;
1319
+ utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
1320
+ /* Patch buf offset so this character will be parsed again as a */
1321
+ /* start byte. */
1322
+ j--;
1323
+ }
1324
+
1325
+ /* Maybe we need to parse more bytes to find a character. */
1326
+ if (utf8_bytes_left != 0) {
1327
+ continue;
1328
+ }
1329
+
1330
+ /* Parse vt100/ansi escape codes */
1331
+ if (ansi_parser_state == ANSI_NORMAL) {
1332
+ switch (utf8_codepoint) {
1333
+ case '\033':
1334
+ ansi_parser_state = ANSI_ESCAPE_SEEN;
1335
+ continue;
1336
+
1337
+ case 0233:
1338
+ ansi_parser_state = ANSI_CSI;
1339
+ handle->ansi_csi_argc = 0;
1340
+ continue;
1341
+ }
1342
+
1343
+ } else if (ansi_parser_state == ANSI_ESCAPE_SEEN) {
1344
+ switch (utf8_codepoint) {
1345
+ case '[':
1346
+ ansi_parser_state = ANSI_CSI;
1347
+ handle->ansi_csi_argc = 0;
1348
+ continue;
1349
+
1350
+ case '^':
1351
+ case '_':
1352
+ case 'P':
1353
+ case ']':
1354
+ /* Not supported, but we'll have to parse until we see a stop */
1355
+ /* code, e.g. ESC \ or BEL. */
1356
+ ansi_parser_state = ANSI_ST_CONTROL;
1357
+ continue;
1358
+
1359
+ case '\033':
1360
+ /* Ignore double escape. */
1361
+ continue;
1362
+
1363
+ case 'c':
1364
+ /* Full console reset. */
1365
+ FLUSH_TEXT();
1366
+ uv_tty_reset(handle, error);
1367
+ ansi_parser_state = ANSI_NORMAL;
1368
+ continue;
1369
+
1370
+ case '7':
1371
+ /* Save the cursor position and text attributes. */
1372
+ FLUSH_TEXT();
1373
+ uv_tty_save_state(handle, 1, error);
1374
+ ansi_parser_state = ANSI_NORMAL;
1375
+ continue;
1376
+
1377
+ case '8':
1378
+ /* Restore the cursor position and text attributes */
1379
+ FLUSH_TEXT();
1380
+ uv_tty_restore_state(handle, 1, error);
1381
+ ansi_parser_state = ANSI_NORMAL;
1382
+ continue;
1383
+
1384
+ default:
1385
+ if (utf8_codepoint >= '@' && utf8_codepoint <= '_') {
1386
+ /* Single-char control. */
1387
+ ansi_parser_state = ANSI_NORMAL;
1388
+ continue;
1389
+ } else {
1390
+ /* Invalid - proceed as normal, */
1391
+ ansi_parser_state = ANSI_NORMAL;
1392
+ }
1393
+ }
1394
+
1395
+ } else if (ansi_parser_state & ANSI_CSI) {
1396
+ if (!(ansi_parser_state & ANSI_IGNORE)) {
1397
+ if (utf8_codepoint >= '0' && utf8_codepoint <= '9') {
1398
+ /* Parsing a numerical argument */
1399
+
1400
+ if (!(ansi_parser_state & ANSI_IN_ARG)) {
1401
+ /* We were not currently parsing a number */
1402
+
1403
+ /* Check for too many arguments */
1404
+ if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) {
1405
+ ansi_parser_state |= ANSI_IGNORE;
1406
+ continue;
1407
+ }
1408
+
1409
+ ansi_parser_state |= ANSI_IN_ARG;
1410
+ handle->ansi_csi_argc++;
1411
+ handle->ansi_csi_argv[handle->ansi_csi_argc - 1] =
1412
+ (unsigned short) utf8_codepoint - '0';
1413
+ continue;
1414
+ } else {
1415
+ /* We were already parsing a number. Parse next digit. */
1416
+ uint32_t value = 10 *
1417
+ handle->ansi_csi_argv[handle->ansi_csi_argc - 1];
1418
+
1419
+ /* Check for overflow. */
1420
+ if (value > UINT16_MAX) {
1421
+ ansi_parser_state |= ANSI_IGNORE;
1422
+ continue;
1423
+ }
1424
+
1425
+ handle->ansi_csi_argv[handle->ansi_csi_argc - 1] =
1426
+ (unsigned short) value + (utf8_codepoint - '0');
1427
+ continue;
1428
+ }
1429
+
1430
+ } else if (utf8_codepoint == ';') {
1431
+ /* Denotes the end of an argument. */
1432
+ if (ansi_parser_state & ANSI_IN_ARG) {
1433
+ ansi_parser_state &= ~ANSI_IN_ARG;
1434
+ continue;
1435
+
1436
+ } else {
1437
+ /* If ANSI_IN_ARG is not set, add another argument and */
1438
+ /* default it to 0. */
1439
+ /* Check for too many arguments */
1440
+ if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) {
1441
+ ansi_parser_state |= ANSI_IGNORE;
1442
+ continue;
1443
+ }
1444
+
1445
+ handle->ansi_csi_argc++;
1446
+ handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = 0;
1447
+ continue;
1448
+ }
1449
+
1450
+ } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
1451
+ (handle->ansi_csi_argc > 0 || utf8_codepoint != '[')) {
1452
+ int x, y, d;
1453
+
1454
+ /* Command byte */
1455
+ switch (utf8_codepoint) {
1456
+ case 'A':
1457
+ /* cursor up */
1458
+ FLUSH_TEXT();
1459
+ y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1);
1460
+ uv_tty_move_caret(handle, 0, 1, y, 1, error);
1461
+ break;
1462
+
1463
+ case 'B':
1464
+ /* cursor down */
1465
+ FLUSH_TEXT();
1466
+ y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1;
1467
+ uv_tty_move_caret(handle, 0, 1, y, 1, error);
1468
+ break;
1469
+
1470
+ case 'C':
1471
+ /* cursor forward */
1472
+ FLUSH_TEXT();
1473
+ x = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1;
1474
+ uv_tty_move_caret(handle, x, 1, 0, 1, error);
1475
+ break;
1476
+
1477
+ case 'D':
1478
+ /* cursor back */
1479
+ FLUSH_TEXT();
1480
+ x = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1);
1481
+ uv_tty_move_caret(handle, x, 1, 0, 1, error);
1482
+ break;
1483
+
1484
+ case 'E':
1485
+ /* cursor next line */
1486
+ FLUSH_TEXT();
1487
+ y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1;
1488
+ uv_tty_move_caret(handle, 0, 0, y, 1, error);
1489
+ break;
1490
+
1491
+ case 'F':
1492
+ /* cursor previous line */
1493
+ FLUSH_TEXT();
1494
+ y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1);
1495
+ uv_tty_move_caret(handle, 0, 0, y, 1, error);
1496
+ break;
1497
+
1498
+ case 'G':
1499
+ /* cursor horizontal move absolute */
1500
+ FLUSH_TEXT();
1501
+ x = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0])
1502
+ ? handle->ansi_csi_argv[0] - 1 : 0;
1503
+ uv_tty_move_caret(handle, x, 0, 0, 1, error);
1504
+ break;
1505
+
1506
+ case 'H':
1507
+ case 'f':
1508
+ /* cursor move absolute */
1509
+ FLUSH_TEXT();
1510
+ y = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0])
1511
+ ? handle->ansi_csi_argv[0] - 1 : 0;
1512
+ x = (handle->ansi_csi_argc >= 2 && handle->ansi_csi_argv[1])
1513
+ ? handle->ansi_csi_argv[1] - 1 : 0;
1514
+ uv_tty_move_caret(handle, x, 0, y, 0, error);
1515
+ break;
1516
+
1517
+ case 'J':
1518
+ /* Erase screen */
1519
+ FLUSH_TEXT();
1520
+ d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0;
1521
+ if (d >= 0 && d <= 2) {
1522
+ uv_tty_clear(handle, d, 1, error);
1523
+ }
1524
+ break;
1525
+
1526
+ case 'K':
1527
+ /* Erase line */
1528
+ FLUSH_TEXT();
1529
+ d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0;
1530
+ if (d >= 0 && d <= 2) {
1531
+ uv_tty_clear(handle, d, 0, error);
1532
+ }
1533
+ break;
1534
+
1535
+ case 'm':
1536
+ /* Set style */
1537
+ FLUSH_TEXT();
1538
+ uv_tty_set_style(handle, error);
1539
+ break;
1540
+
1541
+ case 's':
1542
+ /* Save the cursor position. */
1543
+ FLUSH_TEXT();
1544
+ uv_tty_save_state(handle, 0, error);
1545
+ break;
1546
+
1547
+ case 'u':
1548
+ /* Restore the cursor position */
1549
+ FLUSH_TEXT();
1550
+ uv_tty_restore_state(handle, 0, error);
1551
+ break;
1552
+ }
1553
+
1554
+ /* Sequence ended - go back to normal state. */
1555
+ ansi_parser_state = ANSI_NORMAL;
1556
+ continue;
1557
+
1558
+ } else {
1559
+ /* We don't support commands that use private mode characters or */
1560
+ /* intermediaries. Ignore the rest of the sequence. */
1561
+ ansi_parser_state |= ANSI_IGNORE;
1562
+ continue;
1563
+ }
1564
+ } else {
1565
+ /* We're ignoring this command. Stop only on command character. */
1566
+ if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
1567
+ ansi_parser_state = ANSI_NORMAL;
1568
+ }
1569
+ continue;
1570
+ }
1571
+
1572
+ } else if (ansi_parser_state & ANSI_ST_CONTROL) {
1573
+ /* Unsupported control code */
1574
+ /* Ignore everything until we see BEL or ESC \ */
1575
+ if (ansi_parser_state & ANSI_IN_STRING) {
1576
+ if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
1577
+ if (utf8_codepoint == '"') {
1578
+ ansi_parser_state &= ~ANSI_IN_STRING;
1579
+ } else if (utf8_codepoint == '\\') {
1580
+ ansi_parser_state |= ANSI_BACKSLASH_SEEN;
1581
+ }
1582
+ } else {
1583
+ ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;
1584
+ }
1585
+ } else {
1586
+ if (utf8_codepoint == '\007' || (utf8_codepoint == '\\' &&
1587
+ (ansi_parser_state & ANSI_ESCAPE_SEEN))) {
1588
+ /* End of sequence */
1589
+ ansi_parser_state = ANSI_NORMAL;
1590
+ } else if (utf8_codepoint == '\033') {
1591
+ /* Escape character */
1592
+ ansi_parser_state |= ANSI_ESCAPE_SEEN;
1593
+ } else if (utf8_codepoint == '"') {
1594
+ /* String starting */
1595
+ ansi_parser_state |= ANSI_IN_STRING;
1596
+ ansi_parser_state &= ~ANSI_ESCAPE_SEEN;
1597
+ ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;
1598
+ } else {
1599
+ ansi_parser_state &= ~ANSI_ESCAPE_SEEN;
1600
+ }
1601
+ }
1602
+ continue;
1603
+ } else {
1604
+ /* Inconsistent state */
1605
+ abort();
1606
+ }
1607
+
1608
+ /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
1609
+ /* windows console doesn't really support UTF-16, so just emit the */
1610
+ /* replacement character. */
1611
+ if (utf8_codepoint > 0xffff) {
1612
+ utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
1613
+ }
1614
+
1615
+ if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) {
1616
+ /* EOL conversion - emit \r\n, when we see either \r or \n. */
1617
+ /* If a \n immediately follows a \r or vice versa, ignore it. */
1618
+ if (previous_eol == 0 || utf8_codepoint == previous_eol) {
1619
+ /* If there's no room in the utf16 buf, flush it first. */
1620
+ if (2 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {
1621
+ uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error);
1622
+ utf16_buf_used = 0;
1623
+ }
1624
+
1625
+ utf16_buf[utf16_buf_used++] = L'\r';
1626
+ utf16_buf[utf16_buf_used++] = L'\n';
1627
+ previous_eol = (char) utf8_codepoint;
1628
+ } else {
1629
+ /* Ignore this newline, but don't ignore later ones. */
1630
+ previous_eol = 0;
1631
+ }
1632
+
1633
+ } else if (utf8_codepoint <= 0xffff) {
1634
+ /* Encode character into utf-16 buffer. */
1635
+
1636
+ /* If there's no room in the utf16 buf, flush it first. */
1637
+ if (1 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {
1638
+ uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error);
1639
+ utf16_buf_used = 0;
1640
+ }
1641
+
1642
+ utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;
1643
+ previous_eol = 0;
1644
+ }
1645
+ }
1646
+ }
1647
+
1648
+ /* Flush remaining characters */
1649
+ FLUSH_TEXT();
1650
+
1651
+ /* Copy cached values back to struct. */
1652
+ handle->utf8_bytes_left = utf8_bytes_left;
1653
+ handle->utf8_codepoint = utf8_codepoint;
1654
+ handle->previous_eol = previous_eol;
1655
+ handle->ansi_parser_state = ansi_parser_state;
1656
+
1657
+ LeaveCriticalSection(&uv_tty_output_lock);
1658
+
1659
+ if (*error == STATUS_SUCCESS) {
1660
+ return 0;
1661
+ } else {
1662
+ return -1;
1663
+ }
1664
+
1665
+ #undef FLUSH_TEXT
1666
+ }
1667
+
1668
+
1669
+ int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
1670
+ uv_buf_t bufs[], int bufcnt, uv_write_cb cb) {
1671
+ DWORD error;
1672
+
1673
+ if ((handle->flags & UV_HANDLE_SHUTTING) ||
1674
+ (handle->flags & UV_HANDLE_CLOSING)) {
1675
+ uv__set_sys_error(loop, WSAESHUTDOWN);
1676
+ return -1;
1677
+ }
1678
+
1679
+ uv_req_init(loop, (uv_req_t*) req);
1680
+ req->type = UV_WRITE;
1681
+ req->handle = (uv_stream_t*) handle;
1682
+ req->cb = cb;
1683
+
1684
+ handle->reqs_pending++;
1685
+ handle->write_reqs_pending++;
1686
+ uv_ref(loop);
1687
+
1688
+ req->queued_bytes = 0;
1689
+
1690
+ if (!uv_tty_write_bufs(handle, bufs, bufcnt, &error)) {
1691
+ SET_REQ_SUCCESS(req);
1692
+ } else {
1693
+ SET_REQ_ERROR(req, error);
1694
+ }
1695
+
1696
+ uv_insert_pending_req(loop, (uv_req_t*) req);
1697
+
1698
+ return 0;
1699
+ }
1700
+
1701
+
1702
+ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
1703
+ uv_write_t* req) {
1704
+
1705
+ handle->write_queue_size -= req->queued_bytes;
1706
+
1707
+ if (req->cb) {
1708
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
1709
+ ((uv_write_cb)req->cb)(req, loop->last_err.code == UV_OK ? 0 : -1);
1710
+ }
1711
+
1712
+ handle->write_reqs_pending--;
1713
+ if (handle->flags & UV_HANDLE_SHUTTING &&
1714
+ handle->write_reqs_pending == 0) {
1715
+ uv_want_endgame(loop, (uv_handle_t*)handle);
1716
+ }
1717
+
1718
+ DECREASE_PENDING_REQ_COUNT(handle);
1719
+ uv_unref(loop);
1720
+ }
1721
+
1722
+
1723
+ void uv_tty_close(uv_tty_t* handle) {
1724
+ handle->flags |= UV_HANDLE_SHUTTING;
1725
+
1726
+ uv_tty_read_stop(handle);
1727
+ CloseHandle(handle->handle);
1728
+
1729
+ if (handle->reqs_pending == 0) {
1730
+ uv_want_endgame(handle->loop, (uv_handle_t*) handle);
1731
+ }
1732
+ }
1733
+
1734
+
1735
+ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
1736
+ if ((handle->flags && UV_HANDLE_CONNECTION) &&
1737
+ handle->shutdown_req != NULL &&
1738
+ handle->write_reqs_pending == 0) {
1739
+ /* TTY shutdown is really just a no-op */
1740
+ if (handle->shutdown_req->cb) {
1741
+ if (handle->flags & UV_HANDLE_CLOSING) {
1742
+ uv__set_sys_error(loop, WSAEINTR);
1743
+ handle->shutdown_req->cb(handle->shutdown_req, -1);
1744
+ } else {
1745
+ handle->shutdown_req->cb(handle->shutdown_req, 0);
1746
+ }
1747
+ }
1748
+
1749
+ handle->shutdown_req = NULL;
1750
+
1751
+ uv_unref(loop);
1752
+ DECREASE_PENDING_REQ_COUNT(handle);
1753
+ return;
1754
+ }
1755
+
1756
+ if (handle->flags & UV_HANDLE_CLOSING &&
1757
+ handle->reqs_pending == 0) {
1758
+ /* The console handle duplicate used for line reading should be destroyed */
1759
+ /* by uv_tty_read_stop. */
1760
+ assert(handle->read_line_handle == NULL);
1761
+
1762
+ /* The wait handle used for raw reading should be unregistered when the */
1763
+ /* wait callback runs. */
1764
+ assert(handle->read_raw_wait == NULL);
1765
+
1766
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
1767
+ handle->flags |= UV_HANDLE_CLOSED;
1768
+
1769
+ if (handle->close_cb) {
1770
+ handle->close_cb((uv_handle_t*)handle);
1771
+ }
1772
+
1773
+ uv_unref(loop);
1774
+ }
1775
+ }
1776
+
1777
+
1778
+ /* TODO: remove me */
1779
+ void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
1780
+ uv_req_t* raw_req) {
1781
+ abort();
1782
+ }
1783
+
1784
+
1785
+ /* TODO: remove me */
1786
+ void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
1787
+ uv_connect_t* req) {
1788
+ abort();
1789
+ }
1790
+
1791
+
1792
+ void uv_tty_reset_mode() {
1793
+ /* Not necessary to do anything. */
1794
+ ;
1795
+ }