fix(macos): use strings' utf-8 lengths for libghostty calls

Swift conveniently converts strings to UTF-8 encoded cstrings when
passing them to external functions, however our libghostty functions
also take a length and we were using String.count for that, which
returns the number of _characters_ not the byte length, which caused
searches with multi-byte characters to get truncated.

I went ahead and changed _all_ invocations that pass a string length to
use the utf-8 byte length even if the string is comptime-known and all
ASCII, just so that it's proper and if someone copies one of the calls
in the future for user-inputted data they don't reproduce this bug.

ref:
https://developer.apple.com/documentation/swift/string/count
https://developer.apple.com/documentation/swift/stringprotocol/lengthofbytes(using:)
pull/9715/head
Qwerasd 2025-11-26 11:59:42 -07:00
parent d213091452
commit 4b01163c79
4 changed files with 74 additions and 74 deletions

View File

@ -180,14 +180,14 @@ extension Ghostty {
func newTab(surface: ghostty_surface_t) {
let action = "new_tab"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
func newWindow(surface: ghostty_surface_t) {
let action = "new_window"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
@ -210,14 +210,14 @@ extension Ghostty {
func splitToggleZoom(surface: ghostty_surface_t) {
let action = "toggle_split_zoom"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
func toggleFullscreen(surface: ghostty_surface_t) {
let action = "toggle_fullscreen"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
@ -238,21 +238,21 @@ extension Ghostty {
case .reset:
action = "reset_font_size"
}
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
func toggleTerminalInspector(surface: ghostty_surface_t) {
let action = "inspector:toggle"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}
func resetTerminal(surface: ghostty_surface_t) {
let action = "reset"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
logger.warning("action failed action=\(action)")
}
}

View File

@ -105,7 +105,7 @@ extension Ghostty {
func keyboardShortcut(for action: String) -> KeyboardShortcut? {
guard let cfg = self.config else { return nil }
let trigger = ghostty_config_trigger(cfg, action, UInt(action.count))
let trigger = ghostty_config_trigger(cfg, action, UInt(action.lengthOfBytes(using: .utf8)))
return Ghostty.keyboardShortcut(for: trigger)
}
#endif
@ -120,7 +120,7 @@ extension Ghostty {
guard let config = self.config else { return .init() }
var v: CUnsignedInt = 0
let key = "bell-features"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .init() }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .init() }
return .init(rawValue: v)
}
@ -128,7 +128,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = true;
let key = "initial-window"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -136,7 +136,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false;
let key = "quit-after-last-window-closed"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -144,7 +144,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: UnsafePointer<Int8>? = nil
let key = "title"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
guard let ptr = v else { return nil }
return String(cString: ptr)
}
@ -153,7 +153,7 @@ extension Ghostty {
guard let config = self.config else { return "" }
var v: UnsafePointer<Int8>? = nil
let key = "window-save-state"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return "" }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return "" }
guard let ptr = v else { return "" }
return String(cString: ptr)
}
@ -162,21 +162,21 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: Int16 = 0
let key = "window-position-x"
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
return ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) ? v : nil
}
var windowPositionY: Int16? {
guard let config = self.config else { return nil }
var v: Int16 = 0
let key = "window-position-y"
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
return ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) ? v : nil
}
var windowNewTabPosition: String {
guard let config = self.config else { return "" }
var v: UnsafePointer<Int8>? = nil
let key = "window-new-tab-position"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return "" }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return "" }
guard let ptr = v else { return "" }
return String(cString: ptr)
}
@ -186,7 +186,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "window-decoration"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return WindowDecoration(rawValue: str)?.enabled() ?? defaultValue
@ -196,7 +196,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: UnsafePointer<Int8>? = nil
let key = "window-theme"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
guard let ptr = v else { return nil }
return String(cString: ptr)
}
@ -205,7 +205,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false
let key = "window-step-resize"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -213,7 +213,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false
let key = "fullscreen"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -223,7 +223,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-non-native-fullscreen"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return switch str {
@ -245,7 +245,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: UnsafePointer<Int8>? = nil
let key = "window-title-font-family"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
guard let ptr = v else { return nil }
return String(cString: ptr)
}
@ -255,7 +255,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-window-buttons"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacOSWindowButtons(rawValue: str) ?? defaultValue
@ -266,7 +266,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-titlebar-style"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
return String(cString: ptr)
}
@ -276,7 +276,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-titlebar-proxy-icon"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacOSTitlebarProxyIcon(rawValue: str) ?? defaultValue
@ -287,7 +287,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-dock-drop-behavior"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacDockDropBehavior(rawValue: str) ?? defaultValue
@ -297,7 +297,7 @@ extension Ghostty {
guard let config = self.config else { return false }
var v = false;
let key = "macos-window-shadow"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -306,7 +306,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-icon"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacOSIcon(rawValue: str) ?? defaultValue
@ -318,7 +318,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-custom-icon"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
guard let path = NSString(utf8String: ptr) else { return defaultValue }
return path.expandingTildeInPath
@ -332,7 +332,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-icon-frame"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacOSIconFrame(rawValue: str) ?? defaultValue
@ -342,7 +342,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: ghostty_config_color_s = .init()
let key = "macos-icon-ghost-color"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
return .init(ghostty: v)
}
@ -350,7 +350,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: ghostty_config_color_list_s = .init()
let key = "macos-icon-screen-color"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
guard v.len > 0 else { return nil }
let buffer = UnsafeBufferPointer(start: v.colors, count: v.len)
return buffer.map { .init(ghostty: $0) }
@ -360,7 +360,7 @@ extension Ghostty {
guard let config = self.config else { return .never }
var v: UnsafePointer<Int8>? = nil
let key = "macos-hidden"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .never }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .never }
guard let ptr = v else { return .never }
let str = String(cString: ptr)
return MacHidden(rawValue: str) ?? .never
@ -370,14 +370,14 @@ extension Ghostty {
guard let config = self.config else { return false }
var v = false;
let key = "focus-follows-mouse"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
var backgroundColor: Color {
var color: ghostty_config_color_s = .init();
let bg_key = "background"
if (!ghostty_config_get(config, &color, bg_key, UInt(bg_key.count))) {
if (!ghostty_config_get(config, &color, bg_key, UInt(bg_key.lengthOfBytes(using: .utf8)))) {
#if os(macOS)
return Color(NSColor.windowBackgroundColor)
#elseif os(iOS)
@ -398,7 +398,7 @@ extension Ghostty {
guard let config = self.config else { return 1 }
var v: Double = 1
let key = "background-opacity"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v;
}
@ -406,7 +406,7 @@ extension Ghostty {
guard let config = self.config else { return 1 }
var v: Int = 0
let key = "background-blur"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v;
}
@ -414,7 +414,7 @@ extension Ghostty {
guard let config = self.config else { return 1 }
var opacity: Double = 0.85
let key = "unfocused-split-opacity"
_ = ghostty_config_get(config, &opacity, key, UInt(key.count))
_ = ghostty_config_get(config, &opacity, key, UInt(key.lengthOfBytes(using: .utf8)))
return 1 - opacity
}
@ -423,9 +423,9 @@ extension Ghostty {
var color: ghostty_config_color_s = .init();
let key = "unfocused-split-fill"
if (!ghostty_config_get(config, &color, key, UInt(key.count))) {
if (!ghostty_config_get(config, &color, key, UInt(key.lengthOfBytes(using: .utf8)))) {
let bg_key = "background"
_ = ghostty_config_get(config, &color, bg_key, UInt(bg_key.count));
_ = ghostty_config_get(config, &color, bg_key, UInt(bg_key.lengthOfBytes(using: .utf8)));
}
return .init(
@ -444,7 +444,7 @@ extension Ghostty {
var color: ghostty_config_color_s = .init();
let key = "split-divider-color"
if (!ghostty_config_get(config, &color, key, UInt(key.count))) {
if (!ghostty_config_get(config, &color, key, UInt(key.lengthOfBytes(using: .utf8)))) {
return Color(newColor)
}
@ -460,7 +460,7 @@ extension Ghostty {
guard let config = self.config else { return .top }
var v: UnsafePointer<Int8>? = nil
let key = "quick-terminal-position"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .top }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .top }
guard let ptr = v else { return .top }
let str = String(cString: ptr)
return QuickTerminalPosition(rawValue: str) ?? .top
@ -470,7 +470,7 @@ extension Ghostty {
guard let config = self.config else { return .main }
var v: UnsafePointer<Int8>? = nil
let key = "quick-terminal-screen"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .main }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .main }
guard let ptr = v else { return .main }
let str = String(cString: ptr)
return QuickTerminalScreen(fromGhosttyConfig: str) ?? .main
@ -480,7 +480,7 @@ extension Ghostty {
guard let config = self.config else { return 0.2 }
var v: Double = 0.2
let key = "quick-terminal-animation-duration"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -488,7 +488,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = true
let key = "quick-terminal-autohide"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -496,7 +496,7 @@ extension Ghostty {
guard let config = self.config else { return .move }
var v: UnsafePointer<Int8>? = nil
let key = "quick-terminal-space-behavior"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .move }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .move }
guard let ptr = v else { return .move }
let str = String(cString: ptr)
return QuickTerminalSpaceBehavior(fromGhosttyConfig: str) ?? .move
@ -506,7 +506,7 @@ extension Ghostty {
guard let config = self.config else { return QuickTerminalSize() }
var v = ghostty_config_quick_terminal_size_s()
let key = "quick-terminal-size"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return QuickTerminalSize() }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return QuickTerminalSize() }
return QuickTerminalSize(from: v)
}
#endif
@ -515,7 +515,7 @@ extension Ghostty {
guard let config = self.config else { return .after_first }
var v: UnsafePointer<Int8>? = nil
let key = "resize-overlay"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .after_first }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return .after_first }
guard let ptr = v else { return .after_first }
let str = String(cString: ptr)
return ResizeOverlay(rawValue: str) ?? .after_first
@ -526,7 +526,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "resize-overlay-position"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return ResizeOverlayPosition(rawValue: str) ?? defaultValue
@ -536,7 +536,7 @@ extension Ghostty {
guard let config = self.config else { return 1000 }
var v: UInt = 0
let key = "resize-overlay-duration"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v;
}
@ -544,7 +544,7 @@ extension Ghostty {
guard let config = self.config else { return .seconds(5) }
var v: UInt = 0
let key = "undo-timeout"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return .milliseconds(v)
}
@ -552,7 +552,7 @@ extension Ghostty {
guard let config = self.config else { return nil }
var v: UnsafePointer<Int8>? = nil
let key = "auto-update"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return nil }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return nil }
guard let ptr = v else { return nil }
let str = String(cString: ptr)
return AutoUpdate(rawValue: str)
@ -563,7 +563,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "auto-update-channel"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return AutoUpdateChannel(rawValue: str) ?? defaultValue
@ -573,7 +573,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false;
let key = "macos-auto-secure-input"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -581,7 +581,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false;
let key = "macos-secure-input-indication"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -589,7 +589,7 @@ extension Ghostty {
guard let config = self.config else { return true }
var v = false;
let key = "maximize"
_ = ghostty_config_get(config, &v, key, UInt(key.count))
_ = ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8)))
return v
}
@ -598,7 +598,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-shortcuts"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacShortcuts(rawValue: str) ?? defaultValue
@ -609,7 +609,7 @@ extension Ghostty {
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "scrollbar"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return Scrollbar(rawValue: str) ?? defaultValue

View File

@ -440,14 +440,14 @@ extension Ghostty {
let action = modifiers.contains(.shift)
? "navigate_search:previous"
: "navigate_search:next"
ghostty_surface_binding_action(surface, action, UInt(action.count))
ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))
return .handled
}
Button(action: {
guard let surface = surfaceView.surface else { return }
let action = "navigate_search:next"
ghostty_surface_binding_action(surface, action, UInt(action.count))
ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))
}) {
Image(systemName: "chevron.up")
}
@ -456,7 +456,7 @@ extension Ghostty {
Button(action: {
guard let surface = surfaceView.surface else { return }
let action = "navigate_search:previous"
ghostty_surface_binding_action(surface, action, UInt(action.count))
ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))
}) {
Image(systemName: "chevron.down")
}

View File

@ -88,13 +88,13 @@ extension Ghostty {
.sink { [weak self] needle in
guard let surface = self?.surface else { return }
let action = "search:\(needle)"
ghostty_surface_binding_action(surface, action, UInt(action.count))
ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))
}
} else if oldValue != nil {
searchNeedleCancellable = nil
guard let surface = self.surface else { return }
let action = "end_search"
ghostty_surface_binding_action(surface, action, UInt(action.count))
ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))
}
}
}
@ -1448,7 +1448,7 @@ extension Ghostty {
@IBAction func copy(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "copy_to_clipboard"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1456,7 +1456,7 @@ extension Ghostty {
@IBAction func paste(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "paste_from_clipboard"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1465,7 +1465,7 @@ extension Ghostty {
@IBAction func pasteAsPlainText(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "paste_from_clipboard"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1473,7 +1473,7 @@ extension Ghostty {
@IBAction func pasteSelection(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "paste_from_selection"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1481,7 +1481,7 @@ extension Ghostty {
@IBAction override func selectAll(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "select_all"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1489,7 +1489,7 @@ extension Ghostty {
@IBAction func find(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "start_search"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1497,7 +1497,7 @@ extension Ghostty {
@IBAction func findNext(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "search:next"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1505,7 +1505,7 @@ extension Ghostty {
@IBAction func findPrevious(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "search:previous"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1513,7 +1513,7 @@ extension Ghostty {
@IBAction func findHide(_ sender: Any?) {
guard let surface = self.surface else { return }
let action = "end_search"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1541,7 +1541,7 @@ extension Ghostty {
@objc func resetTerminal(_ sender: Any) {
guard let surface = self.surface else { return }
let action = "reset"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}
@ -1549,7 +1549,7 @@ extension Ghostty {
@objc func toggleTerminalInspector(_ sender: Any) {
guard let surface = self.surface else { return }
let action = "inspector:toggle"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) {
AppDelegate.logger.warning("action failed action=\(action)")
}
}