From bf190cca21c60143942fcd15a786d7463b04026a Mon Sep 17 00:00:00 2001 From: coast Date: Tue, 30 Dec 2025 16:08:52 +0330 Subject: [PATCH] push before new pc --- .bash.d/aliasrc | 4 + {zsh.d => .zsh.d}/zsh-autosuggestions.zsh | 0 .zshrc | 6 +- config/bspwm/bspwmrc | 82 + config/nvim/init.lua | 2 +- config/nvim/lazy-lock.json | 4 +- config/nvim/lua/config.lua | 5 +- config/nvim/lua/plugins/catppuccin/init.lua | 75 +- config/nvim/lua/plugins/lazy/plugins.lua | 3 +- config/nvim/lua/plugins/pinkfly/init.lua | 124 - config/nvim/nvim | 1 - config/piss/pissrc | 43 + config/xmobar/xmobarrc | 13 + config/xmonad/xmonad.hs | 51 + local/bin/Xrec | 32 + local/bin/{mid3v2 => hyfetch} | 6 +- local/bin/{mid3cp => hyfetch.rs} | 6 +- local/bin/{moggsplit => hyfetch.v1} | 6 +- local/bin/mid3iconv | 7 - local/bin/mutagen-inspect | 7 - local/bin/mutagen-pony | 7 - local/bin/tqdm | 8 - st/config.h | 515 +-- st/config.mk | 2 +- st/hb.o | Bin 0 -> 4032 bytes st/st | Bin 0 -> 124128 bytes st/st.c | 4515 +++++++++---------- st/st.o | Bin 0 -> 93800 bytes st/x.o | Bin 0 -> 86192 bytes 29 files changed, 2646 insertions(+), 2878 deletions(-) rename {zsh.d => .zsh.d}/zsh-autosuggestions.zsh (100%) create mode 100755 config/bspwm/bspwmrc delete mode 100644 config/nvim/lua/plugins/pinkfly/init.lua delete mode 120000 config/nvim/nvim create mode 100755 config/piss/pissrc create mode 100644 config/xmobar/xmobarrc create mode 100644 config/xmonad/xmonad.hs create mode 100755 local/bin/Xrec rename local/bin/{mid3v2 => hyfetch} (54%) rename local/bin/{mid3cp => hyfetch.rs} (54%) rename local/bin/{moggsplit => hyfetch.v1} (53%) delete mode 100755 local/bin/mid3iconv delete mode 100755 local/bin/mutagen-inspect delete mode 100755 local/bin/mutagen-pony delete mode 100755 local/bin/tqdm create mode 100644 st/hb.o create mode 100755 st/st create mode 100644 st/st.o create mode 100644 st/x.o diff --git a/.bash.d/aliasrc b/.bash.d/aliasrc index d0f5dd8..ee290ce 100644 --- a/.bash.d/aliasrc +++ b/.bash.d/aliasrc @@ -22,3 +22,7 @@ alias cmatrix="cmatrix -C white" fixaud() { pactl set-card-profile alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic "HiFi (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker)" } + +fixaud2() { + pactl set-default-sink alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink +} diff --git a/zsh.d/zsh-autosuggestions.zsh b/.zsh.d/zsh-autosuggestions.zsh similarity index 100% rename from zsh.d/zsh-autosuggestions.zsh rename to .zsh.d/zsh-autosuggestions.zsh diff --git a/.zshrc b/.zshrc index 8413394..7662aba 100644 --- a/.zshrc +++ b/.zshrc @@ -1,5 +1,4 @@ #!/bin/zsh -. /etc/profile HISTFILE=$HOME/.cache/zsh/history SAVEHIST=100000000 HISTSIZE=$SAVEHIST @@ -10,8 +9,7 @@ zmodload zsh/complist compinit comp_options+=(globdots) zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' -source ~/.local/zsh/zsh-autosuggestions.zsh -source ~/.local/zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +source ~/.zsh.d/* autoload -U colors && colors && setopt prompt_subst ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=5" ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=12" @@ -19,4 +17,4 @@ LIBCLANG_PATH=/usr/lib/llvm/20/lib64 source ~/.zprofile PATH=$PATH:/home/coast/.spicetify -PROMPT="[%n@%m %~]%% " +PROMPT="0 %n %1~ " diff --git a/config/bspwm/bspwmrc b/config/bspwm/bspwmrc new file mode 100755 index 0000000..e4a1ca9 --- /dev/null +++ b/config/bspwm/bspwmrc @@ -0,0 +1,82 @@ +#!/bin/sh +# my bspwmrc + +# desktops +bspc monitor -d I II III IV V VI VII VIII IX X + +# borders +bspc config focused_border_color "#383838" +bspc config normal_border_color "#282828" +bspc config border_width 2 + +# layout +bspc config window_gap 10 +bspc config split_ratio 0.5 +bspc config smart_gap true + +# focus behavior +bspc config focus_follows_pointer true +bspc config click_to_focus false +bspc config pointer_follows_monitor true + +# monitor / window behavior +bspc config remove_disabled_monitors true +bspc config auto_cancel true +bspc config auto_alternate true + +# padding +bspc config bottom_padding 0 + + +### {{{ find and stop processes + +pidb() { + pgrep -x "$1" >/dev/null 2>&1 +} + +run() { + proc="$1" + cmd="$2" + + if ! pidb "$proc"; then + sh -c "$cmd" & + fi +} + +### }}} + + +### {{{ rerun/start processes + +# piss +run "piss" "piss" + +# picom +run "picom" "picom --backend glx" + +# dunst +run "dunst" "dunst" + +# bspbar +run "bspbar" "bspbar" + +# polkit gnome +run "polkit-gnome-authentication-agent-1" \ + "/usr/libexec/polkit-gnome-authentication-agent-1" + +# xsettingsd +run "xsettingsd" "xsettingsd" + +# pulseaudio +run "pulseaudio" "pulseaudio --start" + +# pipewire +run "pipewire" "pipewire" + +# xtkhd +run "xtkhd" "xtkhd" + +xrandr --output eDP-1 --off +hsetroot -center "$HOME/Downloads/wall4.png" + +### }}} diff --git a/config/nvim/init.lua b/config/nvim/init.lua index 3fd75f6..d9da61e 100644 --- a/config/nvim/init.lua +++ b/config/nvim/init.lua @@ -7,5 +7,5 @@ require("config") require("plugins/render-markdown") --require("status_line").setup() require("plugins/lualine") -require("plugins/pinkfly") +require("plugins/catppuccin") require("colorizer").setup() -- #ffffff #edb511 diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json index 34de4af..7d87241 100644 --- a/config/nvim/lazy-lock.json +++ b/config/nvim/lazy-lock.json @@ -8,7 +8,8 @@ "cmp-vsnip": { "branch": "main", "commit": "989a8a73c44e926199bfd05fa7a516d51f2d2752" }, "comfy-line-numbers.nvim": { "branch": "main", "commit": "31e2f9287b4491ad72defb9e0185eb2739983799" }, "fterm.nvim": { "branch": "master", "commit": "d1320892cc2ebab472935242d9d992a2c9570180" }, - "lazy.nvim": { "branch": "main", "commit": "db067881fff0fd4be8c00e5bde7492e0e1c77a2f" }, + "gruvbox": { "branch": "master", "commit": "697c00291db857ca0af00ec154e5bd514a79191f" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lsp_signature.nvim": { "branch": "master", "commit": "d50e40b3bf9324128e71b0b7e589765ce89466d2" }, "lualine.nvim": { "branch": "master", "commit": "a94fc68960665e54408fe37dcf573193c4ce82c9" }, "mason.nvim": { "branch": "main", "commit": "8024d64e1330b86044fed4c8494ef3dcd483a67c" }, @@ -33,7 +34,6 @@ "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, "twilight.nvim": { "branch": "main", "commit": "664e752f4a219801265cc3fc18782b457b58c1e1" }, "typst-preview.nvim": { "branch": "master", "commit": "e544812bba84b4f7976590f2b6c0dfbd099e1893" }, - "vim": { "branch": "main", "commit": "ea0ad226b851b3aa132e2e234cc74ceecf9f4c7c" }, "vim-closetag": { "branch": "master", "commit": "d0a562f8bdb107a50595aefe53b1a690460c3822" }, "vim-vsnip": { "branch": "master", "commit": "0a4b8419e44f47c57eec4c90df17567ad4b1b36e" }, "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } diff --git a/config/nvim/lua/config.lua b/config/nvim/lua/config.lua index 18a9c0f..f37534b 100644 --- a/config/nvim/lua/config.lua +++ b/config/nvim/lua/config.lua @@ -2,6 +2,9 @@ local opt = vim.opt local map = vim.keymap.set local g = vim.g +--filetypes +vim.cmd("autocmd BufRead,BufNewFile *.m set filetype=objc") + g.mapleader = " " opt.shiftwidth = 4 @@ -26,7 +29,7 @@ opt.termguicolors = true opt.spell = false opt.spelllang = { "en_us" } -opt.shell = "/run/current-system/sw/bin/nu" +opt.shell = "/usr/bin/zsh" vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "single", diff --git a/config/nvim/lua/plugins/catppuccin/init.lua b/config/nvim/lua/plugins/catppuccin/init.lua index 48783b2..2c12831 100644 --- a/config/nvim/lua/plugins/catppuccin/init.lua +++ b/config/nvim/lua/plugins/catppuccin/init.lua @@ -1,74 +1 @@ -require("catppuccin").setup({ - flavour = "auto", -- latte, frappe, macchiato, mocha - background = { -- :h background - light = "latte", - dark = "mocha", - }, - transparent_background = false, -- disables setting the background color. - float = { - transparent = false, -- enable transparent floating windows - solid = false, -- use solid styling for floating windows, see |winborder| - }, - show_end_of_buffer = false, -- shows the '~' characters after the end of buffers - term_colors = false, -- sets terminal colors (e.g. `g:terminal_color_0`) - dim_inactive = { - enabled = false, -- dims the background color of inactive window - shade = "dark", - percentage = 0.15, -- percentage of the shade to apply to the inactive window - }, - no_italic = false, -- Force no italic - no_bold = false, -- Force no bold - no_underline = false, -- Force no underline - styles = { -- Handles the styles of general hi groups (see `:h highlight-args`): - comments = { "italic" }, -- Change the style of comments - conditionals = { "italic" }, - loops = {}, - functions = {}, - keywords = {}, - strings = {}, - variables = {}, - numbers = {}, - booleans = {}, - properties = {}, - types = {}, - operators = {}, - -- miscs = {}, -- Uncomment to turn off hard-coded styles - }, - lsp_styles = { -- Handles the style of specific lsp hl groups (see `:h lsp-highlight`). - virtual_text = { - errors = { "italic" }, - hints = { "italic" }, - warnings = { "italic" }, - information = { "italic" }, - ok = { "italic" }, - }, - underlines = { - errors = { "underline" }, - hints = { "underline" }, - warnings = { "underline" }, - information = { "underline" }, - ok = { "underline" }, - }, - inlay_hints = { - background = true, - }, - }, - color_overrides = {}, - custom_highlights = {}, - default_integrations = true, - auto_integrations = false, - integrations = { - cmp = true, - gitsigns = true, - nvimtree = true, - notify = false, - mini = { - enabled = true, - indentscope_color = "", - }, - -- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations) - }, -}) - --- setup must be called before loading -vim.cmd.colorscheme("catppuccin") +vim.cmd.colorscheme("gruvbox") diff --git a/config/nvim/lua/plugins/lazy/plugins.lua b/config/nvim/lua/plugins/lazy/plugins.lua index 9769ea9..fa30702 100644 --- a/config/nvim/lua/plugins/lazy/plugins.lua +++ b/config/nvim/lua/plugins/lazy/plugins.lua @@ -1,7 +1,8 @@ return { { "andweeb/presence.nvim", - "rose-pine/vim", + --"catppuccin/nvim", + "morhetz/gruvbox", "neovim/nvim-lspconfig", "williamboman/mason.nvim", { diff --git a/config/nvim/lua/plugins/pinkfly/init.lua b/config/nvim/lua/plugins/pinkfly/init.lua deleted file mode 100644 index 87cd9b5..0000000 --- a/config/nvim/lua/plugins/pinkfly/init.lua +++ /dev/null @@ -1,124 +0,0 @@ -vim.cmd("colorscheme moonfly") - -local palette = { - black = "#0f0f0f", - surface = "#1a1a1a", - overlay = "#2a2a2a", - text = "#e0def4", - dim = "#6e6a86", - pink = "#ebbcba", - magenta = "#f2a7b0", - peach = "#f6c177", - white = "#ffffff", - comment = "#55505c", -} - -vim.cmd("hi clear") -if vim.fn.exists("syntax_on") then - vim.cmd("syntax reset") -end -vim.o.background = "dark" -vim.g.colors_name = "pinkfly" - -local ui = { - Normal = { fg = palette.text, bg = palette.black }, - NormalNC = { fg = palette.text, bg = palette.black }, - NormalFloat = { fg = palette.text, bg = palette.surface }, - FloatBorder = { fg = palette.pink, bg = palette.surface }, - VertSplit = { fg = palette.overlay, bg = palette.black }, - StatusLine = { fg = palette.pink, bg = palette.black }, - StatusLineNC = { fg = palette.dim, bg = palette.black }, - TabLine = { fg = palette.text, bg = palette.overlay }, - TabLineSel = { fg = palette.black, bg = palette.pink, bold = true }, - Pmenu = { fg = palette.text, bg = palette.surface }, - PmenuSel = { fg = palette.black, bg = palette.pink }, - CursorLine = { bg = palette.surface }, - CursorLineNr = { fg = palette.pink, bold = true }, - LineNr = { fg = palette.comment }, - Visual = { bg = "#2a1f2a" }, - Search = { bg = palette.pink, fg = palette.black }, - IncSearch = { bg = palette.magenta, fg = palette.black }, - MatchParen = { fg = palette.pink, bold = true }, -} - -local syntax = { - Comment = { fg = palette.comment, italic = true }, - Constant = { fg = palette.pink }, - String = { fg = palette.peach }, - Character = { fg = palette.peach }, - Number = { fg = palette.magenta }, - Boolean = { fg = palette.magenta, bold = true }, - Identifier = { fg = palette.pink }, - Function = { fg = palette.pink, bold = true }, - Statement = { fg = palette.magenta }, - Conditional = { fg = palette.pink, bold = true }, - Repeat = { fg = palette.pink }, - Label = { fg = palette.magenta }, - Operator = { fg = palette.pink }, - Keyword = { fg = palette.magenta, bold = true }, - Exception = { fg = palette.pink }, - PreProc = { fg = palette.pink }, - Type = { fg = palette.pink }, - StorageClass = { fg = palette.magenta }, - Structure = { fg = palette.pink }, - Typedef = { fg = palette.pink }, - Delimiter = { fg = palette.text }, - Special = { fg = palette.magenta }, -} - -local diagnostics = { - DiagnosticError = { fg = "#ff7b7b" }, - DiagnosticWarn = { fg = palette.peach }, - DiagnosticInfo = { fg = palette.pink }, - DiagnosticHint = { fg = palette.magenta }, -} - -for group, opts in pairs(ui) do - vim.api.nvim_set_hl(0, group, opts) -end -for group, opts in pairs(syntax) do - vim.api.nvim_set_hl(0, group, opts) -end -for group, opts in pairs(diagnostics) do - vim.api.nvim_set_hl(0, group, opts) -end - -local ok, lualine = pcall(require, "lualine") -if ok then - local lualine_pink = { - normal = { - a = { bg = palette.pink, fg = palette.black, gui = "bold" }, - b = { bg = palette.surface, fg = palette.pink }, - c = { bg = palette.black, fg = palette.text }, - }, - insert = { - a = { bg = palette.magenta, fg = palette.black, gui = "bold" }, - }, - visual = { - a = { bg = palette.peach, fg = palette.black, gui = "bold" }, - }, - replace = { - a = { bg = palette.pink, fg = palette.black, gui = "bold" }, - }, - inactive = { - a = { bg = palette.surface, fg = palette.dim }, - b = { bg = palette.surface, fg = palette.dim }, - c = { bg = palette.black, fg = palette.dim }, - }, - } - - lualine.setup({ - options = { - theme = lualine_pink, - section_separators = { left = "", right = "" }, - component_separators = { left = "", right = "" }, - }, - }) -end - -vim.g.barbar_highlight = { - background = { fg = palette.dim, bg = palette.black }, - buffer_visible = { fg = palette.text, bg = palette.black }, - buffer_selected = { fg = palette.pink, bg = palette.black, bold = true }, - modified_selected = { fg = palette.peach, bg = palette.black, bold = true }, -} diff --git a/config/nvim/nvim b/config/nvim/nvim deleted file mode 120000 index cc731bb..0000000 --- a/config/nvim/nvim +++ /dev/null @@ -1 +0,0 @@ -/nix/store/jpb55c1pi5jlxhsgrvakbq4abf1pcldl-home-manager-files/.config/nvim \ No newline at end of file diff --git a/config/piss/pissrc b/config/piss/pissrc new file mode 100755 index 0000000..f048c66 --- /dev/null +++ b/config/piss/pissrc @@ -0,0 +1,43 @@ +#!/usr/bin/lua + +local piss = os.getenv("PISS_BIN") or "piss" + +os.execute(piss .. " wait") + +local function bind(key, cmd) + os.execute(string.format('%s bind "%s" "%s"', piss, key, cmd)) +end + +bind("Super + Ctrl + l", "slock") +bind("Super + Return", "alacritty") +bind("Super + s", "bspc node -c") +bind("Super + Ctrl + r", "bspc wm -r") + +local dirs = { + {"h", "west"}, + {"j", "south"}, + {"k", "north"}, + {"l", "east"} +} + +for _, dir in ipairs(dirs) do + bind("Super + " .. dir[1], "bspc node -f " .. dir[2]) + bind("Super + Shift + " .. dir[1], "bspc node -s " .. dir[2]) +end + +bind("Super + p", "pkill picom && picom --backend glx & disown") +bind("Super + Shift + p", string.format("pkill piss && %s ~/.config/piss/pissrc & disown", piss)) + +local desktops = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"} +for i, d in ipairs(desktops) do + bind("Super + " .. i, "bspc desktop -f " .. d) + bind("Super + Shift + " .. i, "bspc node -d " .. d) +end + +bind("Super + r", "rofi -show drun -config ~/.config/rofi/gruvbox.rasi") +bind("Super + Shift + Return", "rofi -show run -config ~/.config/rofi/gruvbox.rasi") +bind("Super + Shift + q", "bspc quit") +bind("Super + Shift + s", "flameshot gui") +bind("Super + f", "pcmanfm") +bind("Super + space", "bspc node -t floating") +bind("Super + Shift + space", "bspc node -t tiled") diff --git a/config/xmobar/xmobarrc b/config/xmobar/xmobarrc new file mode 100644 index 0000000..8d75d19 --- /dev/null +++ b/config/xmobar/xmobarrc @@ -0,0 +1,13 @@ +Config { + font = "xft:JetBrainsMono Nerd Font-12", + bgColor = "#282828", + fgColor = "#EBDBB2", + position = TopSize L 100 30, + commands = [ + Run XMonadLog, + Run Date "TIME %I:%M %p" "date" 10, + Run Com "sh" ["-c", "ip -4 addr show | grep inet | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 | head -n1"] "localip" 50 + ], + alignSep = "}{", + template = " %XMonadLog%}{ NET %localip% : %date% " + } diff --git a/config/xmonad/xmonad.hs b/config/xmonad/xmonad.hs new file mode 100644 index 0000000..efec589 --- /dev/null +++ b/config/xmonad/xmonad.hs @@ -0,0 +1,51 @@ +import XMonad +import XMonad.Util.EZConfig (additionalKeysP) +import XMonad.Util.Run +import XMonad.Hooks.DynamicLog +import XMonad.Hooks.StatusBar +import XMonad.Hooks.ManageDocks +import XMonad.Layout.Spacing +import System.IO + +keybinds = + [ + ("M-", spawn "alacritty"), + ("M-r", spawn "rofi -show drun -config ~/.config/rofi/gruvbox.rasi"), + ("M-S-s", spawn "flameshot gui"), + ("M-s", kill) + ] + +cLayoutHook = avoidStruts $ spacing 5 $ layoutHook def + +cXMobarPP :: PP +cXMobarPP = def + { + ppCurrent = xmobarColor "#83A598" "" , + ppHidden = xmobarColor "#EBDBB2" "", + ppHiddenNoWindows = xmobarColor "#EBDBB2" "", + ppTitle = xmobarColor "#EBDBB2" "" . shorten 60 . wrap "[" "]", + ppLayout = \layout -> "" + } + +cXStatusBar = statusBarProp "xmobar" (pure cXMobarPP) + +logHook = dynamicLogWithPP $ def + { ppOutput = \s -> return (), + ppCurrent = id, + ppVisible = id, + ppHidden = id, + ppUrgent = id, + ppTitle = id + } + +main = xmonad . withSB (statusBarProp "xmobar -f 'xft:JetBrainsMono Nerd Font-14'" (pure cXMobarPP)) $ withEasySB cXStatusBar defToggleStrutsKey $ def + { + modMask = mod4Mask, + terminal = "alacritty", + borderWidth = 2, + normalBorderColor = "#282828", + focusedBorderColor = "#383838", + workspaces = map show [1..9], + layoutHook = cLayoutHook + } + `additionalKeysP` keybinds diff --git a/local/bin/Xrec b/local/bin/Xrec new file mode 100755 index 0000000..1d7e956 --- /dev/null +++ b/local/bin/Xrec @@ -0,0 +1,32 @@ +#!/usr/bin/env sh +VIDEO_SIZE="1920x1080" +DISPLAY_NUM=":0.0" +AUDIO_SOURCE="default" +FPS="60" +OUTPUT_FILE="recording_$(date +%Y%m%d_%H%M%S).mkv" +AUDIO_BITRATE="128k" +record() { + local out_file="${1:-$OUTPUT_FILE}" + echo "Starting screen + mic recording..." + echo "Resolution: $VIDEO_SIZE @ ${FPS}fps" + echo "Audio source: $AUDIO_SOURCE" + echo "Output: $out_file" + ffmpeg -y \ + -thread_queue_size 1024 \ + -f x11grab -framerate "$FPS" -video_size "$VIDEO_SIZE" -i "$DISPLAY_NUM" \ + -thread_queue_size 1024 \ + -f pulse -i "$AUDIO_SOURCE" \ + -c:v h264_nvenc -preset p1 -rc vbr -cq 23 \ + -pix_fmt yuv420p \ + -c:a aac -b:a "$AUDIO_BITRATE" \ + -vsync 1 \ + "$out_file" +} +show_help() { + echo "Usage: $0 record [output_file]" +} +if [ "$1" = "--record" ]; then + record "$2" +else + show_help +fi diff --git a/local/bin/mid3v2 b/local/bin/hyfetch similarity index 54% rename from local/bin/mid3v2 rename to local/bin/hyfetch index 6607cba..75b46c2 100755 --- a/local/bin/mid3v2 +++ b/local/bin/hyfetch @@ -1,7 +1,7 @@ -#!/usr/bin/python3.13 +#!/usr/bin/python3 import sys -from mutagen._tools.mid3v2 import entry_point +from hyfetch.__main__ import run_rust if __name__ == '__main__': if sys.argv[0].endswith('.exe'): sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) + sys.exit(run_rust()) diff --git a/local/bin/mid3cp b/local/bin/hyfetch.rs similarity index 54% rename from local/bin/mid3cp rename to local/bin/hyfetch.rs index 871b536..75b46c2 100755 --- a/local/bin/mid3cp +++ b/local/bin/hyfetch.rs @@ -1,7 +1,7 @@ -#!/usr/bin/python3.13 +#!/usr/bin/python3 import sys -from mutagen._tools.mid3cp import entry_point +from hyfetch.__main__ import run_rust if __name__ == '__main__': if sys.argv[0].endswith('.exe'): sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) + sys.exit(run_rust()) diff --git a/local/bin/moggsplit b/local/bin/hyfetch.v1 similarity index 53% rename from local/bin/moggsplit rename to local/bin/hyfetch.v1 index f280aae..547f291 100755 --- a/local/bin/moggsplit +++ b/local/bin/hyfetch.v1 @@ -1,7 +1,7 @@ -#!/usr/bin/python3.13 +#!/usr/bin/python3 import sys -from mutagen._tools.moggsplit import entry_point +from hyfetch.__main__ import run_py if __name__ == '__main__': if sys.argv[0].endswith('.exe'): sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) + sys.exit(run_py()) diff --git a/local/bin/mid3iconv b/local/bin/mid3iconv deleted file mode 100755 index c042779..0000000 --- a/local/bin/mid3iconv +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python3.13 -import sys -from mutagen._tools.mid3iconv import entry_point -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) diff --git a/local/bin/mutagen-inspect b/local/bin/mutagen-inspect deleted file mode 100755 index 9690608..0000000 --- a/local/bin/mutagen-inspect +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python3.13 -import sys -from mutagen._tools.mutagen_inspect import entry_point -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) diff --git a/local/bin/mutagen-pony b/local/bin/mutagen-pony deleted file mode 100755 index 10e8876..0000000 --- a/local/bin/mutagen-pony +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python3.13 -import sys -from mutagen._tools.mutagen_pony import entry_point -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(entry_point()) diff --git a/local/bin/tqdm b/local/bin/tqdm deleted file mode 100755 index d233ee1..0000000 --- a/local/bin/tqdm +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/lib/python-exec/python3.13/python -# -*- coding: utf-8 -*- -import re -import sys -if __name__ == '__main__': - from tqdm.cli import main - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/st/config.h b/st/config.h index d33713a..090a508 100644 --- a/st/config.h +++ b/st/config.h @@ -1,4 +1,5 @@ -static char *font = "monospace:size=13:antialias=true:autohint=true"; +static char *font = + "JetBrainsMono Nerd Font:size=14:antialias=true:autohint=true"; static int borderpx = 2; static char *shell = "/bin/sh"; @@ -29,7 +30,7 @@ static unsigned int cursorthickness = 2; static int bellvolume = 0; -char *termname = "st-256color"; +char *termname = "xterm"; unsigned int tabspaces = 8; @@ -37,27 +38,13 @@ float alpha = 0.95; float alpha_def; static const char *colorname[] = { - "#282828", - "#fb4934", - "#b8bb26", - "#fabd2f", - "#83a598", - "#d3869b", - "#8ec07c", - "#ebdbb2", + "#1E1E2E", "#F38BA8", "#A6E3A1", "#F9E2AF", + "#89B4FA", "#F5C2E7", "#94E2D5", "#CDD6F4", - "#3c3836", - "#cc241d", - "#98971a", - "#d79921", - "#458588", - "#b16286", - "#689d6a", - "#f9f5d7", + "#6C7086", "#F38BA8", "#A6E3A1", "#F9E2AF", + "#89B4FA", "#F5C2E7", "#94E2D5", "#ECEFFF", - [255] = 0, - "#ebdbb2", - "#1a1a1a", + [255] = 0, "#CDD6F4", "#1E1E2E", }; unsigned int defaultfg = 256; @@ -72,8 +59,7 @@ static unsigned int defaultrcs = 257; * 6: Pipe ("|") * 7: Snowman ("☃") */ -static unsigned int cursorshape = 4; - +static unsigned int cursorshape = 2; static unsigned int cols = 160; static unsigned int rows = 40; @@ -87,253 +73,251 @@ static unsigned int defaultattr = 11; static uint forcemousemod = ShiftMask; static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { XK_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, + /* mask button function argument release */ + {XK_NO_MOD, Button4, kscrollup, {.i = 1}}, + {XK_NO_MOD, Button5, kscrolldown, {.i = 1}}, + {XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1}, + {ShiftMask, Button4, ttysend, {.s = "\033[5;2~"}}, + {XK_ANY_MOD, Button4, ttysend, {.s = "\031"}}, + {ShiftMask, Button5, ttysend, {.s = "\033[6;2~"}}, + {XK_ANY_MOD, Button5, ttysend, {.s = "\005"}}, }; -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|ShiftMask) +#define MODKEY Mod1Mask +#define TERMMOD (Mod1Mask | ShiftMask) static Shortcut shortcuts[] = { - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { MODKEY, XK_k, kscrollup, {.i = 1} }, - { MODKEY, XK_j, kscrolldown, {.i = 1} }, + {XK_ANY_MOD, XK_Break, sendbreak, {.i = 0}}, + {ControlMask, XK_Print, toggleprinter, {.i = 0}}, + {ShiftMask, XK_Print, printscreen, {.i = 0}}, + {XK_ANY_MOD, XK_Print, printsel, {.i = 0}}, + {ControlMask, XK_equal, zoom, {.f = +1}}, + {ControlMask, XK_minus, zoom, {.f = -1}}, + {TERMMOD, XK_Home, zoomreset, {.f = 0}}, + {MODKEY, XK_c, clipcopy, {.i = 0}}, + {MODKEY, XK_v, clippaste, {.i = 0}}, + {TERMMOD, XK_Y, selpaste, {.i = 0}}, + {ShiftMask, XK_Insert, selpaste, {.i = 0}}, + {TERMMOD, XK_Num_Lock, numlock, {.i = 0}}, + {MODKEY, XK_k, kscrollup, {.i = 1}}, + {MODKEY, XK_j, kscrolldown, {.i = 1}}, }; +static KeySym mappedkeys[] = {-1}; -static KeySym mappedkeys[] = { -1 }; - -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - +static uint ignoremod = Mod2Mask | XK_SWITCH_MOD; static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, + /* keysym mask string appkey appcursor */ + {XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + {XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + {XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + {XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + {XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + {XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + {XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + {XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + {XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + {XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + {XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + {XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + {XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + {XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + {XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + {XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + {XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + {XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + {XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + {XK_KP_End, ControlMask, "\033[J", -1, 0}, + {XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + {XK_KP_End, ShiftMask, "\033[K", -1, 0}, + {XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + {XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + {XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + {XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + {XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + {XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + {XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + {XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + {XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + {XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + {XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + {XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + {XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + {XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + {XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + {XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + {XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + {XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + {XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + {XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + {XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + {XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + {XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + {XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + {XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + {XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + {XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + {XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + {XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + {XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + {XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + {XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + {XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + {XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + {XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + {XK_Up, ShiftMask | Mod1Mask, "\033[1;4A", 0, 0}, + {XK_Up, ControlMask, "\033[1;5A", 0, 0}, + {XK_Up, ShiftMask | ControlMask, "\033[1;6A", 0, 0}, + {XK_Up, ControlMask | Mod1Mask, "\033[1;7A", 0, 0}, + {XK_Up, ShiftMask | ControlMask | Mod1Mask, "\033[1;8A", 0, 0}, + {XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + {XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + {XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + {XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + {XK_Down, ShiftMask | Mod1Mask, "\033[1;4B", 0, 0}, + {XK_Down, ControlMask, "\033[1;5B", 0, 0}, + {XK_Down, ShiftMask | ControlMask, "\033[1;6B", 0, 0}, + {XK_Down, ControlMask | Mod1Mask, "\033[1;7B", 0, 0}, + {XK_Down, ShiftMask | ControlMask | Mod1Mask, "\033[1;8B", 0, 0}, + {XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + {XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + {XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + {XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + {XK_Left, ShiftMask | Mod1Mask, "\033[1;4D", 0, 0}, + {XK_Left, ControlMask, "\033[1;5D", 0, 0}, + {XK_Left, ShiftMask | ControlMask, "\033[1;6D", 0, 0}, + {XK_Left, ControlMask | Mod1Mask, "\033[1;7D", 0, 0}, + {XK_Left, ShiftMask | ControlMask | Mod1Mask, "\033[1;8D", 0, 0}, + {XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + {XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + {XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + {XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + {XK_Right, ShiftMask | Mod1Mask, "\033[1;4C", 0, 0}, + {XK_Right, ControlMask, "\033[1;5C", 0, 0}, + {XK_Right, ShiftMask | ControlMask, "\033[1;6C", 0, 0}, + {XK_Right, ControlMask | Mod1Mask, "\033[1;7C", 0, 0}, + {XK_Right, ShiftMask | ControlMask | Mod1Mask, "\033[1;8C", 0, 0}, + {XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + {XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + {XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + {XK_Return, Mod1Mask, "\033\r", 0, 0}, + {XK_Return, XK_ANY_MOD, "\r", 0, 0}, + {XK_Insert, ShiftMask, "\033[4l", -1, 0}, + {XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + {XK_Insert, ControlMask, "\033[L", -1, 0}, + {XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + {XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + {XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + {XK_Delete, ControlMask, "\033[M", -1, 0}, + {XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + {XK_Delete, ShiftMask, "\033[2K", -1, 0}, + {XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + {XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + {XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + {XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + {XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + {XK_Home, ShiftMask, "\033[2J", 0, -1}, + {XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + {XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + {XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + {XK_End, ControlMask, "\033[J", -1, 0}, + {XK_End, ControlMask, "\033[1;5F", +1, 0}, + {XK_End, ShiftMask, "\033[K", -1, 0}, + {XK_End, ShiftMask, "\033[1;2F", +1, 0}, + {XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + {XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + {XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + {XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + {XK_Next, ControlMask, "\033[6;5~", 0, 0}, + {XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + {XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + {XK_F1, XK_NO_MOD, "\033OP", 0, 0}, + {XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + {XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + {XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + {XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + {XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + {XK_F2, XK_NO_MOD, "\033OQ", 0, 0}, + {XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + {XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + {XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + {XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + {XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + {XK_F3, XK_NO_MOD, "\033OR", 0, 0}, + {XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + {XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + {XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + {XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + {XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + {XK_F4, XK_NO_MOD, "\033OS", 0, 0}, + {XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + {XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + {XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + {XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + {XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + {XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + {XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + {XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + {XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + {XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + {XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + {XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + {XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + {XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + {XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + {XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + {XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + {XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + {XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + {XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + {XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + {XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + {XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + {XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + {XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + {XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + {XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + {XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + {XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + {XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + {XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + {XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + {XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + {XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + {XK_F16, XK_NO_MOD, "\033[23~", 0, 0}, + {XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + {XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + {XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + {XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + {XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + {XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + {XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + {XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + {XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + {XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + {XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + {XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + {XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + {XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + {XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + {XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + {XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + {XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + {XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + {XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + {XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + {XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + {XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + {XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + {XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + {XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + {XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + {XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + {XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + {XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + {XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + {XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, }; /* @@ -344,14 +328,13 @@ static Key key[] = { * If no match is found, regular selection is used. */ static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, + [SEL_RECTANGULAR] = Mod1Mask, }; /* * Printable characters in ASCII, used to estimate the advance width * of single wide characters. */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; +static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/st/config.mk b/st/config.mk index b6458af..f692cbd 100644 --- a/st/config.mk +++ b/st/config.mk @@ -35,4 +35,4 @@ STLDFLAGS = $(LIBS) $(LDFLAGS) #MANPREFIX = ${PREFIX}/man # compiler and linker -# CC = c99 +CC = clang diff --git a/st/hb.o b/st/hb.o new file mode 100644 index 0000000000000000000000000000000000000000..f2b844f349c590e7f27f7e882a9311b63a4ae4d9 GIT binary patch literal 4032 zcmbtWO>7%Q6kf+p8)&c{2sDMNwM3A5pi5jpYEXe}VwVZ5ARL)EjUqMM6>9l%zQn%3mo$2!v3Jgn;&v6sR!o&CbM=ZT7^Ic4y{$ z-}{+2Gduf2T;JK?^C?1n%0o(hBv3_}X|DIXShq`Q2BtRH-$yDBGQ{qQejkr6ra{!u z<_U(8Y9qF!I@Z?otJCAajy5*#t<90jY*_ESAGL=*CspQ*OxEnMV=&JQn61>UoNn5y z?Vn}w=|7~(%*o`UeYXf%nQ0>Q3T7kc)4AuW-9joeVNzQtUx_YEEZFOQJ4C9=hrWr0 za!!Olc`-mLb36m;q)dNw5~B0bMW;78Q*I?wEa6@{7oB0KPA`+{P0n0zWeq(~&>!6x zB{UXoBDGV5IvPHUdc6j;-P)iwpzZ4Ki_>{}wwHcGV0v^(1Po0?V10V&X$C-4Lg%Lg z5QfKIn#SdGl;%9?WT}@rwW*hDfX63mTBvvaE~QqhHR3`O^D?1M?Reo&UTkn;IkN_f z=liv()_X)*&9lV(lF-j^O1ke4s8S$W(@sRdduX!~tLoF&VzhaCEc8+9w6=6gf!yMu z_!-1V?Ifwp2T11^W8d->)9F%-{vBP2)2mL@DOMPrUef8}$IDaEr^ea?z}4x$&eZ5> zX{6J8b!x(D_k^pl_5kf^BdoAbYx}hQT4LX9y}tce&FaIsHGE_ZmAq-eBcRHn z9%K;9!_3>dgOTpwmhNDO7Tm4{yDDp6TQk*oH1N9rr3QbO53vrW2NrN4gC;O-gXaW1 zDA-3|m4-p4!{KT&0Wky072HeLiC<~B4*MGTKClRL4aP+|#&H%G#sYsI`aWg(#4DSS z4Du=GN7$&&e~05+TsRK>xc6Mr4da`oJjb~n+$`tFA=V^8A##`TeI7XM5$1oKli6BA zf6Rkl@W3~D;7@tr7kJ!0(4(-u0d0o|e+G1`&FdEryw3xF5AYVL&cdhW5jW@I=M@k9 zIN-QmAMmXu_DhQge=XoBNXI?34hJB2I?XaJ&g)i=<4(B|o@?-7L~%}a-H+fqHyxe< z$G6}=#{G!6;=0`B!iAsx97jLM6@DxiU(~bU!o_)c)rE_=Z@F+0_bU(lCyrx2L3l(y zmpCrwCH(v;@k0{-FA2xog`Y;gFVPR4Zh?n5j&X5K1-?Pz<6K2ty!=o^K4QKPc;L@U z{_##0{-2ZZTO__}4j(b-oQAk$=C$UoYXN#K$uy_$3M7AmJ}c`0WyYLc*~&!cPSHD5&NXHYV&{ z$H)0t-v7uK-?>j*eDR%FuM8&>cxfk6R>>~r592slPN%KnGNKl(tfAW0s13?=CYM6K zqMG@U5equQ$#M>V0uU`p=0+-&F!L#^kk6n(O_pTskYy)^vWE-9iA*k?UtLqkmohf| zK$MiUW!UAS1zvO&(u62x)-rPCf)uX=9#fg3Wugh-cG1X{()r?ui(_WXB^#!fwGLWY zMa|`HOMT?=fvqLmFb^ndHhXX+0lCAk%MeEWl!23fC8BZb{Zxd>7oxFv!DQ(r1$`%+Rwq_-) zbn)>Sd2<7X-$YsPUcxikC4BYQuEcj=+=Cg8x#tk(fV)iY_{Sl6%zqm^ zvIu+e|0Q%{{-W&!1@_%>R30C{HL?gh(W3EkUn0ib6XH5I_X)?o;3~61xcxcFCw4{s z1pFx2uU7w2zW&c}BGw;mg}tbM80`IeEf1=3c$Vb?w-@<}{}3@2#5VzO=Z?BIObSGN MKhf?6c--;-1NEqkUjP6A literal 0 HcmV?d00001 diff --git a/st/st b/st/st new file mode 100755 index 0000000000000000000000000000000000000000..c8ea3ded2c798f4b7304b25660c36d5a349268b3 GIT binary patch literal 124128 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 #include #include +#include #include #include #include #include -#include #include #include #include @@ -20,149 +20,147 @@ #include "st.h" #include "win.h" -#if defined(__linux) - #include +#if defined(__linux) +#include #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include +#include #elif defined(__FreeBSD__) || defined(__DragonFly__) - #include +#include #endif /* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128 * UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ /* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) #define TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)] -#define TLINEOFFSET(y) (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size) +#define TLINEOFFSET(y) \ + (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size) #define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)]) enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, }; -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; +enum cursor_movement { CURSOR_SAVE, CURSOR_LOAD }; enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 }; enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN }; enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, }; typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; + Glyph attr; /* current char attributes */ + int x; + int y; + char state; } TCursor; typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; - int alt; + int alt; } Selection; /* Screen lines */ typedef struct { - Line* buffer; /* ring buffer */ - int size; /* size of buffer */ - int cur; /* start of active screen */ - int off; /* scrollback line offset */ - TCursor sc; /* saved cursor */ + Line *buffer; /* ring buffer */ + int size; /* size of buffer */ + int cur; /* start of active screen */ + int off; /* scrollback line offset */ + TCursor sc; /* saved cursor */ } LineBuffer; /* Internal representation of the screen */ typedef struct { - int row; /* nb row */ - int col; /* nb col */ - LineBuffer screen[2]; /* screen and alternate screen */ - int linelen; /* allocated line length */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ + int row; /* nb row */ + int col; /* nb col */ + LineBuffer screen[2]; /* screen and alternate screen */ + int linelen; /* allocated line length */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; /* CSI Escape sequence structs */ /* ESC '[' [[ [] [;]] []] */ typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; } CSIEscape; /* STR Escape sequence structs */ /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ } STREscape; static void execsh(char *, char **); @@ -208,8 +206,8 @@ static void tswapscreen(void); static void tsetmode(int, int, const int *, int); static int twrite(const char *, int, int); static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); +static void tcontrolcode(uchar); +static void tdectest(char); static void tdefutf8(char); static int32_t tdefcolor(const int *, int *, int); static void tdeftran(char); @@ -242,2558 +240,2345 @@ static int iofd = 1; static int cmdfd; static pid_t pid; -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static const Rune utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, + 0x10FFFF}; -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; +ssize_t xwrite(int fd, const char *s, size_t len) { + size_t aux = len; + ssize_t r; - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } - return aux; + return aux; } -void * -xmalloc(size_t len) -{ - void *p; +void *xmalloc(size_t len) { + void *p; - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); - return p; + return p; } -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); +void *xrealloc(void *p, size_t len) { + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); - return p; + return p; } -char * -xstrdup(const char *s) -{ - char *p; +char *xstrdup(const char *s) { + char *p; - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); + if ((p = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); - return p; + return p; } -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; +size_t utf8decode(const char *c, Rune *u, size_t clen) { + size_t i, j, len, type; + Rune udecoded; - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); - return len; + return len; } -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; +Rune utf8decodebyte(char c, size_t *i) { + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; - return 0; + return 0; } -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; +size_t utf8encode(Rune u, char *c) { + size_t len, i; - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); - return len; + return len; } -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); +char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } + +size_t utf8validate(Rune *u, size_t i) { + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; } -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; +char base64dec_getc(const char **src) { + while (**src && !isprint((unsigned char)**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +char *base64dec(const char *src) { + size_t in_len = strlen(src); + char *result, *dst; + static const char base64_digits[256] = { + [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, + 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char)base64dec_getc(&src)]; + int b = base64_digits[(unsigned char)base64dec_getc(&src)]; + int c = base64_digits[(unsigned char)base64dec_getc(&src)]; + int d = base64_digits[(unsigned char)base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; } -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; +void selinit(void) { + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; } -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; +int tlinelen(int y) { + int i = term.col; + Line line = TLINE(y); + + if (line[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && line[i - 1].u == ' ') + --i; + + return i; } -int -tlinelen(int y) -{ - int i = term.col; - Line line = TLINE(y); +void selstart(int col, int row, int snap) { + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); - if (line[i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && line[i - 1].u == ' ') - --i; - - return i; + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); } -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); +void selextend(int col, int row, int type, int done) { + int oldey, oldex, oldsby, oldsey, oldtype; - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || + sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; } -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; +void selnormalize(void) { + int i; - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; - - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; } -void -selnormalize(void) -{ - int i; +int selected(int x, int y) { + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; + return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) && + (y != sel.ne.y || x <= sel.ne.x); } -int -selected(int x, int y) -{ - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; +void selsnap(int *x, int *y, int direction) { + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) - && BETWEEN(x, sel.nb.x, sel.ne.x); + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &TLINE(*y)[*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; - return BETWEEN(y, sel.nb.y, sel.ne.y) - && (y != sel.nb.y || x >= sel.nb.x) - && (y != sel.ne.y || x <= sel.ne.x); + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &TLINE(newy)[newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && + (delim != prevdelim || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(TLINE(*y - 1)[term.col - 1].mode & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row - 1; *y += direction) { + if (!(TLINE(*y)[term.col - 1].mode & ATTR_WRAP)) { + break; + } + } + } + break; + } } -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int delim, prevdelim; - const Glyph *gp, *prevgp; +char *getsel(void) { + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; + if (sel.ob.x == -1) + return NULL; - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } + bufsize = (term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); - if (newx >= tlinelen(newy)) - break; + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } - gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) - break; + if (sel.type == SEL_RECTANGULAR) { + gp = &TLINE(y)[sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col - 1; + } + last = &TLINE(y)[MIN(lastx, linelen - 1)]; + while (last >= gp && last->u == ' ') + --last; - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { - if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } - break; - } + for (; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; } -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - const Glyph *gp, *last; - - if (sel.ob.x == -1) - return NULL; - - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - - for ( ; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; +void selclear(void) { + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); } -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); +void die(const char *errstr, ...) { + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); } -void -die(const char *errstr, ...) -{ - va_list ap; +void execsh(char *cmd, char **args) { + char *sh, *prog, *arg; + const struct passwd *pw; - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]){prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); } -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; +void sigchld(int a) { + int stat; + pid_t p; - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + if (pid != p) + return; - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); } -void -sigchld(int a) -{ - int stat; - pid_t p; +void stty(char **args) { + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); + if ((n = strlen(stty_args)) > sizeof(cmd) - 1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz - 1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); } -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; +int ttynew(const char *line, char *cmd, const char *out, char **args) { + int m, s; - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", out, strerror(errno)); + } + } -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + close(m); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + if (s > 2) + close(s); #ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); #endif - execsh(cmd, args); - break; - default: + execsh(cmd, args); + break; + default: #ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); #endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; } -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; +size_t ttyread(void) { + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf + buflen, LEN(buf) - buflen); - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } } -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; +void ttywrite(const char *s, size_t n, int may_echo) { + const char *next; - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } } -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; +void ttywriteraw(const char *s, size_t n) { + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; + /* Check if we can write. */ + if (pselect(cmdfd + 1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim) ? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; write_error: - die("write error on tty: %s\n", strerror(errno)); + die("write error on tty: %s\n", strerror(errno)); } -void -ttyresize(int tw, int th) -{ - struct winsize w; +void ttyresize(int tw, int th) { + struct winsize w; - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); } -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); +void ttyhangup(void) { + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); } -int -tattrset(int attr) -{ - int i, j; - int y = TLINEOFFSET(0); +int tattrset(int attr) { + int i, j; + int y = TLINEOFFSET(0); - for (i = 0; i < term.row-1; i++) { - Line line = TSCREEN.buffer[y]; - for (j = 0; j < term.col-1; j++) { - if (line[j].mode & attr) - return 1; - } - y = (y+1) % TSCREEN.size; - } + for (i = 0; i < term.row - 1; i++) { + Line line = TSCREEN.buffer[y]; + for (j = 0; j < term.col - 1; j++) { + if (line[j].mode & attr) + return 1; + } + y = (y + 1) % TSCREEN.size; + } - return 0; + return 0; } -void -tsetdirt(int top, int bot) -{ - int i; +void tsetdirt(int top, int bot) { + int i; - LIMIT(top, 0, term.row-1); - LIMIT(bot, 0, term.row-1); + LIMIT(top, 0, term.row - 1); + LIMIT(bot, 0, term.row - 1); - for (i = top; i <= bot; i++) - term.dirty[i] = 1; + for (i = top; i <= bot; i++) + term.dirty[i] = 1; } -void -tsetdirtattr(int attr) -{ - int i, j; - int y = TLINEOFFSET(0); +void tsetdirtattr(int attr) { + int i, j; + int y = TLINEOFFSET(0); - for (i = 0; i < term.row-1; i++) { - Line line = TSCREEN.buffer[y]; - for (j = 0; j < term.col-1; j++) { - if (line[j].mode & attr) { - tsetdirt(i, i); - break; - } - } - y = (y+1) % TSCREEN.size; - } + for (i = 0; i < term.row - 1; i++) { + Line line = TSCREEN.buffer[y]; + for (j = 0; j < term.col - 1; j++) { + if (line[j].mode & attr) { + tsetdirt(i, i); + break; + } + } + y = (y + 1) % TSCREEN.size; + } } -void -tfulldirt(void) -{ - tsetdirt(0, term.row-1); +void tfulldirt(void) { tsetdirt(0, term.row - 1); } + +void tcursor(int mode) { + if (mode == CURSOR_SAVE) { + TSCREEN.sc = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = TSCREEN.sc; + tmoveto(term.c.x, term.c.y); + } } -void -tcursor(int mode) -{ - if (mode == CURSOR_SAVE) { - TSCREEN.sc = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = TSCREEN.sc; - tmoveto(term.c.x, term.c.y); - } +void treset(void) { + int i, j; + Glyph g = (Glyph){.fg = defaultfg, .bg = defaultbg}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP | MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + term.screen[i].sc = (TCursor){{.fg = defaultfg, .bg = defaultbg}}; + term.screen[i].cur = 0; + term.screen[i].off = 0; + for (j = 0; j < term.row; ++j) { + if (term.col != term.linelen) + term.screen[i].buffer[j] = + xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph)); + clearline(term.screen[i].buffer[j], g, 0, term.col); + } + for (j = term.row; j < term.screen[i].size; ++j) { + free(term.screen[i].buffer[j]); + term.screen[i].buffer[j] = NULL; + } + } + tcursor(CURSOR_LOAD); + term.linelen = term.col; + tfulldirt(); } -void -treset(void) -{ - int i, j; - Glyph g = (Glyph){ .fg = defaultfg, .bg = defaultbg}; +void tnew(int col, int row) { + int i; + term = (Term){0}; + term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line)); + term.screen[0].size = HISTSIZE; + term.screen[1].buffer = NULL; + for (i = 0; i < HISTSIZE; ++i) + term.screen[0].buffer[i] = NULL; - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - - for (i = 0; i < 2; i++) { - term.screen[i].sc = (TCursor){{ - .fg = defaultfg, - .bg = defaultbg - }}; - term.screen[i].cur = 0; - term.screen[i].off = 0; - for (j = 0; j < term.row; ++j) { - if (term.col != term.linelen) - term.screen[i].buffer[j] = xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph)); - clearline(term.screen[i].buffer[j], g, 0, term.col); - } - for (j = term.row; j < term.screen[i].size; ++j) { - free(term.screen[i].buffer[j]); - term.screen[i].buffer[j] = NULL; - } - } - tcursor(CURSOR_LOAD); - term.linelen = term.col; - tfulldirt(); + tresize(col, row); + treset(); } -void -tnew(int col, int row) -{ - int i; - term = (Term){0}; - term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line)); - term.screen[0].size = HISTSIZE; - term.screen[1].buffer = NULL; - for (i = 0; i < HISTSIZE; ++i) term.screen[0].buffer[i] = NULL; - - tresize(col, row); - treset(); +void tswapscreen(void) { + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); } -void -tswapscreen(void) -{ - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); +void kscrollup(const Arg *a) { + int n = a->i; + + if (IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = (-n) * term.row; + if (n > TSCREEN.size - term.row - TSCREEN.off) + n = TSCREEN.size - term.row - TSCREEN.off; + while (!TLINE(-n)) + --n; + TSCREEN.off += n; + selscroll(0, n); + tfulldirt(); } -void -kscrollup(const Arg *a) -{ - int n = a->i; +void kscrolldown(const Arg *a) { - if (IS_SET(MODE_ALTSCREEN)) - return; + int n = a->i; - if (n < 0) n = (-n) * term.row; - if (n > TSCREEN.size - term.row - TSCREEN.off) n = TSCREEN.size - term.row - TSCREEN.off; - while (!TLINE(-n)) --n; - TSCREEN.off += n; - selscroll(0, n); - tfulldirt(); + if (IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = (-n) * term.row; + if (n > TSCREEN.off) + n = TSCREEN.off; + TSCREEN.off -= n; + selscroll(0, -n); + tfulldirt(); } -void -kscrolldown(const Arg *a) -{ +void tscrolldown(int orig, int n) { + int i; + Line temp; - int n = a->i; + LIMIT(n, 0, term.bot - orig + 1); - if (IS_SET(MODE_ALTSCREEN)) - return; + /* Ensure that lines are allocated */ + for (i = -n; i < 0; i++) { + TLINE(i) = ensureline(TLINE(i)); + } - if (n < 0) n = (-n) * term.row; - if (n > TSCREEN.off) n = TSCREEN.off; - TSCREEN.off -= n; - selscroll(0, -n); - tfulldirt(); + /* Shift non-scrolling areas in ring buffer */ + for (i = term.bot + 1; i < term.row; i++) { + temp = TLINE(i); + TLINE(i) = TLINE(i - n); + TLINE(i - n) = temp; + } + for (i = 0; i < orig; i++) { + temp = TLINE(i); + TLINE(i) = TLINE(i - n); + TLINE(i - n) = temp; + } + + /* Scroll buffer */ + TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size; + /* Clear lines that have entered the view */ + tclearregion(0, orig, term.linelen - 1, orig + n - 1); + /* Redraw portion of the screen that has scrolled */ + tsetdirt(orig + n - 1, term.bot); + selscroll(orig, n); } -void -tscrolldown(int orig, int n) -{ - int i; - Line temp; +void tscrollup(int orig, int n) { + int i; + Line temp; - LIMIT(n, 0, term.bot-orig+1); + LIMIT(n, 0, term.bot - orig + 1); - /* Ensure that lines are allocated */ - for (i = -n; i < 0; i++) { - TLINE(i) = ensureline(TLINE(i)); - } + /* Ensure that lines are allocated */ + for (i = term.row; i < term.row + n; i++) { + TLINE(i) = ensureline(TLINE(i)); + } - /* Shift non-scrolling areas in ring buffer */ - for (i = term.bot+1; i < term.row; i++) { - temp = TLINE(i); - TLINE(i) = TLINE(i-n); - TLINE(i-n) = temp; - } - for (i = 0; i < orig; i++) { - temp = TLINE(i); - TLINE(i) = TLINE(i-n); - TLINE(i-n) = temp; - } + /* Shift non-scrolling areas in ring buffer */ + for (i = orig - 1; i >= 0; i--) { + temp = TLINE(i); + TLINE(i) = TLINE(i + n); + TLINE(i + n) = temp; + } + for (i = term.row - 1; i > term.bot; i--) { + temp = TLINE(i); + TLINE(i) = TLINE(i + n); + TLINE(i + n) = temp; + } - /* Scroll buffer */ - TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size; - /* Clear lines that have entered the view */ - tclearregion(0, orig, term.linelen-1, orig+n-1); - /* Redraw portion of the screen that has scrolled */ - tsetdirt(orig+n-1, term.bot); - selscroll(orig, n); + /* Scroll buffer */ + TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size; + /* Clear lines that have entered the view */ + tclearregion(0, term.bot - n + 1, term.linelen - 1, term.bot); + /* Redraw portion of the screen that has scrolled */ + tsetdirt(orig, term.bot - n + 1); + selscroll(orig, -n); } -void -tscrollup(int orig, int n) -{ - int i; - Line temp; +void selscroll(int orig, int n) { + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return; - LIMIT(n, 0, term.bot-orig+1); - - /* Ensure that lines are allocated */ - for (i = term.row; i < term.row + n; i++) { - TLINE(i) = ensureline(TLINE(i)); - } - - /* Shift non-scrolling areas in ring buffer */ - for (i = orig-1; i >= 0; i--) { - temp = TLINE(i); - TLINE(i) = TLINE(i+n); - TLINE(i+n) = temp; - } - for (i = term.row-1; i >term.bot; i--) { - temp = TLINE(i); - TLINE(i) = TLINE(i+n); - TLINE(i+n) = temp; - } - - /* Scroll buffer */ - TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size; - /* Clear lines that have entered the view */ - tclearregion(0, term.bot-n+1, term.linelen-1, term.bot); - /* Redraw portion of the screen that has scrolled */ - tsetdirt(orig, term.bot-n+1); - selscroll(orig, -n); + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || + sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } } -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) - return; +void tnewline(int first_col) { + int y = term.c.y; - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || - sel.oe.y < term.top || sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); } -void -tnewline(int first_col) -{ - int y = term.c.y; +void csiparse(void) { + char *p = csiescseq.buf, *np; + long int v; + int sep = ';'; /* colon or semi-colon, but not both */ - if (y == term.bot) { - tscrollup(term.top, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - int sep = ';'; /* colon or semi-colon, but not both */ - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (sep == ';' && *p == ':') - sep = ':'; /* allow override to colon once */ - if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf + csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (sep == ';' && *p == ':') + sep = ':'; /* allow override to colon once */ + if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf + csiescseq.len) ? *p : '\0'; } /* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +void tmoveato(int x, int y) { + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top : 0)); } -void -tmoveto(int x, int y) -{ - int miny, maxy; +void tmoveto(int x, int y) { + int miny, maxy; - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col - 1); + term.c.y = LIMIT(y, miny, maxy); } -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - Line line = TLINE(y); +void tsetchar(Rune u, const Glyph *attr, int x, int y) { + static const char *vt100_0[62] = { + /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + Line line = TLINE(y); - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && - BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && BETWEEN(u, 0x41, 0x7e) && + vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); - if (line[x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - line[x+1].u = ' '; - line[x+1].mode &= ~ATTR_WDUMMY; - } - } else if (line[x].mode & ATTR_WDUMMY) { - line[x-1].u = ' '; - line[x-1].mode &= ~ATTR_WIDE; - } + if (line[x].mode & ATTR_WIDE) { + if (x + 1 < term.col) { + line[x + 1].u = ' '; + line[x + 1].mode &= ~ATTR_WDUMMY; + } + } else if (line[x].mode & ATTR_WDUMMY) { + line[x - 1].u = ' '; + line[x - 1].mode &= ~ATTR_WIDE; + } - term.dirty[y] = 1; - line[x] = *attr; - line[x].u = u; + term.dirty[y] = 1; + line[x] = *attr; + line[x].u = u; } -void -tclearregion(int x1, int y1, int x2, int y2) -{ - int x, y, L, S, temp; - Glyph *gp; +void tclearregion(int x1, int y1, int x2, int y2) { + int x, y, L, S, temp; + Glyph *gp; - if (x1 > x2) - temp = x1, x1 = x2, x2 = temp; - if (y1 > y2) - temp = y1, y1 = y2, y2 = temp; + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; - LIMIT(x1, 0, term.linelen-1); - LIMIT(x2, 0, term.linelen-1); - LIMIT(y1, 0, term.row-1); - LIMIT(y2, 0, term.row-1); + LIMIT(x1, 0, term.linelen - 1); + LIMIT(x2, 0, term.linelen - 1); + LIMIT(y1, 0, term.row - 1); + LIMIT(y2, 0, term.row - 1); - L = TLINEOFFSET(y1); - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &TSCREEN.buffer[L][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; - } - L = (L + 1) % TSCREEN.size; - } + L = TLINEOFFSET(y1); + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &TSCREEN.buffer[L][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + L = (L + 1) % TSCREEN.size; + } } -void -tdeletechar(int n) -{ - int dst, src, size; - Glyph *line; +void tdeletechar(int n) { + int dst, src, size; + Glyph *line; - LIMIT(n, 0, term.col - term.c.x); + LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x; - src = term.c.x + n; - size = term.col - src; - line = TLINE(term.c.y); + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = TLINE(term.c.y); - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col - n, term.c.y, term.col - 1, term.c.y); } -void -tinsertblank(int n) -{ - int dst, src, size; - Glyph *line; +void tinsertblank(int n) { + int dst, src, size; + Glyph *line; - LIMIT(n, 0, term.col - term.c.x); + LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x + n; - src = term.c.x; - size = term.col - dst; - line = TLINE(term.c.y); + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = TLINE(term.c.y); - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); } -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); +void tinsertblankline(int n) { + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); } -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); +void tdeleteline(int n) { + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); } -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; +int32_t tdefcolor(const int *attr, int *npar, int l) { + int32_t idx = -1; + uint r, g, b; - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } - return idx; + return idx; } -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; +void tsetattr(const int *attr, int l) { + int i; + int32_t idx; - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= + ~(ATTR_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_BLINK | + ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]); + csidump(); + } + break; + } + } } -void -tsetscroll(int t, int b) -{ - int temp; +void tsetscroll(int t, int b) { + int temp; - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; + LIMIT(t, 0, term.row - 1); + LIMIT(b, 0, term.row - 1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; } -void -tsetmode(int priv, int set, const int *args, int narg) -{ - int alt; const int *lim; +void tsetmode(int priv, int set, const int *args, int narg) { + int alt; + const int *lim; - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col-1, - term.row-1); - } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col - 1, term.row - 1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, "erresc: unknown set/reset mode %d\n", *args); + break; + } + } + } } -void -csihandle(void) -{ - char buf[40]; - int len; +void csihandle(void) { + char buf[40]; + int len; - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor Down */ - case 'e': /* VPR --Cursor Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it more times */ - LIMIT(csiescseq.arg[0], 1, 65535); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor Forward */ - case 'a': /* HPR -- Cursor Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, - term.row-1); - } - break; - case 1: /* above */ - if (term.c.y > 1) - tclearregion(0, 0, term.col-1, term.c.y-1); - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, 0, term.col-1, term.row-1); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, - term.c.y); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y); - break; - } - break; - case 'S': /* SU -- Scroll line up */ - if (csiescseq.priv) break; - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, - term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR -- Device Status Report */ - switch (csiescseq.arg[0]) { - case 5: /* Status Report "OK" `0n` */ - ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); - break; - case 6: /* Report Cursor Position (CPR) ";R" */ - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - break; - default: - goto unknown; - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y - csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y + csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + LIMIT(csiescseq.arg[0], 1, 65535); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x + csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x - csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y + csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y - csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0] - 1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1] - 1, csiescseq.arg[0] - 1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); + if (term.c.y < term.row - 1) { + tclearregion(0, term.c.y + 1, term.col - 1, term.row - 1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col - 1, term.c.y - 1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col - 1, term.row - 1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col - 1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + if (csiescseq.priv) + break; + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0] - 1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR -- Device Status Report */ + switch (csiescseq.arg[0]) { + case 5: /* Status Report "OK" `0n` */ + ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); + break; + case 6: /* Report Cursor Position (CPR) ";R" */ + len = + snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, term.c.x + 1); + ttywrite(buf, len, 0); + break; + default: + goto unknown; + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0] - 1, csiescseq.arg[1] - 1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } } -void -csidump(void) -{ - size_t i; - uint c; +void csidump(void) { + size_t i; + uint c; - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); } -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); +void csireset(void) { memset(&csiescseq, 0, sizeof(csiescseq)); } + +void osc_color_response(int num, int index, int is_osc4) { + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch %s color %d\n", + is_osc4 ? "osc4" : "osc", is_osc4 ? num : index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + is_osc4 ? "4;" : "", num, r, r, g, g, b, b); + if (n < 0 || n >= sizeof(buf)) { + fprintf(stderr, "error: %s while printing %s response\n", + n < 0 ? "snprintf failed" : "truncation occurred", + is_osc4 ? "osc4" : "osc"); + } else { + ttywrite(buf, n, 1); + } } -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; +void strhandle(void) { + char *p = NULL, *dec; + int j, narg, par; + const struct { + int idx; + char *str; + } osc_table[] = {{defaultfg, "foreground"}, + {defaultbg, "background"}, + {defaultcs, "cursor"}}; - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } + term.esc &= ~(ESC_STR_END | ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 10: + case 11: + case 12: + if (narg < 2) + break; + p = strescseq.args[1]; + if ((j = par - 10) < 0 || j >= LEN(osc_table)) + break; /* shouldn't be possible */ + + if (!strcmp(p, "?")) { + osc_color_response(par, osc_table[j].idx, 0); + } else if (xsetcolorname(osc_table[j].idx, p)) { + fprintf(stderr, "erresc: invalid %s color: %s\n", osc_table[j].str, p); + } else { + tfulldirt(); + } + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + + if (p && !strcmp(p, "?")) { + osc_color_response(j, 0, 1); + } else if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) { + xloadcols(); + return; /* color reset without parameter */ + } + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, + p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + tfulldirt(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); } -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; +void strparse(void) { + int c; + char *p = strescseq.buf; - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: - case 11: - case 12: - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ + if (*p == '\0') + return; - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) { - xloadcols(); - return; /* color reset without parameter */ - } - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } } -void -strparse(void) -{ - int c; - char *p = strescseq.buf; +void strdump(void) { + size_t i; + uint c; - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); } -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); +void strreset(void) { + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; } -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; +void sendbreak(const Arg *arg) { + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); } -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); +void tprinter(char *s, size_t len) { + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } } -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } +void toggleprinter(const Arg *arg) { term.mode ^= MODE_PRINT; } + +void printscreen(const Arg *arg) { tdump(); } + +void printsel(const Arg *arg) { tdumpsel(); } + +void tdumpsel(void) { + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } } -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; +void tdumpline(int n) { + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &TLINE(n)[0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for (; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); } -void -printscreen(const Arg *arg) -{ - tdump(); +void tdump(void) { + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); } -void -printsel(const Arg *arg) -{ - tdumpsel(); +void tputtab(int n) { + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */; + } + term.c.x = LIMIT(x, 0, term.col - 1); } -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } +void tdefutf8(char ascii) { + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; } -void -tdumpline(int n) -{ - char buf[UTF_SIZ]; - const Glyph *bp, *end; +void tdeftran(char ascii) { + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; - bp = &TLINE(n)[0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for ( ; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } } -void -tdump(void) -{ - int i; +void tdectest(char c) { + int x, y; - for (i = 0; i < term.row; ++i) - tdumpline(i); + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } } -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); +void tstrsequence(uchar c) { + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; } -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); +void tcontrolcode(uchar ascii) { + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x - 1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI | ESC_ALTCHARSET | ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END | ESC_STR); } /* * returns 1 when the sequence is finished and it hasn't to read * more characters for this sequence, otherwise 0 */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - xsetmode(0, MODE_HIDE); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; +int eschandle(uchar ascii) { + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y + 1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y - 1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + xsetmode(0, MODE_HIDE); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar)ascii, + isprint(ascii) ? ascii : '.'); + break; + } + return 1; } -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; +void tputc(Rune u) { + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } - if (IS_SET(MODE_PRINT)) - tprinter(c, len); + if (IS_SET(MODE_PRINT)) + tprinter(c, len); - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || ISCONTROLC1(u)) { + term.esc &= ~(ESC_START | ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } + if (strescseq.len + len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - /* in UTF-8 mode ignore handling C1 control characters */ - if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) - return; - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + /* in UTF-8 mode ignore handling C1 control characters */ + if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) + return; + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) || + csiescseq.len >= sizeof(csiescseq.buf) - 1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); - gp = &TLINE(term.c.y)[term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &TLINE(term.c.y)[term.c.x]; - } + gp = &TLINE(term.c.y)[term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &TLINE(term.c.y)[term.c.x]; + } - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - gp->mode &= ~ATTR_WIDE; - } + if (IS_SET(MODE_INSERT) && term.c.x + width < term.col) { + memmove(gp + width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + gp->mode &= ~ATTR_WIDE; + } - if (term.c.x+width > term.col) { - if (IS_SET(MODE_WRAP)) - tnewline(1); - else - tmoveto(term.col - width, term.c.y); - gp = &TLINE(term.c.y)[term.c.x]; - } + if (term.c.x + width > term.col) { + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); + gp = &TLINE(term.c.y)[term.c.x]; + } - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x + 1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x + 2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x + width < term.col) { + tmoveto(term.c.x + width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } } -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; +int twrite(const char *buf, int buflen, int show_ctrl) { + int charsize; + Rune u; + int n; - if (TSCREEN.off) { - TSCREEN.off = 0; - tfulldirt(); - } + if (TSCREEN.off) { + TSCREEN.off = 0; + tfulldirt(); + } - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; } -void -clearline(Line line, Glyph g, int x, int xend) -{ - int i; - g.mode = 0; - g.u = ' '; - for (i = x; i < xend; ++i) { - line[i] = g; - } +void clearline(Line line, Glyph g, int x, int xend) { + int i; + g.mode = 0; + g.u = ' '; + for (i = x; i < xend; ++i) { + line[i] = g; + } } -Line -ensureline(Line line) -{ - if (!line) { - line = xmalloc(term.linelen * sizeof(Glyph)); - } - return line; +Line ensureline(Line line) { + if (!line) { + line = xmalloc(term.linelen * sizeof(Glyph)); + } + return line; } -void -tresize(int col, int row) -{ - int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int linelen = MAX(col, term.linelen); - int *bp; +void tresize(int col, int row) { + int i, j; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int linelen = MAX(col, term.linelen); + int *bp; - if (col < 1 || row < 1 || row > HISTSIZE) { - fprintf(stderr, - "tresize: error resizing to %dx%d\n", col, row); - return; - } + if (col < 1 || row < 1 || row > HISTSIZE) { + fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); + return; + } - /* Shift buffer to keep the cursor where we expect it */ - if (row <= term.c.y) { - term.screen[0].cur = (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size; - } + /* Shift buffer to keep the cursor where we expect it */ + if (row <= term.c.y) { + term.screen[0].cur = + (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size; + } - /* Resize and clear line buffers as needed */ - if (linelen > term.linelen) { - for (i = 0; i < term.screen[0].size; ++i) { - if (term.screen[0].buffer[i]) { - term.screen[0].buffer[i] = xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph)); - clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen); - } - } - for (i = 0; i < minrow; ++i) { - term.screen[1].buffer[i] = xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph)); - clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen); - } - } - /* Allocate all visible lines for regular line buffer */ - for (j = term.screen[0].cur, i = 0; i < row; ++i, j = (j + 1) % term.screen[0].size) - { - if (!term.screen[0].buffer[j]) { - term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph)); - } - if (i >= term.row) { - clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen); - } - } - /* Resize alt screen */ - term.screen[1].cur = 0; - term.screen[1].size = row; - for (i = row; i < term.row; ++i) { - free(term.screen[1].buffer[i]); - } - term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line)); - for (i = term.row; i < row; ++i) { - term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph)); - clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen); - } + /* Resize and clear line buffers as needed */ + if (linelen > term.linelen) { + for (i = 0; i < term.screen[0].size; ++i) { + if (term.screen[0].buffer[i]) { + term.screen[0].buffer[i] = + xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph)); + clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen); + } + } + for (i = 0; i < minrow; ++i) { + term.screen[1].buffer[i] = + xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph)); + clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen); + } + } + /* Allocate all visible lines for regular line buffer */ + for (j = term.screen[0].cur, i = 0; i < row; + ++i, j = (j + 1) % term.screen[0].size) { + if (!term.screen[0].buffer[j]) { + term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph)); + } + if (i >= term.row) { + clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen); + } + } + /* Resize alt screen */ + term.screen[1].cur = 0; + term.screen[1].size = row; + for (i = row; i < term.row; ++i) { + free(term.screen[1].buffer[i]); + } + term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line)); + for (i = term.row; i < row; ++i) { + term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph)); + clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen); + } - /* resize to new height */ - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + /* resize to new height */ + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - /* fix tabstops */ - if (col > term.col) { - bp = term.tabs + term.col; + /* fix tabstops */ + if (col > term.col) { + bp = term.tabs + term.col; - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } - /* update terminal size */ - term.col = col; - term.row = row; - term.linelen = linelen; - /* reset scrolling region */ - tsetscroll(0, row-1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - tfulldirt(); + /* update terminal size */ + term.col = col; + term.row = row; + term.linelen = linelen; + /* reset scrolling region */ + tsetscroll(0, row - 1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + tfulldirt(); } -void -resettitle(void) -{ - xsettitle(NULL); +void resettitle(void) { xsettitle(NULL); } + +void drawregion(int x1, int y1, int x2, int y2) { + int y, L; + + L = TLINEOFFSET(y1); + for (y = y1; y < y2; y++) { + if (term.dirty[y]) { + term.dirty[y] = 0; + xdrawline(TSCREEN.buffer[L], x1, y, x2); + } + L = (L + 1) % TSCREEN.size; + } } -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y, L; +void draw(void) { + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - L = TLINEOFFSET(y1); - for (y = y1; y < y2; y++) { - if (term.dirty[y]) { - term.dirty[y] = 0; - xdrawline(TSCREEN.buffer[L], x1, y, x2); - } - L = (L + 1) % TSCREEN.size; - } + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col - 1); + LIMIT(term.ocy, 0, term.row - 1); + if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + if (TSCREEN.off == 0) + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], term.ocx, term.ocy, + TLINE(term.ocy)[term.ocx], TLINE(term.ocy), term.col); + + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); } -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - if (TSCREEN.off == 0) - xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], - term.ocx, term.ocy, TLINE(term.ocy)[term.ocx], - TLINE(term.ocy), term.col); - - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); +void redraw(void) { + tfulldirt(); + draw(); } diff --git a/st/st.o b/st/st.o new file mode 100644 index 0000000000000000000000000000000000000000..a3f37a56e6f3d1ae0b42f360a3064a2ce9da13ce GIT binary patch literal 93800 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 Axc~qF literal 0 HcmV?d00001 diff --git a/st/x.o b/st/x.o new file mode 100644 index 0000000000000000000000000000000000000000..b829778eda6bf1ae6adeb61df68a72b94c71f727 GIT binary patch literal 86192 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 z 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