|
3504672…
|
ashepilko
|
1 |
/* |
|
3504672…
|
ashepilko
|
2 |
** Copyright (c) 2020 D. Richard Hipp |
|
3504672…
|
ashepilko
|
3 |
** |
|
3504672…
|
ashepilko
|
4 |
** This program is free software; you can redistribute it and/or |
|
3504672…
|
ashepilko
|
5 |
** modify it under the terms of the Simplified BSD License (also |
|
3504672…
|
ashepilko
|
6 |
** known as the "2-Clause License" or "FreeBSD License".) |
|
3504672…
|
ashepilko
|
7 |
|
|
3504672…
|
ashepilko
|
8 |
** This program is distributed in the hope that it will be useful, |
|
3504672…
|
ashepilko
|
9 |
** but without any warranty; without even the implied warranty of |
|
3504672…
|
ashepilko
|
10 |
** merchantability or fitness for a particular purpose. |
|
3504672…
|
ashepilko
|
11 |
** |
|
3504672…
|
ashepilko
|
12 |
** Author contact information: |
|
3504672…
|
ashepilko
|
13 |
** [email protected] |
|
3504672…
|
ashepilko
|
14 |
** http://www.hwaci.com/drh/ |
|
3504672…
|
ashepilko
|
15 |
** |
|
3504672…
|
ashepilko
|
16 |
******************************************************************************* |
|
3504672…
|
ashepilko
|
17 |
** |
|
3504672…
|
ashepilko
|
18 |
** This file contains code used to query terminal info |
|
3504672…
|
ashepilko
|
19 |
*/ |
|
3504672…
|
ashepilko
|
20 |
|
|
3504672…
|
ashepilko
|
21 |
#include "config.h" |
|
3504672…
|
ashepilko
|
22 |
#include "terminal.h" |
|
3504672…
|
ashepilko
|
23 |
#include <assert.h> |
|
3504672…
|
ashepilko
|
24 |
#ifdef _WIN32 |
|
3504672…
|
ashepilko
|
25 |
# include <windows.h> |
|
3504672…
|
ashepilko
|
26 |
#else |
|
a8780e4…
|
preben
|
27 |
#ifdef __EXTENSIONS__ |
|
a8780e4…
|
preben
|
28 |
#include <termio.h> |
|
a8780e4…
|
preben
|
29 |
#endif |
|
3504672…
|
ashepilko
|
30 |
#include <sys/ioctl.h> |
|
3504672…
|
ashepilko
|
31 |
#include <stdio.h> |
|
3504672…
|
ashepilko
|
32 |
#include <unistd.h> |
|
3504672…
|
ashepilko
|
33 |
#endif |
|
3504672…
|
ashepilko
|
34 |
|
|
3504672…
|
ashepilko
|
35 |
|
|
3504672…
|
ashepilko
|
36 |
|
|
3504672…
|
ashepilko
|
37 |
#if INTERFACE |
|
3504672…
|
ashepilko
|
38 |
/* |
|
3504672…
|
ashepilko
|
39 |
** Terminal size defined in terms of columns and lines. |
|
3504672…
|
ashepilko
|
40 |
*/ |
|
3504672…
|
ashepilko
|
41 |
struct TerminalSize { |
|
3504672…
|
ashepilko
|
42 |
unsigned int nColumns; /* Number of characters on a single line */ |
|
3504672…
|
ashepilko
|
43 |
unsigned int nLines; /* Number of lines */ |
|
3504672…
|
ashepilko
|
44 |
}; |
|
3504672…
|
ashepilko
|
45 |
#endif |
|
3504672…
|
ashepilko
|
46 |
|
|
3504672…
|
ashepilko
|
47 |
|
|
3504672…
|
ashepilko
|
48 |
/* Get the current terminal size by calling a system service. |
|
3504672…
|
ashepilko
|
49 |
** |
|
e2bdc10…
|
danield
|
50 |
** Return 1 on success. This sets the size parameters to the values returned by |
|
3504672…
|
ashepilko
|
51 |
** the system call, when such is supported; set the size to zero otherwise. |
|
3504672…
|
ashepilko
|
52 |
** Return 0 on the system service call failure. |
|
3504672…
|
ashepilko
|
53 |
** |
|
3504672…
|
ashepilko
|
54 |
** Under Linux/bash the size info is also available from env $LINES, $COLUMNS. |
|
3504672…
|
ashepilko
|
55 |
** Or it can be queried using tput `echo -e "lines\ncols"|tput -S`. |
|
3504672…
|
ashepilko
|
56 |
** Technically, this info could be cached, but then we'd need to handle |
|
3504672…
|
ashepilko
|
57 |
** SIGWINCH signal to requery the terminal on resize event. |
|
3504672…
|
ashepilko
|
58 |
*/ |
|
b241b9c…
|
drh
|
59 |
int terminal_get_size(TerminalSize *t){ |
|
3504672…
|
ashepilko
|
60 |
memset(t, 0, sizeof(*t)); |
|
3504672…
|
ashepilko
|
61 |
|
|
3504672…
|
ashepilko
|
62 |
#if defined(TIOCGSIZE) |
|
3504672…
|
ashepilko
|
63 |
{ |
|
3504672…
|
ashepilko
|
64 |
struct ttysize ts; |
|
3f30abc…
|
drh
|
65 |
if( ioctl(STDIN_FILENO, TIOCGSIZE, &ts)>=0 |
|
3f30abc…
|
drh
|
66 |
|| ioctl(STDOUT_FILENO, TIOCGSIZE, &ts)>=0 |
|
3f30abc…
|
drh
|
67 |
|| ioctl(STDERR_FILENO, TIOCGSIZE, &ts)>=0 |
|
3f30abc…
|
drh
|
68 |
){ |
|
3504672…
|
ashepilko
|
69 |
t->nColumns = ts.ts_cols; |
|
3504672…
|
ashepilko
|
70 |
t->nLines = ts.ts_lines; |
|
3504672…
|
ashepilko
|
71 |
return 1; |
|
3504672…
|
ashepilko
|
72 |
} |
|
3504672…
|
ashepilko
|
73 |
return 0; |
|
3504672…
|
ashepilko
|
74 |
} |
|
3504672…
|
ashepilko
|
75 |
#elif defined(TIOCGWINSZ) |
|
3504672…
|
ashepilko
|
76 |
{ |
|
3504672…
|
ashepilko
|
77 |
struct winsize ws; |
|
3f30abc…
|
drh
|
78 |
if( ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)>=0 |
|
3f30abc…
|
drh
|
79 |
|| ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws)>=0 |
|
3f30abc…
|
drh
|
80 |
|| ioctl(STDERR_FILENO, TIOCGWINSZ, &ws)>=0 |
|
3f30abc…
|
drh
|
81 |
){ |
|
3504672…
|
ashepilko
|
82 |
t->nColumns = ws.ws_col; |
|
3504672…
|
ashepilko
|
83 |
t->nLines = ws.ws_row; |
|
3504672…
|
ashepilko
|
84 |
return 1; |
|
3504672…
|
ashepilko
|
85 |
} |
|
3504672…
|
ashepilko
|
86 |
return 0; |
|
3504672…
|
ashepilko
|
87 |
} |
|
3504672…
|
ashepilko
|
88 |
#elif defined(_WIN32) |
|
3504672…
|
ashepilko
|
89 |
{ |
|
3504672…
|
ashepilko
|
90 |
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
3f30abc…
|
drh
|
91 |
if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) |
|
3f30abc…
|
drh
|
92 |
|| GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi) |
|
3f30abc…
|
drh
|
93 |
|| GetConsoleScreenBufferInfo(GetStdHandle(STD_INPUT_HANDLE), &csbi) |
|
3f30abc…
|
drh
|
94 |
){ |
|
3504672…
|
ashepilko
|
95 |
t->nColumns = csbi.srWindow.Right - csbi.srWindow.Left + 1; |
|
3504672…
|
ashepilko
|
96 |
t->nLines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; |
|
3504672…
|
ashepilko
|
97 |
return 1; |
|
3504672…
|
ashepilko
|
98 |
} |
|
3504672…
|
ashepilko
|
99 |
return 0; |
|
3504672…
|
ashepilko
|
100 |
} |
|
3504672…
|
ashepilko
|
101 |
#else |
|
3504672…
|
ashepilko
|
102 |
return 1; |
|
3504672…
|
ashepilko
|
103 |
#endif |
|
3504672…
|
ashepilko
|
104 |
} |
|
3504672…
|
ashepilko
|
105 |
|
|
3504672…
|
ashepilko
|
106 |
/* |
|
3504672…
|
ashepilko
|
107 |
** Return the terminal's current width in columns when available, otherwise |
|
3504672…
|
ashepilko
|
108 |
** return the specified default value. |
|
3504672…
|
ashepilko
|
109 |
*/ |
|
b241b9c…
|
drh
|
110 |
unsigned int terminal_get_width(unsigned int nDefault){ |
|
b241b9c…
|
drh
|
111 |
TerminalSize ts; |
|
3504672…
|
ashepilko
|
112 |
if( terminal_get_size(&ts) ){ |
|
3504672…
|
ashepilko
|
113 |
return ts.nColumns; |
|
3504672…
|
ashepilko
|
114 |
} |
|
3504672…
|
ashepilko
|
115 |
return nDefault; |
|
3504672…
|
ashepilko
|
116 |
} |
|
3504672…
|
ashepilko
|
117 |
|
|
3504672…
|
ashepilko
|
118 |
/* |
|
3504672…
|
ashepilko
|
119 |
** Return the terminal's current height in lines when available, otherwise |
|
3504672…
|
ashepilko
|
120 |
** return the specified default value. |
|
3504672…
|
ashepilko
|
121 |
*/ |
|
b241b9c…
|
drh
|
122 |
unsigned int terminal_get_height(unsigned int nDefault){ |
|
b241b9c…
|
drh
|
123 |
TerminalSize ts; |
|
3504672…
|
ashepilko
|
124 |
if( terminal_get_size(&ts) ){ |
|
3504672…
|
ashepilko
|
125 |
return ts.nLines; |
|
3504672…
|
ashepilko
|
126 |
} |
|
3504672…
|
ashepilko
|
127 |
return nDefault; |
|
3504672…
|
ashepilko
|
128 |
} |
|
b241b9c…
|
drh
|
129 |
|
|
b241b9c…
|
drh
|
130 |
/* |
|
f0d9fe2…
|
drh
|
131 |
** Return true if it is reasonable is emit VT100 escape codes. |
|
f0d9fe2…
|
drh
|
132 |
*/ |
|
f0d9fe2…
|
drh
|
133 |
int terminal_is_vt100(void){ |
|
f0d9fe2…
|
drh
|
134 |
char *zNoColor; |
|
360abc5…
|
florian
|
135 |
#ifdef _WIN32 |
|
360abc5…
|
florian
|
136 |
if( !win32_terminal_is_vt100(1) ) return 0; |
|
360abc5…
|
florian
|
137 |
#endif /* _WIN32 */ |
|
f0d9fe2…
|
drh
|
138 |
if( !fossil_isatty(1) ) return 0; |
|
f0d9fe2…
|
drh
|
139 |
zNoColor =fossil_getenv("NO_COLOR"); |
|
f0d9fe2…
|
drh
|
140 |
if( zNoColor==0 ) return 1; |
|
f0d9fe2…
|
drh
|
141 |
if( zNoColor[0]==0 ) return 1; |
|
f0d9fe2…
|
drh
|
142 |
if( is_false(zNoColor) ) return 1; |
|
f0d9fe2…
|
drh
|
143 |
return 0; |
|
f0d9fe2…
|
drh
|
144 |
} |
|
360abc5…
|
florian
|
145 |
|
|
360abc5…
|
florian
|
146 |
#ifdef _WIN32 |
|
360abc5…
|
florian
|
147 |
/* |
|
360abc5…
|
florian
|
148 |
** Return true if the Windows console supports VT100 escape codes. |
|
360abc5…
|
florian
|
149 |
** |
|
360abc5…
|
florian
|
150 |
** Support for VT100 escape codes is enabled by default in Windows Terminal |
|
360abc5…
|
florian
|
151 |
** on Windows 10 and Windows 11, and disabled by default in Legacy Consoles |
|
360abc5…
|
florian
|
152 |
** and on older versions of Windows. Programs can turn on VT100 support for |
|
360abc5…
|
florian
|
153 |
** Legacy Consoles using the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag. |
|
360abc5…
|
florian
|
154 |
** |
|
360abc5…
|
florian
|
155 |
** NOTE: If this function needs to be called in more complex scenarios with |
|
360abc5…
|
florian
|
156 |
** reassigned stdout and stderr streams, the following CRT calls are useful |
|
360abc5…
|
florian
|
157 |
** to translate from CRT streams to file descriptors and to Win32 handles: |
|
360abc5…
|
florian
|
158 |
** |
|
360abc5…
|
florian
|
159 |
** HANDLE hOutputHandle = (HANDLE)_get_osfhandle(_fileno(<FILE*>)); |
|
360abc5…
|
florian
|
160 |
*/ |
|
360abc5…
|
florian
|
161 |
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING |
|
360abc5…
|
florian
|
162 |
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 |
|
360abc5…
|
florian
|
163 |
#endif |
|
360abc5…
|
florian
|
164 |
int win32_terminal_is_vt100(int fd){ |
|
360abc5…
|
florian
|
165 |
HANDLE hConsole = NULL; |
|
360abc5…
|
florian
|
166 |
DWORD dwConsoleMode; |
|
360abc5…
|
florian
|
167 |
switch( fd ){ |
|
360abc5…
|
florian
|
168 |
case 1: |
|
360abc5…
|
florian
|
169 |
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
|
360abc5…
|
florian
|
170 |
break; |
|
360abc5…
|
florian
|
171 |
case 2: |
|
360abc5…
|
florian
|
172 |
hConsole = GetStdHandle(STD_ERROR_HANDLE); |
|
360abc5…
|
florian
|
173 |
break; |
|
360abc5…
|
florian
|
174 |
} |
|
360abc5…
|
florian
|
175 |
if( GetConsoleMode(hConsole,&dwConsoleMode) ){ |
|
360abc5…
|
florian
|
176 |
return (dwConsoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)!=0; |
|
360abc5…
|
florian
|
177 |
} |
|
360abc5…
|
florian
|
178 |
return 0; |
|
360abc5…
|
florian
|
179 |
} |
|
360abc5…
|
florian
|
180 |
#endif /* _WIN32 */ |