mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
commit
353e51b0a1
8 changed files with 158 additions and 69 deletions
|
|
@ -41,6 +41,10 @@
|
|||
* Terminal content is now auto-scrolled when moving the mouse above or
|
||||
below the window while selecting
|
||||
(https://codeberg.org/dnkl/foot/issues/149).
|
||||
* **font-bold**, **font-italic** and **font-bold-italic** options to
|
||||
`foot.ini`. These options allow custom bold/italic fonts. They are
|
||||
unset by default, meaning the bold/italic version of the regular
|
||||
font is used (https://codeberg.org/dnkl/foot/issues/169).
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
32
config.c
32
config.c
|
|
@ -547,14 +547,28 @@ parse_section_main(const char *key, const char *value, struct config *conf,
|
|||
}
|
||||
}
|
||||
|
||||
else if (strcmp(key, "font") == 0) {
|
||||
else if (strcmp(key, "font") == 0 ||
|
||||
strcmp(key, "font-bold") == 0 ||
|
||||
strcmp(key, "font-italic") == 0 ||
|
||||
strcmp(key, "font-bold-italic") == 0)
|
||||
|
||||
{
|
||||
size_t idx =
|
||||
strcmp(key, "font") == 0 ? 0 :
|
||||
strcmp(key, "font-bold") == 0 ? 1 :
|
||||
strcmp(key, "font-italic") == 0 ? 2 : 3;
|
||||
|
||||
tll_foreach(conf->fonts[idx], it)
|
||||
config_font_destroy(&it->item);
|
||||
tll_free(conf->fonts[idx]);
|
||||
|
||||
char *copy = xstrdup(value);
|
||||
for (const char *font = strtok(copy, ","); font != NULL; font = strtok(NULL, ",")) {
|
||||
/* Trim spaces, strictly speaking not necessary, but looks nice :) */
|
||||
while (*font != '\0' && isspace(*font))
|
||||
font++;
|
||||
if (*font != '\0')
|
||||
tll_push_back(conf->fonts, config_font_parse(font));
|
||||
tll_push_back(conf->fonts[idx], config_font_parse(font));
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
|
|
@ -1904,7 +1918,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.pad_y = 2,
|
||||
.bell_is_urgent = false,
|
||||
.startup_mode = STARTUP_WINDOWED,
|
||||
.fonts = tll_init(),
|
||||
.fonts = {tll_init(), tll_init(), tll_init(), tll_init()},
|
||||
.scrollback = {
|
||||
.lines = 1000,
|
||||
.indicator = {
|
||||
|
|
@ -2028,8 +2042,8 @@ config_load(struct config *conf, const char *conf_path,
|
|||
conf->colors.selection_bg >> 24 == 0;
|
||||
|
||||
out:
|
||||
if (ret && tll_length(conf->fonts) == 0)
|
||||
tll_push_back(conf->fonts, config_font_parse("monospace"));
|
||||
if (ret && tll_length(conf->fonts[0]) == 0)
|
||||
tll_push_back(conf->fonts[0], config_font_parse("monospace"));
|
||||
|
||||
free(conf_file.path);
|
||||
if (conf_file.fd >= 0)
|
||||
|
|
@ -2047,9 +2061,11 @@ config_free(struct config conf)
|
|||
free(conf.app_id);
|
||||
free(conf.word_delimiters);
|
||||
free(conf.scrollback.indicator.text);
|
||||
tll_foreach(conf.fonts, it)
|
||||
config_font_destroy(&it->item);
|
||||
tll_free(conf.fonts);
|
||||
for (size_t i = 0; i < ALEN(conf.fonts); i++) {
|
||||
tll_foreach(conf.fonts[i], it)
|
||||
config_font_destroy(&it->item);
|
||||
tll_free(conf.fonts[i]);
|
||||
}
|
||||
free(conf.server_socket_path);
|
||||
|
||||
tll_foreach(conf.bindings.key, it) {
|
||||
|
|
|
|||
3
config.h
3
config.h
|
|
@ -16,6 +16,7 @@ struct config_font {
|
|||
double pt_size;
|
||||
int px_size;
|
||||
};
|
||||
typedef tll(struct config_font) config_font_list_t;
|
||||
|
||||
struct config_key_modifiers {
|
||||
bool shift;
|
||||
|
|
@ -77,7 +78,7 @@ struct config {
|
|||
|
||||
enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode;
|
||||
|
||||
tll(struct config_font) fonts;
|
||||
config_font_list_t fonts[4];
|
||||
|
||||
struct {
|
||||
int lines;
|
||||
|
|
|
|||
|
|
@ -20,20 +20,30 @@ in this order:
|
|||
|
||||
# SECTION: default
|
||||
|
||||
*font*
|
||||
*font*, *font-bold*, *font-italic*, *font-bold-italic*
|
||||
Comma separated list of fonts to use, in fontconfig format (see
|
||||
*FONT FORMAT*).
|
||||
|
||||
The first font is the primary font. The remaining fonts are
|
||||
fallback fonts that will be used whenever a glyph cannot be found
|
||||
in the primary font.
|
||||
For each option, the first font is the primary font. The remaining
|
||||
fonts are fallback fonts that will be used whenever a glyph cannot
|
||||
be found in the primary font.
|
||||
|
||||
The fallback fonts are searched in the order they appear. If a
|
||||
glyph cannot be found in any of the fallback fonts, the dynamic
|
||||
fallback list from fontconfig (for the primary font) is
|
||||
searched.
|
||||
|
||||
Default: _monospace_.
|
||||
*font-bold*, *font-italic* and *font-bold-italic* allow custom
|
||||
fonts to be used for bold/italic/bold+italic fonts. If left
|
||||
unconfigured, the bold/italic variants of the regular font(s)
|
||||
specified in *font* are used. *Note*: you _may_ have to tweak the
|
||||
size(s) of the custom bold/italic fonts to match the regular font.
|
||||
|
||||
To disable bold and/or italic fonts, set e.g. *font-bold* to
|
||||
_exactly_ the same value as *font*.
|
||||
|
||||
Default: _monospace_ (*font*), _not set_ (*font-bold*,
|
||||
*font-italic*, *font-bold-italic*).
|
||||
|
||||
*pad*
|
||||
Padding between border and glyphs, in pixels (subject to output
|
||||
|
|
|
|||
3
foot.ini
3
foot.ini
|
|
@ -1,6 +1,9 @@
|
|||
# -*- conf -*-
|
||||
|
||||
# font=monospace
|
||||
# font-bold=<bold variant of regular font>
|
||||
# font-italic=<italic variant of regular font>
|
||||
# font-bold-italic=<bold+italic variant of regular font>
|
||||
# initial-window-size-pixels=700x500 # Or,
|
||||
# initial-window-size-chars=<COLSxROWS>
|
||||
# initial-window-mode=windowed
|
||||
|
|
|
|||
11
main.c
11
main.c
|
|
@ -27,6 +27,7 @@
|
|||
#include "server.h"
|
||||
#include "shm.h"
|
||||
#include "terminal.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
|
@ -387,11 +388,13 @@ main(int argc, char *const *argv)
|
|||
if (login_shell)
|
||||
conf.login_shell = true;
|
||||
if (tll_length(conf_fonts) > 0) {
|
||||
tll_foreach(conf.fonts, it)
|
||||
config_font_destroy(&it->item);
|
||||
tll_free(conf.fonts);
|
||||
for (size_t i = 0; i < ALEN(conf.fonts); i++) {
|
||||
tll_foreach(conf.fonts[i], it)
|
||||
config_font_destroy(&it->item);
|
||||
tll_free(conf.fonts[i]);
|
||||
}
|
||||
tll_foreach(conf_fonts, it)
|
||||
tll_push_back(conf.fonts, config_font_parse(it->item));
|
||||
tll_push_back(conf.fonts[0], config_font_parse(it->item));
|
||||
tll_free(conf_fonts);
|
||||
}
|
||||
if (conf_width > 0 && conf_height > 0) {
|
||||
|
|
|
|||
152
terminal.c
152
terminal.c
|
|
@ -764,39 +764,77 @@ font_loader_thread(void *_data)
|
|||
static bool
|
||||
reload_fonts(struct terminal *term)
|
||||
{
|
||||
const size_t count = tll_length(term->conf->fonts);
|
||||
char *names[count];
|
||||
const size_t counts[4] = {
|
||||
tll_length(term->conf->fonts[0]),
|
||||
tll_length(term->conf->fonts[1]),
|
||||
tll_length(term->conf->fonts[2]),
|
||||
tll_length(term->conf->fonts[3]),
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
tll_foreach(term->conf->fonts, it) {
|
||||
bool use_px_size = term->font_sizes[i].px_size > 0;
|
||||
char size[64];
|
||||
/* Configure size (which may have been changed run-time) */
|
||||
char **names[4];
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
names[i] = xmalloc(counts[i] * sizeof(names[i][0]));
|
||||
|
||||
if (use_px_size)
|
||||
snprintf(size, sizeof(size), ":pixelsize=%d", term->font_sizes[i].px_size);
|
||||
else
|
||||
snprintf(size, sizeof(size), ":size=%.2f", term->font_sizes[i].pt_size);
|
||||
size_t j = 0;
|
||||
tll_foreach(term->conf->fonts[i], it) {
|
||||
bool use_px_size = term->font_sizes[i][j].px_size > 0;
|
||||
char size[64];
|
||||
|
||||
size_t len = strlen(it->item.pattern) + strlen(size) + 1;
|
||||
names[i] = xmalloc(len);
|
||||
if (use_px_size)
|
||||
snprintf(size, sizeof(size), ":pixelsize=%d", term->font_sizes[i][j].px_size);
|
||||
else
|
||||
snprintf(size, sizeof(size), ":size=%.2f", term->font_sizes[i][j].pt_size);
|
||||
|
||||
strcpy(names[i], it->item.pattern);
|
||||
strcat(names[i], size);
|
||||
i++;
|
||||
size_t len = strlen(it->item.pattern) + strlen(size) + 1;
|
||||
names[i][j] = xmalloc(len);
|
||||
|
||||
strcpy(names[i][j], it->item.pattern);
|
||||
strcat(names[i][j], size);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
char attrs0[256], attrs1[256], attrs2[256], attrs3[256];
|
||||
snprintf(attrs0, sizeof(attrs0), "dpi=%.2f", term->font_dpi);
|
||||
snprintf(attrs1, sizeof(attrs1), "dpi=%.2f:weight=bold", term->font_dpi);
|
||||
snprintf(attrs2, sizeof(attrs2), "dpi=%.2f:slant=italic", term->font_dpi);
|
||||
snprintf(attrs3, sizeof(attrs3), "dpi=%.2f:weight=bold:slant=italic", term->font_dpi);
|
||||
/* Did user configure custom bold/italic fonts?
|
||||
* Or should we use the regular font, with weight/slant attributes? */
|
||||
const bool custom_bold = counts[1] > 0;
|
||||
const bool custom_italic = counts[2] > 0;
|
||||
const bool custom_bold_italic = counts[3] > 0;
|
||||
|
||||
const size_t count_regular = counts[0];
|
||||
const char **names_regular = (const char **)names[0];
|
||||
|
||||
const size_t count_bold = custom_bold ? counts[1] : counts[0];
|
||||
const char **names_bold = (const char **)(custom_bold ? names[1] : names[0]);
|
||||
|
||||
const size_t count_italic = custom_italic ? counts[2] : counts[0];
|
||||
const char **names_italic = (const char **)(custom_italic ? names[2] : names[0]);
|
||||
|
||||
const size_t count_bold_italic = custom_bold_italic ? counts[3] : counts[0];
|
||||
const char **names_bold_italic = (const char **)(custom_bold_italic ? names[3] : names[0]);
|
||||
|
||||
char *attrs[4] = {NULL};
|
||||
int attr_len[4] = {-1, -1, -1, -1}; /* -1, so that +1 (below) results in 0 */
|
||||
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
attr_len[0] = snprintf(attrs[0], attr_len[0] + 1, "dpi=%.2f", term->font_dpi);
|
||||
attr_len[1] = snprintf(attrs[1], attr_len[1] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_bold ? "weight=bold" : "");
|
||||
attr_len[2] = snprintf(attrs[2], attr_len[2] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_italic ? "slant=italic" : "");
|
||||
attr_len[3] = snprintf(attrs[3], attr_len[3] + 1, "dpi=%.2f:%s", term->font_dpi, !custom_bold_italic ? "weight=bold:slant=italic" : "");
|
||||
|
||||
if (i > 0)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
attrs[i] = xmalloc(attr_len[i] + 1);
|
||||
}
|
||||
|
||||
struct fcft_font *fonts[4];
|
||||
struct font_load_data data[4] = {
|
||||
{count, (const char **)names, attrs0, &fonts[0]},
|
||||
{count, (const char **)names, attrs1, &fonts[1]},
|
||||
{count, (const char **)names, attrs2, &fonts[2]},
|
||||
{count, (const char **)names, attrs3, &fonts[3]},
|
||||
{count_regular, names_regular, attrs[0], &fonts[0]},
|
||||
{count_bold, names_bold, attrs[1], &fonts[1]},
|
||||
{count_italic, names_italic, attrs[2], &fonts[2]},
|
||||
{count_bold_italic, names_bold_italic, attrs[3], &fonts[3]},
|
||||
};
|
||||
|
||||
thrd_t tids[4] = {0};
|
||||
|
|
@ -819,6 +857,13 @@ reload_fonts(struct terminal *term)
|
|||
success = false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < counts[i]; j++)
|
||||
free(names[i][j]);
|
||||
free(names[i]);
|
||||
free(attrs[i]);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
LOG_ERR("failed to load primary fonts");
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
|
|
@ -827,19 +872,18 @@ reload_fonts(struct terminal *term)
|
|||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
free(names[i]);
|
||||
|
||||
return success ? term_set_fonts(term, fonts) : success;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_fonts_from_conf(struct terminal *term)
|
||||
{
|
||||
size_t i = 0;
|
||||
tll_foreach(term->conf->fonts, it) {
|
||||
term->font_sizes[i++] = (struct config_font){
|
||||
.pt_size = it->item.pt_size, .px_size = it->item.px_size};
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
size_t j = 0;
|
||||
tll_foreach(term->conf->fonts[i], it) {
|
||||
term->font_sizes[i][j++] = (struct config_font){
|
||||
.pt_size = it->item.pt_size, .px_size = it->item.px_size};
|
||||
}
|
||||
}
|
||||
|
||||
return reload_fonts(term);
|
||||
|
|
@ -922,7 +966,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.ptmx = ptmx,
|
||||
.ptmx_buffers = tll_init(),
|
||||
.ptmx_paste_buffers = tll_init(),
|
||||
.font_sizes = xmalloc(sizeof(term->font_sizes[0]) * tll_length(conf->fonts)),
|
||||
.font_sizes = {
|
||||
xmalloc(sizeof(term->font_sizes[0][0]) * tll_length(conf->fonts[0])),
|
||||
xmalloc(sizeof(term->font_sizes[1][0]) * tll_length(conf->fonts[1])),
|
||||
xmalloc(sizeof(term->font_sizes[2][0]) * tll_length(conf->fonts[2])),
|
||||
xmalloc(sizeof(term->font_sizes[3][0]) * tll_length(conf->fonts[3])),
|
||||
},
|
||||
.font_dpi = 0.,
|
||||
.font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */
|
||||
? FCFT_SUBPIXEL_DEFAULT
|
||||
|
|
@ -1025,10 +1074,10 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.cwd = xstrdup(cwd),
|
||||
};
|
||||
|
||||
{
|
||||
size_t i = 0;
|
||||
tll_foreach(conf->fonts, it) {
|
||||
term->font_sizes[i++] = (struct config_font){
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
size_t j = 0;
|
||||
tll_foreach(conf->fonts[i], it) {
|
||||
term->font_sizes[i][j++] = (struct config_font){
|
||||
.pt_size = it->item.pt_size, .px_size = it->item.px_size};
|
||||
}
|
||||
}
|
||||
|
|
@ -1277,7 +1326,8 @@ term_destroy(struct terminal *term)
|
|||
|
||||
for (size_t i = 0; i < sizeof(term->fonts) / sizeof(term->fonts[0]); i++)
|
||||
fcft_destroy(term->fonts[i]);
|
||||
free(term->font_sizes);
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
free(term->font_sizes[i]);
|
||||
|
||||
free(term->search.buf);
|
||||
|
||||
|
|
@ -1518,22 +1568,24 @@ term_reset(struct terminal *term, bool hard)
|
|||
static bool
|
||||
term_font_size_adjust(struct terminal *term, double amount)
|
||||
{
|
||||
for (size_t i = 0; i < tll_length(term->conf->fonts); i++) {
|
||||
double old_pt_size = term->font_sizes[i].pt_size;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < tll_length(term->conf->fonts[i]); j++) {
|
||||
double old_pt_size = term->font_sizes[i][j].pt_size;
|
||||
|
||||
/*
|
||||
* To ensure primary and user-configured fallback fonts are
|
||||
* resizes by the same amount, convert pixel sizes to point
|
||||
* sizes, and to the adjustment on point sizes only.
|
||||
*/
|
||||
/*
|
||||
* To ensure primary and user-configured fallback fonts are
|
||||
* resizes by the same amount, convert pixel sizes to point
|
||||
* sizes, and to the adjustment on point sizes only.
|
||||
*/
|
||||
|
||||
if (term->font_sizes[i].px_size > 0) {
|
||||
double dpi = term->font_dpi;
|
||||
old_pt_size = term->font_sizes[i].px_size * 72. / dpi;
|
||||
if (term->font_sizes[i][j].px_size > 0) {
|
||||
double dpi = term->font_dpi;
|
||||
old_pt_size = term->font_sizes[i][j].px_size * 72. / dpi;
|
||||
}
|
||||
|
||||
term->font_sizes[i][j].pt_size = fmax(old_pt_size + amount, 0);
|
||||
term->font_sizes[i][j].px_size = -1;
|
||||
}
|
||||
|
||||
term->font_sizes[i].pt_size = fmax(old_pt_size + amount, 0);
|
||||
term->font_sizes[i].px_size = -1;
|
||||
}
|
||||
|
||||
return reload_fonts(term);
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ struct terminal {
|
|||
struct composed *composed;
|
||||
|
||||
struct fcft_font *fonts[4];
|
||||
struct config_font *font_sizes;
|
||||
struct config_font *font_sizes[4];
|
||||
float font_dpi;
|
||||
enum fcft_subpixel font_subpixel;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue