Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebased last PR #352

Merged
merged 4 commits into from
Oct 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions rust_src/remacs-sys/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,98 @@ pub struct Lisp_Process {
// TODO: this struct is incomplete.
}

#[repr(C)]
pub struct Lisp_Frame {
pub header: Lisp_Vectorlike_Header,

/// All Lisp_Object components must come first.
/// That ensures they are all aligned normally.

/// Name of this frame: a Lisp string. It is used for looking up resources,
/// as well as for the title in some cases.
pub name: Lisp_Object,

/// The name to use for the icon, the last time
/// it was refreshed. nil means not explicitly specified.
pub icon_name: Lisp_Object,

/// This is the frame title specified explicitly, if any.
/// Usually it is nil.
pub title: Lisp_Object,

/// The frame which should receive keystrokes that occur in this
/// frame, or nil if they should go to the frame itself. This is
/// usually nil, but if the frame is minibufferless, we can use this
/// to redirect keystrokes to a surrogate minibuffer frame when
/// needed.
///
/// Note that a value of nil is different than having the field point
/// to the frame itself. Whenever the Fselect_frame function is used
/// to shift from one frame to the other, any redirections to the
/// original frame are shifted to the newly selected frame; if
/// focus_frame is nil, Fselect_frame will leave it alone.
pub focus_frame: Lisp_Object,

/// This frame's root window. Every frame has one.
/// If the frame has only a minibuffer window, this is it.
/// Otherwise, if the frame has a minibuffer window, this is its sibling.
pub root_window: Lisp_Object,

/// This frame's selected window.
/// Each frame has its own window hierarchy
/// and one of the windows in it is selected within the frame.
/// The selected window of the selected frame is Emacs's selected window.
pub selected_window: Lisp_Object,

/// This frame's minibuffer window.
/// Most frames have their own minibuffer windows,
/// but only the selected frame's minibuffer window
/// can actually appear to exist.
pub minibuffer_window: Lisp_Object,

/// Parameter alist of this frame.
/// These are the parameters specified when creating the frame
/// or modified with modify-frame-parameters.
pub param_alist: Lisp_Object,

/// List of scroll bars on this frame.
/// Actually, we don't specify exactly what is stored here at all; the
/// scroll bar implementation code can use it to store anything it likes.
/// This field is marked by the garbage collector. It is here
/// instead of in the `device' structure so that the garbage
/// collector doesn't need to look inside the window-system-dependent
/// structure.
pub scroll_bars: Lisp_Object,
pub condemned_scroll_bars: Lisp_Object,

/// Vector describing the items to display in the menu bar.
/// Each item has four elements in this vector.
/// They are KEY, STRING, SUBMAP, and HPOS.
/// (HPOS is not used in when the X toolkit is in use.)
/// There are four additional elements of nil at the end, to terminate.
pub menu_bar_items: Lisp_Object,

/// Alist of elements (FACE-NAME . FACE-VECTOR-DATA).
pub face_alist: Lisp_Object,

/// A vector that records the entire structure of this frame's menu bar.
/// For the format of the data, see extensive comments in xmenu.c.
/// Only the X toolkit version uses this.
pub menu_bar_vector: Lisp_Object,

/// Predicate for selecting buffers for other-buffer.
pub buffer_predicate: Lisp_Object,

/// List of buffers viewed in this frame, for other-buffer.
pub buffer_list: Lisp_Object,

/// List of buffers that were viewed, then buried in this frame. The
/// most recently buried buffer is first. For last-buffer.
pub buried_buffer_list: Lisp_Object,

// TODO: this struct is incomplete.
}

#[repr(C)]
pub struct hash_table_test {
pub name: Lisp_Object,
Expand Down Expand Up @@ -863,6 +955,8 @@ extern "C" {
pub static Qbufferp: Lisp_Object;
pub static Qwindowp: Lisp_Object;
pub static Qwindow_live_p: Lisp_Object;
pub static Qframep: Lisp_Object;
pub static Qframe_live_p: Lisp_Object;
pub static Qprocessp: Lisp_Object;
pub static Qthreadp: Lisp_Object;
pub static Qoverlayp: Lisp_Object;
Expand Down Expand Up @@ -920,6 +1014,7 @@ extern "C" {
pub static minibuf_level: EmacsInt;
pub static minibuf_window: Lisp_Object;
pub static selected_window: Lisp_Object;
pub static selected_frame: Lisp_Object;

pub fn Faref(array: Lisp_Object, idx: Lisp_Object) -> Lisp_Object;
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
Expand Down Expand Up @@ -1040,6 +1135,8 @@ extern "C" {
) -> ptrdiff_t;

pub fn hash_remove_from_table(h: *mut Lisp_Hash_Table, key: Lisp_Object);
pub fn set_point_both(charpos: ptrdiff_t, bytepos: ptrdiff_t);
pub fn buf_charpos_to_bytepos(buffer: *const Lisp_Buffer, charpos: ptrdiff_t) -> ptrdiff_t;
}

/// Contains C definitions from the font.h header.
Expand Down
24 changes: 22 additions & 2 deletions rust_src/src/editfns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
use remacs_macros::lisp_fn;
use lisp::LispObject;
use util::clip_to_bounds;
use remacs_sys::{EmacsInt, globals, Qmark_inactive};
use remacs_sys::{buf_charpos_to_bytepos, globals, set_point_both, EmacsInt, Qinteger_or_marker_p,
Qmark_inactive};
use threads::ThreadState;
use buffers::get_buffer;
use marker::marker_position;
use marker::{marker_position, set_point_from_marker};

/// Return value of point, as an integer.
/// Beginning of buffer is position (point-min).
Expand Down Expand Up @@ -132,3 +133,22 @@ pub fn point_min() -> LispObject {
pub fn point_max() -> LispObject {
LispObject::from_natnum(ThreadState::current_buffer().zv() as EmacsInt)
}

/// Set point to POSITION, a number or marker.
/// Beginning of buffer is position (point-min), end is (point-max).
///
/// The return value is POSITION.
#[lisp_fn]
pub fn goto_char(position: LispObject) -> LispObject {
if let Some(marker) = position.as_marker() {
set_point_from_marker(marker);
} else if let Some(num) = position.as_fixnum() {
let cur_buf = ThreadState::current_buffer();
let pos = clip_to_bounds(cur_buf.begv, num, cur_buf.zv);
let bytepos = unsafe { buf_charpos_to_bytepos(cur_buf.as_ptr(), pos) };
unsafe { set_point_both(pos, bytepos) };
} else {
wrong_type!(Qinteger_or_marker_p, position)
};
position
}
14 changes: 14 additions & 0 deletions rust_src/src/frames.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Generic frame functions.

use remacs_macros::lisp_fn;
use remacs_sys::{Lisp_Frame, selected_frame as current_frame};
use lisp::{LispObject, ExternalPtr};

pub type LispFrameRef = ExternalPtr<Lisp_Frame>;


/// Return the frame that is now selected.
#[lisp_fn]
pub fn selected_frame() -> LispObject {
unsafe { LispObject::from_raw(current_frame) }
}
4 changes: 4 additions & 0 deletions rust_src/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ mod str2sig;
mod multibyte;
mod buffers;
mod windows;
mod frames;
mod hashtable;
mod interactive;
mod process;
Expand Down Expand Up @@ -164,6 +165,7 @@ pub use obarray::Fintern_soft;
pub use marker::Fmarker_position;
pub use marker::Fmarker_buffer;
pub use windows::Fwindow_point;
pub use editfns::Fgoto_char;
pub use data::Findirect_function;
pub use data::indirect_function;

Expand Down Expand Up @@ -402,10 +404,12 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*editfns::Smark_marker);
defsubr(&*editfns::Spoint_min);
defsubr(&*editfns::Spoint_max);
defsubr(&*editfns::Sgoto_char);
defsubr(&*minibuf::Sminibufferp);
defsubr(&*minibuf::Sactive_minibuffer_window);
defsubr(&*threads::Sthread_name);
defsubr(&*cmds::Sforward_point);
defsubr(&*data::Sindirect_function);
defsubr(&*frames::Sselected_frame);
}
}
23 changes: 22 additions & 1 deletion rust_src/src/lisp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use symbols::LispSymbolRef;
use vectors::LispVectorlikeRef;
use buffers::{LispBufferRef, LispOverlayRef};
use windows::LispWindowRef;
use frames::LispFrameRef;
use process::LispProcessRef;
use marker::LispMarkerRef;
use hashtable::LispHashTableRef;
Expand All @@ -31,7 +32,7 @@ use remacs_sys::{EmacsInt, EmacsUint, EmacsDouble, VALMASK, VALBITS, INTTYPEBITS
Qnumberp, Qfloatp, Qstringp, Qsymbolp, Qnumber_or_marker_p, Qinteger_or_marker_p,
Qwholenump, Qvectorp, Qcharacterp, Qlistp, Qplistp, Qintegerp, Qhash_table_p,
Qchar_table_p, Qconsp, Qbufferp, Qmarkerp, Qoverlayp, Qwindowp, Qwindow_live_p,
Qprocessp, Qthreadp, SYMBOL_NAME, PseudovecType, EqualKind};
Qframep, Qprocessp, Qthreadp, SYMBOL_NAME, PseudovecType, EqualKind};

#[cfg(test)]
use functions::ExternCMocks;
Expand Down Expand Up @@ -226,6 +227,16 @@ impl<T> DerefMut for ExternalPtr<T> {
}
}

impl<T> PartialEq for ExternalPtr<T> {
fn eq(&self, other: &ExternalPtr<T>) -> bool {
self.as_ptr() == other.as_ptr()
}

fn ne(&self, other: &ExternalPtr<T>) -> bool {
self.as_ptr() != other.as_ptr()
}
}

pub type LispMiscRef = ExternalPtr<Lisp_Misc_Any>;

#[test]
Expand Down Expand Up @@ -553,6 +564,16 @@ impl LispObject {
})
}

pub fn as_frame(self) -> Option<LispFrameRef> {
self.as_vectorlike().map_or(None, |v| v.as_frame())
}

pub fn as_frame_or_error(self) -> LispFrameRef {
self.as_frame().unwrap_or_else(
|| wrong_type!(Qframep, self),
)
}

pub fn is_hash_table(self) -> bool {
self.as_vectorlike().map_or(false, |v| {
v.is_pseudovector(PseudovecType::PVEC_HASH_TABLE)
Expand Down
31 changes: 30 additions & 1 deletion rust_src/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::mem;

use remacs_sys::make_lisp_ptr;
use lisp::{LispObject, ExternalPtr};
use remacs_sys::{Lisp_Marker, EmacsInt, Lisp_Type};
use remacs_sys::{buf_charpos_to_bytepos, set_point_both, EmacsInt, Lisp_Marker, Lisp_Type};
use remacs_macros::lisp_fn;
use util::clip_to_bounds;
use threads::ThreadState;

use buffers::LispBufferRef;

Expand All @@ -28,6 +30,14 @@ impl LispMarkerRef {
self.charpos
}

pub fn bytepos_or_error(self) -> ptrdiff_t {
if self.buffer.is_null() {
error!("Marker does not point anywhere");
} else {
self.bytepos
}
}

pub fn buffer(self) -> Option<LispBufferRef> {
let buf = self.buffer;
if buf.is_null() {
Expand Down Expand Up @@ -70,3 +80,22 @@ pub fn marker_buffer(marker: LispObject) -> LispObject {
None => LispObject::constant_nil(),
}
}

/// Set PT from MARKER's clipped position.
pub fn set_point_from_marker(marker: LispMarkerRef) {
let cur_buf = ThreadState::current_buffer();
let charpos = clip_to_bounds(
cur_buf.begv,
marker.charpos_or_error() as EmacsInt,
cur_buf.zv,
);
let mut bytepos = marker.bytepos_or_error();
// Don't trust the byte position if the marker belongs to a
// different buffer.
if marker.buffer().map_or(false, |b| b != cur_buf) {
bytepos = unsafe { buf_charpos_to_bytepos(cur_buf.as_ptr(), charpos) };
} else {
bytepos = clip_to_bounds(cur_buf.begv_byte, bytepos as EmacsInt, cur_buf.zv_byte);
};
unsafe { set_point_both(charpos, bytepos) };
}
10 changes: 10 additions & 0 deletions rust_src/src/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use multibyte::MAX_CHAR;
use lists::{sort_list, inorder, nthcdr, car};
use buffers::LispBufferRef;
use windows::LispWindowRef;
use frames::LispFrameRef;
use process::LispProcessRef;
use chartable::LispCharTableRef;
use threads::ThreadStateRef;
Expand Down Expand Up @@ -77,6 +78,15 @@ impl LispVectorlikeRef {
}
}

#[inline]
pub fn as_frame(&self) -> Option<LispFrameRef> {
if self.is_pseudovector(PseudovecType::PVEC_FRAME) {
Some(unsafe { mem::transmute(*self) })
} else {
None
}
}

#[inline]
pub fn as_process(&self) -> Option<LispProcessRef> {
if self.is_pseudovector(PseudovecType::PVEC_PROCESS) {
Expand Down
18 changes: 0 additions & 18 deletions src/editfns.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,23 +369,6 @@ DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
{
return build_marker (current_buffer, PT, PT_BYTE);
}

DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
doc: /* Set point to POSITION, a number or marker.
Beginning of buffer is position (point-min), end is (point-max).

The return value is POSITION. */)
(register Lisp_Object position)
{
if (MARKERP (position))
set_point_from_marker (position);
else if (INTEGERP (position))
SET_PT (clip_to_bounds (BEGV, XINT (position), ZV));
else
wrong_type_argument (Qinteger_or_marker_p, position);
return position;
}


/* Find all the overlays in the current buffer that touch position POS.
Return the number found, and store them in a vector in VEC
Expand Down Expand Up @@ -5280,7 +5263,6 @@ functions if all the text being accessed has this property. */);

defsubr (&Spropertize);
defsubr (&Schar_equal);
defsubr (&Sgoto_char);
defsubr (&Sstring_to_char);
defsubr (&Schar_to_string);
defsubr (&Sbyte_to_string);
Expand Down
8 changes: 0 additions & 8 deletions src/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -1414,13 +1414,6 @@ to that frame. */)
call1 (intern ("handle-focus-in"), event);
return value;
}

DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
doc: /* Return the frame that is now selected. */)
(void)
{
return selected_frame;
}

DEFUN ("frame-list", Fframe_list, Sframe_list,
0, 0, 0,
Expand Down Expand Up @@ -5960,7 +5953,6 @@ Gtk+ tooltips are not used) and on Windows. */);
defsubr (&Smake_terminal_frame);
defsubr (&Shandle_switch_frame);
defsubr (&Sselect_frame);
defsubr (&Sselected_frame);
defsubr (&Sframe_list);
defsubr (&Sframe_parent);
defsubr (&Sframe_ancestor_p);
Expand Down