diff options
Diffstat (limited to 'src/interface.c')
| -rw-r--r-- | src/interface.c | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/src/interface.c b/src/interface.c index 9ec1bed..2343a16 100644 --- a/src/interface.c +++ b/src/interface.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2025 Robin Haberkorn + * Copyright (C) 2012-2026 Robin Haberkorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #endif #include <stdarg.h> +#include <string.h> #include <stdio.h> #include <glib.h> @@ -36,6 +37,9 @@ //#define DEBUG +/** minimum level of messages to print to stdout/stderr */ +teco_msg_t teco_interface_msg_level = TECO_MSG_USER; + teco_view_t *teco_interface_current_view = NULL; TECO_DEFINE_UNDO_CALL(teco_interface_show_view, teco_view_t *); @@ -81,35 +85,82 @@ teco_interface_undo_set_clipboard(const gchar *name, gchar *str, gsize len) } } +void +teco_interface_msg(teco_msg_t type, const gchar *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + g_autofree gchar *buf = g_strdup_vprintf(fmt, ap); + va_end(ap); + + teco_interface_msg_literal(type, buf, strlen(buf)); +} + /** - * Print a message to the appropriate stdio streams. + * Print a raw message to the appropriate stdio streams. * - * This method has similar semantics to `vprintf`, i.e. - * it leaves `ap` undefined. Therefore to pass the format - * string and arguments to another `vprintf`-like function, - * you have to copy the arguments via `va_copy`. + * This deliberately does not echo (i.e. escape non-printable characters) + * the string. Either they are supposed to be written verbatim + * (TECO_MSG_USER) or are already echoed. + * Everything higher than TECO_MSG_USER is also terminated by LF. + * + * @fixme TECO_MSG_USER could always be flushed. + * This however makes the message disappear on UNIX since stdout/stderr + * have been redirected to /dev/null. + * Also it would probably be detrimental for performance in scripts + * that write individual characters. + * Perhaps we should put flushing under control of the language instead. */ void -teco_interface_stdio_vmsg(teco_msg_t type, const gchar *fmt, va_list ap) +teco_interface_stdio_msg(teco_msg_t type, const gchar *str, gsize len) { - FILE *stream = stdout; + /* "user"-level messages are always printed */ + if (type != TECO_MSG_USER && type < teco_interface_msg_level) + return; switch (type) { case TECO_MSG_USER: + fwrite(str, 1, len, stdout); + //fflush(stdout); break; case TECO_MSG_INFO: - fputs("Info: ", stream); + g_fprintf(stdout, "Info: %.*s\n", (gint)len, str); break; case TECO_MSG_WARNING: - stream = stderr; - fputs("Warning: ", stream); + g_fprintf(stderr, "Warning: %.*s\n", (gint)len, str); break; case TECO_MSG_ERROR: - stream = stderr; - fputs("Error: ", stream); + g_fprintf(stderr, "Error: %.*s\n", (gint)len, str); break; } +} - g_vfprintf(stream, fmt, ap); - fputc('\n', stream); +/** + * Get character from stdin. + * + * @param widechar If TRUE reads one glyph encoded in UTF-8. + * If FALSE, returns exactly one byte. + * @return Codepoint or -1 in case of EOF. + */ +teco_int_t +teco_interface_stdio_getch(gboolean widechar) +{ + gchar buf[4]; + gint i = 0; + gint32 cp; + + do { + if (G_UNLIKELY(fread(buf+i, 1, 1, stdin) < 1)) + return -1; /* EOF */ + if (!widechar || !buf[i]) + return (guchar)buf[i]; + + /* doesn't work as expected when passed a null byte */ + cp = g_utf8_get_char_validated(buf, ++i); + if (i >= sizeof(buf) || cp != -2) + i = 0; + } while (cp < 0); + + return cp; } |
