Commit graph

582 commits

Author SHA1 Message Date
Daniel Eklöf
49fb0cf359
sixel: re-scale images when the cell dimensions change
Before this patch, when the cell dimensions changed (i.e. when the
font size changes), sixel images were either removed (the new cell
dimensions are smaller than the old), or simply kept at their original
size (new cell dimensions are larger).

With this patch, sixels are instead resized. This means a
sixel *always* occupies the same number of rows and columns,
regardless of how much the font size is changed.

This is done by maintaining two sets of image data and pixman images,
as well as their dimensions. These two sets are the new ‘original’ and
‘scaled’ members of the sixel struct.

The "top-level" pixman image pointer, and the ‘width’ and ‘height’
members either point to the "original", or the "scaled" version.

They are invalidated as soon as the cell dimensions change. They, and
the ‘scaled’ image is updated on-demand (when we need to render a
sixel).

Note that the ‘scaled’ image is always NULL when the current cell
dimensions matches the ones used when emitting the sixel (to save
run-time memory).

Closes #1383
2023-06-30 08:29:35 +02:00
Daniel Eklöf
64b6b5d2a7
config: dpi-aware: remove ‘auto’ value, and default to ‘no’
We now default to scaling fonts using the scaling factor, not monitor
DPI.

The ‘auto’ value for dpi-aware has been removed.

Documentation (man pages and README) have been updated to reflect the
new default.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
ba46a039ac
wayland: refactor: wrap wl_surface pointers in a wayl_surface struct
And add a viewport object to accompany the surface (to be used when
scaling the surface).

Also rename the wl_surf_subsurf struct to wayl_sub_surface, and add a
wayl_surface object to it, rather than a plain wl_surface pointer (to
also get the viewport pointer).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
424d045084
term: reload_fonts(): ‘scale’ is not a float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
8a3620bafa
term: scroll: only record scroll damage when viewport is at the bottom
We don’t need to record scroll damage if the viewport isn’t at the
bottom, since in this case, the renderer ignores the scroll damage
anyway.

This fixes a performance corner case, when the viewport is at the top
of the scrollback history.

When application scrolls the terminal contents, and the scrollback
history is full, and the viewport is at top of the history, then the
viewport needs to be moved (the scrollback history is a circular
buffer, and thus the top of the history “moves” when we’re scrolling
in new contents).

Moving the viewport typically results in another type of scroll
damage (DAMAGE_SCROLL_IN_VIEW, instead of the “normal” DAMAGE_SCROLL).

Thus, each application triggered scroll, will result in two scroll
damage records: one DAMAGE_SCROLL, and one
DAMAGE_SCROLL_IN_VIEW. These two are incompatible, meaning they can’t
be merged. What’s worse, it also means the DAMAGE_SCROLL records from
two application triggered scrolls cannot be merged (since there’s a
DAMAGE_SCROLL_IN_VIEW in between).

As a result, the renderer will not see one, or “a few” scroll damage
events, but a *ton*. _Each_ one typically a single line, or so. And
each one resulting in lots of traffic on the wayland socket, as we
create and destroy new buffer pools, when doing “shm scrolling”.

This eventually leads to the socket not being able to keep up, and the
socket is closed on us, forcing us to exit.

The fix is really simple: don’t record “normal” scroll damage when
scrolling, _unless_ the viewport is at the bottom (and thus “follows”
the application output).

As soon as the user scrolls up in the history, we’ll stop emitting
normal scroll damage records. This is just fine, since, as mentioned
above, the renderer ignores them when the viewport isn’t at the
bottom.

What if the viewport is moved back down again, before the next frame
has been rendered? Wont there be “missing” scroll damage records? No,
because moving the viewport results in scroll damage records by
itself.

Closes #1380
2023-06-23 20:38:03 +02:00
Daniel Eklöf
24f12c7b5e
term: add term_cursor_col()
Set cursor column, absolute.

term_cursor_to() needs to reload the current row pointer, and is thus
not very effective when we only need to modify the column.
2023-06-20 14:55:32 +02:00
Daniel Eklöf
e78319fccd
utmp: rewrite utmp logging
This patch generalizes the utmp support, to not only support
libutempter, but also ulog (and in the future, even more interfaces).

* Rename config option main.utempter to main.utmp-helper
* Add meson option -Dutmp-backend=none|libutempter|ulog|auto
* Rename meson option -Ddefault-utempter-path to -Dutmp-default-helper-path
* utmp is no longer detected at compile time, but at runtime instead.

Meson will configure the following pre-processor macros, based on the
selected utmp backend:

* UTMP_ADD - argument to pass to utmp helper when adding a record (starting foot)
* UTMP_DEL - argument to pass to utmp helper when removing a record (exiting foot)
* UTMP_DEL_HAVE_ARGUMENT - if defined, UTMP_DEL expects an extra argument ($WAYLAND_DISPLAY)
* UTMP_DEFAULT_HELPER_PATH - path to the default utmp helper binary

The documentation has been updated to mention which arguments are
passed to the helper binary.

Closes #1314
2023-05-22 18:47:25 +02:00
Daniel Eklöf
3b41379be4
quirks: sway does not damage surface beneath sub-surface, when unmapped
When unmapping a sub-surface, Sway <= 1.8 does not damage the surface
beneath the sub-surface.

https://github.com/swaywm/sway/issues/6960

The workaround is to manually damage the main surface. Previously,
this was done when exiting scrollback search, and after the ‘flash’
OSC. But other sub-surfaces, that may also be unmapped, did not.

This patch adds a quirk handler that does this, and calls it when:

* Exiting scrollback search
* Ending the ‘flash’ OSC
* Exiting unicode input mode
* Clearing URL labels
* Removing the scrollback position indicator

Closes #1335
2023-05-12 14:51:05 +02:00
Daniel Eklöf
7eea69df89
term: reset: switch modifyOtherKeys back to level 1 2023-05-12 09:42:35 +02:00
Daniel Eklöf
e2baa65238
render: ensure scroll region’s endpoint is valid after a window resize
If we had a non-empty bottom scroll region, and the window was resized
to a smaller size, the scroll region was not reset correctly.

This led to a crash when scrolling the screen content.

Fix by making sure the scroll region’s endpoint is within range.
2023-04-12 17:57:53 +02:00
Daniel Eklöf
981e4b77cb
term: protect against integer overflow when accumulating scroll damage
When accumulating scroll damage, we check if the last scroll damage’s
scrolling region, and type, matches the new/current scroll damage. If
so, the number of lines in the last scroll damage is increased,
instead of adding a new scroll damage instance to the list.

If the scroll damage list isn’t consumed, this build up of scroll
damage would eventually overflow.

And, even if it didn’t overflow, it could become large enough, that
when later used to calculate e.g. the affected surface area, while
rendering a frame, would cause an overflow there instead.

This patch fixes both issues by:

a) do an overflow check before increasing the line count
b) limit the line count to UINT16_MAX
2023-03-30 16:13:19 +02:00
Daniel Eklöf
f6ca8c90e1
config: add ‘font-size-adjustment=N[px|%]’ option
This patch adds a new config option, font-size-adjustment.

It lets you configure how much the font size should be
incremented/decremented when zooming in or out (ctrl-+, ctrl+-).

Values can be specified in points, pixels or percent.

Closes #1188
2022-12-17 10:59:17 +01:00
Daniel Eklöf
fa6b07abea
term: apply scale factor when converting a px value to pt 2022-11-24 17:20:05 +01:00
Daniel Eklöf
e85257bcae
term: initialize term->font_line_height when there’s no user-set line-height 2022-11-24 17:09:31 +01:00
Daniel Eklöf
94bac0513a
term: update user-set line-height just before calculating the cell dimensions
This ensures *all* font-size affecting changes (DPI, output scaling,
font size increment/decrement) also updates the line-height.
2022-11-24 14:34:31 +01:00
Daniel Eklöf
5a54423000
term: adjust user-set line-height by the same percentage as the primary font
Before this patch, a user-set line-height was increased/decreased by
the exact same amount of pt’s as the font(s).

This means, that when there’s a large discrepancy between the
line-height and the font size, the proportion between the line’s
height and the font size will change as we increase or decrease the
font size.

This patch changes how the line height is adjusted when the font size
is incremented or decremented. We calculate the difference, in
percent, between the primary font’s original (default) size, and its
current size, and then apply that to the configured line-height.

Closes #1218
2022-11-23 16:29:42 +01:00
Daniel Eklöf
09d52d5db6
term_destroy(): free interactive_resizing.grid
This grid is normally unallocated, but may be allocated if we are
exiting (for whatever reason) in the middle of an interactive resize.
2022-10-18 18:29:20 +02:00
Daniel Eklöf
2e9b3ceb95
fdm_ptmx(): regression: don’t return false when an interactive resize is in progress 2022-10-18 18:28:51 +02:00
Daniel Eklöf
3d9a429499
term: reverse scroll: free scrolled out lines
This ensures *everything* in the circular scrollback history, after
the bottom of the screen, is either NULL rows, or belong to the
scrollback *history* (as opposed to the future history).

This fixes an issue when calculating the scrollback start, which for
example would trigger a crash when moving the viewport (i.e. scrolling
with the mouse, or PgUp/PgDown).

Closes #1190
2022-10-16 10:31:08 +02:00
Daniel Eklöf
c5c97c2fd4
term_ptmx_{pause,resume}: return success/fail 2022-10-10 17:19:18 +02:00
Daniel Eklöf
54d637e2b4
term: ptmx: don’t consume anything while doing an interactive resize
The ‘normal’ grid in use during an interactive resize is temporary;
all changes done to it will be lost when the resize is finished.
2022-10-10 17:19:18 +02:00
Daniel Eklöf
66e4592d91
term: use SIZE_MAX instead of (size_t)-1ll 2022-10-10 17:19:18 +02:00
Daniel Eklöf
f4f1989b6e
render: resize: ignore ptmx read events during interactive resize 2022-10-10 17:19:18 +02:00
Daniel Eklöf
c93eb45b42
term: utmp: set ‘host’ to WAYLAND_DISPLAY
This is similar to what XTerm does (setting it to DISPLAY)
2022-09-23 23:04:10 +02:00
Daniel Eklöf
aa10b1d2da
Add support for creating utmp records
This patch adds support for creating utmp records using the ‘utempter’
helper binary from the ‘libutempter’ package.

* New config option ‘main.utempter’
* New meson command line option, -Ddefault-utempter-path. Defaults to
  auto-detecting the path.

The default value of the new ‘main.utempter’ config option depends on
the meson command line option ‘-Ddefault-utempter-path’.

If ‘main.utempter’ is *not* set to ‘none’, foot will try to execute
the utempter helper binary to create utmp records when a new terminal
is instantiated. The record is removed when the terminal instance is
destroyed.
2022-09-23 23:02:25 +02:00
Daniel Eklöf
d2e67689ea
terminal: don’t unref a not-yet-referenced key-binding set
Key-binding sets are bound to a seat/configuration pair. The conf
reference is done when a new terminal instance is created.

When that same terminal instance is destroyed, the key binding set is
unref:ed.

If the terminal instance is destroyed *before* the key binding set has
been referenced, we’ll still unref it. This creates an imbalance.

In particular, when the there is exactly one other terminal instance
referencing that same key binding set, that terminal instance will
trigger a foot server crash as soon as it receives a key press/release
event. This happens because the next-to-last terminal instance brought
the reference count of the binding set down to 0, causing it to be
free:d.

Thus, we *must* reference the binding set *before* we can error
out (when instantiating a new terminal instance).

At this point, we don’t yet have a valid terminal instance. But,
that’s ok, because all the key_binding_new_for_term() did with the
terminal instance was get the "struct wayland" and "struct config"
pointers. So, rename the function and simply pass these pointers
explicitly.

Similarly, change key_binding_for() to take a "struct config" pointer,
rather than a "struct terminal" pointer.

Also rename key_binding_unref_term() -> key_binding_unref().
2022-09-06 20:44:05 +02:00
Daniel Eklöf
a05eaf28bd
selection: selection_on_rows(): use scrollback relative coords
When checking if the current selection intersects with the
region (passed as parameter to the function), use scrollback relative
coordinates.

This fixes an issue where selections crossing the scrollback
wrap-around being misdetected, resulting in either the selection being
canceled while scrolling, even though it wasn’t scrolled out, or the
selection _not_ being canceled, when it _was_ scrolled out.
2022-07-28 21:06:57 +02:00
Daniel Eklöf
37f094280b
Revert "grid: invert the default value of ‘linebreak’, from false to true"
This reverts commit cdd46cdf85.
2022-06-30 19:37:01 +02:00
Daniel Eklöf
bdb79e8b9f
osc: add support for OSC 133;A (prompt markers)
This patch adds support for the OSC-133;A sequence, introduced by
FinalTerm and implemented by iTerm2, Kitty and more. See
https://iterm2.com/documentation-one-page.html#documentation-escape-codes.html.

The shell emits the OSC just before printing the prompt. This lets the
terminal know where, in the scrollback, there are prompts.

We implement this using a simple boolean in the row struct ("this row
has a prompt"). The prompt marker must be reflowed along with the text
on window resizes.

In an ideal world, erasing, or overwriting the cell where the OSC was
emitted, would remove the prompt mark. Since we don't store this
information in the cell struct, we can't do that. The best we can do
is reset it in erase_line(). This works well enough in the "normal"
screen, when used with a "normal" shell. It doesn't really work in
fullscreen apps, on the alt screen. But that doesn't matter since we
don't support jumping between prompts on the alt screen anyway.

To be able to jump between prompts, two new key bindings have been
added: prompt-prev and prompt-next, bound to ctrl+shift+z and
ctrl+shift+x respectively.

prompt-prev will jump to the previous, not currently visible, prompt,
by moving the viewport, ensuring the prompt is at the top of the
screen.

prompt-next jumps to the next prompt, visible or not. Again, by moving
the viewport to ensure the prompt is at the top of the screen. If
we're at the bottom of the scrollback, the viewport is instead moved
as far down as possible.

Closes #30
2022-06-16 19:02:10 +02:00
Daniel Eklöf
755f96321a
config: add a new ‘environment’ section
This section allows the user to define custom environment variables to
be set in the child process:

  [environment]
  name=value
2022-06-13 11:55:23 +02:00
Daniel Eklöf
cdd46cdf85
grid: invert the default value of ‘linebreak’, from false to true 2022-06-11 12:02:20 +02:00
Daniel Eklöf
fc67bff9c0
terminal: move viewport when part of it is scrolled out
If the viewport is at the top of the scrollback, and a program is
scrolling (e.g. by emitting newlines), the viewport needs to be
moved. Otherwise, the top of the viewport will show the *bottom* of
the scrollback (i.e. the newly emitted lines), and the bottom of the
viewport shows the top of the scrollback.

How do we detect if the viewport needs to be moved?

We convert its absolute row number to a scrollback relative row. This
number is also the maximum number of rows we can scroll without the
viewport being scrolled out.

In other words, if the number of rows to scroll is larger than the
viewports scrollback relative row number, the viewport needs to
moved.

How much do we need to move it? The difference between the number of
rows to scroll, and the viewports scrollback relative row number.

Example:

if the viewport is at the very top of the scrollback, its scrollback
relative row number is 0. In this case, it needs to be moved the same
number of rows as is being scrolled.
2022-05-11 17:58:18 +02:00
Daniel Eklöf
ea1aac88db
url-mode: add support for XDG activation when opening URLs
First, add a ‘token’ argument to spawn(). When non-NULL, spawn() will
set the ‘XDG_ACTIVATION_TOKEN’ environment variable in the forked
process. If DISPLAY is non-NULL, we also set DESKTOP_STARTUP_ID, for
compatibility with X11 applications. Note that failing to set either
of these environment variables are considered non-fatal - i.e. we
ignore failures.

Next, add a helper function, wayl_get_activation_token(), to generate
an XDG activation token, and call a user-provided callback when it’s
‘done (since token generation is asynchronous). This function takes an
optional ‘seat’ and ‘serial’ arguments - when both are non-NULL/zero,
we set the serial on the token. ‘win’ is a required argument, used to
set the surface on the token.

Re-write wayl_win_set_urgent() to use the new helper function.

Finally, rewrite activate_url() to first try to get an activation
token (and spawn the URL launcher in the token callback). If that
fails, or if we don’t have XDG activation support, spawn the URL
launcher immediately (like before this patch).

Closes #1058
2022-05-05 10:02:28 +02:00
Daniel Eklöf
32d9895697
term: reset sixel options when hard resetting the terminal state 2022-04-26 21:05:17 +02:00
Daniel Eklöf
398d96fdb2
term: flash: work around Sway sub-surface unmap bug
Unmapping a sub-surface in Sway does not damage the underlying
surface.

As a result, the OSC-555 escape (“flash”) will leave yellow margins on
~every second frame.

Out of sway, river, weston and mutter, only Sway needs this
workaround.

This is a workaround for https://github.com/swaywm/sway/issues/6960

Closes #1046
2022-04-26 17:41:38 +02:00
Daniel Eklöf
1d4e1b921d
sixel/terminal: use the new grid and selection APIs
Use grid_row_abs_to_sb() instead of manually “rebasing” row numbers.

Use selection_get_{start,end}() to retrieve the current selection
coordinates.
2022-04-25 20:00:14 +02:00
Daniel Eklöf
876044df8d
wayland: remove selection_override_modmask member
This member is no longer valid - we need to use one from the current
key-binding set.
2022-04-19 17:24:25 +02:00
Daniel Eklöf
24ee3dcc10
wayland: refactor: remove ‘struct config’ pointer from wayland struct
The global config doesn’t necessarily reflect the correct
configuration to use - we should *always* use the current terminal
instance’s conf pointer.

* Move selection override modifier mask to the key_binding_set struct
* Always warn if XDG activation is unavailable, not just if
  bell.urgent is set (we no longer have access to this information)
* Pass ‘bool presentation_timings’ as a parameter to wayl_init()
* Remove ‘presentation_timings’ member from the ‘terminal’ struct

Closes #932
2022-04-17 16:34:04 +02:00
Daniel Eklöf
90a2ca966f
key-binding: new API, for handling sets of key bindings
Up until now, our Wayland seats have been tracking key bindings. This
makes sense, since the seat’s keymap determines how the key bindings
are resolved.

However, tying bindings to the seat/keymap alone isn’t enough, since
we also depend on the current configuration (i.e. user settings) when
resolving a key binding.

This means configurations that doesn’t match the wayland object’s
configuration, currently don’t resolve key bindings correctly. This
applies to footclients where the user has overridden key bindings on
the command line (e.g. --override key-bindings.foo=bar).

Thus, to correctly resolve key bindings, each set of key bindings must
be tied *both* to a seat/keymap, *and* a configuration.

This patch introduces a key-binding manager, with an API to
add/remove/lookup, and load/unload keymaps from sets of key bindings.

In the API, sets are tied to a seat and terminal instance, since this
makes the most sense (we need to instantiate, or incref a set whenever
a new terminal instance is created). Internally, the set is tied to a
seat and the terminal’s configuration.

Sets are *added* when a new seat is added, and when a new terminal
instance is created. Since there can only be one instance of each
seat, sets are always removed when a seat is removed.

Terminals on the other hand can re-use the same configuration (and
typically do). Thus, sets ref-count the configuration. In other words,
when instantiating a new terminal, we may not have to instantiate a
new set of key bindings, but can often be incref:ed instead.

Whenever the keymap changes on a seat, all key bindings sets
associated with that seat reloads (re-resolves) their key bindings.

Closes #931
2022-04-17 15:39:51 +02:00
Daniel Eklöf
78fcdc5787
render: implement ‘flash’ and search mode’s ‘dimming’ with a sub-surface
Search mode and ‘flash’ (OSC-555) both achieves similar visual
effects: flash tints the entire window yellow, and search mode dims
it (except the search match).

But, they do so in completely different ways. Search mode is detected
in render_cell(), and the colors are then dimmed there.

Flash is implemented by blending a yellow, semi-transparent color on
top of the rendered grid.

This patch replaces those two implementations with a single one. We
add a new sub-surface, called the ‘overlay’. In normal mode, it’s
unmapped.

When either search mode, or flash, is enabled, we enable it, and
fill it with a semi-transparent color. Yellow for ‘flash’, and
“black” (i.e. no color) for search mode.

The compositor then blends it with the grid. Hopefully on the GPU,
meaning it’ll be faster than if we blend in software.

There are more performance benefits however. By using a separate
surface, we can do much better damage tracking.

The normal grid rendering code no longer have to care about neither
search mode, nor flash. Thus, we get rid of a couple of ‘if’
statements in render_cell(), which is nice. But more importantly, we
can drop full grid repaints in a couple of circumstances:

* Entering/exiting search mode
* Every frame while flash is active

Now, when rendering the search mode overlay, we do want to do some
damage tracking, also of the overlay.

This, since search mode doesn’t dim the *entire* window. The search
match is *not* dimmed. This is implemented by punching a hole in the
overlay sub-surface. That is, we make part of it *fully*
transparent. The basic idea is to set a clip region that excludes the
search match, and then dim the rest of the overlay.

It’s slightly more complicated than that however, if we want to reuse
the last frame’s overlay buffer (i.e we don’t want to re-render
the *entire* overlay every frame).

In short, we need to:

* Clear (punch hole) in areas that are part of this frame’s search
  match, but not the last frame’s (since those parts are _already_
  cleared).
* Dim the areas that were part of the last frame’s search match, but
  aren’t anymore (the rest of the overlay should already be dimmed).

To do this, we save the last frame’s “holes” (as a pixman
region). Then, when rendering the next frame, we first calculate the
new frame’s “holes” region.

The region to clear is “this frame’s holes minus last frame’s holes”
The region to dim is “last frame’s holes minus this frames holes”.

Finally, we compute the bounding box of all modified cells by taking
the union of the two diff regions mentioned above. This allows us to
limit the buffer damage sent to the compositor.
2022-04-16 18:31:02 +02:00
Daniel Eklöf
129deaffa8
wayland: optionally disable pointer input on subsurfaces
We have a number of sub-surfaces for which we are *not* interrested in
pointer (or touch) input.

Up until now, we’ve manually dealt with these, by recognizing these
surfaces in all pointer events, and ignoring them.

But, lo and behold, there are better ways of doing this. By clearing
the subsurface’s input region, the compositor will do this for us -
when a pointer is outside a surface’s input region, the event is
passed to the next surface underneath it.

This is exactly what we want! Do this for all subsurfaces, *except*
the CSDs.
2022-04-16 17:41:14 +02:00
Daniel Eklöf
d02124902b
client: add -E,--client-environment
When this option is used, the child process in the new terminal
instance will inherit its environment from the footclient process,
instead of the foot server’s.

Implemented by sending (yet another) dynamic string list as part of
the client -> server setup packet. When the new option is *not* used,
the setup packet is now 2 bytes larger than before.

On the server side, the slave process now uses execvpe() instead of
execvp(). There’s plumbing to propagate a new ‘envp’ argument from
term_init() all the way down to slave_exec(). If ‘envp’ is NULL, we
use ‘environ’ instead (thus matching the old behavior of execvp()).

Closes #1004
2022-04-12 15:07:40 +02:00
Daniel Eklöf
5b1f1602bc
refactor: add a ‘range’ struct, grouping a start and end coord together 2022-04-09 15:09:02 +02:00
Craig Barnes
23cf80667a Explicitly initialize sigaction::sa_mask members with sigemptyset(3)
Not doing so before calling sigaction(3) is "undefined" according to
POSIX[1]:

> Applications shall call either sigemptyset() or sigfillset() at least
> once for each object of type sigset_t prior to any other use of that
> object. If such an object is not initialized in this way, but is
> nonetheless supplied as an argument to any of pthread_sigmask(),
> sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(),
> sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or
> sigwaitinfo(), the results are undefined.

The use of designated initializers means that sa_mask members were
still being initialized, but sigset_t is an opaque type and implicit
initialization doesn't necessarily produce the same results as using
sigemptyset(3) (although it typically does on most implementations).

[1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html
2022-02-12 12:26:42 +00:00
Craig Barnes
e32707ffc0 csi/input: remove private mode 27127
This effectively reverts commit 31c73f0cf0.
2022-02-09 20:50:20 +00:00
Ashish SHUKLA
4df73585e7
Specify a fallback mouse cursor
`text' cursor is not available in lots of cursor themes, but `xterm'
is, so specify `xterm' as a fallback cursor name.
2022-02-07 22:15:47 +05:30
Daniel Eklöf
0bf92fff05
term: add term_set_user_mouse_cursor()
This function allows setting a custom mouse cursor.

This is done by adding a ‘char*’ member to the term struct. When it is
non-NULL, we *always* use that pointer (the exception being when the
pointer is hidden), while the pointer is over the grid. This is
instead of the hand/beam pointers we otherwise would use.
2022-02-07 17:28:37 +01:00
Daniel Eklöf
631c63d5a4
term: scrollback-to-text: crash when trying to extract the entire scrollback
We calculated the ‘start’ row by adding the number of screen rows to
the current grid offset. This works in most cases. But not when the
offset is close to the wrap-around.

This triggered a crash when we tried to access a row number larger
than the number of available grid rows.

Fix by bounding the start row to the number of grid rows.

This unearthed a second bug, where trying to extract the scrollback
resulted in nothing getting copied.

The extraction logic did:

   for (r = start; r != (end + 1); r++)
       ....

This works, as long as end isn’t start-1. When we try to extract the
entire scrollback, it _is_ start-1.

Fix by rewriting the loop logic to check for r==end *after* copying
the row contents, but *before* incrementing r.

Closes #926
2022-02-07 15:12:38 +01:00
Daniel Eklöf
b4027118e6
term: init: initialize selection pivot point coords to -1,-1
While this _shouldn’t_ be necessary (pivot points are only used while
a selection is ongoing). But it doesn’t hurt to initialize them
anyway.
2022-02-07 10:36:59 +01:00
Daniel Eklöf
e0227266ca
fcft: adapt to API changes in fcft-3.x
Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.

Since we do a fair amount of string operations in foot, it still makes
sense to use something that actually _is_ a string (or character),
rather than an array of uint32_t.

For this reason, we switch out all wchar_t usage in foot to
char32_t. We also verify, at compile-time, that char32_t used
UTF-32 (which is what fcft expects).

Unfortunately, there are no string functions for char32_t. To avoid
having to re-implement all wcs*() functions, we add a small wrapper
layer of c32*() functions.

These wrapper functions take char32_t arguments, but then simply call
the corresponding wcs*() function.

For this to work, wcs*() must _also_ be UTF-32 compatible. We can
check for the presence of the  __STDC_ISO_10646__ macro. If set,
wchar_t is at least 4 bytes and its internal representation is UTF-32.

FreeBSD does *not* define this macro, because its internal wchar_t
representation depends on the current locale. It _does_ use UTF-32
_if_ the current locale is UTF-8.

Since foot enforces UTF-8, we simply need to check if __FreeBSD__ is
defined.

Other fcft API changes:

* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
2022-02-05 17:00:54 +01:00