Skip to content

Commit a052033

Browse files
committed
IO: allow issuing multiple terminal queries in one call
1 parent fed2c87 commit a052033

File tree

10 files changed

+75
-63
lines changed

10 files changed

+75
-63
lines changed

src/common/io/io.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ bool ffPathExpandEnv(const char* in, FFstrbuf* out);
130130

131131
#define FF_IO_TERM_RESP_WAIT_MS 100 // #554
132132

133-
FF_C_SCANF(2, 3)
134-
const char* ffGetTerminalResponse(const char* request, const char* format, ...);
133+
FF_C_SCANF(3, 4)
134+
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...);
135135

136136
// Not thread safe!
137137
bool ffSuppressIO(bool suppress);

src/common/io/io_unix.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ void restoreTerm(void)
144144
tcsetattr(ftty, TCSAFLUSH, &oldTerm);
145145
}
146146

147-
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
147+
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...)
148148
{
149149
if (ftty < 0)
150150
{
@@ -180,17 +180,29 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
180180
}
181181
#endif
182182

183-
char buffer[512];
184-
ssize_t bytesRead = read(ftty, buffer, sizeof(buffer) - 1);
185-
186-
if(bytesRead <= 0)
187-
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
188-
189-
buffer[bytesRead] = '\0';
183+
char buffer[1024];
184+
size_t bytesRead = 0;
190185

191186
va_list args;
192187
va_start(args, format);
193-
vsscanf(buffer, format, args);
188+
189+
while (true)
190+
{
191+
ssize_t nRead = read(ftty, buffer + bytesRead, sizeof(buffer) - bytesRead - 1);
192+
193+
if (nRead <= 0)
194+
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
195+
196+
bytesRead += (size_t) nRead;
197+
buffer[bytesRead] = '\0';
198+
199+
int ret = vsscanf(buffer, format, args);
200+
if (ret <= 0)
201+
return "vsscanf(buffer, format, args) failed";
202+
if (ret >= nParams)
203+
break;
204+
}
205+
194206
va_end(args);
195207

196208
return NULL;

src/common/io/io_windows.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ void ffListFilesRecursively(const char* path, bool pretty)
205205
listFilesRecursively(folder.length, &folder, 0, NULL, pretty);
206206
}
207207

208-
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
208+
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...)
209209
{
210210
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
211211
FF_AUTO_CLOSE_FD HANDLE hConin = INVALID_HANDLE_VALUE;
@@ -256,20 +256,30 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
256256
ReadConsoleInputW(hInput, &record, 1, &len);
257257
}
258258

259-
char buffer[512];
260-
DWORD bytes = 0;
261-
ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL);
259+
va_list args;
260+
va_start(args, format);
262261

263-
SetConsoleMode(hInput, inputMode);
262+
char buffer[1024];
263+
uint32_t bytesRead = 0;
264264

265-
if(bytes <= 0)
266-
return "ReadFile() failed";
265+
while (true)
266+
{
267+
DWORD bytes = 0;
268+
if (!ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL) || bytes == 0)
269+
return "ReadFile() failed";
267270

268-
buffer[bytes] = '\0';
271+
bytesRead += bytes;
272+
buffer[bytesRead] = '\0';
273+
274+
int ret = vsscanf(buffer, format, args);
275+
if (ret <= 0)
276+
return "vsscanf(buffer, format, args) failed";
277+
if (ret >= nParams)
278+
break;
279+
}
280+
281+
SetConsoleMode(hInput, inputMode);
269282

270-
va_list args;
271-
va_start(args, format);
272-
vsscanf(buffer, format, args);
273283
va_end(args);
274284

275285
return NULL;

src/detection/terminalfont/terminalfont.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,32 @@ FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont)
7272
ffStrbufAppendS(&terminalFont->error, "Couldn't find Font in "FASTFETCH_TARGET_DIR_ETC"/vconsole.conf");
7373
}
7474

75-
static bool queryKittyTerm(const char* query, FFstrbuf* res)
75+
FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResult* result)
7676
{
77+
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
78+
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
79+
80+
char fontHex[512] = "", sizeHex[512] = "";
7781
// https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233
78-
char buffer[256] = "";
7982
if (ffGetTerminalResponse(
80-
query, // kitty-query-font_family;kitty-query-font_size
81-
"\eP1+r%*[^=]=%255[^\e]\e\\", buffer) == NULL)
83+
"\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size
84+
2,
85+
"\eP1+r%*[^=]=%64[^\e]\e\\\eP1+r%*[^=]=%64[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex)
8286
{
8387
// decode hex string
84-
for (const char* p = buffer; p[0] && p[1]; p += 2)
88+
for (const char* p = fontHex; p[0] && p[1]; p += 2)
89+
{
90+
unsigned value;
91+
if (sscanf(p, "%2x", &value))
92+
ffStrbufAppendC(&fontName, (char) value);
93+
}
94+
for (const char* p = sizeHex; p[0] && p[1]; p += 2)
8595
{
8696
unsigned value;
87-
if (sscanf(p, "%2x", &value) == 1)
88-
ffStrbufAppendC(res, (char) value);
97+
if (sscanf(p, "%2x", &value))
98+
ffStrbufAppendC(&fontSize, (char) value);
8999
}
90-
return true;
91100
}
92-
return false;
93-
}
94-
95-
FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResult* result)
96-
{
97-
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
98-
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
99-
100-
// Kitty generates response independently even if we query font family and size in one query
101-
// which may result in short read in `ffGetTerminalResponse`
102-
if (queryKittyTerm("\eP+q6b697474792d71756572792d666f6e745f66616d696c79\e\\", &fontName)) // kitty-query-font_family
103-
queryKittyTerm("\eP+q6b697474792d71756572792d666f6e745f73697a65\e\\", &fontSize); // kitty-query-font_size
104101
else
105102
{
106103
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();

src/detection/terminalshell/terminalshell.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
583583
// https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233
584584
if (ffGetTerminalResponse(
585585
"\eP+q6b697474792d71756572792d76657273696f6e\e\\", // kitty-query-version
586+
1,
586587
"\eP1+r%*[^=]=%63[^\e]\e\\\\", versionHex) == NULL)
587588
{
588589
// decode hex string

src/detection/terminalsize/terminalsize_linux.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result)
1414
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
1515

1616
if (winsize.ws_row == 0 || winsize.ws_col == 0)
17-
ffGetTerminalResponse("\e[18t", "\e[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
17+
ffGetTerminalResponse("\e[18t", 2, "\e[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
1818

1919
if (winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
20-
ffGetTerminalResponse("\e[14t", "\e[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
20+
ffGetTerminalResponse("\e[14t", 2, "\e[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
2121

2222
if (winsize.ws_row == 0 && winsize.ws_col == 0)
2323
return false;

src/detection/terminalsize/terminalsize_windows.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result)
2525
else
2626
{
2727
// Windows Terminal doesn't report `\e` for some reason
28-
ffGetTerminalResponse("\e[18t", "%*[^;];%hu;%hut", &result->rows, &result->columns);
28+
ffGetTerminalResponse("\e[18t", 2, "%*[^;];%hu;%hut", &result->rows, &result->columns);
2929
}
3030
}
3131

@@ -42,7 +42,7 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result)
4242
if (result->width == 0 || result->height == 0)
4343
{
4444
// Windows Terminal doesn't report `\e` for some reason
45-
ffGetTerminalResponse("\e[14t", "%*[^;];%hu;%hut", &result->height, &result->width);
45+
ffGetTerminalResponse("\e[14t", 2, "%*[^;];%hu;%hut", &result->height, &result->width);
4646
}
4747
}
4848

src/detection/terminaltheme/terminaltheme.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,15 @@
66

77
static bool detectByEscapeCode(FFTerminalThemeResult* result)
88
{
9-
int command = 0;
10-
11-
// Windows Terminal doesn't report `\e` for some reason
12-
if (ffGetTerminalResponse("\e]10;?\e\\", "%*[^0-9]%d;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 "\e\\", &command, &result->fg.r, &result->fg.g, &result->fg.b) == NULL)
9+
// Windows Terminal removes all `\e`s in its output
10+
if (ffGetTerminalResponse("\e]10;?\e\\" /*fg*/ "\e]11;?\e\\" /*bg*/,
11+
6,
12+
"%*[^0-9]10;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 /*"\e\\"*/ "%*[^0-9]11;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 /*"\e\\"*/,
13+
&result->fg.r, &result->fg.g, &result->fg.b,
14+
&result->bg.r, &result->bg.g, &result->bg.b) == NULL)
1315
{
14-
if (command != 10)
15-
return false;
1616
if (result->fg.r > 0x0100 || result->fg.g > 0x0100 || result->fg.b > 0x0100)
1717
result->fg.r /= 0x0100, result->fg.g /= 0x0100, result->fg.b /= 0x0100;
18-
}
19-
else
20-
return false;
21-
22-
if (ffGetTerminalResponse("\e]11;?\e\\", "%*[^0-9]%d;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 "\e\\", &command, &result->bg.r, &result->bg.g, &result->bg.b) == NULL)
23-
{
24-
if (command != 11)
25-
return false;
2618
if (result->bg.r > 0x0100 || result->bg.g > 0x0100 || result->bg.b > 0x0100)
2719
result->bg.r /= 0x0100, result->bg.g /= 0x0100, result->bg.b /= 0x0100;
2820
}

src/logo/image/image.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static bool printImageIterm(bool printError)
7878
if (options->position == FF_LOGO_POSITION_LEFT || options->position == FF_LOGO_POSITION_RIGHT)
7979
{
8080
uint16_t X = 0, Y = 0;
81-
const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X);
81+
const char* error = ffGetTerminalResponse("\e[6n", 2, "%*[^0-9]%hu;%huR", &Y, &X);
8282
if (error)
8383
{
8484
fprintf(stderr, "\nLogo (iterm): fail to query cursor position: %s\n", error);
@@ -203,7 +203,7 @@ static bool printImageKittyDirect(bool printError)
203203
if (options->position == FF_LOGO_POSITION_LEFT || options->position == FF_LOGO_POSITION_RIGHT)
204204
{
205205
uint16_t X = 0, Y = 0;
206-
const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X);
206+
const char* error = ffGetTerminalResponse("\e[6n", 2, "%*[^0-9]%hu;%huR", &Y, &X);
207207
if (error)
208208
{
209209
if (printError)

src/logo/logo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static bool ffLogoPrintCharsRaw(const char* data, size_t length, bool printError
5252
{
5353
uint16_t X = 0, Y = 0;
5454
// Windows Terminal doesn't report `\e` for some reason
55-
const char* error = ffGetTerminalResponse("\e[6n", "%*[^0-9]%hu;%huR", &Y, &X); // %*[^0-9]: ignore optional \e[
55+
const char* error = ffGetTerminalResponse("\e[6n", 2, "%*[^0-9]%hu;%huR", &Y, &X); // %*[^0-9]: ignore optional \e[
5656
if (error)
5757
{
5858
if (printError)

0 commit comments

Comments
 (0)