use crate::emacs_core::display::{expect_frame_designator, live_frame_designator_p};
use crate::emacs_core::error::{EvalResult, Flow, signal};
use crate::emacs_core::terminal::pure::{
expect_terminal_designator, expect_terminal_designator_eval,
expect_terminal_designator_in_state,
};
use crate::emacs_core::value::*;
use crate::emacs_core::value::{ValueKind, VecLikeType};
use crate::window::WindowId;
pub(crate) fn reset_dispnew_thread_locals() {}
fn expect_args(name: &str, args: &[Value], n: usize) -> Result<(), Flow> {
if args.len() != n {
Err(signal(
"wrong-number-of-arguments",
vec![Value::symbol(name), Value::fixnum(args.len() as i64)],
))
} else {
Ok(())
}
}
fn expect_range_args(name: &str, args: &[Value], min: usize, max: usize) -> Result<(), Flow> {
if args.len() < min || args.len() > max {
Err(signal(
"wrong-number-of-arguments",
vec![Value::symbol(name), Value::fixnum(args.len() as i64)],
))
} else {
Ok(())
}
}
fn expect_max_args(name: &str, args: &[Value], max: usize) -> Result<(), Flow> {
if args.len() > max {
Err(signal(
"wrong-number-of-arguments",
vec![Value::symbol(name), Value::fixnum(args.len() as i64)],
))
} else {
Ok(())
}
}
fn expect_window_designator(value: &Value) -> Result<(), Flow> {
if value.is_nil() {
Ok(())
} else {
Err(signal(
"wrong-type-argument",
vec![Value::symbol("windowp"), *value],
))
}
}
fn live_window_designator_p(eval: &mut crate::emacs_core::eval::Context, value: &Value) -> bool {
match value.kind() {
ValueKind::Veclike(VecLikeType::Window) => eval
.frames
.find_window_frame_id(WindowId(value.as_window_id().unwrap()))
.is_some(),
ValueKind::Fixnum(id) if id >= 0 => eval
.frames
.find_window_frame_id(WindowId(id as u64))
.is_some(),
_ => false,
}
}
fn expect_window_designator_eval(
eval: &mut crate::emacs_core::eval::Context,
value: &Value,
) -> Result<(), Flow> {
if value.is_nil() || live_window_designator_p(eval, value) {
Ok(())
} else {
Err(signal(
"wrong-type-argument",
vec![Value::symbol("windowp"), *value],
))
}
}
fn live_window_designator_p_in_state(frames: &crate::window::FrameManager, value: &Value) -> bool {
match value.kind() {
ValueKind::Veclike(VecLikeType::Window) => frames
.find_window_frame_id(WindowId(value.as_window_id().unwrap()))
.is_some(),
ValueKind::Fixnum(id) if id >= 0 => {
frames.find_window_frame_id(WindowId(id as u64)).is_some()
}
_ => false,
}
}
fn expect_window_designator_in_state(
frames: &crate::window::FrameManager,
value: &Value,
) -> Result<(), Flow> {
if value.is_nil() || live_window_designator_p_in_state(frames, value) {
Ok(())
} else {
Err(signal(
"wrong-type-argument",
vec![Value::symbol("windowp"), *value],
))
}
}
fn window_id_from_window_designator(value: &Value) -> Option<WindowId> {
match value.kind() {
ValueKind::Veclike(VecLikeType::Window) => Some(WindowId(value.as_window_id().unwrap())),
ValueKind::Fixnum(id) if id >= 0 => Some(WindowId(id as u64)),
_ => None,
}
}
fn selected_window_id(eval: &mut crate::emacs_core::eval::Context) -> Option<WindowId> {
let frame_id = crate::emacs_core::window_cmds::ensure_selected_frame_id(eval);
eval.frames.get(frame_id).map(|frame| frame.selected_window)
}
fn selected_window_id_in_state(
frames: &mut crate::window::FrameManager,
buffers: &mut crate::buffer::BufferManager,
) -> Option<WindowId> {
let frame_id =
crate::emacs_core::window_cmds::ensure_selected_frame_id_in_state(frames, buffers);
frames.get(frame_id).map(|frame| frame.selected_window)
}
fn resolve_internal_show_cursor_window_id(
eval: &mut crate::emacs_core::eval::Context,
value: &Value,
) -> Option<WindowId> {
if value.is_nil() {
selected_window_id(eval)
} else {
window_id_from_window_designator(value)
}
}
fn resolve_internal_show_cursor_window_id_in_state(
frames: &mut crate::window::FrameManager,
buffers: &mut crate::buffer::BufferManager,
value: &Value,
) -> Option<WindowId> {
if value.is_nil() {
selected_window_id_in_state(frames, buffers)
} else {
window_id_from_window_designator(value)
}
}
pub(crate) fn builtin_redraw_frame(
eval: &mut crate::emacs_core::eval::Context,
args: Vec<Value>,
) -> EvalResult {
expect_range_args("redraw-frame", &args, 0, 1)?;
if let Some(frame) = args.first() {
if !frame.is_nil() && !live_frame_designator_p(eval, frame) {
return Err(signal(
"wrong-type-argument",
vec![Value::symbol("frame-live-p"), *frame],
));
}
}
Ok(Value::NIL)
}
pub(crate) fn builtin_redraw_display(args: Vec<Value>) -> EvalResult {
expect_args("redraw-display", &args, 0)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_open_termscript(args: Vec<Value>) -> EvalResult {
expect_args("open-termscript", &args, 1)?;
Err(signal(
"error",
vec![Value::string("Current frame is not on a tty device")],
))
}
pub(crate) fn builtin_ding(args: Vec<Value>) -> EvalResult {
expect_range_args("ding", &args, 0, 1)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_send_string_to_terminal(
eval: &mut crate::emacs_core::eval::Context,
args: Vec<Value>,
) -> EvalResult {
expect_range_args("send-string-to-terminal", &args, 1, 2)?;
match args[0].kind() {
ValueKind::String => {
if let Some(terminal) = args.get(1) {
expect_terminal_designator_eval(eval, terminal)?;
}
Ok(Value::NIL)
}
other => Err(signal(
"wrong-type-argument",
vec![Value::symbol("stringp"), args[0]],
)),
}
}
pub(crate) fn builtin_internal_show_cursor(
eval: &mut crate::emacs_core::eval::Context,
args: Vec<Value>,
) -> EvalResult {
expect_args("internal-show-cursor", &args, 2)?;
expect_window_designator_eval(eval, &args[0])?;
let visible = !args[1].is_nil();
if let Some(window_id) = resolve_internal_show_cursor_window_id(eval, &args[0]) {
eval.frames.set_window_cursor_visible(window_id, visible);
}
Ok(Value::NIL)
}
pub(crate) fn builtin_internal_show_cursor_p(
eval: &mut crate::emacs_core::eval::Context,
args: Vec<Value>,
) -> EvalResult {
expect_range_args("internal-show-cursor-p", &args, 0, 1)?;
if let Some(window) = args.first() {
expect_window_designator_eval(eval, window)?;
}
let query_window = args.first().unwrap_or(&Value::NIL);
if let Some(window_id) = resolve_internal_show_cursor_window_id(eval, query_window) {
return Ok(Value::bool_val(
eval.frames.window_cursor_visible(window_id),
));
}
Ok(Value::T)
}
pub(crate) fn builtin_force_window_update(args: Vec<Value>) -> EvalResult {
expect_max_args("force-window-update", &args, 1)?;
if args.first().is_some_and(|v| !v.is_nil()) {
Ok(Value::NIL)
} else {
Ok(Value::T)
}
}
pub(crate) fn builtin_frame_z_order_lessp(args: Vec<Value>) -> EvalResult {
expect_args("frame--z-order-lessp", &args, 2)?;
Ok(Value::NIL)
}