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 4 commits into from Oct 12, 2017
Changes from all commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.


Just for now

@@ -809,6 +809,98 @@ pub struct Lisp_Process {
// TODO: this struct is incomplete.

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.

pub struct hash_table_test {
pub name: Lisp_Object,
@@ -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;
@@ -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;
@@ -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.
@@ -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,
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).
@@ -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.
pub fn goto_char(position: LispObject) -> LispObject {
if let Some(marker) = position.as_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)
@@ -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.
pub fn selected_frame() -> LispObject {
unsafe { LispObject::from_raw(current_frame) }
@@ -52,6 +52,7 @@ mod str2sig;
mod multibyte;
mod buffers;
mod windows;
mod frames;
mod hashtable;
mod interactive;
mod process;
@@ -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;

@@ -402,10 +404,12 @@ pub extern "C" fn rust_init_syms() {
@@ -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;
@@ -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};

use functions::ExternCMocks;
@@ -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>;

@@ -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 {
|| wrong_type!(Qframep, self),

pub fn is_hash_table(self) -> bool {
self.as_vectorlike().map_or(false, |v| {
@@ -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;

@@ -28,6 +30,14 @@ impl LispMarkerRef {

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

pub fn buffer(self) -> Option<LispBufferRef> {
let buf = self.buffer;
if buf.is_null() {
@@ -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(
marker.charpos_or_error() as EmacsInt,
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) };
@@ -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;
@@ -77,6 +78,15 @@ impl LispVectorlikeRef {

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

pub fn as_process(&self) -> Option<LispProcessRef> {
if self.is_pseudovector(PseudovecType::PVEC_PROCESS) {
@@ -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));
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
@@ -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);
@@ -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. */)
return selected_frame;

DEFUN ("frame-list", Fframe_list, Sframe_list,
0, 0, 0,
@@ -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);
ProTip! Use n and p to navigate between commits in a pull request.