|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
Patch 0001-Start-adding-VT100-support-for-Windows.patch for Output Control Bug #72768Patch version 2016-08-25 13:05 UTC Return to Bug #72768 | Download this patchThis patch is obsolete Obsoleted by patches:
Developer: mlocati@gmail.com
From 3bc04bce67678e22de7f962bc67731e1b962e7de Mon Sep 17 00:00:00 2001
From: Michele Locati <mlocati@gmail.com>
Date: Thu, 25 Aug 2016 10:44:41 +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 | 45 ++++++++++++++
6 files changed, 256 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 6323d18..06e01ab 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -2019,6 +2019,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) */
@@ -3118,6 +3123,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 def1fb8..f968a92 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
@@ -1632,6 +1633,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 609f5c5..60e4e8c 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -161,7 +161,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");
+ getrusage.c ftok.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..0cde76e
--- /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 SystamHasVT100Support()
+{
+ 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 (SystamHasVT100Support()) {
+ 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 (SystamHasVT100Support()) {
+ 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) == (enabled ? 1 : 0)) {
+ result = TRUE;
+ }
+ else {
+ if (enabled) {
+ 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..81e686e
--- /dev/null
+++ b/win32/win_streams.h
@@ -0,0 +1,45 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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 _WIN32_WIN_STREAMS_H_
+
+#include <config.w32.h>
+#include <windows.h>
+#include <versionhelpers.h>
+#include <fileapi.h>
+#include "php_streams.h"
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+typedef NTSTATUS (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-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 21:00:01 2025 UTC |