From 8744502cbe42c98422a798c06f4c8ce033725412 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Mon, 16 Sep 2024 22:30:35 +0200 Subject: [PATCH] Curses: added support for cool Unicode icons (refs #5) * Practically requires one of the "Nerd Font" fonts, so it's disabled by default. Add 0,512ED to the profile to enable them. * The new ED flag could be used to control Gtk icons as well, but they are left always-enabled for the time being. Is there any reason anybody would like to disable icons in Gtk? * The list of icons has been adapted and extended from exa: https://github.com/ogham/exa/blob/master/src/output/icons.rs * The icons are hardcoded as presorted lists, so we can binary search them. This could change in the future. If there is any demand, they could be made configurable via Q-Registers as well. --- doc/sciteco.7.template | 6 + sample.teco_ini | 3 + src/core-commands.c | 5 + src/interface-curses/Makefile.am | 3 +- src/interface-curses/curses-icons.c | 395 +++++++++++++++++++++++ src/interface-curses/curses-icons.h | 28 ++ src/interface-curses/curses-info-popup.c | 17 +- src/interface-curses/interface.c | 27 +- src/sciteco.h | 3 +- 9 files changed, 473 insertions(+), 14 deletions(-) create mode 100644 src/interface-curses/curses-icons.c create mode 100644 src/interface-curses/curses-icons.h diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index 1eebecb..b5105ac 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -2304,6 +2304,12 @@ Scinterm manual, documenting the mapping of Scinterm manual .UE .TP +Suitable terminal fonts for icon support in Curses (see +.BR ED command). +.UR https://www.nerdfonts.com/ +Nerd Fonts +.UE +.TP Gtk+ 3 documentation, containg details about its CSS support and syntax: .UR https://developer.gnome.org/gtk3/stable/GtkCssProvider.html diff --git a/sample.teco_ini b/sample.teco_ini index f0f5208..869bfb9 100644 --- a/sample.teco_ini +++ b/sample.teco_ini @@ -59,6 +59,9 @@ EMQ[$SCITECOPATH]/fnkeys.tes ! Uncomment if XTerm allows clipboard operations ! ! 0,256ED ! +! Uncomment to enable Unicode icons in the Curses UI ! +! 0,512ED ! + ! Uncomment to tweak the memory limit ! ! 500*1000*1000,2EJ ! diff --git a/src/core-commands.c b/src/core-commands.c index c5c60a8..fb8f142 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -2065,6 +2065,11 @@ teco_state_ecommand_close(teco_machine_main_t *ctx, GError **error) * Should only be enabled if XTerm allows the * \fIGetSelection\fP and \fISetSelection\fP window * operations. + * - 512: Enable/Disable Unicode icons in the Curses UI. + * This requires a capable font, like the ones provided + * by the \(lqNerd Fonts\(rq project. + * Changes to this flag in interactive mode may not become + * effective immediately. * * The features controlled thus are discribed in other sections * of this manual. diff --git a/src/interface-curses/Makefile.am b/src/interface-curses/Makefile.am index 14fc920..44fb658 100644 --- a/src/interface-curses/Makefile.am +++ b/src/interface-curses/Makefile.am @@ -6,4 +6,5 @@ AM_CFLAGS = -std=gnu11 -Wall -Wno-initializer-overrides -Wno-unused-value noinst_LTLIBRARIES = libsciteco-interface.la libsciteco_interface_la_SOURCES = interface.c \ curses-utils.c curses-utils.h \ - curses-info-popup.c curses-info-popup.h + curses-info-popup.c curses-info-popup.h \ + curses-icons.c curses-icons.h diff --git a/src/interface-curses/curses-icons.c b/src/interface-curses/curses-icons.c new file mode 100644 index 0000000..087d454 --- /dev/null +++ b/src/interface-curses/curses-icons.c @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2012-2024 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include + +#include "sciteco.h" +#include "curses-icons.h" + +typedef struct { + const gchar *name; + gunichar c; +} teco_curses_icon_t; + +/* + * The following icons have initially been adapted from exa, + * but icons have since been added and removed. + * + * They require fonts with additional symbols, eg. + * Nerd Fonts (https://www.nerdfonts.com/). + * + * They MUST be kept presorted, so we can perform binary searches. + */ + +/** Mapping of complete filenames to Unicode "icons" */ +static const teco_curses_icon_t teco_icons_file[] = { + {".Trash", 0xf1f8}, /*  */ + {".atom", 0xe764}, /*  */ + {".bash_history", 0xf489}, /*  */ + {".bash_profile", 0xf489}, /*  */ + {".bashrc", 0xf489}, /*  */ + {".git", 0xf1d3}, /*  */ + {".gitattributes", 0xf1d3}, /*  */ + {".gitconfig", 0xf1d3}, /*  */ + {".github", 0xf408}, /*  */ + {".gitignore", 0xf1d3}, /*  */ + {".gitmodules", 0xf1d3}, /*  */ + {".rvm", 0xe21e}, /*  */ + {".teco_ini", 0xedaa}, /*  */ + {".teco_session", 0xedaa}, /*  */ + {".vimrc", 0xe62b}, /*  */ + {".vscode", 0xe70c}, /*  */ + {".zshrc", 0xf489}, /*  */ + {"Cargo.lock", 0xe7a8}, /*  */ + {"Dockerfile", 0xf308}, /*  */ + {"GNUmakefile", 0xf489}, /*  */ + {"Makefile", 0xf489}, /*  */ + {"PKGBUILD", 0xf303}, /*  */ + {"bin", 0xe5fc}, /*  */ + {"config", 0xe5fc}, /*  */ + {"docker-compose.yml", 0xf308}, /*  */ + {"ds_store", 0xf179}, /*  */ + {"gitignore_global", 0xf1d3}, /*  */ + {"go.mod", 0xe626}, /*  */ + {"go.sum", 0xe626}, /*  */ + {"gradle", 0xe256}, /*  */ + {"gruntfile.coffee", 0xe611}, /*  */ + {"gruntfile.js", 0xe611}, /*  */ + {"gruntfile.ls", 0xe611}, /*  */ + {"gulpfile.coffee", 0xe610}, /*  */ + {"gulpfile.js", 0xe610}, /*  */ + {"gulpfile.ls", 0xe610}, /*  */ + {"hidden", 0xf023}, /*  */ + {"include", 0xe5fc}, /*  */ + {"lib", 0xf121}, /*  */ + {"localized", 0xf179}, /*  */ + {"node_modules", 0xe718}, /*  */ + {"npmignore", 0xe71e}, /*  */ + {"rubydoc", 0xe73b}, /*  */ + {"yarn.lock", 0xe718}, /*  */ +}; + +/** Mapping of file extensions to Unicode "icons" */ +static const teco_curses_icon_t teco_icons_ext[] = { + {"DS_store", 0xf179}, /*  */ + {"ai", 0xe7b4}, /*  */ + {"android", 0xe70e}, /*  */ + {"apk", 0xe70e}, /*  */ + {"apple", 0xf179}, /*  */ + {"avi", 0xf03d}, /*  */ + {"avif", 0xf1c5}, /*  */ + {"avro", 0xe60b}, /*  */ + {"awk", 0xf489}, /*  */ + {"bash", 0xf489}, /*  */ + {"bat", 0xf17a}, /*  */ + {"bats", 0xf489}, /*  */ + {"bmp", 0xf1c5}, /*  */ + {"bz", 0xf410}, /*  */ + {"bz2", 0xf410}, /*  */ + {"c", 0xe61e}, /*  */ + {"c++", 0xe61d}, /*  */ + {"cab", 0xe70f}, /*  */ + {"cc", 0xe61d}, /*  */ + {"cfg", 0xe615}, /*  */ + {"class", 0xe256}, /*  */ + {"clj", 0xe768}, /*  */ + {"cljs", 0xe76a}, /*  */ + {"cls", 0xf034}, /*  */ + {"cmd", 0xe70f}, /*  */ + {"coffee", 0xf0f4}, /*  */ + {"conf", 0xe615}, /*  */ + {"cp", 0xe61d}, /*  */ + {"cpio", 0xf410}, /*  */ + {"cpp", 0xe61d}, /*  */ + {"cs", 0xf031b}, /* 󰌛 */ + {"csh", 0xf489}, /*  */ + {"cshtml", 0xf1fa}, /*  */ + {"csproj", 0xf031b}, /* 󰌛 */ + {"css", 0xe749}, /*  */ + {"csv", 0xf1c3}, /*  */ + {"csx", 0xf031b}, /* 󰌛 */ + {"cxx", 0xe61d}, /*  */ + {"d", 0xe7af}, /*  */ + {"dart", 0xe798}, /*  */ + {"db", 0xf1c0}, /*  */ + {"deb", 0xe77d}, /*  */ + {"diff", 0xf440}, /*  */ + {"djvu", 0xf02d}, /*  */ + {"dll", 0xe70f}, /*  */ + {"doc", 0xf1c2}, /*  */ + {"docx", 0xf1c2}, /*  */ + {"ds_store", 0xf179}, /*  */ + {"dump", 0xf1c0}, /*  */ + {"ebook", 0xe28b}, /*  */ + {"ebuild", 0xf30d}, /*  */ + {"editorconfig", 0xe615}, /*  */ + {"ejs", 0xe618}, /*  */ + {"elm", 0xe62c}, /*  */ + {"env", 0xf462}, /*  */ + {"eot", 0xf031}, /*  */ + {"epub", 0xe28a}, /*  */ + {"erb", 0xe73b}, /*  */ + {"erl", 0xe7b1}, /*  */ + {"ex", 0xe62d}, /*  */ + {"exe", 0xf17a}, /*  */ + {"exs", 0xe62d}, /*  */ + {"fish", 0xf489}, /*  */ + {"flac", 0xf001}, /*  */ + {"flv", 0xf03d}, /*  */ + {"font", 0xf031}, /*  */ + {"fs", 0xe7a7}, /*  */ + {"fsi", 0xe7a7}, /*  */ + {"fsx", 0xe7a7}, /*  */ + {"gdoc", 0xf1c2}, /*  */ + {"gem", 0xe21e}, /*  */ + {"gemfile", 0xe21e}, /*  */ + {"gemspec", 0xe21e}, /*  */ + {"gform", 0xf298}, /*  */ + {"gif", 0xf1c5}, /*  */ + {"go", 0xe626}, /*  */ + {"gradle", 0xe256}, /*  */ + {"groovy", 0xe775}, /*  */ + {"gsheet", 0xf1c3}, /*  */ + {"gslides", 0xf1c4}, /*  */ + {"guardfile", 0xe21e}, /*  */ + {"gz", 0xf410}, /*  */ + {"h", 0xf0fd}, /*  */ + {"hbs", 0xe60f}, /*  */ + {"hpp", 0xf0fd}, /*  */ + {"hs", 0xe777}, /*  */ + {"htm", 0xf13b}, /*  */ + {"html", 0xf13b}, /*  */ + {"hxx", 0xf0fd}, /*  */ + {"ico", 0xf1c5}, /*  */ + {"image", 0xf1c5}, /*  */ + {"img", 0xe271}, /*  */ + {"iml", 0xe7b5}, /*  */ + {"ini", 0xf17a}, /*  */ + {"ipynb", 0xe678}, /*  */ + {"iso", 0xe271}, /*  */ + {"j2c", 0xf1c5}, /*  */ + {"j2k", 0xf1c5}, /*  */ + {"jad", 0xe256}, /*  */ + {"jar", 0xe256}, /*  */ + {"java", 0xe256}, /*  */ + {"jfi", 0xf1c5}, /*  */ + {"jfif", 0xf1c5}, /*  */ + {"jif", 0xf1c5}, /*  */ + {"jl", 0xe624}, /*  */ + {"jmd", 0xf48a}, /*  */ + {"jp2", 0xf1c5}, /*  */ + {"jpe", 0xf1c5}, /*  */ + {"jpeg", 0xf1c5}, /*  */ + {"jpg", 0xf1c5}, /*  */ + {"jpx", 0xf1c5}, /*  */ + {"js", 0xe74e}, /*  */ + {"json", 0xe60b}, /*  */ + {"jsx", 0xe7ba}, /*  */ + {"jxl", 0xf1c5}, /*  */ + {"ksh", 0xf489}, /*  */ + {"latex", 0xf034}, /*  */ + {"less", 0xe758}, /*  */ + {"lhs", 0xe777}, /*  */ + {"license", 0xf0219}, /* 󰈙 */ + {"localized", 0xf179}, /*  */ + {"lock", 0xf023}, /*  */ + {"log", 0xf18d}, /*  */ + {"lua", 0xe620}, /*  */ + {"lz", 0xf410}, /*  */ + {"lz4", 0xf410}, /*  */ + {"lzh", 0xf410}, /*  */ + {"lzma", 0xf410}, /*  */ + {"lzo", 0xf410}, /*  */ + {"m", 0xe61e}, /*  */ + {"m4a", 0xf001}, /*  */ + {"markdown", 0xf48a}, /*  */ + {"md", 0xf48a}, /*  */ + {"mjs", 0xe74e}, /*  */ + {"mk", 0xf489}, /*  */ + {"mkd", 0xf48a}, /*  */ + {"mkv", 0xf03d}, /*  */ + {"mm", 0xe61d}, /*  */ + {"mobi", 0xe28b}, /*  */ + {"mov", 0xf03d}, /*  */ + {"mp3", 0xf001}, /*  */ + {"mp4", 0xf03d}, /*  */ + {"msi", 0xe70f}, /*  */ + {"mustache", 0xe60f}, /*  */ + {"nix", 0xf313}, /*  */ + {"node", 0xf0399}, /* 󰎙 */ + {"npmignore", 0xe71e}, /*  */ + {"odp", 0xf1c4}, /*  */ + {"ods", 0xf1c3}, /*  */ + {"odt", 0xf1c2}, /*  */ + {"ogg", 0xf001}, /*  */ + {"ogv", 0xf03d}, /*  */ + {"otf", 0xf031}, /*  */ + {"part", 0xf43a}, /*  */ + {"patch", 0xf440}, /*  */ + {"pdf", 0xf1c1}, /*  */ + {"php", 0xe73d}, /*  */ + {"pl", 0xe769}, /*  */ + {"plx", 0xe769}, /*  */ + {"pm", 0xe769}, /*  */ + {"png", 0xf1c5}, /*  */ + {"pod", 0xe769}, /*  */ + {"ppt", 0xf1c4}, /*  */ + {"pptx", 0xf1c4}, /*  */ + {"procfile", 0xe21e}, /*  */ + {"properties", 0xe60b}, /*  */ + {"ps1", 0xf489}, /*  */ + {"psd", 0xe7b8}, /*  */ + {"pxm", 0xf1c5}, /*  */ + {"py", 0xe606}, /*  */ + {"pyc", 0xe606}, /*  */ + {"r", 0xf25d}, /*  */ + {"rakefile", 0xe21e}, /*  */ + {"rar", 0xf410}, /*  */ + {"razor", 0xf1fa}, /*  */ + {"rb", 0xe21e}, /*  */ + {"rdata", 0xf25d}, /*  */ + {"rdb", 0xe76d}, /*  */ + {"rdoc", 0xf48a}, /*  */ + {"rds", 0xf25d}, /*  */ + {"readme", 0xf48a}, /*  */ + {"rlib", 0xe7a8}, /*  */ + {"rmd", 0xf48a}, /*  */ + {"rpm", 0xe7bb}, /*  */ + {"rs", 0xe7a8}, /*  */ + {"rspec", 0xe21e}, /*  */ + {"rspec_parallel", 0xe21e}, /*  */ + {"rspec_status", 0xe21e}, /*  */ + {"rss", 0xf09e}, /*  */ + {"rtf", 0xf0219}, /* 󰈙 */ + {"ru", 0xe21e}, /*  */ + {"rubydoc", 0xe73b}, /*  */ + {"sass", 0xe603}, /*  */ + {"scala", 0xe737}, /*  */ + {"scss", 0xe749}, /*  */ + {"sh", 0xf489}, /*  */ + {"shell", 0xf489}, /*  */ + {"slim", 0xe73b}, /*  */ + {"sln", 0xe70c}, /*  */ + {"so", 0xf17c}, /*  */ + {"sql", 0xf1c0}, /*  */ + {"sqlite3", 0xe7c4}, /*  */ + {"sty", 0xf034}, /*  */ + {"styl", 0xe600}, /*  */ + {"stylus", 0xe600}, /*  */ + {"svg", 0xf1c5}, /*  */ + {"swift", 0xe755}, /*  */ + {"t", 0xe769}, /*  */ + {"tar", 0xf410}, /*  */ + {"taz", 0xf410}, /*  */ + {"tbz", 0xf410}, /*  */ + {"tbz2", 0xf410}, /*  */ + {"tec", 0xedaa}, /*  */ + {"tes", 0xedaa}, /*  */ + {"tex", 0xf034}, /*  */ + {"tgz", 0xf410}, /*  */ + {"tiff", 0xf1c5}, /*  */ + {"tlz", 0xf410}, /*  */ + {"toml", 0xe615}, /*  */ + {"torrent", 0xe275}, /*  */ + {"ts", 0xe628}, /*  */ + {"tsv", 0xf1c3}, /*  */ + {"tsx", 0xe7ba}, /*  */ + {"ttf", 0xf031}, /*  */ + {"twig", 0xe61c}, /*  */ + {"txt", 0xf15c}, /*  */ + {"txz", 0xf410}, /*  */ + {"tz", 0xf410}, /*  */ + {"tzo", 0xf410}, /*  */ + {"video", 0xf03d}, /*  */ + {"vim", 0xe62b}, /*  */ + {"vue", 0xf0844}, /* 󰡄 */ + {"war", 0xe256}, /*  */ + {"wav", 0xf001}, /*  */ + {"webm", 0xf03d}, /*  */ + {"webp", 0xf1c5}, /*  */ + {"windows", 0xf17a}, /*  */ + {"woff", 0xf031}, /*  */ + {"woff2", 0xf031}, /*  */ + {"woman", 0xeaa4}, /*  */ + {"xhtml", 0xf13b}, /*  */ + {"xls", 0xf1c3}, /*  */ + {"xlsx", 0xf1c3}, /*  */ + {"xml", 0xf05c0}, /* 󰗀 */ + {"xul", 0xf05c0}, /* 󰗀 */ + {"xz", 0xf410}, /*  */ + {"yaml", 0xf481}, /*  */ + {"yml", 0xf481}, /*  */ + {"zip", 0xf410}, /*  */ + {"zsh", 0xf489}, /*  */ + {"zsh-theme", 0xf489}, /*  */ + {"zst", 0xf410}, /*  */ +}; + +static int +teco_curses_icon_cmp(const void *a, const void *b) +{ + const gchar *str = a; + const teco_curses_icon_t *icon = b; + + return strcmp(str, icon->name); +} + +gunichar +teco_curses_icons_lookup_file(const gchar *filename) +{ + g_autofree gchar *basename = g_path_get_basename(filename); + const teco_curses_icon_t *icon; + + /* try to find icon by complete file name */ + icon = bsearch(basename, teco_icons_file, G_N_ELEMENTS(teco_icons_file), + sizeof(teco_icons_file[0]), teco_curses_icon_cmp); + if (icon) + return icon->c; + + /* try to find icon by extension */ + const gchar *ext = strrchr(basename, '.'); + if (ext) { + icon = bsearch(ext+1, teco_icons_ext, G_N_ELEMENTS(teco_icons_ext), + sizeof(teco_icons_ext[0]), teco_curses_icon_cmp); + return icon ? icon->c : 0xf15b; /*  */ + } + + /* default file icon for files without extension */ + return 0xf016; /*  */ +} + +gunichar +teco_curses_icons_lookup_dir(const gchar *dirname) +{ + g_autofree gchar *basename = g_path_get_basename(dirname); + const teco_curses_icon_t *icon; + + icon = bsearch(basename, teco_icons_file, G_N_ELEMENTS(teco_icons_file), + sizeof(teco_icons_file[0]), teco_curses_icon_cmp); + + /* default folder icon */ + return icon ? icon->c : 0xf115; /*  */ +} diff --git a/src/interface-curses/curses-icons.h b/src/interface-curses/curses-icons.h new file mode 100644 index 0000000..c1be06f --- /dev/null +++ b/src/interface-curses/curses-icons.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012-2024 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +/** + * Q-Register icon. + * 0xf04cf would look more similar to the current Gtk icon. + */ +#define TECO_CURSES_ICONS_QREG 0xe236 /*  */ + +gunichar teco_curses_icons_lookup_file(const gchar *filename); +gunichar teco_curses_icons_lookup_dir(const gchar *dirname); diff --git a/src/interface-curses/curses-info-popup.c b/src/interface-curses/curses-info-popup.c index be4773b..24dee41 100644 --- a/src/interface-curses/curses-info-popup.c +++ b/src/interface-curses/curses-info-popup.c @@ -28,6 +28,7 @@ #include "interface.h" #include "curses-utils.h" #include "curses-info-popup.h" +#include "curses-icons.h" /* * FIXME: This is redundant with gtk-info-popup.c. @@ -75,8 +76,13 @@ teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr) gint pad_cols; /**! entry columns */ gint pad_colwidth; /**! width per entry column */ - /* reserve 2 spaces between columns */ - pad_colwidth = MIN(ctx->longest + 2, cols - 2); + /* + * With Unicode icons enabled, we reserve 2 characters at the beginning and one + * after the filename/directory. + * Otherwise 2 characters after the entry. + */ + gint reserve = teco_ed & TECO_ED_ICONS ? 2+1 : 2; + pad_colwidth = MIN(ctx->longest + reserve, cols - 2); /* pad_cols = floor((cols - 2) / pad_colwidth) */ pad_cols = (cols - 2) / pad_colwidth; @@ -111,8 +117,15 @@ teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr) switch (entry->type) { case TECO_POPUP_FILE: + g_assert(!teco_string_contains(&entry->name, '\0')); + if (teco_ed & TECO_ED_ICONS) + wprintw(ctx->pad, "%C ", teco_curses_icons_lookup_file(entry->name.data)); + teco_curses_format_filename(ctx->pad, entry->name.data, -1); + break; case TECO_POPUP_DIRECTORY: g_assert(!teco_string_contains(&entry->name, '\0')); + if (teco_ed & TECO_ED_ICONS) + wprintw(ctx->pad, "%C ", teco_curses_icons_lookup_dir(entry->name.data)); teco_curses_format_filename(ctx->pad, entry->name.data, -1); break; default: diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index 1581d98..bf7770d 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -64,11 +64,12 @@ #include "qreg.h" #include "ring.h" #include "error.h" -#include "curses-utils.h" -#include "curses-info-popup.h" #include "view.h" #include "memory.h" #include "interface.h" +#include "curses-utils.h" +#include "curses-info-popup.h" +#include "curses-icons.h" #if defined(__PDCURSES__) && defined(G_OS_WIN32) && \ !defined(PDCURSES_GUI) @@ -339,6 +340,7 @@ static struct { TECO_INFO_TYPE_QREG } info_type; teco_string_t info_current; + gboolean info_dirty; WINDOW *msg_window; @@ -977,7 +979,8 @@ teco_interface_draw_info(void) switch (teco_interface.info_type) { case TECO_INFO_TYPE_QREG: info_type_str = PACKAGE_NAME " - "; - waddstr(teco_interface.info_window, info_type_str); + wprintw(teco_interface.info_window, "%s %C ", PACKAGE_NAME, + teco_ed & TECO_ED_ICONS ? TECO_CURSES_ICONS_QREG : '-'); /* same formatting as in command lines */ teco_curses_format_str(teco_interface.info_window, teco_interface.info_current.data, @@ -986,10 +989,14 @@ teco_interface_draw_info(void) case TECO_INFO_TYPE_BUFFER: info_type_str = PACKAGE_NAME " - "; - waddstr(teco_interface.info_window, info_type_str); g_assert(!teco_string_contains(&teco_interface.info_current, '\0')); + wprintw(teco_interface.info_window, "%s %C ", PACKAGE_NAME, + teco_ed & TECO_ED_ICONS ? teco_curses_icons_lookup_file(teco_interface.info_current.data) : '-'); teco_curses_format_filename(teco_interface.info_window, - teco_interface.info_current.data, -1); + teco_interface.info_current.data, + getmaxx(teco_interface.info_window) - + getcurx(teco_interface.info_window) - 1); + waddch(teco_interface.info_window, teco_interface.info_dirty ? '*' : ' '); break; default: @@ -999,13 +1006,13 @@ teco_interface_draw_info(void) wclrtoeol(teco_interface.info_window); /* - * Make sure the title will consist only of printable - * characters + * Make sure the title will consist only of printable characters. */ g_autofree gchar *info_current_printable; info_current_printable = teco_string_echo(teco_interface.info_current.data, teco_interface.info_current.len); - g_autofree gchar *title = g_strconcat(info_type_str, info_current_printable, NULL); + g_autofree gchar *title = g_strconcat(info_type_str, info_current_printable, + teco_interface.info_dirty ? "*" : "", NULL); teco_interface_set_window_title(title); } @@ -1015,6 +1022,7 @@ teco_interface_info_update_qreg(const teco_qreg_t *reg) teco_string_clear(&teco_interface.info_current); teco_string_init(&teco_interface.info_current, reg->head.name.data, reg->head.name.len); + teco_interface.info_dirty = FALSE; teco_interface.info_type = TECO_INFO_TYPE_QREG; /* NOTE: drawn in teco_interface_event_loop_iter() */ } @@ -1026,8 +1034,7 @@ teco_interface_info_update_buffer(const teco_buffer_t *buffer) teco_string_clear(&teco_interface.info_current); teco_string_init(&teco_interface.info_current, filename, strlen(filename)); - teco_string_append_c(&teco_interface.info_current, - buffer->dirty ? '*' : ' '); + teco_interface.info_dirty = buffer->dirty; teco_interface.info_type = TECO_INFO_TYPE_BUFFER; /* NOTE: drawn in teco_interface_event_loop_iter() */ } diff --git a/src/sciteco.h b/src/sciteco.h index 894bb90..1597439 100644 --- a/src/sciteco.h +++ b/src/sciteco.h @@ -91,7 +91,8 @@ enum { TECO_ED_HOOKS = (1 << 5), //TECO_ED_MOUSEKEY = (1 << 6), TECO_ED_SHELLEMU = (1 << 7), - TECO_ED_XTERM_CLIPBOARD = (1 << 8) + TECO_ED_XTERM_CLIPBOARD = (1 << 8), + TECO_ED_ICONS = (1 << 9) }; /* in main.c */