asyncengine 0.0.1.testing

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }