Rewrite match_to_end_of_word() in terms of
* selection_find_word_boundary_right()
* extract_begin() + extract_one() + extract_finish()
This adds a small overhead, in that extract_*() allocates an internal
buffer, from which we then immediately copy, into our newly resized
prompt buffer.
On the other hand, this makes the matching behavior more consistent
with regular mouse selections, and we don’t have to keep two very
similar match-to-next-word-boundary implementations in sync.
Besides disallowing matches that crosses the scrollback wrap-around,
this also fixes a crash when the trying to search beyond the last
output, when the scrollback history hasn’t yet been completely filled.
Instead of using CELL_SPACER for *all* cells that previously used
CELL_MULT_COL_SPACER, include the remaining number of spacers
following, and including, itself. This is encoded by adding to the
CELL_SPACER value.
So, a double width character will now store the character itself in
the first cell (just like before), and CELL_SPACER+1 in the second
cell.
A three-cell character would store the character itself, then
CELL_SPACER+2, and finally CELL_SPACER+1.
In other words, the last spacer is always CELL_SPACER+1.
CELL_SPACER+0 is used when padding at the right margin. I.e. when
writing e.g. a double width character in the last column, we insert a
CELL_SPACER+0 pad character, and then write the double width character
in the first column on the next row.
Bindings are matched in one out of three ways:
* By translated (by XKB) symbols
* By untranslated symbols
* By raw key codes
A translated symbol is affected by pressed modifiers, some of which
can be “consumed”. Consumed modifiers to not partake in the comparison
with the binding’s modifiers. In this mode, ctrl+shift+2 maps to
ctrl+@ on a US layout.
Untranslated symbols, or un-shifted symbols refer to the “base” symbol
of the pressed key, i.e. it’s unaffected by modifiers. In this mode,
consumed modifiers *do* partake in the comparison with the binding’s
modifiers, and ctrl+shift+2 maps to ctrl+shift+2 on a US layout.
More examples: ctrl+shift+u maps to ctrl+U in the translated lookup,
while ctrl+shift+u maps to ctrl+shift+u in the untranslated lookup.
Finally, we also match raw key codes. This allows our bindings to work
using the same physical keys when the user switches between latin and
non-latin layouts.
This means key bindings in foot.ini *must* not include both +shift+
and a *shifted* key. I.e. ctrl+shift+U is not a valid combo as it
cannot be triggered. Unfortunately, this was how you were supposed to
write bindings up until now... so, we try to detect such bindings, log
a deprecation warning and then “fix” the binding for the user.
When specifying bindings in foot.ini, both ctrl+U and ctrl+shift+u are
valid, and will work. The latter is preferred though, since we cannot
detect the raw key code for the former variant. Personally, I also
prefer the latter one because it is more explicit; it’s more obvious
which keys are involved.
However, in some cases it makes more sense to use the other
variant. Typically for non-letter combos.
Up until now, the various key binding modes (“normal”, “search” and
“url”) have used their own struct definitions for their key bindings.
The only reason for this was to have a properly typed “action” (using
the appropriate “action” enum).
This caused lots of duplicated code. This patch refactors this to use
a single struct definition for the “unparsed” key bindings handled by
the configuration, and another single definition for “parsed” bindings
used while handling input.
This allows us to implement configuration parsing, keymap translation
and so on using one set of functions, regardless of key binding mode.
This removes the selection_mark_word() and selection_mark_row()
functions. To start a word/row-based selection, use selection_start()
with SELECTION_SEMANTIC_{WORD,ROW}
When calculating the offset into the search string, from where to
start rendering, take into account that the cursor position is
in *characters*, and the glyph-offset is in *cells*.
These bindings copy from the clipboard or primary selection into the
search buffer.
Default bindings:
* clipboard-paste: ctrl+v, ctrl+y
* primary-paste: shift+insert
This option lets the user configure which characters act as word
delimiters when selecting text.
This affects both “double clicking”, and ‘ctrl-w’ in scrollback search
mode.
Closes#156
If the match was somewhere near the scrollback beginning, and if the
entire scrollback hadn't yet been filled, we ended up trying to move
the viewport past the beginning of the scrollback, which we then
adjusted in the wrong direction, causing the viewport to not move at
all.
Besides being a bad user experience, since the new match wasn't
visible, foot would also crash if you manually scrolled up to the
match.
search_update_selection() was changed in 1.4.x to *first* update the
selection, *then* move the viewport.
This leads to a crash if the new match (selection) is outside the
current viewport; the selection code assumes the updated selection
endpoint is in the visible viewport.
Changing back to *first* move the viewport, *then* update the
selection solves this.
* Don't move the viewport if the new match is already fully visible
* When we do have to move the viewport, position it such that the new
match ends up roughly in the middle.
They aren't really user configurable. At least not yet.
However, with this, we now handle raw key codes just like the normal
key bindings. Meaning, e.g. ctrl+g, ctrl+a, ctrl+e etc now works while
searching with e.g. a russian layout.
Before, when looking for a matching user key binding, we only
matched *symbols*.
This means that the physical keys that generate a specific key binding
is layout dependent. What's worse, it may not even be possible to
generate the key binding at all.
Russian is one such layout, where all the "normal" (us) symbols are
replaced.
By using raw key codes, we can get around this - the key code has a
direct mapping to the physical key.
However, matching raw key codes **only** doesn't always make sense
either. For now, match **both** symbols _and_ key codes. Symbols take
precedence.
TODO: we might have to make this configurable _per binding_.
Note: 'search' mode still uses mostly hardcoded shortcuts that still
have this problem (i.e. ctrl+g doesn't work with a russian layout).
Handle the CSDs and the search box the same way we handle the main
grid; when we need to redraw them, call
render_refresh_{csd,search}(). This sets a flag that is checked after
each FDM iteration. All actual rendering is done here.
This also ties the commits of the Wayland sub-surfaces to the commit
of the main surface.