php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | |
Patch 0001-Start-adding-VT100-support-for-Windows-v2 for Output Control Bug #72768Patch version 2016-08-26 14:10 UTC Return to Bug #72768 | Download this patchThis patch is obsolete Obsoleted by patches: This patch renders other patches obsolete Obsolete patches: Patch Revisions:Developer: mlocati@gmail.comFrom 1d3a8752157e44d006c1040951473862155a5345 Mon Sep 17 00:00:00 2001 From: Michele Locati <michele@locati.it> Date: Fri, 26 Aug 2016 14:10:16 +0200 Subject: [PATCH] Start adding VT100 support for Windows The first parameter should be a stream (STDOUT or STDERR). If no second parameter is specified: the function checks if the stream supports VT100 control codes: - Windows: returns TRUE if Windows is 10.0.10586 or greater, the console has the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag and the stream is not redirected. - POSIX: returns TRUE if the stream is not redirected. - Others: returns FALSE If the second parameter is specified: the function tries to enable or disable the VT100 control codes. - Windows: returns TRUE if Windows is 10.0.10586 or greater, the stream is not redirected and the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag has been set/unset - Others: returns FALSE --- ext/standard/basic_functions.c | 6 ++ ext/standard/streamsfuncs.c | 65 +++++++++++++++++++ ext/standard/streamsfuncs.h | 1 + win32/build/config.w32 | 2 +- win32/win_streams.c | 138 +++++++++++++++++++++++++++++++++++++++++ win32/win_streams.h | 44 +++++++++++++ 6 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 win32/win_streams.c create mode 100644 win32/win_streams.h diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 58f9b49..0564301 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2011,6 +2011,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_supports_lock, 0, 0, 1) ZEND_ARG_INFO(0, stream) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_vt100_support, 0, 0, 1) + ZEND_ARG_INFO(0, stream) + ZEND_ARG_INFO(0, enable) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_select, 0, 0, 4) ZEND_ARG_INFO(1, read_streams) /* ARRAY_INFO(1, read_streams, 1) */ ZEND_ARG_INFO(1, write_streams) /* ARRAY_INFO(1, write_streams, 1) */ @@ -3134,6 +3139,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(stream_copy_to_stream, arginfo_stream_copy_to_stream) PHP_FE(stream_get_contents, arginfo_stream_get_contents) PHP_FE(stream_supports_lock, arginfo_stream_supports_lock) + PHP_FE(stream_vt100_support, arginfo_stream_vt100_support) PHP_FE(fgetcsv, arginfo_fgetcsv) PHP_FE(fputcsv, arginfo_fputcsv) PHP_FE(flock, arginfo_flock) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 3ab362f..f12dd44 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -37,6 +37,7 @@ typedef unsigned long long php_timeout_ull; #else #include "win32/select.h" #include "win32/sockets.h" +#include "win32/win_streams.h" typedef unsigned __int64 php_timeout_ull; #endif @@ -1635,6 +1636,70 @@ PHP_FUNCTION(stream_supports_lock) RETURN_TRUE; } +/* {{{ proto proto stream_vt100_support(resource stream[, bool enable]) +Get or set VT100 support for the specified stream. */ +PHP_FUNCTION(stream_vt100_support) +{ + php_stream *stream; + zend_bool enable; + #ifdef PHP_WIN32 + DWORD stdHandle; + #endif + int argc = ZEND_NUM_ARGS(); + + if (zend_parse_parameters(argc, "r|b", &stream, &enable) == FAILURE) { + return; + } + #ifdef PHP_WIN32 + if (!SystemHasVT100Support()) { + RETURN_FALSE; + } + stdHandle = StreamToStdHandle(stream); + if (!stdHandle) { + RETURN_FALSE; + } + if (StdHandleIsRedirectedToFile(stdHandle)) { + RETURN_FALSE; + } + #endif + + if (argc == 1) { + #ifdef PHP_WIN32 + if (StdHandleHasColorSupport(stdHandle)) { + RETURN_TRUE; + } + else { + RETURN_FALSE; + } + #elif HAVE_POSIX + int fd; + if (!php_posix_stream_get_fd(stream, &fd)) { + RETURN_FALSE; + } + if (isatty(fd)) { + RETURN_TRUE; + } + else { + RETURN_FALSE; + } + #else + RETURN_FALSE; + #endif + } + else { + #ifdef PHP_WIN32 + if (EnableStdHandleColorSupport(stdHandle, enable ? TRUE : FALSE)) { + RETURN_TRUE; + } + else { + RETURN_FALSE; + } + #else + RETURN_FALSE; + #endif + } +} + #ifdef HAVE_SHUTDOWN /* {{{ proto int stream_socket_shutdown(resource stream, int how) causes all or part of a full-duplex connection on the socket associated diff --git a/ext/standard/streamsfuncs.h b/ext/standard/streamsfuncs.h index 45f51c2..ab169a3 100644 --- a/ext/standard/streamsfuncs.h +++ b/ext/standard/streamsfuncs.h @@ -61,6 +61,7 @@ PHP_FUNCTION(stream_socket_shutdown); PHP_FUNCTION(stream_resolve_include_path); PHP_FUNCTION(stream_is_local); PHP_FUNCTION(stream_supports_lock); +PHP_FUNCTION(stream_vt100_support); #if HAVE_SOCKETPAIR PHP_FUNCTION(stream_socket_pair); diff --git a/win32/build/config.w32 b/win32/build/config.w32 index fa9ed62..88d597f 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -165,7 +165,7 @@ ADD_FLAG("CFLAGS_BD_MAIN_STREAMS", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ADD_SOURCES("win32", "dllmain.c glob.c readdir.c \ registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c \ - getrusage.c ftok.c ioutil.c codepage.c"); + getrusage.c ftok.c ioutil.c codepage.c win_streams.c"); ADD_FLAG("CFLAGS_BD_WIN32", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); diff --git a/win32/win_streams.c b/win32/win_streams.c new file mode 100644 index 0000000..d2648d0 --- /dev/null +++ b/win32/win_streams.c @@ -0,0 +1,138 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Michele Locati <mlocati@gmail.com> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#include "win_streams.h" + +BOOL SystemHasVT100Support() +{ + static BOOL result = 2; + if (result == 2) { + const DWORD MINV_MAJOR = 10, MINV_MINOR = 0, MINV_BUILD = 10586; + result = FALSE; + HMODULE hMod = GetModuleHandle(TEXT("ntdll.dll")); + if (hMod) { + RtlGetVersionPtr fn = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion"); + if (fn != NULL) { + RTL_OSVERSIONINFOW rovi = { 0 }; + rovi.dwOSVersionInfoSize = sizeof(rovi); + if (fn(&rovi) == 0) { + if ( + rovi.dwMajorVersion > MINV_MAJOR + || + ( + rovi.dwMajorVersion == MINV_MAJOR + && + ( + rovi.dwMinorVersion > MINV_MINOR + || + ( + rovi.dwMinorVersion == MINV_MINOR + && rovi.dwBuildNumber >= MINV_BUILD + ) + ) + ) + ) { + result = TRUE; + } + } + } + } + } + return result; +} + +DWORD StreamToStdHandle(php_stream *stream) +{ + DWORD result = 0; + if (stream != NULL && stream->orig_path != NULL) { + if (strcmp(stream->orig_path, "php://stdin") == 0) { + result = STD_INPUT_HANDLE; + } + else if (strcmp(stream->orig_path, "php://stdout") == 0) { + result = STD_OUTPUT_HANDLE; + } + else if (strcmp(stream->orig_path, "php://stderr") == 0) { + result = STD_ERROR_HANDLE; + } + } + return result; +} + +BOOL StdHandleIsRedirectedToFile(DWORD stdHandle) +{ + BOOL result = FALSE; + + HANDLE hStd = stdHandle ? GetStdHandle(stdHandle) : INVALID_HANDLE_VALUE; + if (hStd != INVALID_HANDLE_VALUE) { + if (GetFinalPathNameByHandle(hStd, NULL, 0, 0) != 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + result = TRUE; + } + } + + return result; +} + +BOOL StdHandleHasColorSupport(DWORD stdHandle) +{ + BOOL result = FALSE; + if (SystemHasVT100Support()) { + HANDLE hStdOut = stdHandle ? GetStdHandle(stdHandle) : INVALID_HANDLE_VALUE; + if (hStdOut != INVALID_HANDLE_VALUE) { + DWORD mode; + if (GetConsoleMode(hStdOut, &mode)) { + if (mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) { + result = TRUE; + } + } + } + } + + return result; +} + +BOOL EnableStdHandleColorSupport(DWORD stdHandle, BOOL enable) +{ + BOOL result = FALSE; + if (SystemHasVT100Support()) { + HANDLE hStdOut; + hStdOut = stdHandle ? GetStdHandle(STD_OUTPUT_HANDLE) : INVALID_HANDLE_VALUE; + if (hStdOut != INVALID_HANDLE_VALUE) { + DWORD mode; + if (GetConsoleMode(hStdOut, &mode)) { + if (((mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? 1 : 0) == (enable ? 1 : 0)) { + result = TRUE; + } + else { + if (enable) { + mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + } + else { + mode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING; + } + if (SetConsoleMode(hStdOut, mode)) { + result = TRUE; + } + } + } + } + } + + return result; +} diff --git a/win32/win_streams.h b/win32/win_streams.h new file mode 100644 index 0000000..a0c8250 --- /dev/null +++ b/win32/win_streams.h @@ -0,0 +1,44 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Michele Locati <mlocati@gmail.com> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_WIN32_WIN_STREAMS_H +#define PHP_WIN32_WIN_STREAMS_H + +#include "php.h" +#include "php_streams.h" +#include <windows.h> + +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + +typedef LONG (WINAPI * RtlGetVersionPtr) (PRTL_OSVERSIONINFOW); + +BOOL SystemHasVT100Support(); + +DWORD StreamToStdHandle(php_stream *stream); + +BOOL StdHandleIsRedirectedToFile(DWORD stdHandle); + +BOOL StdHandleHasColorSupport(DWORD stdHandle); + +BOOL EnableStdHandleColorSupport(DWORD stdHandle, BOOL enable); + +#endif -- 2.9.3.windows.1 |
Copyright © 2001-2024 The PHP Group All rights reserved. |
Last updated: Wed Dec 11 17:01:28 2024 UTC |