mirror of
https://github.com/neovim/neovim.git
synced 2026-07-16 06:10:39 +00:00
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
This commit is contained in:
114
src/nvim/CMakeLists.txt
Normal file
114
src/nvim/CMakeLists.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
include(CheckLibraryExists)
|
||||
|
||||
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/auto)
|
||||
set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/msgpack-gen.lua)
|
||||
file(GLOB API_HEADERS api/*.h)
|
||||
set(MSGPACK_RPC_HEADER ${PROJECT_SOURCE_DIR}/src/os/msgpack_rpc.h)
|
||||
set(MSGPACK_DISPATCH ${GENERATED_DIR}/msgpack_dispatch.c)
|
||||
|
||||
# Remove helpers.h from API_HEADERS since it doesn't contain public API
|
||||
# functions
|
||||
foreach(sfile ${API_HEADERS})
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
if(${f} MATCHES "^(helpers.h)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_ITEM API_HEADERS ${to_remove})
|
||||
set(to_remove)
|
||||
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR})
|
||||
|
||||
add_custom_command(OUTPUT ${MSGPACK_DISPATCH}
|
||||
COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${MSGPACK_DISPATCH}
|
||||
DEPENDS
|
||||
${API_HEADERS}
|
||||
${MSGPACK_RPC_HEADER}
|
||||
${DISPATCH_GENERATOR}
|
||||
)
|
||||
|
||||
file( GLOB NEOVIM_SOURCES *.c )
|
||||
|
||||
foreach(sfile ${NEOVIM_SOURCES})
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
if(${f} MATCHES "^(regexp_nfa.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove})
|
||||
list(APPEND NEOVIM_SOURCES "${PROJECT_BINARY_DIR}/config/auto/pathdef.c")
|
||||
list(APPEND NEOVIM_SOURCES "${MSGPACK_DISPATCH}")
|
||||
|
||||
file( GLOB OS_SOURCES os/*.c )
|
||||
file( GLOB API_SOURCES api/*.c )
|
||||
|
||||
set(CONV_SRCS
|
||||
api.c
|
||||
arabic.c
|
||||
garray.c
|
||||
memory.c
|
||||
os/env.c
|
||||
os/event.c
|
||||
os/job.c
|
||||
os/mem.c
|
||||
os/rstream.c
|
||||
os/signal.c
|
||||
os/users.c
|
||||
os/wstream.c
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${CONV_SRCS} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wconversion")
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
if(DEFINED ENV{SANITIZE})
|
||||
message(STATUS "Enabling the sanitizers")
|
||||
add_definitions(-DEXITFREE) # is this necessary for LeakSanitizer?
|
||||
add_definitions(-fno-sanitize-recover -fno-omit-frame-pointer
|
||||
-fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined)
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"-fsanitize=address -fsanitize=undefined ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS
|
||||
"-fsanitize=address -fsanitize=undefined ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Our dependencies come first.
|
||||
|
||||
if (LibIntl_FOUND)
|
||||
list(APPEND NVIM_LINK_LIBRARIES ${LibIntl_LIBRARY})
|
||||
endif()
|
||||
|
||||
check_library_exists(curses tgetent "" HAVE_LIBCURSES)
|
||||
if (HAVE_LIBCURSES)
|
||||
list(APPEND NVIM_LINK_LIBRARIES curses)
|
||||
else()
|
||||
check_library_exists(tinfo tgetent "" HAVE_LIBTINFO)
|
||||
if (HAVE_LIBTINFO)
|
||||
list(APPEND NVIM_LINK_LIBRARIES tinfo)
|
||||
else()
|
||||
find_package(Curses REQUIRED)
|
||||
list(APPEND NVIM_LINK_LIBRARIES ${CURSES_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Put these last on the link line, since multiple things may depend on them.
|
||||
list(APPEND NVIM_LINK_LIBRARIES
|
||||
${LIBUV_LIBRARIES}
|
||||
${MSGPACK_LIBRARIES}
|
||||
${LUAJIT_LIBRARIES}
|
||||
m
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
if(NOT DEFINED ENV{SKIP_EXEC})
|
||||
add_executable(nvim ${NEOVIM_SOURCES} ${OS_SOURCES} ${API_SOURCES})
|
||||
target_link_libraries(nvim ${NVIM_LINK_LIBRARIES})
|
||||
install(TARGETS nvim RUNTIME DESTINATION bin)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ENV{SKIP_UNITTEST})
|
||||
add_library(nvim-test MODULE EXCLUDE_FROM_ALL ${NEOVIM_SOURCES}
|
||||
${OS_SOURCES} ${API_SOURCES})
|
||||
target_link_libraries(nvim-test ${NVIM_LINK_LIBRARIES})
|
||||
endif()
|
||||
413
src/nvim/api/buffer.c
Normal file
413
src/nvim/api/buffer.c
Normal file
@@ -0,0 +1,413 @@
|
||||
// Much of this code was adapted from 'if_py_both.h' from the original
|
||||
// vim source
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/buffer.h"
|
||||
#include "api/helpers.h"
|
||||
#include "api/defs.h"
|
||||
#include "../vim.h"
|
||||
#include "../buffer.h"
|
||||
#include "memline.h"
|
||||
#include "memory.h"
|
||||
#include "misc1.h"
|
||||
#include "misc2.h"
|
||||
#include "ex_cmds.h"
|
||||
#include "mark.h"
|
||||
#include "fileio.h"
|
||||
#include "move.h"
|
||||
#include "../window.h"
|
||||
#include "undo.h"
|
||||
|
||||
// Find a window that contains "buf" and switch to it.
|
||||
// If there is no such window, use the current window and change "curbuf".
|
||||
// Caller must initialize save_curbuf to NULL.
|
||||
// restore_win_for_buf() MUST be called later!
|
||||
static void switch_to_win_for_buf(buf_T *buf,
|
||||
win_T **save_curwinp,
|
||||
tabpage_T **save_curtabp,
|
||||
buf_T **save_curbufp);
|
||||
|
||||
static void restore_win_for_buf(win_T *save_curwin,
|
||||
tabpage_T *save_curtab,
|
||||
buf_T *save_curbuf);
|
||||
|
||||
// Check if deleting lines made the cursor position invalid.
|
||||
// Changed the lines from "lo" to "hi" and added "extra" lines (negative if
|
||||
// deleted).
|
||||
static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra);
|
||||
|
||||
// Normalizes 0-based indexes to buffer line numbers
|
||||
static int64_t normalize_index(buf_T *buf, int64_t index);
|
||||
|
||||
int64_t buffer_get_length(Buffer buffer, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buf->b_ml.ml_line_count;
|
||||
}
|
||||
|
||||
String buffer_get_line(Buffer buffer, int64_t index, Error *err)
|
||||
{
|
||||
String rv = {.size = 0};
|
||||
StringArray slice = buffer_get_slice(buffer, index, index, true, true, err);
|
||||
|
||||
if (slice.size) {
|
||||
rv = slice.items[0];
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void buffer_set_line(Buffer buffer, int64_t index, String line, Error *err)
|
||||
{
|
||||
StringArray array = {.items = &line, .size = 1};
|
||||
buffer_set_slice(buffer, index, index, true, true, array, err);
|
||||
}
|
||||
|
||||
void buffer_del_line(Buffer buffer, int64_t index, Error *err)
|
||||
{
|
||||
StringArray array = {.size = 0};
|
||||
buffer_set_slice(buffer, index, index, true, true, array, err);
|
||||
}
|
||||
|
||||
StringArray buffer_get_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
Error *err)
|
||||
{
|
||||
StringArray rv = {.size = 0};
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
start = normalize_index(buf, start) + (include_start ? 0 : 1);
|
||||
end = normalize_index(buf, end) + (include_end ? 1 : 0);
|
||||
|
||||
if (start >= end) {
|
||||
// Return 0-length array
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv.size = end - start;
|
||||
rv.items = xmalloc(sizeof(String) * rv.size);
|
||||
|
||||
for (uint32_t i = 0; i < rv.size; i++) {
|
||||
rv.items[i].data = xstrdup((char *)ml_get_buf(buf, start + i, false));
|
||||
rv.items[i].size = strlen(rv.items[i].data);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void buffer_set_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
StringArray replacement,
|
||||
Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
start = normalize_index(buf, start) + (include_start ? 0 : 1);
|
||||
end = normalize_index(buf, end) + (include_end ? 1 : 0);
|
||||
|
||||
if (start > end) {
|
||||
set_api_error("start > end", err);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_T *save_curbuf = NULL;
|
||||
win_T *save_curwin = NULL;
|
||||
tabpage_T *save_curtab = NULL;
|
||||
uint32_t new_len = replacement.size;
|
||||
uint32_t old_len = end - start;
|
||||
uint32_t i;
|
||||
int32_t extra = 0; // lines added to text, can be negative
|
||||
char **lines;
|
||||
|
||||
if (new_len == 0) {
|
||||
// avoid allocating zero bytes
|
||||
lines = NULL;
|
||||
} else {
|
||||
lines = xcalloc(sizeof(char *), new_len);
|
||||
}
|
||||
|
||||
for (i = 0; i < new_len; i++) {
|
||||
String l = replacement.items[i];
|
||||
lines[i] = xstrndup(l.data, l.size);
|
||||
}
|
||||
|
||||
try_start();
|
||||
switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
|
||||
|
||||
if (u_save(start - 1, end) == FAIL) {
|
||||
set_api_error("Cannot save undo information", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// If the size of the range is reducing (ie, new_len < old_len) we
|
||||
// need to delete some old_len. We do this at the start, by
|
||||
// repeatedly deleting line "start".
|
||||
for (i = 0; new_len < old_len && i < old_len - new_len; i++) {
|
||||
if (ml_delete(start, false) == FAIL) {
|
||||
set_api_error("Cannot delete line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
extra -= i;
|
||||
|
||||
// For as long as possible, replace the existing old_len with the
|
||||
// new old_len. This is a more efficient operation, as it requires
|
||||
// less memory allocation and freeing.
|
||||
for (i = 0; i < old_len && i < new_len; i++) {
|
||||
if (ml_replace(start + i, (char_u *)lines[i], false) == FAIL) {
|
||||
set_api_error("Cannot replace line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
// Mark lines that haven't been passed to the buffer as they need
|
||||
// to be freed later
|
||||
lines[i] = NULL;
|
||||
}
|
||||
|
||||
// Now we may need to insert the remaining new old_len
|
||||
while (i < new_len) {
|
||||
if (ml_append(start + i - 1, (char_u *)lines[i], 0, false) == FAIL) {
|
||||
set_api_error("Cannot insert line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
// Same as with replacing
|
||||
lines[i] = NULL;
|
||||
i++;
|
||||
extra++;
|
||||
}
|
||||
|
||||
// Adjust marks. Invalidate any which lie in the
|
||||
// changed range, and move any in the remainder of the buffer.
|
||||
// Only adjust marks if we managed to switch to a window that holds
|
||||
// the buffer, otherwise line numbers will be invalid.
|
||||
if (save_curbuf == NULL) {
|
||||
mark_adjust(start, end - 1, MAXLNUM, extra);
|
||||
}
|
||||
|
||||
changed_lines(start, 0, end, extra);
|
||||
|
||||
if (buf == curbuf) {
|
||||
fix_cursor(start, end, extra);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (uint32_t i = 0; i < new_len; i++) {
|
||||
if (lines[i] != NULL) {
|
||||
free(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(lines);
|
||||
restore_win_for_buf(save_curwin, save_curtab, save_curbuf);
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
Object buffer_get_var(Buffer buffer, String name, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_get_value(buf->b_vars, name, err);
|
||||
}
|
||||
|
||||
Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_set_value(buf->b_vars, name, value, err);
|
||||
}
|
||||
|
||||
Object buffer_get_option(Buffer buffer, String name, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return get_option_from(buf, SREQ_BUF, name, err);
|
||||
}
|
||||
|
||||
void buffer_set_option(Buffer buffer, String name, Object value, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_option_to(buf, SREQ_BUF, name, value, err);
|
||||
}
|
||||
|
||||
String buffer_get_name(Buffer buffer, Error *err)
|
||||
{
|
||||
String rv = {.size = 0, .data = ""};
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf || buf->b_ffname == NULL) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv.data = xstrdup((char *)buf->b_ffname);
|
||||
rv.size = strlen(rv.data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void buffer_set_name(Buffer buffer, String name, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
aco_save_T aco;
|
||||
int ren_ret;
|
||||
char *val = xstrndup(name.data, name.size);
|
||||
|
||||
try_start();
|
||||
// Using aucmd_*: autocommands will be executed by rename_buffer
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
ren_ret = rename_buffer((char_u *)val);
|
||||
aucmd_restbuf(&aco);
|
||||
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ren_ret == FAIL) {
|
||||
set_api_error("failed to rename buffer", err);
|
||||
}
|
||||
}
|
||||
|
||||
bool buffer_is_valid(Buffer buffer)
|
||||
{
|
||||
Error stub = {.set = false};
|
||||
return find_buffer(buffer, &stub) != NULL;
|
||||
}
|
||||
|
||||
void buffer_insert(Buffer buffer, int64_t index, StringArray lines, Error *err)
|
||||
{
|
||||
buffer_set_slice(buffer, index, index, false, true, lines, err);
|
||||
}
|
||||
|
||||
Position buffer_get_mark(Buffer buffer, String name, Error *err)
|
||||
{
|
||||
Position rv;
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (name.size != 0) {
|
||||
set_api_error("mark name must be a single character", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
pos_T *posp;
|
||||
buf_T *savebuf;
|
||||
char mark = *name.data;
|
||||
|
||||
try_start();
|
||||
switch_buffer(&savebuf, buf);
|
||||
posp = getmark(mark, false);
|
||||
restore_buffer(savebuf);
|
||||
|
||||
if (try_end(err)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (posp == NULL) {
|
||||
set_api_error("invalid mark name", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv.row = posp->lnum;
|
||||
rv.col = posp->col;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void switch_to_win_for_buf(buf_T *buf,
|
||||
win_T **save_curwinp,
|
||||
tabpage_T **save_curtabp,
|
||||
buf_T **save_curbufp)
|
||||
{
|
||||
win_T *wp;
|
||||
tabpage_T *tp;
|
||||
|
||||
if (find_win_for_buf(buf, &wp, &tp) == FAIL
|
||||
|| switch_win(save_curwinp, save_curtabp, wp, tp, true) == FAIL)
|
||||
switch_buffer(save_curbufp, buf);
|
||||
}
|
||||
|
||||
static void restore_win_for_buf(win_T *save_curwin,
|
||||
tabpage_T *save_curtab,
|
||||
buf_T *save_curbuf)
|
||||
{
|
||||
if (save_curbuf == NULL) {
|
||||
restore_win(save_curwin, save_curtab, true);
|
||||
} else {
|
||||
restore_buffer(save_curbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
|
||||
{
|
||||
if (curwin->w_cursor.lnum >= lo) {
|
||||
// Adjust the cursor position if it's in/after the changed
|
||||
// lines.
|
||||
if (curwin->w_cursor.lnum >= hi) {
|
||||
curwin->w_cursor.lnum += extra;
|
||||
check_cursor_col();
|
||||
} else if (extra < 0) {
|
||||
curwin->w_cursor.lnum = lo;
|
||||
check_cursor();
|
||||
} else {
|
||||
check_cursor_col();
|
||||
}
|
||||
changed_cline_bef_curs();
|
||||
}
|
||||
invalidate_botline();
|
||||
}
|
||||
|
||||
static int64_t normalize_index(buf_T *buf, int64_t index)
|
||||
{
|
||||
// Fix if < 0
|
||||
index = index < 0 ? buf->b_ml.ml_line_count + index : index;
|
||||
// Convert the index to a vim line number
|
||||
index++;
|
||||
// Fix if > line_count
|
||||
index = index > buf->b_ml.ml_line_count ? buf->b_ml.ml_line_count : index;
|
||||
return index;
|
||||
}
|
||||
145
src/nvim/api/buffer.h
Normal file
145
src/nvim/api/buffer.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef NEOVIM_API_BUFFER_H
|
||||
#define NEOVIM_API_BUFFER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "api/defs.h"
|
||||
|
||||
/// Gets the buffer line count
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The line count
|
||||
int64_t buffer_get_length(Buffer buffer, Error *err);
|
||||
|
||||
/// Gets a buffer line
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param index The line index
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The line string
|
||||
String buffer_get_line(Buffer buffer, int64_t index, Error *err);
|
||||
|
||||
/// Sets a buffer line
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param index The line index
|
||||
/// @param line The new line.
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_set_line(Buffer buffer, int64_t index, String line, Error *err);
|
||||
|
||||
/// Deletes a buffer line
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param index The line index
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_del_line(Buffer buffer, int64_t index, Error *err);
|
||||
|
||||
/// Retrieves a line range from the buffer
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param start The first line index
|
||||
/// @param end The last line index
|
||||
/// @param include_start True if the slice includes the `start` parameter
|
||||
/// @param include_end True if the slice includes the `end` parameter
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return An array of lines
|
||||
StringArray buffer_get_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
Error *err);
|
||||
|
||||
/// Replaces a line range on the buffer
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param start The first line index
|
||||
/// @param end The last line index
|
||||
/// @param include_start True if the slice includes the `start` parameter
|
||||
/// @param include_end True if the slice includes the `end` parameter
|
||||
/// @param lines An array of lines to use as replacement(A 0-length array
|
||||
/// will simply delete the line range)
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_set_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
StringArray replacement,
|
||||
Error *err);
|
||||
|
||||
/// Gets a buffer variable
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The variable value
|
||||
Object buffer_get_var(Buffer buffer, String name, Error *err);
|
||||
|
||||
/// Sets a buffer variable. Passing 'nil' as value deletes the variable.
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value
|
||||
Object buffer_set_var(Buffer buffer, String name, Object value, Error *err);
|
||||
|
||||
/// Gets a buffer option value
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The option name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The option value
|
||||
Object buffer_get_option(Buffer buffer, String name, Error *err);
|
||||
|
||||
/// Sets a buffer option value. Passing 'nil' as value deletes the option(only
|
||||
/// works if there's a global fallback)
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The option name
|
||||
/// @param value The option value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_set_option(Buffer buffer, String name, Object value, Error *err);
|
||||
|
||||
/// Gets the full file name for the buffer
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The buffer name
|
||||
String buffer_get_name(Buffer buffer, Error *err);
|
||||
|
||||
/// Sets the full file name for a buffer
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The buffer name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_set_name(Buffer buffer, String name, Error *err);
|
||||
|
||||
/// Checks if a buffer is valid
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @return true if the buffer is valid, false otherwise
|
||||
bool buffer_is_valid(Buffer buffer);
|
||||
|
||||
/// Inserts a sequence of lines to a buffer at a certain index
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param lnum Insert the lines before `lnum`. If negative, it will append
|
||||
/// to the end of the buffer.
|
||||
/// @param lines An array of lines
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_insert(Buffer buffer, int64_t index, StringArray lines, Error *err);
|
||||
|
||||
/// Return a tuple (row,col) representing the position of the named mark
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The mark's name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The (row, col) tuple
|
||||
Position buffer_get_mark(Buffer buffer, String name, Error *err);
|
||||
|
||||
#endif // NEOVIM_API_BUFFER_H
|
||||
|
||||
74
src/nvim/api/defs.h
Normal file
74
src/nvim/api/defs.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef NEOVIM_API_DEFS_H
|
||||
#define NEOVIM_API_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Basic types
|
||||
typedef struct {
|
||||
char msg[256];
|
||||
bool set;
|
||||
} Error;
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
size_t size;
|
||||
} String;
|
||||
|
||||
typedef uint16_t Buffer;
|
||||
typedef uint16_t Window;
|
||||
typedef uint16_t Tabpage;
|
||||
|
||||
typedef struct object Object;
|
||||
|
||||
typedef struct {
|
||||
String *items;
|
||||
size_t size;
|
||||
} StringArray;
|
||||
|
||||
typedef struct {
|
||||
uint16_t row, col;
|
||||
} Position;
|
||||
|
||||
typedef struct {
|
||||
Object *items;
|
||||
size_t size;
|
||||
} Array;
|
||||
|
||||
typedef struct key_value_pair KeyValuePair;
|
||||
|
||||
typedef struct {
|
||||
KeyValuePair *items;
|
||||
size_t size;
|
||||
} Dictionary;
|
||||
|
||||
typedef enum {
|
||||
kObjectTypeNil,
|
||||
kObjectTypeBool,
|
||||
kObjectTypeInt,
|
||||
kObjectTypeFloat,
|
||||
kObjectTypeString,
|
||||
kObjectTypeArray,
|
||||
kObjectTypeDictionary
|
||||
} ObjectType;
|
||||
|
||||
struct object {
|
||||
ObjectType type;
|
||||
union {
|
||||
bool boolean;
|
||||
int64_t integer;
|
||||
double floating_point;
|
||||
String string;
|
||||
Array array;
|
||||
Dictionary dictionary;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct key_value_pair {
|
||||
String key;
|
||||
Object value;
|
||||
};
|
||||
|
||||
|
||||
#endif // NEOVIM_API_DEFS_H
|
||||
|
||||
578
src/nvim/api/helpers.c
Normal file
578
src/nvim/api/helpers.c
Normal file
@@ -0,0 +1,578 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "api/helpers.h"
|
||||
#include "api/defs.h"
|
||||
#include "../vim.h"
|
||||
#include "../buffer.h"
|
||||
#include "../window.h"
|
||||
#include "memory.h"
|
||||
#include "eval.h"
|
||||
#include "option.h"
|
||||
#include "option_defs.h"
|
||||
|
||||
#include "lib/khash.h"
|
||||
|
||||
#if defined(ARCH_64)
|
||||
typedef uint64_t ptr_int_t;
|
||||
KHASH_SET_INIT_INT64(Lookup)
|
||||
#elif defined(ARCH_32)
|
||||
typedef uint32_t ptr_int_t;
|
||||
KHASH_SET_INIT_INT(Lookup)
|
||||
#endif
|
||||
|
||||
/// Recursion helper for the `vim_to_object`. This uses a pointer table
|
||||
/// to avoid infinite recursion due to cyclic references
|
||||
///
|
||||
/// @param obj The source object
|
||||
/// @param lookup Lookup table containing pointers to all processed objects
|
||||
/// @return The converted value
|
||||
static Object vim_to_object_rec(typval_T *obj, khash_t(Lookup) *lookup);
|
||||
|
||||
static bool object_to_vim(Object obj, typval_T *tv, Error *err);
|
||||
|
||||
static void set_option_value_for(char *key,
|
||||
int numval,
|
||||
char *stringval,
|
||||
int opt_flags,
|
||||
int opt_type,
|
||||
void *from,
|
||||
Error *err);
|
||||
|
||||
static void set_option_value_err(char *key,
|
||||
int numval,
|
||||
char *stringval,
|
||||
int opt_flags,
|
||||
Error *err);
|
||||
|
||||
void try_start()
|
||||
{
|
||||
++trylevel;
|
||||
}
|
||||
|
||||
bool try_end(Error *err)
|
||||
{
|
||||
--trylevel;
|
||||
|
||||
// Without this it stops processing all subsequent VimL commands and
|
||||
// generates strange error messages if I e.g. try calling Test() in a
|
||||
// cycle
|
||||
did_emsg = false;
|
||||
|
||||
if (got_int) {
|
||||
if (did_throw) {
|
||||
// If we got an interrupt, discard the current exception
|
||||
discard_current_exception();
|
||||
}
|
||||
|
||||
set_api_error("Keyboard interrupt", err);
|
||||
got_int = false;
|
||||
} else if (msg_list != NULL && *msg_list != NULL) {
|
||||
int should_free;
|
||||
char *msg = (char *)get_exception_string(*msg_list,
|
||||
ET_ERROR,
|
||||
NULL,
|
||||
&should_free);
|
||||
strncpy(err->msg, msg, sizeof(err->msg));
|
||||
err->set = true;
|
||||
free_global_msglist();
|
||||
|
||||
if (should_free) {
|
||||
free(msg);
|
||||
}
|
||||
} else if (did_throw) {
|
||||
set_api_error((char *)current_exception->value, err);
|
||||
}
|
||||
|
||||
return err->set;
|
||||
}
|
||||
|
||||
Object dict_get_value(dict_T *dict, String key, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
hashitem_T *hi;
|
||||
dictitem_T *di;
|
||||
char *k = xstrndup(key.data, key.size);
|
||||
hi = hash_find(&dict->dv_hashtab, (uint8_t *)k);
|
||||
free(k);
|
||||
|
||||
if (HASHITEM_EMPTY(hi)) {
|
||||
set_api_error("Key not found", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
di = dict_lookup(hi);
|
||||
rv = vim_to_object(&di->di_tv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Object dict_set_value(dict_T *dict, String key, Object value, Error *err)
|
||||
{
|
||||
Object rv = {.type = kObjectTypeNil};
|
||||
|
||||
if (dict->dv_lock) {
|
||||
set_api_error("Dictionary is locked", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (key.size == 0) {
|
||||
set_api_error("Empty dictionary keys aren't allowed", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
dictitem_T *di = dict_find(dict, (uint8_t *)key.data, key.size);
|
||||
|
||||
if (value.type == kObjectTypeNil) {
|
||||
// Delete the key
|
||||
if (di == NULL) {
|
||||
// Doesn't exist, fail
|
||||
set_api_error("Key doesn't exist", err);
|
||||
} else {
|
||||
// Return the old value
|
||||
rv = vim_to_object(&di->di_tv);
|
||||
// Delete the entry
|
||||
hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
|
||||
hash_remove(&dict->dv_hashtab, hi);
|
||||
dictitem_free(di);
|
||||
}
|
||||
} else {
|
||||
// Update the key
|
||||
typval_T tv;
|
||||
|
||||
// Convert the object to a vimscript type in the temporary variable
|
||||
if (!object_to_vim(value, &tv, err)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (di == NULL) {
|
||||
// Need to create an entry
|
||||
char *k = xstrndup(key.data, key.size);
|
||||
di = dictitem_alloc((uint8_t *)k);
|
||||
free(k);
|
||||
dict_add(dict, di);
|
||||
} else {
|
||||
// Return the old value
|
||||
clear_tv(&di->di_tv);
|
||||
}
|
||||
|
||||
// Update the value
|
||||
copy_tv(&tv, &di->di_tv);
|
||||
// Clear the temporary variable
|
||||
clear_tv(&tv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Object get_option_from(void *from, int type, String name, Error *err)
|
||||
{
|
||||
Object rv = {.type = kObjectTypeNil};
|
||||
|
||||
if (name.size == 0) {
|
||||
set_api_error("Empty option name", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Return values
|
||||
int64_t numval;
|
||||
char *stringval = NULL;
|
||||
// copy the option name into 0-delimited string
|
||||
char *key = xstrndup(name.data, name.size);
|
||||
int flags = get_option_value_strict(key, &numval, &stringval, type, from);
|
||||
free(key);
|
||||
|
||||
if (!flags) {
|
||||
set_api_error("invalid option name", err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (flags & SOPT_BOOL) {
|
||||
rv.type = kObjectTypeBool;
|
||||
rv.data.boolean = numval ? true : false;
|
||||
} else if (flags & SOPT_NUM) {
|
||||
rv.type = kObjectTypeInt;
|
||||
rv.data.integer = numval;
|
||||
} else if (flags & SOPT_STRING) {
|
||||
if (stringval) {
|
||||
rv.type = kObjectTypeString;
|
||||
rv.data.string.data = stringval;
|
||||
rv.data.string.size = strlen(stringval);
|
||||
} else {
|
||||
set_api_error(N_("Unable to get option value"), err);
|
||||
}
|
||||
} else {
|
||||
set_api_error(N_("internal error: unknown option type"), err);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void set_option_to(void *to, int type, String name, Object value, Error *err)
|
||||
{
|
||||
if (name.size == 0) {
|
||||
set_api_error("Empty option name", err);
|
||||
return;
|
||||
}
|
||||
|
||||
char *key = xstrndup(name.data, name.size);
|
||||
int flags = get_option_value_strict(key, NULL, NULL, type, to);
|
||||
|
||||
if (flags == 0) {
|
||||
set_api_error("invalid option name", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (value.type == kObjectTypeNil) {
|
||||
if (type == SREQ_GLOBAL) {
|
||||
set_api_error("unable to unset option", err);
|
||||
goto cleanup;
|
||||
} else if (!(flags & SOPT_GLOBAL)) {
|
||||
set_api_error("cannot unset option that doesn't have a global value",
|
||||
err);
|
||||
goto cleanup;
|
||||
} else {
|
||||
unset_global_local_option(key, to);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
int opt_flags = (type ? OPT_LOCAL : OPT_GLOBAL);
|
||||
|
||||
if (flags & SOPT_BOOL) {
|
||||
if (value.type != kObjectTypeBool) {
|
||||
set_api_error("option requires a boolean value", err);
|
||||
goto cleanup;
|
||||
}
|
||||
bool val = value.data.boolean;
|
||||
set_option_value_for(key, val, NULL, opt_flags, type, to, err);
|
||||
|
||||
} else if (flags & SOPT_NUM) {
|
||||
if (value.type != kObjectTypeInt) {
|
||||
set_api_error("option requires an integer value", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
int val = value.data.integer;
|
||||
set_option_value_for(key, val, NULL, opt_flags, type, to, err);
|
||||
} else {
|
||||
if (value.type != kObjectTypeString) {
|
||||
set_api_error("option requires a string value", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
char *val = xstrndup(value.data.string.data, value.data.string.size);
|
||||
set_option_value_for(key, 0, val, opt_flags, type, to, err);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(key);
|
||||
}
|
||||
|
||||
Object vim_to_object(typval_T *obj)
|
||||
{
|
||||
Object rv;
|
||||
// We use a lookup table to break out of cyclic references
|
||||
khash_t(Lookup) *lookup = kh_init(Lookup);
|
||||
rv = vim_to_object_rec(obj, lookup);
|
||||
// Free the table
|
||||
kh_destroy(Lookup, lookup);
|
||||
return rv;
|
||||
}
|
||||
|
||||
buf_T *find_buffer(Buffer buffer, Error *err)
|
||||
{
|
||||
buf_T *buf = buflist_findnr(buffer);
|
||||
|
||||
if (buf == NULL) {
|
||||
set_api_error("Invalid buffer id", err);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
win_T * find_window(Window window, Error *err)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (!--window) {
|
||||
return wp;
|
||||
}
|
||||
}
|
||||
|
||||
set_api_error("Invalid window id", err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tabpage_T * find_tab(Tabpage tabpage, Error *err)
|
||||
{
|
||||
tabpage_T *rv = find_tabpage(tabpage);
|
||||
|
||||
if (!rv) {
|
||||
set_api_error("Invalid tabpage id", err);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
{
|
||||
tv->v_type = VAR_UNKNOWN;
|
||||
tv->v_lock = 0;
|
||||
|
||||
switch (obj.type) {
|
||||
case kObjectTypeNil:
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = 0;
|
||||
break;
|
||||
|
||||
case kObjectTypeBool:
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = obj.data.boolean;
|
||||
break;
|
||||
|
||||
case kObjectTypeInt:
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = obj.data.integer;
|
||||
break;
|
||||
|
||||
case kObjectTypeFloat:
|
||||
tv->v_type = VAR_FLOAT;
|
||||
tv->vval.v_float = obj.data.floating_point;
|
||||
break;
|
||||
|
||||
case kObjectTypeString:
|
||||
tv->v_type = VAR_STRING;
|
||||
tv->vval.v_string = (uint8_t *)xstrndup(obj.data.string.data,
|
||||
obj.data.string.size);
|
||||
break;
|
||||
|
||||
case kObjectTypeArray:
|
||||
tv->v_type = VAR_LIST;
|
||||
tv->vval.v_list = list_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.array.size; i++) {
|
||||
Object item = obj.data.array.items[i];
|
||||
listitem_T *li = listitem_alloc();
|
||||
|
||||
if (!object_to_vim(item, &li->li_tv, err)) {
|
||||
// cleanup
|
||||
listitem_free(li);
|
||||
list_free(tv->vval.v_list, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
list_append(tv->vval.v_list, li);
|
||||
}
|
||||
tv->vval.v_list->lv_refcount++;
|
||||
break;
|
||||
|
||||
case kObjectTypeDictionary:
|
||||
tv->v_type = VAR_DICT;
|
||||
tv->vval.v_dict = dict_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
|
||||
KeyValuePair item = obj.data.dictionary.items[i];
|
||||
String key = item.key;
|
||||
|
||||
if (key.size == 0) {
|
||||
set_api_error("Empty dictionary keys aren't allowed", err);
|
||||
// cleanup
|
||||
dict_free(tv->vval.v_dict, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *k = xstrndup(key.data, key.size);
|
||||
dictitem_T *di = dictitem_alloc((uint8_t *)k);
|
||||
free(k);
|
||||
|
||||
if (!object_to_vim(item.value, &di->di_tv, err)) {
|
||||
// cleanup
|
||||
dictitem_free(di);
|
||||
dict_free(tv->vval.v_dict, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
dict_add(tv->vval.v_dict, di);
|
||||
}
|
||||
tv->vval.v_dict->dv_refcount++;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static Object vim_to_object_rec(typval_T *obj, khash_t(Lookup) *lookup)
|
||||
{
|
||||
Object rv = {.type = kObjectTypeNil};
|
||||
|
||||
if (obj->v_type == VAR_LIST || obj->v_type == VAR_DICT) {
|
||||
int ret;
|
||||
// Container object, add it to the lookup table
|
||||
kh_put(Lookup, lookup, (ptr_int_t)obj, &ret);
|
||||
if (!ret) {
|
||||
// It's already present, meaning we alredy processed it so just return
|
||||
// nil instead.
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
switch (obj->v_type) {
|
||||
case VAR_STRING:
|
||||
if (obj->vval.v_string != NULL) {
|
||||
rv.type = kObjectTypeString;
|
||||
rv.data.string.data = xstrdup((char *)obj->vval.v_string);
|
||||
rv.data.string.size = strlen(rv.data.string.data);
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR_NUMBER:
|
||||
rv.type = kObjectTypeInt;
|
||||
rv.data.integer = obj->vval.v_number;
|
||||
break;
|
||||
|
||||
case VAR_FLOAT:
|
||||
rv.type = kObjectTypeFloat;
|
||||
rv.data.floating_point = obj->vval.v_float;
|
||||
break;
|
||||
|
||||
case VAR_LIST:
|
||||
{
|
||||
list_T *list = obj->vval.v_list;
|
||||
listitem_T *item;
|
||||
|
||||
if (list != NULL) {
|
||||
rv.type = kObjectTypeArray;
|
||||
rv.data.array.size = list->lv_len;
|
||||
rv.data.array.items = xmalloc(list->lv_len * sizeof(Object));
|
||||
|
||||
uint32_t i = 0;
|
||||
for (item = list->lv_first; item != NULL; item = item->li_next) {
|
||||
rv.data.array.items[i] = vim_to_object_rec(&item->li_tv, lookup);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR_DICT:
|
||||
{
|
||||
dict_T *dict = obj->vval.v_dict;
|
||||
hashtab_T *ht;
|
||||
uint64_t todo;
|
||||
hashitem_T *hi;
|
||||
dictitem_T *di;
|
||||
|
||||
if (dict != NULL) {
|
||||
ht = &obj->vval.v_dict->dv_hashtab;
|
||||
todo = ht->ht_used;
|
||||
rv.type = kObjectTypeDictionary;
|
||||
|
||||
// Count items
|
||||
rv.data.dictionary.size = 0;
|
||||
for (hi = ht->ht_array; todo > 0; ++hi) {
|
||||
if (!HASHITEM_EMPTY(hi)) {
|
||||
todo--;
|
||||
rv.data.dictionary.size++;
|
||||
}
|
||||
}
|
||||
|
||||
rv.data.dictionary.items =
|
||||
xmalloc(rv.data.dictionary.size * sizeof(KeyValuePair));
|
||||
todo = ht->ht_used;
|
||||
uint32_t i = 0;
|
||||
|
||||
// Convert all
|
||||
for (hi = ht->ht_array; todo > 0; ++hi) {
|
||||
if (!HASHITEM_EMPTY(hi)) {
|
||||
di = dict_lookup(hi);
|
||||
// Convert key
|
||||
rv.data.dictionary.items[i].key.data =
|
||||
xstrdup((char *)hi->hi_key);
|
||||
rv.data.dictionary.items[i].key.size =
|
||||
strlen((char *)hi->hi_key);
|
||||
// Convert value
|
||||
rv.data.dictionary.items[i].value =
|
||||
vim_to_object_rec(&di->di_tv, lookup);
|
||||
todo--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static void set_option_value_for(char *key,
|
||||
int numval,
|
||||
char *stringval,
|
||||
int opt_flags,
|
||||
int opt_type,
|
||||
void *from,
|
||||
Error *err)
|
||||
{
|
||||
win_T *save_curwin = NULL;
|
||||
tabpage_T *save_curtab = NULL;
|
||||
buf_T *save_curbuf = NULL;
|
||||
|
||||
try_start();
|
||||
switch (opt_type)
|
||||
{
|
||||
case SREQ_WIN:
|
||||
if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
|
||||
win_find_tabpage((win_T *)from), false) == FAIL)
|
||||
{
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
set_api_error("problem while switching windows", err);
|
||||
return;
|
||||
}
|
||||
set_option_value_err(key, numval, stringval, opt_flags, err);
|
||||
restore_win(save_curwin, save_curtab, true);
|
||||
break;
|
||||
case SREQ_BUF:
|
||||
switch_buffer(&save_curbuf, (buf_T *)from);
|
||||
set_option_value_err(key, numval, stringval, opt_flags, err);
|
||||
restore_buffer(save_curbuf);
|
||||
break;
|
||||
case SREQ_GLOBAL:
|
||||
set_option_value_err(key, numval, stringval, opt_flags, err);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err->set) {
|
||||
return;
|
||||
}
|
||||
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
|
||||
static void set_option_value_err(char *key,
|
||||
int numval,
|
||||
char *stringval,
|
||||
int opt_flags,
|
||||
Error *err)
|
||||
{
|
||||
char *errmsg;
|
||||
|
||||
if ((errmsg = (char *)set_option_value((uint8_t *)key,
|
||||
numval,
|
||||
(uint8_t *)stringval,
|
||||
opt_flags)))
|
||||
{
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_api_error(errmsg, err);
|
||||
}
|
||||
}
|
||||
90
src/nvim/api/helpers.h
Normal file
90
src/nvim/api/helpers.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef NEOVIM_API_HELPERS_H
|
||||
#define NEOVIM_API_HELPERS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "api/defs.h"
|
||||
#include "../vim.h"
|
||||
|
||||
#define set_api_error(message, err) \
|
||||
do { \
|
||||
strncpy(err->msg, message, sizeof(err->msg)); \
|
||||
err->set = true; \
|
||||
} while (0)
|
||||
|
||||
/// Start block that may cause vimscript exceptions
|
||||
void try_start(void);
|
||||
|
||||
/// End try block, set the error message if any and return true if an error
|
||||
/// occurred.
|
||||
///
|
||||
/// @param err Pointer to the stack-allocated error object
|
||||
/// @return true if an error occurred
|
||||
bool try_end(Error *err);
|
||||
|
||||
/// Recursively expands a vimscript value in a dict
|
||||
///
|
||||
/// @param dict The vimscript dict
|
||||
/// @param key The key
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
Object dict_get_value(dict_T *dict, String key, Error *err);
|
||||
|
||||
/// Set a value in a dict. Objects are recursively expanded into their
|
||||
/// vimscript equivalents. Passing 'nil' as value deletes the key.
|
||||
///
|
||||
/// @param dict The vimscript dict
|
||||
/// @param key The key
|
||||
/// @param value The new value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the old value, if any
|
||||
Object dict_set_value(dict_T *dict, String key, Object value, Error *err);
|
||||
|
||||
/// Gets the value of a global or local(buffer, window) option.
|
||||
///
|
||||
/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
|
||||
/// to the window or buffer.
|
||||
/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
|
||||
/// @param name The option name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the option value
|
||||
Object get_option_from(void *from, int type, String name, Error *err);
|
||||
|
||||
/// Sets the value of a global or local(buffer, window) option.
|
||||
///
|
||||
/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
|
||||
/// to the window or buffer.
|
||||
/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
|
||||
/// @param name The option name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void set_option_to(void *to, int type, String name, Object value, Error *err);
|
||||
|
||||
/// Convert a vim object to an `Object` instance, recursively expanding
|
||||
/// Arrays/Dictionaries.
|
||||
///
|
||||
/// @param obj The source object
|
||||
/// @return The converted value
|
||||
Object vim_to_object(typval_T *obj);
|
||||
|
||||
/// Finds the pointer for a window number
|
||||
///
|
||||
/// @param window the window number
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the window pointer
|
||||
buf_T *find_buffer(Buffer buffer, Error *err);
|
||||
|
||||
/// Finds the pointer for a window number
|
||||
///
|
||||
/// @param window the window number
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the window pointer
|
||||
win_T * find_window(Window window, Error *err);
|
||||
|
||||
/// Finds the pointer for a tabpage number
|
||||
///
|
||||
/// @param tabpage the tabpage number
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the tabpage pointer
|
||||
tabpage_T * find_tab(Tabpage tabpage, Error *err);
|
||||
|
||||
#endif // NEOVIM_API_HELPERS_H
|
||||
|
||||
88
src/nvim/api/tabpage.c
Normal file
88
src/nvim/api/tabpage.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/tabpage.h"
|
||||
#include "api/vim.h"
|
||||
#include "api/defs.h"
|
||||
#include "api/helpers.h"
|
||||
|
||||
int64_t tabpage_get_window_count(Tabpage tabpage, Error *err)
|
||||
{
|
||||
uint64_t rv = 0;
|
||||
tabpage_T *tab = find_tab(tabpage, err);
|
||||
|
||||
if (!tab) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (tp != tab) {
|
||||
break;
|
||||
}
|
||||
rv++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Object tabpage_get_var(Tabpage tabpage, String name, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
tabpage_T *tab = find_tab(tabpage, err);
|
||||
|
||||
if (!tab) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_get_value(tab->tp_vars, name, err);
|
||||
}
|
||||
|
||||
Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
tabpage_T *tab = find_tab(tabpage, err);
|
||||
|
||||
if (!tab) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_set_value(tab->tp_vars, name, value, err);
|
||||
}
|
||||
|
||||
Window tabpage_get_window(Tabpage tabpage, Error *err)
|
||||
{
|
||||
Window rv = 0;
|
||||
tabpage_T *tab = find_tab(tabpage, err);
|
||||
|
||||
if (!tab) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (tab == curtab) {
|
||||
return vim_get_current_window();
|
||||
} else {
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
rv = 1;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (tp == tab && wp == tab->tp_curwin) {
|
||||
return rv;
|
||||
}
|
||||
rv++;
|
||||
}
|
||||
// There should always be a current window for a tabpage
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool tabpage_is_valid(Tabpage tabpage)
|
||||
{
|
||||
Error stub = {.set = false};
|
||||
return find_tab(tabpage, &stub) != NULL;
|
||||
}
|
||||
|
||||
47
src/nvim/api/tabpage.h
Normal file
47
src/nvim/api/tabpage.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef NEOVIM_API_TABPAGE_H
|
||||
#define NEOVIM_API_TABPAGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "api/defs.h"
|
||||
|
||||
/// Gets the number of windows in a tabpage
|
||||
///
|
||||
/// @param tabpage The tabpage
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The number of windows in `tabpage`
|
||||
int64_t tabpage_get_window_count(Tabpage tabpage, Error *err);
|
||||
|
||||
/// Gets a tabpage variable
|
||||
///
|
||||
/// @param tabpage The tab page handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The variable value
|
||||
Object tabpage_get_var(Tabpage tabpage, String name, Error *err);
|
||||
|
||||
/// Sets a tabpage variable. Passing 'nil' as value deletes the variable.
|
||||
///
|
||||
/// @param tabpage handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The tab page handle
|
||||
Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err);
|
||||
|
||||
/// Gets the current window in a tab page
|
||||
///
|
||||
/// @param tabpage The tab page handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The Window handle
|
||||
Window tabpage_get_window(Tabpage tabpage, Error *err);
|
||||
|
||||
/// Checks if a tab page is valid
|
||||
///
|
||||
/// @param tabpage The tab page handle
|
||||
/// @return true if the tab page is valid, false otherwise
|
||||
bool tabpage_is_valid(Tabpage tabpage);
|
||||
|
||||
#endif // NEOVIM_API_TABPAGE_H
|
||||
|
||||
321
src/nvim/api/vim.c
Normal file
321
src/nvim/api/vim.c
Normal file
@@ -0,0 +1,321 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "api/vim.h"
|
||||
#include "api/helpers.h"
|
||||
#include "api/defs.h"
|
||||
#include "api/buffer.h"
|
||||
#include "../vim.h"
|
||||
#include "../buffer.h"
|
||||
#include "../window.h"
|
||||
#include "types.h"
|
||||
#include "ascii.h"
|
||||
#include "ex_docmd.h"
|
||||
#include "screen.h"
|
||||
#include "memory.h"
|
||||
#include "message.h"
|
||||
#include "eval.h"
|
||||
#include "misc2.h"
|
||||
|
||||
#define LINE_BUFFER_SIZE 4096
|
||||
|
||||
/// Writes a message to vim output or error buffer. The string is split
|
||||
/// and flushed after each newline. Incomplete lines are kept for writing
|
||||
/// later.
|
||||
///
|
||||
/// @param message The message to write
|
||||
/// @param to_err True if it should be treated as an error message(use
|
||||
/// `emsg` instead of `msg` to print each line)
|
||||
static void write_msg(String message, bool to_err);
|
||||
|
||||
void vim_push_keys(String str)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void vim_command(String str, Error *err)
|
||||
{
|
||||
// We still use 0-terminated strings, so we must convert.
|
||||
char *cmd_str = xstrndup(str.data, str.size);
|
||||
// Run the command
|
||||
try_start();
|
||||
do_cmdline_cmd((char_u *)cmd_str);
|
||||
free(cmd_str);
|
||||
update_screen(VALID);
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
Object vim_eval(String str, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
char *expr_str = xstrndup(str.data, str.size);
|
||||
// Evaluate the expression
|
||||
try_start();
|
||||
typval_T *expr_result = eval_expr((char_u *)expr_str, NULL);
|
||||
free(expr_str);
|
||||
|
||||
if (!try_end(err)) {
|
||||
// No errors, convert the result
|
||||
rv = vim_to_object(expr_result);
|
||||
}
|
||||
|
||||
// Free the vim object
|
||||
free_tv(expr_result);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int64_t vim_strwidth(String str)
|
||||
{
|
||||
return mb_string2cells((char_u *)str.data, str.size);
|
||||
}
|
||||
|
||||
StringArray vim_list_runtime_paths(void)
|
||||
{
|
||||
StringArray rv = {.size = 0};
|
||||
uint8_t *rtp = p_rtp;
|
||||
|
||||
if (*rtp == NUL) {
|
||||
// No paths
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Count the number of paths in rtp
|
||||
while (*rtp != NUL) {
|
||||
if (*rtp == ',') {
|
||||
rv.size++;
|
||||
}
|
||||
rtp++;
|
||||
}
|
||||
|
||||
// index
|
||||
uint32_t i = 0;
|
||||
// Allocate memory for the copies
|
||||
rv.items = xmalloc(sizeof(String) * rv.size);
|
||||
// reset the position
|
||||
rtp = p_rtp;
|
||||
// Start copying
|
||||
while (*rtp != NUL) {
|
||||
rv.items[i].data = xmalloc(MAXPATHL);
|
||||
// Copy the path from 'runtimepath' to rv.items[i]
|
||||
rv.items[i].size = copy_option_part(&rtp,
|
||||
(char_u *)rv.items[i].data,
|
||||
MAXPATHL,
|
||||
",");
|
||||
i++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void vim_change_directory(String dir, Error *err)
|
||||
{
|
||||
char string[MAXPATHL];
|
||||
strncpy(string, dir.data, dir.size);
|
||||
|
||||
try_start();
|
||||
|
||||
if (vim_chdir((char_u *)string)) {
|
||||
if (!try_end(err)) {
|
||||
set_api_error("failed to change directory", err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
post_chdir(false);
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
String vim_get_current_line(Error *err)
|
||||
{
|
||||
return buffer_get_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, err);
|
||||
}
|
||||
|
||||
void vim_set_current_line(String line, Error *err)
|
||||
{
|
||||
buffer_set_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, line, err);
|
||||
}
|
||||
|
||||
void vim_del_current_line(Error *err)
|
||||
{
|
||||
buffer_del_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, err);
|
||||
}
|
||||
|
||||
Object vim_get_var(String name, Error *err)
|
||||
{
|
||||
return dict_get_value(&globvardict, name, err);
|
||||
}
|
||||
|
||||
Object vim_set_var(String name, Object value, Error *err)
|
||||
{
|
||||
return dict_set_value(&globvardict, name, value, err);
|
||||
}
|
||||
|
||||
Object vim_get_vvar(String name, Error *err)
|
||||
{
|
||||
return dict_get_value(&vimvardict, name, err);
|
||||
}
|
||||
|
||||
Object vim_get_option(String name, Error *err)
|
||||
{
|
||||
return get_option_from(NULL, SREQ_GLOBAL, name, err);
|
||||
}
|
||||
|
||||
void vim_set_option(String name, Object value, Error *err)
|
||||
{
|
||||
set_option_to(NULL, SREQ_GLOBAL, name, value, err);
|
||||
}
|
||||
|
||||
void vim_out_write(String str)
|
||||
{
|
||||
write_msg(str, false);
|
||||
}
|
||||
|
||||
void vim_err_write(String str)
|
||||
{
|
||||
write_msg(str, true);
|
||||
}
|
||||
|
||||
int64_t vim_get_buffer_count(void)
|
||||
{
|
||||
buf_T *b = firstbuf;
|
||||
uint64_t n = 0;
|
||||
|
||||
while (b) {
|
||||
n++;
|
||||
b = b->b_next;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
Buffer vim_get_current_buffer(void)
|
||||
{
|
||||
return curbuf->b_fnum;
|
||||
}
|
||||
|
||||
void vim_set_current_buffer(Buffer buffer, Error *err)
|
||||
{
|
||||
try_start();
|
||||
if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buffer, 0) == FAIL) {
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char msg[256];
|
||||
snprintf(msg, sizeof(msg), "failed to switch to buffer %d", (int)buffer);
|
||||
set_api_error(msg, err);
|
||||
return;
|
||||
}
|
||||
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
int64_t vim_get_window_count(void)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
uint64_t rv = 0;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
rv++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Window vim_get_current_window(void)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
Window rv = 1;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp == curwin) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv++;
|
||||
}
|
||||
|
||||
// There should always be a current window
|
||||
abort();
|
||||
}
|
||||
|
||||
void vim_set_current_window(Window window, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
try_start();
|
||||
win_goto(win);
|
||||
|
||||
if (win != curwin) {
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
set_api_error("did not switch to the specified window", err);
|
||||
return;
|
||||
}
|
||||
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
int64_t vim_get_tabpage_count(void)
|
||||
{
|
||||
tabpage_T *tp = first_tabpage;
|
||||
uint64_t rv = 0;
|
||||
|
||||
while (tp != NULL) {
|
||||
tp = tp->tp_next;
|
||||
rv++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Tabpage vim_get_current_tabpage(void)
|
||||
{
|
||||
Tabpage rv = 1;
|
||||
tabpage_T *t;
|
||||
|
||||
for (t = first_tabpage; t != NULL && t != curtab; t = t->tp_next) {
|
||||
rv++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void vim_set_current_tabpage(Tabpage tabpage, Error *err)
|
||||
{
|
||||
try_start();
|
||||
goto_tabpage(tabpage);
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
static void write_msg(String message, bool to_err)
|
||||
{
|
||||
static int pos = 0;
|
||||
static char line_buf[LINE_BUFFER_SIZE];
|
||||
|
||||
for (uint32_t i = 0; i < message.size; i++) {
|
||||
if (message.data[i] == NL || pos == LINE_BUFFER_SIZE - 1) {
|
||||
// Flush line
|
||||
line_buf[pos] = NUL;
|
||||
if (to_err) {
|
||||
emsg((uint8_t *)line_buf);
|
||||
} else {
|
||||
msg((uint8_t *)line_buf);
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
line_buf[pos++] = message.data[i];
|
||||
}
|
||||
}
|
||||
158
src/nvim/api/vim.h
Normal file
158
src/nvim/api/vim.h
Normal file
@@ -0,0 +1,158 @@
|
||||
#ifndef NEOVIM_API_VIM_H
|
||||
#define NEOVIM_API_VIM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "api/defs.h"
|
||||
|
||||
/// Send keys to vim input buffer, simulating user input.
|
||||
///
|
||||
/// @param str The keys to send
|
||||
void vim_push_keys(String str);
|
||||
|
||||
/// Executes an ex-mode command str
|
||||
///
|
||||
/// @param str The command str
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_command(String str, Error *err);
|
||||
|
||||
/// Evaluates the expression str using the vim internal expression
|
||||
/// evaluator (see |expression|).
|
||||
/// Dictionaries and lists are recursively expanded.
|
||||
///
|
||||
/// @param str The expression str
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The expanded object
|
||||
Object vim_eval(String str, Error *err);
|
||||
|
||||
/// Calculates the number of display cells `str` occupies, tab is counted as
|
||||
/// one cell.
|
||||
///
|
||||
/// @param str Some text
|
||||
/// @return The number of cells
|
||||
int64_t vim_strwidth(String str);
|
||||
|
||||
/// Returns a list of paths contained in 'runtimepath'
|
||||
///
|
||||
/// @return The list of paths
|
||||
StringArray vim_list_runtime_paths(void);
|
||||
|
||||
/// Changes vim working directory
|
||||
///
|
||||
/// @param dir The new working directory
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_change_directory(String dir, Error *err);
|
||||
|
||||
/// Return the current line
|
||||
///
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The current line string
|
||||
String vim_get_current_line(Error *err);
|
||||
|
||||
/// Delete the current line
|
||||
///
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_del_current_line(Error *err);
|
||||
|
||||
/// Sets the current line
|
||||
///
|
||||
/// @param line The line contents
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_set_current_line(String line, Error *err);
|
||||
|
||||
/// Gets a global variable
|
||||
///
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The variable value
|
||||
Object vim_get_var(String name, Error *err);
|
||||
|
||||
/// Sets a global variable. Passing 'nil' as value deletes the variable.
|
||||
///
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the old value if any
|
||||
Object vim_set_var(String name, Object value, Error *err);
|
||||
|
||||
/// Gets a vim variable
|
||||
///
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The variable value
|
||||
Object vim_get_vvar(String name, Error *err);
|
||||
|
||||
/// Get an option value string
|
||||
///
|
||||
/// @param name The option name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The option value
|
||||
Object vim_get_option(String name, Error *err);
|
||||
|
||||
/// Sets an option value
|
||||
///
|
||||
/// @param name The option name
|
||||
/// @param value The new option value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_set_option(String name, Object value, Error *err);
|
||||
|
||||
/// Write a message to vim output buffer
|
||||
///
|
||||
/// @param str The message
|
||||
void vim_out_write(String str);
|
||||
|
||||
/// Write a message to vim error buffer
|
||||
///
|
||||
/// @param str The message
|
||||
void vim_err_write(String str);
|
||||
|
||||
/// Gets the number of buffers
|
||||
///
|
||||
/// @return The number of buffers
|
||||
int64_t vim_get_buffer_count(void);
|
||||
|
||||
/// Return the current buffer
|
||||
///
|
||||
/// @reqturn The buffer handle
|
||||
Buffer vim_get_current_buffer(void);
|
||||
|
||||
/// Sets the current buffer
|
||||
///
|
||||
/// @param id The buffer handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_set_current_buffer(Buffer buffer, Error *err);
|
||||
|
||||
/// Gets the number of windows
|
||||
///
|
||||
/// @return The number of windows
|
||||
int64_t vim_get_window_count(void);
|
||||
|
||||
/// Return the current window
|
||||
///
|
||||
/// @return The window handle
|
||||
Window vim_get_current_window(void);
|
||||
|
||||
/// Sets the current window
|
||||
///
|
||||
/// @param handle The window handle
|
||||
void vim_set_current_window(Window window, Error *err);
|
||||
|
||||
/// Gets the number of tab pages
|
||||
///
|
||||
/// @return The number of tab pages
|
||||
int64_t vim_get_tabpage_count(void);
|
||||
|
||||
/// Return the current tab page
|
||||
///
|
||||
/// @return The tab page handle
|
||||
Tabpage vim_get_current_tabpage(void);
|
||||
|
||||
/// Sets the current tab page
|
||||
///
|
||||
/// @param handle The tab page handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void vim_set_current_tabpage(Tabpage tabpage, Error *err);
|
||||
|
||||
#endif // NEOVIM_API_VIM_H
|
||||
|
||||
184
src/nvim/api/window.c
Normal file
184
src/nvim/api/window.c
Normal file
@@ -0,0 +1,184 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/window.h"
|
||||
#include "api/defs.h"
|
||||
#include "api/helpers.h"
|
||||
#include "../vim.h"
|
||||
#include "../window.h"
|
||||
#include "screen.h"
|
||||
#include "misc2.h"
|
||||
|
||||
|
||||
Buffer window_get_buffer(Window window, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return win->w_buffer->b_fnum;
|
||||
}
|
||||
|
||||
Position window_get_cursor(Window window, Error *err)
|
||||
{
|
||||
Position rv = {.row = 0, .col = 0};
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (win) {
|
||||
rv.row = win->w_cursor.lnum;
|
||||
rv.col = win->w_cursor.col;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void window_set_cursor(Window window, Position pos, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos.row <= 0 || pos.row > win->w_buffer->b_ml.ml_line_count) {
|
||||
set_api_error("cursor position outside buffer", err);
|
||||
return;
|
||||
}
|
||||
|
||||
win->w_cursor.lnum = pos.row;
|
||||
win->w_cursor.col = pos.col;
|
||||
win->w_cursor.coladd = 0;
|
||||
// When column is out of range silently correct it.
|
||||
check_cursor_col_win(win);
|
||||
update_screen(VALID);
|
||||
}
|
||||
|
||||
int64_t window_get_height(Window window, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return win->w_height;
|
||||
}
|
||||
|
||||
void window_set_height(Window window, int64_t height, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
win_T *savewin = curwin;
|
||||
curwin = win;
|
||||
try_start();
|
||||
win_setheight(height);
|
||||
curwin = savewin;
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
int64_t window_get_width(Window window, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return win->w_width;
|
||||
}
|
||||
|
||||
void window_set_width(Window window, int64_t width, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
win_T *savewin = curwin;
|
||||
curwin = win;
|
||||
try_start();
|
||||
win_setwidth(width);
|
||||
curwin = savewin;
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
Object window_get_var(Window window, String name, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_get_value(win->w_vars, name, err);
|
||||
}
|
||||
|
||||
Object window_set_var(Window window, String name, Object value, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return dict_set_value(win->w_vars, name, value, err);
|
||||
}
|
||||
|
||||
Object window_get_option(Window window, String name, Error *err)
|
||||
{
|
||||
Object rv;
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return get_option_from(win, SREQ_WIN, name, err);
|
||||
}
|
||||
|
||||
void window_set_option(Window window, String name, Object value, Error *err)
|
||||
{
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_option_to(win, SREQ_WIN, name, value, err);
|
||||
}
|
||||
|
||||
Position window_get_position(Window window, Error *err)
|
||||
{
|
||||
Position rv;
|
||||
win_T *win = find_window(window, err);
|
||||
|
||||
if (win) {
|
||||
rv.col = win->w_wincol;
|
||||
rv.row = win->w_winrow;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Tabpage window_get_tabpage(Window window, Error *err)
|
||||
{
|
||||
set_api_error("Not implemented", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool window_is_valid(Window window)
|
||||
{
|
||||
Error stub = {.set = false};
|
||||
return find_window(window, &stub) != NULL;
|
||||
}
|
||||
|
||||
115
src/nvim/api/window.h
Normal file
115
src/nvim/api/window.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef NEOVIM_API_WINDOW_H
|
||||
#define NEOVIM_API_WINDOW_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "api/defs.h"
|
||||
|
||||
/// Gets the current buffer in a window
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The buffer handle
|
||||
Buffer window_get_buffer(Window window, Error *err);
|
||||
|
||||
/// Gets the cursor position in the window
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the (row, col) tuple
|
||||
Position window_get_cursor(Window window, Error *err);
|
||||
|
||||
/// Sets the cursor position in the window
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param pos the (row, col) tuple representing the new position
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void window_set_cursor(Window window, Position pos, Error *err);
|
||||
|
||||
/// Gets the window height
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the height in rows
|
||||
int64_t window_get_height(Window window, Error *err);
|
||||
|
||||
/// Sets the window height. This will only succeed if the screen is split
|
||||
/// horizontally.
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param height the new height in rows
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void window_set_height(Window window, int64_t height, Error *err);
|
||||
|
||||
/// Gets the window width
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the width in columns
|
||||
int64_t window_get_width(Window window, Error *err);
|
||||
|
||||
/// Sets the window width. This will only succeed if the screen is split
|
||||
/// vertically.
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param width the new width in columns
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void window_set_width(Window window, int64_t width, Error *err);
|
||||
|
||||
/// Gets a window variable
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The variable value
|
||||
Object window_get_var(Window window, String name, Error *err);
|
||||
|
||||
/// Sets a window variable. Passing 'nil' as value deletes the variable.
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value
|
||||
Object window_set_var(Window window, String name, Object value, Error *err);
|
||||
|
||||
/// Gets a window option value
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The option name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The option value
|
||||
Object window_get_option(Window window, String name, Error *err);
|
||||
|
||||
/// Sets a window option value. Passing 'nil' as value deletes the option(only
|
||||
/// works if there's a global fallback)
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The option name
|
||||
/// @param value The option value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void window_set_option(Window window, String name, Object value, Error *err);
|
||||
|
||||
/// Gets the window position in display cells. First position is zero.
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The (row, col) tuple with the window position
|
||||
Position window_get_position(Window window, Error *err);
|
||||
|
||||
/// Gets the window tab page
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The tab page that contains the window
|
||||
Tabpage window_get_tabpage(Window window, Error *err);
|
||||
|
||||
/// Checks if a window is valid
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @return true if the window is valid, false otherwise
|
||||
bool window_is_valid(Window window);
|
||||
|
||||
#endif // NEOVIM_API_WINDOW_H
|
||||
|
||||
1532
src/nvim/arabic.c
Normal file
1532
src/nvim/arabic.c
Normal file
File diff suppressed because it is too large
Load Diff
16
src/nvim/arabic.h
Normal file
16
src/nvim/arabic.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef NEOVIM_ARABIC_H
|
||||
#define NEOVIM_ARABIC_H
|
||||
|
||||
/// Whether c belongs to the range of Arabic characters that might be shaped.
|
||||
static inline int arabic_char(int c)
|
||||
{
|
||||
// return c >= a_HAMZA && c <= a_MINI_ALEF;
|
||||
return c >= 0x0621 && c <= 0x0670;
|
||||
}
|
||||
|
||||
int arabic_shape(int c, int *ccp, int *c1p, int prev_c, int prev_c1,
|
||||
int next_c);
|
||||
int arabic_combine(int one, int two);
|
||||
int arabic_maycombine(int two);
|
||||
|
||||
#endif // NEOVIM_ARABIC_H
|
||||
97
src/nvim/ascii.h
Normal file
97
src/nvim/ascii.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* VIM - Vi IMproved by Bram Moolenaar
|
||||
*
|
||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||
*/
|
||||
|
||||
#ifndef NEOVIM_ASCII_H
|
||||
#define NEOVIM_ASCII_H
|
||||
|
||||
/*
|
||||
* Definitions of various common control characters.
|
||||
* For EBCDIC we have to use different values.
|
||||
*/
|
||||
|
||||
|
||||
/* IF_EB(ASCII_constant, EBCDIC_constant) */
|
||||
#define IF_EB(a, b) a
|
||||
|
||||
#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a')
|
||||
#define CharOrdLow(x) ((x) - 'a')
|
||||
#define CharOrdUp(x) ((x) - 'A')
|
||||
#define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a))
|
||||
|
||||
#define NUL '\000'
|
||||
#define BELL '\007'
|
||||
#define BS '\010'
|
||||
#define TAB '\011'
|
||||
#define NL '\012'
|
||||
#define NL_STR (char_u *)"\012"
|
||||
#define FF '\014'
|
||||
#define CAR '\015' /* CR is used by Mac OS X */
|
||||
#define ESC '\033'
|
||||
#define ESC_STR (char_u *)"\033"
|
||||
#define ESC_STR_nc "\033"
|
||||
#define DEL 0x7f
|
||||
#define DEL_STR (char_u *)"\177"
|
||||
#define CSI 0x9b /* Control Sequence Introducer */
|
||||
#define CSI_STR "\233"
|
||||
#define DCS 0x90 /* Device Control String */
|
||||
#define STERM 0x9c /* String Terminator */
|
||||
|
||||
#define POUND 0xA3
|
||||
|
||||
#define Ctrl_chr(x) (TOUPPER_ASC(x) ^ 0x40) /* '?' -> DEL, '@' -> ^@, etc. */
|
||||
#define Meta(x) ((x) | 0x80)
|
||||
|
||||
#define CTRL_F_STR "\006"
|
||||
#define CTRL_H_STR "\010"
|
||||
#define CTRL_V_STR "\026"
|
||||
|
||||
#define Ctrl_AT 0 /* @ */
|
||||
#define Ctrl_A 1
|
||||
#define Ctrl_B 2
|
||||
#define Ctrl_C 3
|
||||
#define Ctrl_D 4
|
||||
#define Ctrl_E 5
|
||||
#define Ctrl_F 6
|
||||
#define Ctrl_G 7
|
||||
#define Ctrl_H 8
|
||||
#define Ctrl_I 9
|
||||
#define Ctrl_J 10
|
||||
#define Ctrl_K 11
|
||||
#define Ctrl_L 12
|
||||
#define Ctrl_M 13
|
||||
#define Ctrl_N 14
|
||||
#define Ctrl_O 15
|
||||
#define Ctrl_P 16
|
||||
#define Ctrl_Q 17
|
||||
#define Ctrl_R 18
|
||||
#define Ctrl_S 19
|
||||
#define Ctrl_T 20
|
||||
#define Ctrl_U 21
|
||||
#define Ctrl_V 22
|
||||
#define Ctrl_W 23
|
||||
#define Ctrl_X 24
|
||||
#define Ctrl_Y 25
|
||||
#define Ctrl_Z 26
|
||||
/* CTRL- [ Left Square Bracket == ESC*/
|
||||
#define Ctrl_BSL 28 /* \ BackSLash */
|
||||
#define Ctrl_RSB 29 /* ] Right Square Bracket */
|
||||
#define Ctrl_HAT 30 /* ^ */
|
||||
#define Ctrl__ 31
|
||||
|
||||
|
||||
/*
|
||||
* Character that separates dir names in a path.
|
||||
*/
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
# define PATHSEP psepc
|
||||
# define PATHSEPSTR pseps
|
||||
#else
|
||||
# define PATHSEP '/'
|
||||
# define PATHSEPSTR "/"
|
||||
#endif
|
||||
|
||||
#endif /* NEOVIM_ASCII_H */
|
||||
622
src/nvim/blowfish.c
Normal file
622
src/nvim/blowfish.c
Normal file
@@ -0,0 +1,622 @@
|
||||
/*
|
||||
* VIM - Vi IMproved by Bram Moolenaar
|
||||
*
|
||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||
* See README.txt for an overview of the Vim source code.
|
||||
*
|
||||
* Blowfish encryption for Vim; in Blowfish cipher feedback mode.
|
||||
* Contributed by Mohsin Ahmed, http://www.cs.albany.edu/~mosh
|
||||
* Based on http://www.schneier.com/blowfish.html by Bruce Schneier.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "vim.h"
|
||||
#include "blowfish.h"
|
||||
#include "message.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))
|
||||
|
||||
#define BF_BLOCK 8
|
||||
#define BF_BLOCK_MASK 7
|
||||
#define BF_CFB_LEN (8 * (BF_BLOCK))
|
||||
|
||||
typedef union {
|
||||
uint32_t ul[2];
|
||||
char_u uc[8];
|
||||
} block8;
|
||||
|
||||
|
||||
static void bf_e_block(uint32_t *p_xl, uint32_t *p_xr);
|
||||
static void bf_e_cblock(char_u *block);
|
||||
static int bf_check_tables(uint32_t a_ipa[18], uint32_t a_sbi[4][256],
|
||||
uint32_t val);
|
||||
static int bf_self_test(void);
|
||||
|
||||
/* Blowfish code */
|
||||
static uint32_t pax[18];
|
||||
static uint32_t ipa[18] = {
|
||||
0x243f6a88u, 0x85a308d3u, 0x13198a2eu,
|
||||
0x03707344u, 0xa4093822u, 0x299f31d0u,
|
||||
0x082efa98u, 0xec4e6c89u, 0x452821e6u,
|
||||
0x38d01377u, 0xbe5466cfu, 0x34e90c6cu,
|
||||
0xc0ac29b7u, 0xc97c50ddu, 0x3f84d5b5u,
|
||||
0xb5470917u, 0x9216d5d9u, 0x8979fb1bu
|
||||
};
|
||||
|
||||
static uint32_t sbx[4][256];
|
||||
static uint32_t sbi[4][256] = {
|
||||
{0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u,
|
||||
0xb8e1afedu, 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u,
|
||||
0x24a19947u, 0xb3916cf7u, 0x0801f2e2u, 0x858efc16u,
|
||||
0x636920d8u, 0x71574e69u, 0xa458fea3u, 0xf4933d7eu,
|
||||
0x0d95748fu, 0x728eb658u, 0x718bcd58u, 0x82154aeeu,
|
||||
0x7b54a41du, 0xc25a59b5u, 0x9c30d539u, 0x2af26013u,
|
||||
0xc5d1b023u, 0x286085f0u, 0xca417918u, 0xb8db38efu,
|
||||
0x8e79dcb0u, 0x603a180eu, 0x6c9e0e8bu, 0xb01e8a3eu,
|
||||
0xd71577c1u, 0xbd314b27u, 0x78af2fdau, 0x55605c60u,
|
||||
0xe65525f3u, 0xaa55ab94u, 0x57489862u, 0x63e81440u,
|
||||
0x55ca396au, 0x2aab10b6u, 0xb4cc5c34u, 0x1141e8ceu,
|
||||
0xa15486afu, 0x7c72e993u, 0xb3ee1411u, 0x636fbc2au,
|
||||
0x2ba9c55du, 0x741831f6u, 0xce5c3e16u, 0x9b87931eu,
|
||||
0xafd6ba33u, 0x6c24cf5cu, 0x7a325381u, 0x28958677u,
|
||||
0x3b8f4898u, 0x6b4bb9afu, 0xc4bfe81bu, 0x66282193u,
|
||||
0x61d809ccu, 0xfb21a991u, 0x487cac60u, 0x5dec8032u,
|
||||
0xef845d5du, 0xe98575b1u, 0xdc262302u, 0xeb651b88u,
|
||||
0x23893e81u, 0xd396acc5u, 0x0f6d6ff3u, 0x83f44239u,
|
||||
0x2e0b4482u, 0xa4842004u, 0x69c8f04au, 0x9e1f9b5eu,
|
||||
0x21c66842u, 0xf6e96c9au, 0x670c9c61u, 0xabd388f0u,
|
||||
0x6a51a0d2u, 0xd8542f68u, 0x960fa728u, 0xab5133a3u,
|
||||
0x6eef0b6cu, 0x137a3be4u, 0xba3bf050u, 0x7efb2a98u,
|
||||
0xa1f1651du, 0x39af0176u, 0x66ca593eu, 0x82430e88u,
|
||||
0x8cee8619u, 0x456f9fb4u, 0x7d84a5c3u, 0x3b8b5ebeu,
|
||||
0xe06f75d8u, 0x85c12073u, 0x401a449fu, 0x56c16aa6u,
|
||||
0x4ed3aa62u, 0x363f7706u, 0x1bfedf72u, 0x429b023du,
|
||||
0x37d0d724u, 0xd00a1248u, 0xdb0fead3u, 0x49f1c09bu,
|
||||
0x075372c9u, 0x80991b7bu, 0x25d479d8u, 0xf6e8def7u,
|
||||
0xe3fe501au, 0xb6794c3bu, 0x976ce0bdu, 0x04c006bau,
|
||||
0xc1a94fb6u, 0x409f60c4u, 0x5e5c9ec2u, 0x196a2463u,
|
||||
0x68fb6fafu, 0x3e6c53b5u, 0x1339b2ebu, 0x3b52ec6fu,
|
||||
0x6dfc511fu, 0x9b30952cu, 0xcc814544u, 0xaf5ebd09u,
|
||||
0xbee3d004u, 0xde334afdu, 0x660f2807u, 0x192e4bb3u,
|
||||
0xc0cba857u, 0x45c8740fu, 0xd20b5f39u, 0xb9d3fbdbu,
|
||||
0x5579c0bdu, 0x1a60320au, 0xd6a100c6u, 0x402c7279u,
|
||||
0x679f25feu, 0xfb1fa3ccu, 0x8ea5e9f8u, 0xdb3222f8u,
|
||||
0x3c7516dfu, 0xfd616b15u, 0x2f501ec8u, 0xad0552abu,
|
||||
0x323db5fau, 0xfd238760u, 0x53317b48u, 0x3e00df82u,
|
||||
0x9e5c57bbu, 0xca6f8ca0u, 0x1a87562eu, 0xdf1769dbu,
|
||||
0xd542a8f6u, 0x287effc3u, 0xac6732c6u, 0x8c4f5573u,
|
||||
0x695b27b0u, 0xbbca58c8u, 0xe1ffa35du, 0xb8f011a0u,
|
||||
0x10fa3d98u, 0xfd2183b8u, 0x4afcb56cu, 0x2dd1d35bu,
|
||||
0x9a53e479u, 0xb6f84565u, 0xd28e49bcu, 0x4bfb9790u,
|
||||
0xe1ddf2dau, 0xa4cb7e33u, 0x62fb1341u, 0xcee4c6e8u,
|
||||
0xef20cadau, 0x36774c01u, 0xd07e9efeu, 0x2bf11fb4u,
|
||||
0x95dbda4du, 0xae909198u, 0xeaad8e71u, 0x6b93d5a0u,
|
||||
0xd08ed1d0u, 0xafc725e0u, 0x8e3c5b2fu, 0x8e7594b7u,
|
||||
0x8ff6e2fbu, 0xf2122b64u, 0x8888b812u, 0x900df01cu,
|
||||
0x4fad5ea0u, 0x688fc31cu, 0xd1cff191u, 0xb3a8c1adu,
|
||||
0x2f2f2218u, 0xbe0e1777u, 0xea752dfeu, 0x8b021fa1u,
|
||||
0xe5a0cc0fu, 0xb56f74e8u, 0x18acf3d6u, 0xce89e299u,
|
||||
0xb4a84fe0u, 0xfd13e0b7u, 0x7cc43b81u, 0xd2ada8d9u,
|
||||
0x165fa266u, 0x80957705u, 0x93cc7314u, 0x211a1477u,
|
||||
0xe6ad2065u, 0x77b5fa86u, 0xc75442f5u, 0xfb9d35cfu,
|
||||
0xebcdaf0cu, 0x7b3e89a0u, 0xd6411bd3u, 0xae1e7e49u,
|
||||
0x00250e2du, 0x2071b35eu, 0x226800bbu, 0x57b8e0afu,
|
||||
0x2464369bu, 0xf009b91eu, 0x5563911du, 0x59dfa6aau,
|
||||
0x78c14389u, 0xd95a537fu, 0x207d5ba2u, 0x02e5b9c5u,
|
||||
0x83260376u, 0x6295cfa9u, 0x11c81968u, 0x4e734a41u,
|
||||
0xb3472dcau, 0x7b14a94au, 0x1b510052u, 0x9a532915u,
|
||||
0xd60f573fu, 0xbc9bc6e4u, 0x2b60a476u, 0x81e67400u,
|
||||
0x08ba6fb5u, 0x571be91fu, 0xf296ec6bu, 0x2a0dd915u,
|
||||
0xb6636521u, 0xe7b9f9b6u, 0xff34052eu, 0xc5855664u,
|
||||
0x53b02d5du, 0xa99f8fa1u, 0x08ba4799u, 0x6e85076au},
|
||||
{0x4b7a70e9u, 0xb5b32944u, 0xdb75092eu, 0xc4192623u,
|
||||
0xad6ea6b0u, 0x49a7df7du, 0x9cee60b8u, 0x8fedb266u,
|
||||
0xecaa8c71u, 0x699a17ffu, 0x5664526cu, 0xc2b19ee1u,
|
||||
0x193602a5u, 0x75094c29u, 0xa0591340u, 0xe4183a3eu,
|
||||
0x3f54989au, 0x5b429d65u, 0x6b8fe4d6u, 0x99f73fd6u,
|
||||
0xa1d29c07u, 0xefe830f5u, 0x4d2d38e6u, 0xf0255dc1u,
|
||||
0x4cdd2086u, 0x8470eb26u, 0x6382e9c6u, 0x021ecc5eu,
|
||||
0x09686b3fu, 0x3ebaefc9u, 0x3c971814u, 0x6b6a70a1u,
|
||||
0x687f3584u, 0x52a0e286u, 0xb79c5305u, 0xaa500737u,
|
||||
0x3e07841cu, 0x7fdeae5cu, 0x8e7d44ecu, 0x5716f2b8u,
|
||||
0xb03ada37u, 0xf0500c0du, 0xf01c1f04u, 0x0200b3ffu,
|
||||
0xae0cf51au, 0x3cb574b2u, 0x25837a58u, 0xdc0921bdu,
|
||||
0xd19113f9u, 0x7ca92ff6u, 0x94324773u, 0x22f54701u,
|
||||
0x3ae5e581u, 0x37c2dadcu, 0xc8b57634u, 0x9af3dda7u,
|
||||
0xa9446146u, 0x0fd0030eu, 0xecc8c73eu, 0xa4751e41u,
|
||||
0xe238cd99u, 0x3bea0e2fu, 0x3280bba1u, 0x183eb331u,
|
||||
0x4e548b38u, 0x4f6db908u, 0x6f420d03u, 0xf60a04bfu,
|
||||
0x2cb81290u, 0x24977c79u, 0x5679b072u, 0xbcaf89afu,
|
||||
0xde9a771fu, 0xd9930810u, 0xb38bae12u, 0xdccf3f2eu,
|
||||
0x5512721fu, 0x2e6b7124u, 0x501adde6u, 0x9f84cd87u,
|
||||
0x7a584718u, 0x7408da17u, 0xbc9f9abcu, 0xe94b7d8cu,
|
||||
0xec7aec3au, 0xdb851dfau, 0x63094366u, 0xc464c3d2u,
|
||||
0xef1c1847u, 0x3215d908u, 0xdd433b37u, 0x24c2ba16u,
|
||||
0x12a14d43u, 0x2a65c451u, 0x50940002u, 0x133ae4ddu,
|
||||
0x71dff89eu, 0x10314e55u, 0x81ac77d6u, 0x5f11199bu,
|
||||
0x043556f1u, 0xd7a3c76bu, 0x3c11183bu, 0x5924a509u,
|
||||
0xf28fe6edu, 0x97f1fbfau, 0x9ebabf2cu, 0x1e153c6eu,
|
||||
0x86e34570u, 0xeae96fb1u, 0x860e5e0au, 0x5a3e2ab3u,
|
||||
0x771fe71cu, 0x4e3d06fau, 0x2965dcb9u, 0x99e71d0fu,
|
||||
0x803e89d6u, 0x5266c825u, 0x2e4cc978u, 0x9c10b36au,
|
||||
0xc6150ebau, 0x94e2ea78u, 0xa5fc3c53u, 0x1e0a2df4u,
|
||||
0xf2f74ea7u, 0x361d2b3du, 0x1939260fu, 0x19c27960u,
|
||||
0x5223a708u, 0xf71312b6u, 0xebadfe6eu, 0xeac31f66u,
|
||||
0xe3bc4595u, 0xa67bc883u, 0xb17f37d1u, 0x018cff28u,
|
||||
0xc332ddefu, 0xbe6c5aa5u, 0x65582185u, 0x68ab9802u,
|
||||
0xeecea50fu, 0xdb2f953bu, 0x2aef7dadu, 0x5b6e2f84u,
|
||||
0x1521b628u, 0x29076170u, 0xecdd4775u, 0x619f1510u,
|
||||
0x13cca830u, 0xeb61bd96u, 0x0334fe1eu, 0xaa0363cfu,
|
||||
0xb5735c90u, 0x4c70a239u, 0xd59e9e0bu, 0xcbaade14u,
|
||||
0xeecc86bcu, 0x60622ca7u, 0x9cab5cabu, 0xb2f3846eu,
|
||||
0x648b1eafu, 0x19bdf0cau, 0xa02369b9u, 0x655abb50u,
|
||||
0x40685a32u, 0x3c2ab4b3u, 0x319ee9d5u, 0xc021b8f7u,
|
||||
0x9b540b19u, 0x875fa099u, 0x95f7997eu, 0x623d7da8u,
|
||||
0xf837889au, 0x97e32d77u, 0x11ed935fu, 0x16681281u,
|
||||
0x0e358829u, 0xc7e61fd6u, 0x96dedfa1u, 0x7858ba99u,
|
||||
0x57f584a5u, 0x1b227263u, 0x9b83c3ffu, 0x1ac24696u,
|
||||
0xcdb30aebu, 0x532e3054u, 0x8fd948e4u, 0x6dbc3128u,
|
||||
0x58ebf2efu, 0x34c6ffeau, 0xfe28ed61u, 0xee7c3c73u,
|
||||
0x5d4a14d9u, 0xe864b7e3u, 0x42105d14u, 0x203e13e0u,
|
||||
0x45eee2b6u, 0xa3aaabeau, 0xdb6c4f15u, 0xfacb4fd0u,
|
||||
0xc742f442u, 0xef6abbb5u, 0x654f3b1du, 0x41cd2105u,
|
||||
0xd81e799eu, 0x86854dc7u, 0xe44b476au, 0x3d816250u,
|
||||
0xcf62a1f2u, 0x5b8d2646u, 0xfc8883a0u, 0xc1c7b6a3u,
|
||||
0x7f1524c3u, 0x69cb7492u, 0x47848a0bu, 0x5692b285u,
|
||||
0x095bbf00u, 0xad19489du, 0x1462b174u, 0x23820e00u,
|
||||
0x58428d2au, 0x0c55f5eau, 0x1dadf43eu, 0x233f7061u,
|
||||
0x3372f092u, 0x8d937e41u, 0xd65fecf1u, 0x6c223bdbu,
|
||||
0x7cde3759u, 0xcbee7460u, 0x4085f2a7u, 0xce77326eu,
|
||||
0xa6078084u, 0x19f8509eu, 0xe8efd855u, 0x61d99735u,
|
||||
0xa969a7aau, 0xc50c06c2u, 0x5a04abfcu, 0x800bcadcu,
|
||||
0x9e447a2eu, 0xc3453484u, 0xfdd56705u, 0x0e1e9ec9u,
|
||||
0xdb73dbd3u, 0x105588cdu, 0x675fda79u, 0xe3674340u,
|
||||
0xc5c43465u, 0x713e38d8u, 0x3d28f89eu, 0xf16dff20u,
|
||||
0x153e21e7u, 0x8fb03d4au, 0xe6e39f2bu, 0xdb83adf7u},
|
||||
{0xe93d5a68u, 0x948140f7u, 0xf64c261cu, 0x94692934u,
|
||||
0x411520f7u, 0x7602d4f7u, 0xbcf46b2eu, 0xd4a20068u,
|
||||
0xd4082471u, 0x3320f46au, 0x43b7d4b7u, 0x500061afu,
|
||||
0x1e39f62eu, 0x97244546u, 0x14214f74u, 0xbf8b8840u,
|
||||
0x4d95fc1du, 0x96b591afu, 0x70f4ddd3u, 0x66a02f45u,
|
||||
0xbfbc09ecu, 0x03bd9785u, 0x7fac6dd0u, 0x31cb8504u,
|
||||
0x96eb27b3u, 0x55fd3941u, 0xda2547e6u, 0xabca0a9au,
|
||||
0x28507825u, 0x530429f4u, 0x0a2c86dau, 0xe9b66dfbu,
|
||||
0x68dc1462u, 0xd7486900u, 0x680ec0a4u, 0x27a18deeu,
|
||||
0x4f3ffea2u, 0xe887ad8cu, 0xb58ce006u, 0x7af4d6b6u,
|
||||
0xaace1e7cu, 0xd3375fecu, 0xce78a399u, 0x406b2a42u,
|
||||
0x20fe9e35u, 0xd9f385b9u, 0xee39d7abu, 0x3b124e8bu,
|
||||
0x1dc9faf7u, 0x4b6d1856u, 0x26a36631u, 0xeae397b2u,
|
||||
0x3a6efa74u, 0xdd5b4332u, 0x6841e7f7u, 0xca7820fbu,
|
||||
0xfb0af54eu, 0xd8feb397u, 0x454056acu, 0xba489527u,
|
||||
0x55533a3au, 0x20838d87u, 0xfe6ba9b7u, 0xd096954bu,
|
||||
0x55a867bcu, 0xa1159a58u, 0xcca92963u, 0x99e1db33u,
|
||||
0xa62a4a56u, 0x3f3125f9u, 0x5ef47e1cu, 0x9029317cu,
|
||||
0xfdf8e802u, 0x04272f70u, 0x80bb155cu, 0x05282ce3u,
|
||||
0x95c11548u, 0xe4c66d22u, 0x48c1133fu, 0xc70f86dcu,
|
||||
0x07f9c9eeu, 0x41041f0fu, 0x404779a4u, 0x5d886e17u,
|
||||
0x325f51ebu, 0xd59bc0d1u, 0xf2bcc18fu, 0x41113564u,
|
||||
0x257b7834u, 0x602a9c60u, 0xdff8e8a3u, 0x1f636c1bu,
|
||||
0x0e12b4c2u, 0x02e1329eu, 0xaf664fd1u, 0xcad18115u,
|
||||
0x6b2395e0u, 0x333e92e1u, 0x3b240b62u, 0xeebeb922u,
|
||||
0x85b2a20eu, 0xe6ba0d99u, 0xde720c8cu, 0x2da2f728u,
|
||||
0xd0127845u, 0x95b794fdu, 0x647d0862u, 0xe7ccf5f0u,
|
||||
0x5449a36fu, 0x877d48fau, 0xc39dfd27u, 0xf33e8d1eu,
|
||||
0x0a476341u, 0x992eff74u, 0x3a6f6eabu, 0xf4f8fd37u,
|
||||
0xa812dc60u, 0xa1ebddf8u, 0x991be14cu, 0xdb6e6b0du,
|
||||
0xc67b5510u, 0x6d672c37u, 0x2765d43bu, 0xdcd0e804u,
|
||||
0xf1290dc7u, 0xcc00ffa3u, 0xb5390f92u, 0x690fed0bu,
|
||||
0x667b9ffbu, 0xcedb7d9cu, 0xa091cf0bu, 0xd9155ea3u,
|
||||
0xbb132f88u, 0x515bad24u, 0x7b9479bfu, 0x763bd6ebu,
|
||||
0x37392eb3u, 0xcc115979u, 0x8026e297u, 0xf42e312du,
|
||||
0x6842ada7u, 0xc66a2b3bu, 0x12754cccu, 0x782ef11cu,
|
||||
0x6a124237u, 0xb79251e7u, 0x06a1bbe6u, 0x4bfb6350u,
|
||||
0x1a6b1018u, 0x11caedfau, 0x3d25bdd8u, 0xe2e1c3c9u,
|
||||
0x44421659u, 0x0a121386u, 0xd90cec6eu, 0xd5abea2au,
|
||||
0x64af674eu, 0xda86a85fu, 0xbebfe988u, 0x64e4c3feu,
|
||||
0x9dbc8057u, 0xf0f7c086u, 0x60787bf8u, 0x6003604du,
|
||||
0xd1fd8346u, 0xf6381fb0u, 0x7745ae04u, 0xd736fcccu,
|
||||
0x83426b33u, 0xf01eab71u, 0xb0804187u, 0x3c005e5fu,
|
||||
0x77a057beu, 0xbde8ae24u, 0x55464299u, 0xbf582e61u,
|
||||
0x4e58f48fu, 0xf2ddfda2u, 0xf474ef38u, 0x8789bdc2u,
|
||||
0x5366f9c3u, 0xc8b38e74u, 0xb475f255u, 0x46fcd9b9u,
|
||||
0x7aeb2661u, 0x8b1ddf84u, 0x846a0e79u, 0x915f95e2u,
|
||||
0x466e598eu, 0x20b45770u, 0x8cd55591u, 0xc902de4cu,
|
||||
0xb90bace1u, 0xbb8205d0u, 0x11a86248u, 0x7574a99eu,
|
||||
0xb77f19b6u, 0xe0a9dc09u, 0x662d09a1u, 0xc4324633u,
|
||||
0xe85a1f02u, 0x09f0be8cu, 0x4a99a025u, 0x1d6efe10u,
|
||||
0x1ab93d1du, 0x0ba5a4dfu, 0xa186f20fu, 0x2868f169u,
|
||||
0xdcb7da83u, 0x573906feu, 0xa1e2ce9bu, 0x4fcd7f52u,
|
||||
0x50115e01u, 0xa70683fau, 0xa002b5c4u, 0x0de6d027u,
|
||||
0x9af88c27u, 0x773f8641u, 0xc3604c06u, 0x61a806b5u,
|
||||
0xf0177a28u, 0xc0f586e0u, 0x006058aau, 0x30dc7d62u,
|
||||
0x11e69ed7u, 0x2338ea63u, 0x53c2dd94u, 0xc2c21634u,
|
||||
0xbbcbee56u, 0x90bcb6deu, 0xebfc7da1u, 0xce591d76u,
|
||||
0x6f05e409u, 0x4b7c0188u, 0x39720a3du, 0x7c927c24u,
|
||||
0x86e3725fu, 0x724d9db9u, 0x1ac15bb4u, 0xd39eb8fcu,
|
||||
0xed545578u, 0x08fca5b5u, 0xd83d7cd3u, 0x4dad0fc4u,
|
||||
0x1e50ef5eu, 0xb161e6f8u, 0xa28514d9u, 0x6c51133cu,
|
||||
0x6fd5c7e7u, 0x56e14ec4u, 0x362abfceu, 0xddc6c837u,
|
||||
0xd79a3234u, 0x92638212u, 0x670efa8eu, 0x406000e0u},
|
||||
{0x3a39ce37u, 0xd3faf5cfu, 0xabc27737u, 0x5ac52d1bu,
|
||||
0x5cb0679eu, 0x4fa33742u, 0xd3822740u, 0x99bc9bbeu,
|
||||
0xd5118e9du, 0xbf0f7315u, 0xd62d1c7eu, 0xc700c47bu,
|
||||
0xb78c1b6bu, 0x21a19045u, 0xb26eb1beu, 0x6a366eb4u,
|
||||
0x5748ab2fu, 0xbc946e79u, 0xc6a376d2u, 0x6549c2c8u,
|
||||
0x530ff8eeu, 0x468dde7du, 0xd5730a1du, 0x4cd04dc6u,
|
||||
0x2939bbdbu, 0xa9ba4650u, 0xac9526e8u, 0xbe5ee304u,
|
||||
0xa1fad5f0u, 0x6a2d519au, 0x63ef8ce2u, 0x9a86ee22u,
|
||||
0xc089c2b8u, 0x43242ef6u, 0xa51e03aau, 0x9cf2d0a4u,
|
||||
0x83c061bau, 0x9be96a4du, 0x8fe51550u, 0xba645bd6u,
|
||||
0x2826a2f9u, 0xa73a3ae1u, 0x4ba99586u, 0xef5562e9u,
|
||||
0xc72fefd3u, 0xf752f7dau, 0x3f046f69u, 0x77fa0a59u,
|
||||
0x80e4a915u, 0x87b08601u, 0x9b09e6adu, 0x3b3ee593u,
|
||||
0xe990fd5au, 0x9e34d797u, 0x2cf0b7d9u, 0x022b8b51u,
|
||||
0x96d5ac3au, 0x017da67du, 0xd1cf3ed6u, 0x7c7d2d28u,
|
||||
0x1f9f25cfu, 0xadf2b89bu, 0x5ad6b472u, 0x5a88f54cu,
|
||||
0xe029ac71u, 0xe019a5e6u, 0x47b0acfdu, 0xed93fa9bu,
|
||||
0xe8d3c48du, 0x283b57ccu, 0xf8d56629u, 0x79132e28u,
|
||||
0x785f0191u, 0xed756055u, 0xf7960e44u, 0xe3d35e8cu,
|
||||
0x15056dd4u, 0x88f46dbau, 0x03a16125u, 0x0564f0bdu,
|
||||
0xc3eb9e15u, 0x3c9057a2u, 0x97271aecu, 0xa93a072au,
|
||||
0x1b3f6d9bu, 0x1e6321f5u, 0xf59c66fbu, 0x26dcf319u,
|
||||
0x7533d928u, 0xb155fdf5u, 0x03563482u, 0x8aba3cbbu,
|
||||
0x28517711u, 0xc20ad9f8u, 0xabcc5167u, 0xccad925fu,
|
||||
0x4de81751u, 0x3830dc8eu, 0x379d5862u, 0x9320f991u,
|
||||
0xea7a90c2u, 0xfb3e7bceu, 0x5121ce64u, 0x774fbe32u,
|
||||
0xa8b6e37eu, 0xc3293d46u, 0x48de5369u, 0x6413e680u,
|
||||
0xa2ae0810u, 0xdd6db224u, 0x69852dfdu, 0x09072166u,
|
||||
0xb39a460au, 0x6445c0ddu, 0x586cdecfu, 0x1c20c8aeu,
|
||||
0x5bbef7ddu, 0x1b588d40u, 0xccd2017fu, 0x6bb4e3bbu,
|
||||
0xdda26a7eu, 0x3a59ff45u, 0x3e350a44u, 0xbcb4cdd5u,
|
||||
0x72eacea8u, 0xfa6484bbu, 0x8d6612aeu, 0xbf3c6f47u,
|
||||
0xd29be463u, 0x542f5d9eu, 0xaec2771bu, 0xf64e6370u,
|
||||
0x740e0d8du, 0xe75b1357u, 0xf8721671u, 0xaf537d5du,
|
||||
0x4040cb08u, 0x4eb4e2ccu, 0x34d2466au, 0x0115af84u,
|
||||
0xe1b00428u, 0x95983a1du, 0x06b89fb4u, 0xce6ea048u,
|
||||
0x6f3f3b82u, 0x3520ab82u, 0x011a1d4bu, 0x277227f8u,
|
||||
0x611560b1u, 0xe7933fdcu, 0xbb3a792bu, 0x344525bdu,
|
||||
0xa08839e1u, 0x51ce794bu, 0x2f32c9b7u, 0xa01fbac9u,
|
||||
0xe01cc87eu, 0xbcc7d1f6u, 0xcf0111c3u, 0xa1e8aac7u,
|
||||
0x1a908749u, 0xd44fbd9au, 0xd0dadecbu, 0xd50ada38u,
|
||||
0x0339c32au, 0xc6913667u, 0x8df9317cu, 0xe0b12b4fu,
|
||||
0xf79e59b7u, 0x43f5bb3au, 0xf2d519ffu, 0x27d9459cu,
|
||||
0xbf97222cu, 0x15e6fc2au, 0x0f91fc71u, 0x9b941525u,
|
||||
0xfae59361u, 0xceb69cebu, 0xc2a86459u, 0x12baa8d1u,
|
||||
0xb6c1075eu, 0xe3056a0cu, 0x10d25065u, 0xcb03a442u,
|
||||
0xe0ec6e0eu, 0x1698db3bu, 0x4c98a0beu, 0x3278e964u,
|
||||
0x9f1f9532u, 0xe0d392dfu, 0xd3a0342bu, 0x8971f21eu,
|
||||
0x1b0a7441u, 0x4ba3348cu, 0xc5be7120u, 0xc37632d8u,
|
||||
0xdf359f8du, 0x9b992f2eu, 0xe60b6f47u, 0x0fe3f11du,
|
||||
0xe54cda54u, 0x1edad891u, 0xce6279cfu, 0xcd3e7e6fu,
|
||||
0x1618b166u, 0xfd2c1d05u, 0x848fd2c5u, 0xf6fb2299u,
|
||||
0xf523f357u, 0xa6327623u, 0x93a83531u, 0x56cccd02u,
|
||||
0xacf08162u, 0x5a75ebb5u, 0x6e163697u, 0x88d273ccu,
|
||||
0xde966292u, 0x81b949d0u, 0x4c50901bu, 0x71c65614u,
|
||||
0xe6c6c7bdu, 0x327a140au, 0x45e1d006u, 0xc3f27b9au,
|
||||
0xc9aa53fdu, 0x62a80f00u, 0xbb25bfe2u, 0x35bdd2f6u,
|
||||
0x71126905u, 0xb2040222u, 0xb6cbcf7cu, 0xcd769c2bu,
|
||||
0x53113ec0u, 0x1640e3d3u, 0x38abbd60u, 0x2547adf0u,
|
||||
0xba38209cu, 0xf746ce76u, 0x77afa1c5u, 0x20756060u,
|
||||
0x85cbfe4eu, 0x8ae88dd8u, 0x7aaaf9b0u, 0x4cf9aa7eu,
|
||||
0x1948c25cu, 0x02fb8a8cu, 0x01c36ae4u, 0xd6ebe1f9u,
|
||||
0x90d4f869u, 0xa65cdea0u, 0x3f09252du, 0xc208e69fu,
|
||||
0xb74e6132u, 0xce77e25bu, 0x578fdfe3u, 0x3ac372e6u}
|
||||
};
|
||||
|
||||
#define F1(i) \
|
||||
xl ^= pax[i]; \
|
||||
xr ^= ((sbx[0][xl >> 24] + \
|
||||
sbx[1][(xl & 0xFF0000) >> 16]) ^ \
|
||||
sbx[2][(xl & 0xFF00) >> 8]) + \
|
||||
sbx[3][xl & 0xFF];
|
||||
|
||||
#define F2(i) \
|
||||
xr ^= pax[i]; \
|
||||
xl ^= ((sbx[0][xr >> 24] + \
|
||||
sbx[1][(xr & 0xFF0000) >> 16]) ^ \
|
||||
sbx[2][(xr & 0xFF00) >> 8]) + \
|
||||
sbx[3][xr & 0xFF];
|
||||
|
||||
|
||||
static void bf_e_block(uint32_t *p_xl, uint32_t *p_xr)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint32_t xl = *p_xl;
|
||||
uint32_t xr = *p_xr;
|
||||
|
||||
F1(0) F2(1) F1(2) F2(3) F1(4) F2(5) F1(6) F2(7)
|
||||
F1(8) F2(9) F1(10) F2(11) F1(12) F2(13) F1(14) F2(15)
|
||||
xl ^= pax[16];
|
||||
xr ^= pax[17];
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
*p_xl = xl;
|
||||
*p_xr = xr;
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define htonl2(x) \
|
||||
x = ((((x) & 0xffL) << 24) | (((x) & 0xff00L) << 8) | \
|
||||
(((x) & 0xff0000L) >> 8) | (((x) & 0xff000000L) >> 24))
|
||||
#else // ifdef WORDS_BIGENDIAN
|
||||
# define htonl2(x)
|
||||
#endif // ifdef WORDS_BIGENDIAN
|
||||
|
||||
static void bf_e_cblock(char_u *block)
|
||||
{
|
||||
block8 bk;
|
||||
|
||||
memcpy(bk.uc, block, 8);
|
||||
htonl2(bk.ul[0]);
|
||||
htonl2(bk.ul[1]);
|
||||
bf_e_block(&bk.ul[0], &bk.ul[1]);
|
||||
htonl2(bk.ul[0]);
|
||||
htonl2(bk.ul[1]);
|
||||
memcpy(block, bk.uc, 8);
|
||||
}
|
||||
|
||||
// Initialize the crypt method using "password" as the encryption key and
|
||||
// "salt[salt_len]" as the salt.
|
||||
void bf_key_init(char_u *password, char_u *salt, int salt_len)
|
||||
{
|
||||
// Process the key 1000 times.
|
||||
// See http://en.wikipedia.org/wiki/Key_strengthening.
|
||||
char_u *key = sha256_key(password, salt, salt_len);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
key = sha256_key(key, salt, salt_len);
|
||||
}
|
||||
|
||||
// Convert the key from 64 hex chars to 32 binary chars.
|
||||
int keylen = (int)STRLEN(key) / 2;
|
||||
|
||||
if (keylen == 0) {
|
||||
EMSG(_("E831: bf_key_init() called with empty password"));
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned u;
|
||||
for (i = 0; i < keylen; i++) {
|
||||
sscanf((char *)&key[i * 2], "%2x", &u);
|
||||
key[i] = u;
|
||||
}
|
||||
|
||||
memmove(sbx, sbi, 4 * 4 * 256);
|
||||
|
||||
int keypos = 0;
|
||||
for (i = 0; i < 18; i++) {
|
||||
uint32_t val = 0;
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 4; j++) {
|
||||
val = (val << 8) | key[keypos++ % keylen];
|
||||
}
|
||||
pax[i] = ipa[i] ^ val;
|
||||
}
|
||||
|
||||
uint32_t data_l = 0;
|
||||
uint32_t data_r = 0;
|
||||
for (i = 0; i < 18; i += 2) {
|
||||
bf_e_block(&data_l, &data_r);
|
||||
pax[i + 0] = data_l;
|
||||
pax[i + 1] = data_r;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 256; j += 2) {
|
||||
bf_e_block(&data_l, &data_r);
|
||||
sbx[i][j + 0] = data_l;
|
||||
sbx[i][j + 1] = data_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// BF Self test for corrupted tables or instructions
|
||||
static int bf_check_tables(uint32_t a_ipa[18], uint32_t a_sbi[4][256],
|
||||
uint32_t val)
|
||||
{
|
||||
uint32_t c = 0;
|
||||
int i;
|
||||
for (i = 0; i < 18; i++) {
|
||||
c ^= a_ipa[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 256; j++) {
|
||||
c ^= a_sbi[i][j];
|
||||
}
|
||||
}
|
||||
return c == val;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char_u password[64];
|
||||
char_u salt[9];
|
||||
char_u plaintxt[9];
|
||||
char_u cryptxt[9];
|
||||
char_u badcryptxt[9]; // cryptxt when big/little endian is wrong.
|
||||
uint32_t keysum;
|
||||
} struct_bf_test_data;
|
||||
|
||||
// Assert bf(password, plaintxt) is cryptxt.
|
||||
// Assert csum(pax sbx(password)) is keysum.
|
||||
static struct_bf_test_data bf_test_data[] = {
|
||||
{
|
||||
"password",
|
||||
"salt",
|
||||
"plaintxt",
|
||||
"\xad\x3d\xfa\x7f\xe8\xea\x40\xf6", // cryptxt
|
||||
"\x72\x50\x3b\x38\x10\x60\x22\xa7", // badcryptxt
|
||||
0x56701b5du // keysum
|
||||
},
|
||||
};
|
||||
|
||||
// Return FAIL when there is something wrong with blowfish encryption.
|
||||
static int bf_self_test(void)
|
||||
{
|
||||
int err = 0;
|
||||
if (!bf_check_tables(ipa, sbi, 0x6ffa520a)) {
|
||||
err++;
|
||||
}
|
||||
|
||||
int bn = ARRAY_LENGTH(bf_test_data);
|
||||
int i;
|
||||
for (i = 0; i < bn; i++) {
|
||||
bf_key_init((char_u *)(bf_test_data[i].password), bf_test_data[i].salt,
|
||||
(int)STRLEN(bf_test_data[i].salt));
|
||||
|
||||
if (!bf_check_tables(pax, sbx, bf_test_data[i].keysum)) {
|
||||
err++;
|
||||
}
|
||||
|
||||
// Don't modify bf_test_data[i].plaintxt, self test is idempotent.
|
||||
block8 bk;
|
||||
memcpy(bk.uc, bf_test_data[i].plaintxt, 8);
|
||||
bf_e_cblock(bk.uc);
|
||||
|
||||
if (memcmp(bk.uc, bf_test_data[i].cryptxt, 8) != 0) {
|
||||
if ((err == 0) && (memcmp(bk.uc, bf_test_data[i].badcryptxt, 8) == 0)) {
|
||||
EMSG(_("E817: Blowfish big/little endian use wrong"));
|
||||
}
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
return err > 0 ? FAIL : OK;
|
||||
}
|
||||
|
||||
// Cipher feedback mode.
|
||||
static int randbyte_offset = 0;
|
||||
static int update_offset = 0;
|
||||
static char_u cfb_buffer[BF_CFB_LEN]; // 64 bytes
|
||||
|
||||
// Initialize with seed "iv[iv_len]".
|
||||
void bf_cfb_init(char_u *iv, int iv_len)
|
||||
{
|
||||
randbyte_offset = update_offset = 0;
|
||||
memset(cfb_buffer, 0, BF_CFB_LEN);
|
||||
|
||||
if (iv_len > 0) {
|
||||
int mi = iv_len > BF_CFB_LEN ? iv_len : BF_CFB_LEN;
|
||||
int i;
|
||||
for (i = 0; i < mi; i++) {
|
||||
cfb_buffer[i % BF_CFB_LEN] ^= iv[i % iv_len];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BF_CFB_UPDATE(c) \
|
||||
{ \
|
||||
cfb_buffer[update_offset] ^= (char_u)c; \
|
||||
if (++update_offset == BF_CFB_LEN) { \
|
||||
update_offset = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BF_RANBYTE(t) \
|
||||
{ \
|
||||
if ((randbyte_offset & BF_BLOCK_MASK) == 0) { \
|
||||
bf_e_cblock(&cfb_buffer[randbyte_offset]); \
|
||||
} \
|
||||
t = cfb_buffer[randbyte_offset]; \
|
||||
if (++randbyte_offset == BF_CFB_LEN) { \
|
||||
randbyte_offset = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Encrypt "from[len]" into "to[len]".
|
||||
// "from" and "to" can be equal to encrypt in place.
|
||||
void bf_crypt_encode(char_u *from, size_t len, char_u *to)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
int ztemp = from[i];
|
||||
int t;
|
||||
BF_RANBYTE(t);
|
||||
BF_CFB_UPDATE(ztemp);
|
||||
to[i] = t ^ ztemp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt "ptr[len]" in place.
|
||||
*/
|
||||
void bf_crypt_decode(char_u *ptr, long len)
|
||||
{
|
||||
char_u *p;
|
||||
for (p = ptr; p < ptr + len; p++) {
|
||||
int t;
|
||||
BF_RANBYTE(t);
|
||||
*p ^= t;
|
||||
BF_CFB_UPDATE(*p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the encryption keys and the random header according to
|
||||
* the given password.
|
||||
* in: "passwd" password string with which to modify keys
|
||||
*/
|
||||
void bf_crypt_init_keys(char_u *passwd)
|
||||
{
|
||||
char_u *p;
|
||||
for (p = passwd; *p != NUL; p++) {
|
||||
BF_CFB_UPDATE(*p);
|
||||
}
|
||||
}
|
||||
|
||||
static int save_randbyte_offset;
|
||||
static int save_update_offset;
|
||||
static char_u save_cfb_buffer[BF_CFB_LEN];
|
||||
static uint32_t save_pax[18];
|
||||
static uint32_t save_sbx[4][256];
|
||||
|
||||
/*
|
||||
* Save the current crypt state. Can only be used once before
|
||||
* bf_crypt_restore().
|
||||
*/
|
||||
void bf_crypt_save(void)
|
||||
{
|
||||
save_randbyte_offset = randbyte_offset;
|
||||
save_update_offset = update_offset;
|
||||
memmove(save_cfb_buffer, cfb_buffer, BF_CFB_LEN);
|
||||
memmove(save_pax, pax, 4 * 18);
|
||||
memmove(save_sbx, sbx, 4 * 4 * 256);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the current crypt state. Can only be used after
|
||||
* bf_crypt_save().
|
||||
*/
|
||||
void bf_crypt_restore(void)
|
||||
{
|
||||
randbyte_offset = save_randbyte_offset;
|
||||
update_offset = save_update_offset;
|
||||
memmove(cfb_buffer, save_cfb_buffer, BF_CFB_LEN);
|
||||
memmove(pax, save_pax, 4 * 18);
|
||||
memmove(sbx, save_sbx, 4 * 4 * 256);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run a test to check if the encryption works as expected.
|
||||
* Give an error and return FAIL when not.
|
||||
*/
|
||||
int blowfish_self_test(void)
|
||||
{
|
||||
if (sha256_self_test() == FAIL) {
|
||||
EMSG(_("E818: sha256 test failed"));
|
||||
return FAIL;
|
||||
}
|
||||
if (bf_self_test() == FAIL) {
|
||||
EMSG(_("E819: Blowfish test failed"));
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
13
src/nvim/blowfish.h
Normal file
13
src/nvim/blowfish.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef NEOVIM_BLOWFISH_H
|
||||
#define NEOVIM_BLOWFISH_H
|
||||
|
||||
void bf_key_init(char_u *password, char_u *salt, int salt_len);
|
||||
void bf_cfb_init(char_u *iv, int iv_len);
|
||||
void bf_crypt_encode(char_u *from, size_t len, char_u *to);
|
||||
void bf_crypt_decode(char_u *ptr, long len);
|
||||
void bf_crypt_init_keys(char_u *passwd);
|
||||
void bf_crypt_save(void);
|
||||
void bf_crypt_restore(void);
|
||||
int blowfish_self_test(void);
|
||||
|
||||
#endif // NEOVIM_BLOWFISH_H
|
||||
4657
src/nvim/buffer.c
Normal file
4657
src/nvim/buffer.c
Normal file
File diff suppressed because it is too large
Load Diff
81
src/nvim/buffer.h
Normal file
81
src/nvim/buffer.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef NEOVIM_BUFFER_H
|
||||
#define NEOVIM_BUFFER_H
|
||||
/* buffer.c */
|
||||
int open_buffer(int read_stdin, exarg_T *eap, int flags);
|
||||
int buf_valid(buf_T *buf);
|
||||
void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last);
|
||||
void buf_clear_file(buf_T *buf);
|
||||
void buf_freeall(buf_T *buf, int flags);
|
||||
void goto_buffer(exarg_T *eap, int start, int dir, int count);
|
||||
void handle_swap_exists(buf_T *old_curbuf);
|
||||
char_u *do_bufdel(int command, char_u *arg, int addr_count,
|
||||
int start_bnr, int end_bnr,
|
||||
int forceit);
|
||||
int do_buffer(int action, int start, int dir, int count, int forceit);
|
||||
void set_curbuf(buf_T *buf, int action);
|
||||
void enter_buffer(buf_T *buf);
|
||||
void do_autochdir(void);
|
||||
buf_T *buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum,
|
||||
int flags);
|
||||
void free_buf_options(buf_T *buf, int free_p_ff);
|
||||
int buflist_getfile(int n, linenr_T lnum, int options, int forceit);
|
||||
void buflist_getfpos(void);
|
||||
buf_T *buflist_findname_exp(char_u *fname);
|
||||
buf_T *buflist_findname(char_u *ffname);
|
||||
int buflist_findpat(char_u *pattern, char_u *pattern_end, int unlisted,
|
||||
int diffmode,
|
||||
int curtab_only);
|
||||
int ExpandBufnames(char_u *pat, int *num_file, char_u ***file,
|
||||
int options);
|
||||
buf_T *buflist_findnr(int nr);
|
||||
char_u *buflist_nr2name(int n, int fullname, int helptail);
|
||||
void get_winopts(buf_T *buf);
|
||||
pos_T *buflist_findfpos(buf_T *buf);
|
||||
linenr_T buflist_findlnum(buf_T *buf);
|
||||
void buflist_list(exarg_T *eap);
|
||||
int buflist_name_nr(int fnum, char_u **fname, linenr_T *lnum);
|
||||
int setfname(buf_T *buf, char_u *ffname, char_u *sfname, int message);
|
||||
void buf_set_name(int fnum, char_u *name);
|
||||
void buf_name_changed(buf_T *buf);
|
||||
buf_T *setaltfname(char_u *ffname, char_u *sfname, linenr_T lnum);
|
||||
char_u *getaltfname(int errmsg);
|
||||
int buflist_add(char_u *fname, int flags);
|
||||
void buflist_slash_adjust(void);
|
||||
void buflist_altfpos(win_T *win);
|
||||
int otherfile(char_u *ffname);
|
||||
void buf_setino(buf_T *buf);
|
||||
void fileinfo(int fullname, int shorthelp, int dont_truncate);
|
||||
void col_print(char_u *buf, size_t buflen, int col, int vcol);
|
||||
void maketitle(void);
|
||||
void resettitle(void);
|
||||
void free_titles(void);
|
||||
int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt,
|
||||
int use_sandbox, int fillchar, int maxwidth,
|
||||
struct stl_hlrec *hltab,
|
||||
struct stl_hlrec *tabtab);
|
||||
void get_rel_pos(win_T *wp, char_u *buf, int buflen);
|
||||
void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname);
|
||||
char_u *alist_name(aentry_T *aep);
|
||||
void do_arg_all(int count, int forceit, int keep_tabs);
|
||||
void ex_buffer_all(exarg_T *eap);
|
||||
void do_modelines(int flags);
|
||||
int read_viminfo_bufferlist(vir_T *virp, int writing);
|
||||
void write_viminfo_bufferlist(FILE *fp);
|
||||
char_u *buf_spname(buf_T *buf);
|
||||
int find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp);
|
||||
void buf_addsign(buf_T *buf, int id, linenr_T lnum, int typenr);
|
||||
linenr_T buf_change_sign_type(buf_T *buf, int markId, int typenr);
|
||||
int buf_getsigntype(buf_T *buf, linenr_T lnum, int type);
|
||||
linenr_T buf_delsign(buf_T *buf, int id);
|
||||
int buf_findsign(buf_T *buf, int id);
|
||||
int buf_findsign_id(buf_T *buf, linenr_T lnum);
|
||||
void buf_delete_signs(buf_T *buf);
|
||||
void buf_delete_all_signs(void);
|
||||
void sign_list_placed(buf_T *rbuf);
|
||||
void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount,
|
||||
long amount_after);
|
||||
void set_buflisted(int on);
|
||||
int buf_contents_changed(buf_T *buf);
|
||||
void wipe_buffer(buf_T *buf, int aucmd);
|
||||
|
||||
#endif /* NEOVIM_BUFFER_H */
|
||||
1081
src/nvim/buffer_defs.h
Normal file
1081
src/nvim/buffer_defs.h
Normal file
File diff suppressed because it is too large
Load Diff
1918
src/nvim/charset.c
Normal file
1918
src/nvim/charset.c
Normal file
File diff suppressed because it is too large
Load Diff
66
src/nvim/charset.h
Normal file
66
src/nvim/charset.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef NEOVIM_CHARSET_H
|
||||
#define NEOVIM_CHARSET_H
|
||||
|
||||
int init_chartab(void);
|
||||
int buf_init_chartab(buf_T *buf, int global);
|
||||
void trans_characters(char_u *buf, int bufsize);
|
||||
char_u *transstr(char_u *s);
|
||||
char_u *str_foldcase(char_u *str, int orglen, char_u *buf, int buflen);
|
||||
char_u *transchar(int c);
|
||||
char_u *transchar_byte(int c);
|
||||
void transchar_nonprint(char_u *buf, int c);
|
||||
void transchar_hex(char_u *buf, int c);
|
||||
int byte2cells(int b);
|
||||
int char2cells(int c);
|
||||
int ptr2cells(char_u *p);
|
||||
int vim_strsize(char_u *s);
|
||||
int vim_strnsize(char_u *s, int len);
|
||||
int chartabsize(char_u *p, colnr_T col);
|
||||
int linetabsize(char_u *s);
|
||||
int linetabsize_col(int startcol, char_u *s);
|
||||
int win_linetabsize(win_T *wp, char_u *p, colnr_T len);
|
||||
int vim_isIDc(int c);
|
||||
int vim_iswordc(int c);
|
||||
int vim_iswordc_buf(int c, buf_T *buf);
|
||||
int vim_iswordp(char_u *p);
|
||||
int vim_iswordp_buf(char_u *p, buf_T *buf);
|
||||
int vim_isfilec(int c);
|
||||
int vim_isfilec_or_wc(int c);
|
||||
int vim_isprintc(int c);
|
||||
int vim_isprintc_strict(int c);
|
||||
int lbr_chartabsize(unsigned char *s, colnr_T col);
|
||||
int lbr_chartabsize_adv(char_u **s, colnr_T col);
|
||||
int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp);
|
||||
int in_win_border(win_T *wp, colnr_T vcol);
|
||||
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor,
|
||||
colnr_T *end);
|
||||
colnr_T getvcol_nolist(pos_T *posp);
|
||||
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor,
|
||||
colnr_T *end);
|
||||
void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
|
||||
colnr_T *right);
|
||||
char_u *skipwhite(char_u *q);
|
||||
char_u *skipdigits(char_u *q);
|
||||
char_u *skiphex(char_u *q);
|
||||
char_u *skiptodigit(char_u *q);
|
||||
char_u *skiptohex(char_u *q);
|
||||
int vim_isdigit(int c);
|
||||
int vim_isxdigit(int c);
|
||||
int vim_islower(int c);
|
||||
int vim_isupper(int c);
|
||||
int vim_toupper(int c);
|
||||
int vim_tolower(int c);
|
||||
char_u *skiptowhite(char_u *p);
|
||||
char_u *skiptowhite_esc(char_u *p);
|
||||
long getdigits(char_u **pp);
|
||||
int vim_isblankline(char_u *lbuf);
|
||||
void vim_str2nr(char_u *start, int *hexp, int *len, int dooct,
|
||||
int dohex, long *nptr,
|
||||
unsigned long *unptr);
|
||||
int hex2nr(int c);
|
||||
int hexhex2nr(char_u *p);
|
||||
int rem_backslash(char_u *str);
|
||||
void backslash_halve(char_u *p);
|
||||
char_u *backslash_halve_save(char_u *p);
|
||||
|
||||
#endif // NEOVIM_CHARSET_H
|
||||
236
src/nvim/crypt.c
Normal file
236
src/nvim/crypt.c
Normal file
@@ -0,0 +1,236 @@
|
||||
// Optional encryption support.
|
||||
// Mohsin Ahmed, mosh@sasi.com, 98-09-24
|
||||
// Based on zip/crypt sources.
|
||||
//
|
||||
// NOTE FOR USA: Since 2000 exporting this code from the USA is allowed to
|
||||
// most countries. There are a few exceptions, but that still should not be a
|
||||
// problem since this code was originally created in Europe and India.
|
||||
//
|
||||
// Blowfish addition originally made by Mohsin Ahmed,
|
||||
// http://www.cs.albany.edu/~mosh 2010-03-14
|
||||
// Based on blowfish by Bruce Schneier (http://www.schneier.com/blowfish.html)
|
||||
// and sha256 by Christophe Devine.
|
||||
|
||||
#include "vim.h"
|
||||
#include "misc2.h"
|
||||
#include "blowfish.h"
|
||||
#include "ex_getln.h"
|
||||
#include "message.h"
|
||||
#include "option.h"
|
||||
|
||||
static void make_crc_tab(void);
|
||||
|
||||
static uint32_t crc_32_tab[256];
|
||||
|
||||
// Fills the CRC table.
|
||||
static void make_crc_tab(void)
|
||||
{
|
||||
uint32_t s;
|
||||
uint32_t t;
|
||||
uint32_t v;
|
||||
static bool done = false;
|
||||
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (t = 0; t < 256; t++) {
|
||||
v = t;
|
||||
|
||||
for (s = 0; s < 8; s++) {
|
||||
v = (v >> 1) ^ ((v & 1) * (uint32_t)0xedb88320L);
|
||||
}
|
||||
crc_32_tab[t] = v;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
#define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
|
||||
|
||||
static uint32_t keys[3]; // keys defining the pseudo-random sequence
|
||||
|
||||
// Returns the next byte in the pseudo-random sequence.
|
||||
#define DECRYPT_BYTE_ZIP(t) { \
|
||||
uint16_t temp; \
|
||||
temp = (uint16_t)keys[2] | 2; \
|
||||
t = (int)(((unsigned)(temp * (temp ^ 1U)) >> 8) & 0xff); \
|
||||
}
|
||||
|
||||
// Updates the encryption keys with the next byte of plain text.
|
||||
#define UPDATE_KEYS_ZIP(c) { \
|
||||
keys[0] = CRC32(keys[0], (c)); \
|
||||
keys[1] += keys[0] & 0xff; \
|
||||
keys[1] = keys[1] * 134775813L + 1; \
|
||||
keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
|
||||
}
|
||||
|
||||
static int crypt_busy = 0;
|
||||
static uint32_t saved_keys[3];
|
||||
static int saved_crypt_method;
|
||||
|
||||
int crypt_method_from_string(char_u *s)
|
||||
{
|
||||
return *s == 'b' ? 1 : 0;
|
||||
}
|
||||
|
||||
int get_crypt_method(buf_T *buf)
|
||||
{
|
||||
return crypt_method_from_string(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
|
||||
}
|
||||
|
||||
void set_crypt_method(buf_T *buf, int method)
|
||||
{
|
||||
free_string_option(buf->b_p_cm);
|
||||
buf->b_p_cm = vim_strsave((char_u *)(method == 0 ? "zip" : "blowfish"));
|
||||
}
|
||||
|
||||
void crypt_push_state(void)
|
||||
{
|
||||
if (crypt_busy == 1) {
|
||||
// Save the state
|
||||
if (use_crypt_method == 0) {
|
||||
saved_keys[0] = keys[0];
|
||||
saved_keys[1] = keys[1];
|
||||
saved_keys[2] = keys[2];
|
||||
} else {
|
||||
bf_crypt_save();
|
||||
}
|
||||
saved_crypt_method = use_crypt_method;
|
||||
} else if (crypt_busy > 1) {
|
||||
EMSG2(_(e_intern2), "crypt_push_state()");
|
||||
}
|
||||
crypt_busy++;
|
||||
}
|
||||
|
||||
void crypt_pop_state(void)
|
||||
{
|
||||
crypt_busy--;
|
||||
|
||||
if (crypt_busy == 1) {
|
||||
use_crypt_method = saved_crypt_method;
|
||||
|
||||
if (use_crypt_method == 0) {
|
||||
keys[0] = saved_keys[0];
|
||||
keys[1] = saved_keys[1];
|
||||
keys[2] = saved_keys[2];
|
||||
} else {
|
||||
bf_crypt_restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crypt_encode(char_u *from, size_t len, char_u *to)
|
||||
{
|
||||
size_t i;
|
||||
int ztemp;
|
||||
int t;
|
||||
|
||||
if (use_crypt_method == 0) {
|
||||
for (i = 0; i < len; i++) {
|
||||
ztemp = from[i];
|
||||
DECRYPT_BYTE_ZIP(t);
|
||||
UPDATE_KEYS_ZIP(ztemp);
|
||||
to[i] = t ^ ztemp;
|
||||
}
|
||||
} else {
|
||||
bf_crypt_encode(from, len, to);
|
||||
}
|
||||
}
|
||||
|
||||
void crypt_decode(char_u *ptr, long len)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (use_crypt_method == 0) {
|
||||
for (p = ptr; p < ptr + len; p++) {
|
||||
uint16_t temp;
|
||||
|
||||
temp = (uint16_t)keys[2] | 2;
|
||||
temp = (int)(((unsigned)(temp * (temp ^ 1U)) >> 8) & 0xff);
|
||||
UPDATE_KEYS_ZIP(*p ^= temp);
|
||||
}
|
||||
} else {
|
||||
bf_crypt_decode(ptr, len);
|
||||
}
|
||||
}
|
||||
|
||||
void crypt_init_keys(char_u *passwd)
|
||||
{
|
||||
if ((passwd != NULL) && (*passwd != NUL)) {
|
||||
if (use_crypt_method == 0) {
|
||||
char_u *p;
|
||||
|
||||
make_crc_tab();
|
||||
keys[0] = 305419896L;
|
||||
keys[1] = 591751049L;
|
||||
keys[2] = 878082192L;
|
||||
|
||||
for (p = passwd; *p != NUL; p++) {
|
||||
UPDATE_KEYS_ZIP((int)*p);
|
||||
}
|
||||
} else {
|
||||
bf_crypt_init_keys(passwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_crypt_key(char_u *key)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (key != NULL) {
|
||||
for (p = key; *p != NUL; p++) {
|
||||
*p = 0;
|
||||
}
|
||||
free(key);
|
||||
}
|
||||
}
|
||||
|
||||
char_u *get_crypt_key(int store, int twice)
|
||||
{
|
||||
char_u *p1;
|
||||
char_u *p2 = NULL;
|
||||
int round;
|
||||
|
||||
for (round = 0;; round++) {
|
||||
cmdline_star = TRUE;
|
||||
cmdline_row = msg_row;
|
||||
char_u *prompt = (round == 0)
|
||||
? (char_u *) _("Enter encryption key: ")
|
||||
: (char_u *) _("Enter same key again: ");
|
||||
p1 = getcmdline_prompt(NUL, prompt, 0, EXPAND_NOTHING, NULL);
|
||||
cmdline_star = FALSE;
|
||||
if (p1 == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (round == twice) {
|
||||
if ((p2 != NULL) && (STRCMP(p1, p2) != 0)) {
|
||||
MSG(_("Keys don't match!"));
|
||||
free_crypt_key(p1);
|
||||
free_crypt_key(p2);
|
||||
p2 = NULL;
|
||||
round = -1; // Do it again
|
||||
continue;
|
||||
}
|
||||
|
||||
if (store) {
|
||||
set_option_value((char_u *) "key", 0L, p1, OPT_LOCAL);
|
||||
free_crypt_key(p1);
|
||||
p1 = curbuf->b_p_key;
|
||||
}
|
||||
break;
|
||||
}
|
||||
p2 = p1;
|
||||
}
|
||||
|
||||
// Since the user typed this, no need to wait for return.
|
||||
if (msg_didout) {
|
||||
msg_putchar('\n');
|
||||
}
|
||||
need_wait_return = FALSE;
|
||||
msg_didout = FALSE;
|
||||
|
||||
free_crypt_key(p2);
|
||||
return p1;
|
||||
}
|
||||
82
src/nvim/crypt.h
Normal file
82
src/nvim/crypt.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef NEOVIM_CRYPT_H
|
||||
#define NEOVIM_CRYPT_H
|
||||
|
||||
/// Returns the crypt method string as a number.
|
||||
///
|
||||
/// @param s Pointer to the crypt method string.
|
||||
///
|
||||
/// @return An integer value of the crypt method:
|
||||
/// 0 for "zip", the old method. Also for any non-valid value.
|
||||
/// 1 for "blowfish".
|
||||
int crypt_method_from_string(char_u *s);
|
||||
|
||||
/// Returns the crypt method of the buffer "buf" as a number.
|
||||
///
|
||||
/// @param buf Pointer to the buffer.
|
||||
///
|
||||
/// @return An integer value of the crypt method:
|
||||
/// 0 for "zip", the old method. Also for any non-valid value.
|
||||
/// 1 for "blowfish".
|
||||
int get_crypt_method(buf_T *buf);
|
||||
|
||||
/// Sets the crypt method for buffer "buf" to "method" using the
|
||||
/// int value as returned by crypt_method_from_string().
|
||||
///
|
||||
/// @param buf Pointer to the buffer.
|
||||
/// @param method Crypt method.
|
||||
void set_crypt_method(buf_T *buf, int method);
|
||||
|
||||
/// Prepares for initializing the encryption. If already doing encryption,
|
||||
/// then save the state.
|
||||
///
|
||||
/// This function must always be called symmetrically with crypt_pop_state().
|
||||
void crypt_push_state(void);
|
||||
|
||||
/// Ends encryption. If already doing encryption before crypt_push_state(),
|
||||
/// then restore the saved state.
|
||||
///
|
||||
/// This function must always be called symmetrically with crypt_push_state().
|
||||
void crypt_pop_state(void);
|
||||
|
||||
/// Encrypts "from[len]" into "to[len]".
|
||||
/// For in-place encryption, "from" and "len" must be the same.
|
||||
///
|
||||
/// @param from Pointer to the source string.
|
||||
/// @param len Length of the strings.
|
||||
/// @param to Pointer to the destination string.
|
||||
void crypt_encode(char_u *from, size_t len, char_u *to);
|
||||
|
||||
/// Decrypts "ptr[len]" in-place.
|
||||
///
|
||||
/// @param ptr Pointer to the string.
|
||||
/// @param len Length of the string.
|
||||
void crypt_decode(char_u *ptr, long len);
|
||||
|
||||
/// Initializes the encryption keys and the random header according to
|
||||
/// the given password.
|
||||
///
|
||||
/// If "password" is NULL or empty, the function doesn't do anything.
|
||||
///
|
||||
/// @param passwd The password string with which to modify keys.
|
||||
void crypt_init_keys(char_u *passwd);
|
||||
|
||||
/// Frees an allocated crypt key and clears the text to make sure
|
||||
/// nothing stays in memory.
|
||||
///
|
||||
/// @param key The crypt key to be freed.
|
||||
void free_crypt_key(char_u *key);
|
||||
|
||||
/// Asks the user for the crypt key.
|
||||
///
|
||||
/// When "store" is TRUE, the new key is stored in the 'key' option
|
||||
/// and the 'key' option value is returned, which MUST NOT be freed
|
||||
/// manually, but using free_crypt_key().
|
||||
/// When "store" is FALSE, the typed key is returned in allocated memory.
|
||||
///
|
||||
/// @param store Determines, whether the new crypt key is stored.
|
||||
/// @param twice Ask for the key twice.
|
||||
///
|
||||
/// @return The crypt key. On failure, NULL is returned.
|
||||
char_u *get_crypt_key(int store, int twice);
|
||||
|
||||
#endif // NEOVIM_CRYPT_H
|
||||
209
src/nvim/cursor_shape.c
Normal file
209
src/nvim/cursor_shape.c
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "vim.h"
|
||||
#include "cursor_shape.h"
|
||||
#include "misc2.h"
|
||||
#include "ex_getln.h"
|
||||
#include "charset.h"
|
||||
#include "syntax.h"
|
||||
|
||||
/*
|
||||
* Handling of cursor and mouse pointer shapes in various modes.
|
||||
*/
|
||||
|
||||
static cursorentry_T shape_table[SHAPE_IDX_COUNT] =
|
||||
{
|
||||
/* The values will be filled in from the 'guicursor' and 'mouseshape'
|
||||
* defaults when Vim starts.
|
||||
* Adjust the SHAPE_IDX_ defines when making changes! */
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE},
|
||||
{0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
|
||||
* ("what" is SHAPE_MOUSE).
|
||||
* Returns error message for an illegal option, NULL otherwise.
|
||||
*/
|
||||
char_u *parse_shape_opt(int what)
|
||||
{
|
||||
char_u *modep;
|
||||
char_u *colonp;
|
||||
char_u *commap;
|
||||
char_u *slashp;
|
||||
char_u *p, *endp;
|
||||
int idx = 0; /* init for GCC */
|
||||
int all_idx;
|
||||
int len;
|
||||
int i;
|
||||
long n;
|
||||
int found_ve = FALSE; /* found "ve" flag */
|
||||
int round;
|
||||
|
||||
/*
|
||||
* First round: check for errors; second round: do it for real.
|
||||
*/
|
||||
for (round = 1; round <= 2; ++round) {
|
||||
/*
|
||||
* Repeat for all comma separated parts.
|
||||
*/
|
||||
modep = p_guicursor;
|
||||
while (*modep != NUL) {
|
||||
colonp = vim_strchr(modep, ':');
|
||||
if (colonp == NULL)
|
||||
return (char_u *)N_("E545: Missing colon");
|
||||
if (colonp == modep)
|
||||
return (char_u *)N_("E546: Illegal mode");
|
||||
commap = vim_strchr(modep, ',');
|
||||
|
||||
/*
|
||||
* Repeat for all mode's before the colon.
|
||||
* For the 'a' mode, we loop to handle all the modes.
|
||||
*/
|
||||
all_idx = -1;
|
||||
while (modep < colonp || all_idx >= 0) {
|
||||
if (all_idx < 0) {
|
||||
/* Find the mode. */
|
||||
if (modep[1] == '-' || modep[1] == ':')
|
||||
len = 1;
|
||||
else
|
||||
len = 2;
|
||||
if (len == 1 && TOLOWER_ASC(modep[0]) == 'a')
|
||||
all_idx = SHAPE_IDX_COUNT - 1;
|
||||
else {
|
||||
for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
|
||||
if (STRNICMP(modep, shape_table[idx].name, len)
|
||||
== 0)
|
||||
break;
|
||||
if (idx == SHAPE_IDX_COUNT
|
||||
|| (shape_table[idx].used_for & what) == 0)
|
||||
return (char_u *)N_("E546: Illegal mode");
|
||||
if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
|
||||
found_ve = TRUE;
|
||||
}
|
||||
modep += len + 1;
|
||||
}
|
||||
|
||||
if (all_idx >= 0)
|
||||
idx = all_idx--;
|
||||
else if (round == 2) {
|
||||
{
|
||||
/* Set the defaults, for the missing parts */
|
||||
shape_table[idx].shape = SHAPE_BLOCK;
|
||||
shape_table[idx].blinkwait = 700L;
|
||||
shape_table[idx].blinkon = 400L;
|
||||
shape_table[idx].blinkoff = 250L;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the part after the colon */
|
||||
for (p = colonp + 1; *p && *p != ','; ) {
|
||||
{
|
||||
/*
|
||||
* First handle the ones with a number argument.
|
||||
*/
|
||||
i = *p;
|
||||
len = 0;
|
||||
if (STRNICMP(p, "ver", 3) == 0)
|
||||
len = 3;
|
||||
else if (STRNICMP(p, "hor", 3) == 0)
|
||||
len = 3;
|
||||
else if (STRNICMP(p, "blinkwait", 9) == 0)
|
||||
len = 9;
|
||||
else if (STRNICMP(p, "blinkon", 7) == 0)
|
||||
len = 7;
|
||||
else if (STRNICMP(p, "blinkoff", 8) == 0)
|
||||
len = 8;
|
||||
if (len != 0) {
|
||||
p += len;
|
||||
if (!VIM_ISDIGIT(*p))
|
||||
return (char_u *)N_("E548: digit expected");
|
||||
n = getdigits(&p);
|
||||
if (len == 3) { /* "ver" or "hor" */
|
||||
if (n == 0)
|
||||
return (char_u *)N_("E549: Illegal percentage");
|
||||
if (round == 2) {
|
||||
if (TOLOWER_ASC(i) == 'v')
|
||||
shape_table[idx].shape = SHAPE_VER;
|
||||
else
|
||||
shape_table[idx].shape = SHAPE_HOR;
|
||||
shape_table[idx].percentage = n;
|
||||
}
|
||||
} else if (round == 2) {
|
||||
if (len == 9)
|
||||
shape_table[idx].blinkwait = n;
|
||||
else if (len == 7)
|
||||
shape_table[idx].blinkon = n;
|
||||
else
|
||||
shape_table[idx].blinkoff = n;
|
||||
}
|
||||
} else if (STRNICMP(p, "block", 5) == 0) {
|
||||
if (round == 2)
|
||||
shape_table[idx].shape = SHAPE_BLOCK;
|
||||
p += 5;
|
||||
} else { /* must be a highlight group name then */
|
||||
endp = vim_strchr(p, '-');
|
||||
if (commap == NULL) { /* last part */
|
||||
if (endp == NULL)
|
||||
endp = p + STRLEN(p); /* find end of part */
|
||||
} else if (endp > commap || endp == NULL)
|
||||
endp = commap;
|
||||
slashp = vim_strchr(p, '/');
|
||||
if (slashp != NULL && slashp < endp) {
|
||||
/* "group/langmap_group" */
|
||||
i = syn_check_group(p, (int)(slashp - p));
|
||||
p = slashp + 1;
|
||||
}
|
||||
if (round == 2) {
|
||||
shape_table[idx].id = syn_check_group(p,
|
||||
(int)(endp - p));
|
||||
shape_table[idx].id_lm = shape_table[idx].id;
|
||||
if (slashp != NULL && slashp < endp)
|
||||
shape_table[idx].id = i;
|
||||
}
|
||||
p = endp;
|
||||
}
|
||||
} /* if (what != SHAPE_MOUSE) */
|
||||
|
||||
if (*p == '-')
|
||||
++p;
|
||||
}
|
||||
}
|
||||
modep = p;
|
||||
if (*modep == ',')
|
||||
++modep;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the 's' flag is not given, use the 'v' cursor for 's' */
|
||||
if (!found_ve) {
|
||||
{
|
||||
shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
|
||||
shape_table[SHAPE_IDX_VE].percentage =
|
||||
shape_table[SHAPE_IDX_V].percentage;
|
||||
shape_table[SHAPE_IDX_VE].blinkwait =
|
||||
shape_table[SHAPE_IDX_V].blinkwait;
|
||||
shape_table[SHAPE_IDX_VE].blinkon =
|
||||
shape_table[SHAPE_IDX_V].blinkon;
|
||||
shape_table[SHAPE_IDX_VE].blinkoff =
|
||||
shape_table[SHAPE_IDX_V].blinkoff;
|
||||
shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
|
||||
shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
52
src/nvim/cursor_shape.h
Normal file
52
src/nvim/cursor_shape.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef NEOVIM_CURSOR_SHAPE_H
|
||||
#define NEOVIM_CURSOR_SHAPE_H
|
||||
|
||||
/*
|
||||
* struct to store values from 'guicursor' and 'mouseshape'
|
||||
*/
|
||||
/* Indexes in shape_table[] */
|
||||
#define SHAPE_IDX_N 0 /* Normal mode */
|
||||
#define SHAPE_IDX_V 1 /* Visual mode */
|
||||
#define SHAPE_IDX_I 2 /* Insert mode */
|
||||
#define SHAPE_IDX_R 3 /* Replace mode */
|
||||
#define SHAPE_IDX_C 4 /* Command line Normal mode */
|
||||
#define SHAPE_IDX_CI 5 /* Command line Insert mode */
|
||||
#define SHAPE_IDX_CR 6 /* Command line Replace mode */
|
||||
#define SHAPE_IDX_O 7 /* Operator-pending mode */
|
||||
#define SHAPE_IDX_VE 8 /* Visual mode with 'selection' exclusive */
|
||||
#define SHAPE_IDX_CLINE 9 /* On command line */
|
||||
#define SHAPE_IDX_STATUS 10 /* A status line */
|
||||
#define SHAPE_IDX_SDRAG 11 /* dragging a status line */
|
||||
#define SHAPE_IDX_VSEP 12 /* A vertical separator line */
|
||||
#define SHAPE_IDX_VDRAG 13 /* dragging a vertical separator line */
|
||||
#define SHAPE_IDX_MORE 14 /* Hit-return or More */
|
||||
#define SHAPE_IDX_MOREL 15 /* Hit-return or More in last line */
|
||||
#define SHAPE_IDX_SM 16 /* showing matching paren */
|
||||
#define SHAPE_IDX_COUNT 17
|
||||
|
||||
#define SHAPE_BLOCK 0 /* block cursor */
|
||||
#define SHAPE_HOR 1 /* horizontal bar cursor */
|
||||
#define SHAPE_VER 2 /* vertical bar cursor */
|
||||
|
||||
#define MSHAPE_NUMBERED 1000 /* offset for shapes identified by number */
|
||||
#define MSHAPE_HIDE 1 /* hide mouse pointer */
|
||||
|
||||
#define SHAPE_MOUSE 1 /* used for mouse pointer shape */
|
||||
#define SHAPE_CURSOR 2 /* used for text cursor shape */
|
||||
|
||||
typedef struct cursor_entry {
|
||||
int shape; /* one of the SHAPE_ defines */
|
||||
int mshape; /* one of the MSHAPE defines */
|
||||
int percentage; /* percentage of cell for bar */
|
||||
long blinkwait; /* blinking, wait time before blinking starts */
|
||||
long blinkon; /* blinking, on time */
|
||||
long blinkoff; /* blinking, off time */
|
||||
int id; /* highlight group ID */
|
||||
int id_lm; /* highlight group ID for :lmap mode */
|
||||
char *name; /* mode name (fixed) */
|
||||
char used_for; /* SHAPE_MOUSE and/or SHAPE_CURSOR */
|
||||
} cursorentry_T;
|
||||
|
||||
char_u *parse_shape_opt(int what);
|
||||
|
||||
#endif /* NEOVIM_CURSOR_SHAPE_H */
|
||||
2611
src/nvim/diff.c
Normal file
2611
src/nvim/diff.c
Normal file
File diff suppressed because it is too large
Load Diff
33
src/nvim/diff.h
Normal file
33
src/nvim/diff.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef NEOVIM_DIFF_H
|
||||
#define NEOVIM_DIFF_H
|
||||
|
||||
void diff_buf_delete(buf_T *buf);
|
||||
void diff_buf_adjust(win_T *win);
|
||||
void diff_buf_add(buf_T *buf);
|
||||
void diff_invalidate(buf_T *buf);
|
||||
void diff_mark_adjust(linenr_T line1, linenr_T line2, long amount,
|
||||
long amount_after);
|
||||
void ex_diffupdate(exarg_T *eap);
|
||||
void ex_diffpatch(exarg_T *eap);
|
||||
void ex_diffsplit(exarg_T *eap);
|
||||
void ex_diffthis(exarg_T *eap);
|
||||
void diff_win_options(win_T *wp, int addbuf);
|
||||
void ex_diffoff(exarg_T *eap);
|
||||
void diff_clear(tabpage_T *tp);
|
||||
int diff_check(win_T *wp, linenr_T lnum);
|
||||
int diff_check_fill(win_T *wp, linenr_T lnum);
|
||||
void diff_set_topline(win_T *fromwin, win_T *towin);
|
||||
int diffopt_changed(void);
|
||||
int diffopt_horizontal(void);
|
||||
int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp);
|
||||
int diff_infold(win_T *wp, linenr_T lnum);
|
||||
void nv_diffgetput(int put);
|
||||
void ex_diffgetput(exarg_T *eap);
|
||||
int diff_mode_buf(buf_T *buf);
|
||||
int diff_move_to(int dir, long count);
|
||||
linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1,
|
||||
buf_T *buf2,
|
||||
linenr_T lnum3);
|
||||
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp);
|
||||
|
||||
#endif // NEOVIM_DIFF_H
|
||||
1881
src/nvim/digraph.c
Normal file
1881
src/nvim/digraph.c
Normal file
File diff suppressed because it is too large
Load Diff
12
src/nvim/digraph.h
Normal file
12
src/nvim/digraph.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef NEOVIM_DIGRAPH_H
|
||||
#define NEOVIM_DIGRAPH_H
|
||||
|
||||
int do_digraph(int c);
|
||||
int get_digraph(int cmdline);
|
||||
int getdigraph(int char1, int char2, int meta_char);
|
||||
void putdigraph(char_u *str);
|
||||
void listdigraphs(void);
|
||||
char_u *keymap_init(void);
|
||||
void ex_loadkeymap(exarg_T *eap);
|
||||
|
||||
#endif // NEOVIM_DIGRAPH_H
|
||||
8444
src/nvim/edit.c
Normal file
8444
src/nvim/edit.c
Normal file
File diff suppressed because it is too large
Load Diff
58
src/nvim/edit.h
Normal file
58
src/nvim/edit.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef NEOVIM_EDIT_H
|
||||
#define NEOVIM_EDIT_H
|
||||
|
||||
#include "vim.h"
|
||||
|
||||
/*
|
||||
* Array indexes used for cptext argument of ins_compl_add().
|
||||
*/
|
||||
#define CPT_ABBR 0 /* "abbr" */
|
||||
#define CPT_MENU 1 /* "menu" */
|
||||
#define CPT_KIND 2 /* "kind" */
|
||||
#define CPT_INFO 3 /* "info" */
|
||||
#define CPT_COUNT 4 /* Number of entries */
|
||||
|
||||
int edit(int cmdchar, int startln, long count);
|
||||
void edit_putchar(int c, int highlight);
|
||||
void edit_unputchar(void);
|
||||
void display_dollar(colnr_T col);
|
||||
void change_indent(int type, int amount, int round, int replaced,
|
||||
int call_changed_bytes);
|
||||
void truncate_spaces(char_u *line);
|
||||
void backspace_until_column(int col);
|
||||
int vim_is_ctrl_x_key(int c);
|
||||
int ins_compl_add_infercase(char_u *str, int len, int icase,
|
||||
char_u *fname, int dir,
|
||||
int flags);
|
||||
void set_completion(colnr_T startcol, list_T *list);
|
||||
void ins_compl_show_pum(void);
|
||||
char_u *find_word_start(char_u *ptr);
|
||||
char_u *find_word_end(char_u *ptr);
|
||||
int ins_compl_active(void);
|
||||
int ins_compl_add_tv(typval_T *tv, int dir);
|
||||
void ins_compl_check_keys(int frequency);
|
||||
int get_literal(void);
|
||||
void insertchar(int c, int flags, int second_indent);
|
||||
void auto_format(int trailblank, int prev_line);
|
||||
int comp_textwidth(int ff);
|
||||
int stop_arrow(void);
|
||||
void set_last_insert(int c);
|
||||
void free_last_insert(void);
|
||||
char_u *add_char2buf(int c, char_u *s);
|
||||
void beginline(int flags);
|
||||
int oneright(void);
|
||||
int oneleft(void);
|
||||
int cursor_up(long n, int upd_topline);
|
||||
int cursor_down(long n, int upd_topline);
|
||||
int stuff_inserted(int c, long count, int no_esc);
|
||||
char_u *get_last_insert(void);
|
||||
char_u *get_last_insert_save(void);
|
||||
void replace_push(int c);
|
||||
int replace_push_mb(char_u *p);
|
||||
void fixthisline(int (*get_the_indent)(void));
|
||||
void fix_indent(void);
|
||||
int in_cinkeys(int keytyped, int when, int line_is_empty);
|
||||
int hkmap(int c);
|
||||
int ins_copychar(linenr_T lnum);
|
||||
|
||||
#endif /* NEOVIM_EDIT_H */
|
||||
19819
src/nvim/eval.c
Normal file
19819
src/nvim/eval.c
Normal file
File diff suppressed because it is too large
Load Diff
152
src/nvim/eval.h
Normal file
152
src/nvim/eval.h
Normal file
@@ -0,0 +1,152 @@
|
||||
#ifndef NEOVIM_EVAL_H
|
||||
#define NEOVIM_EVAL_H
|
||||
/* eval.c */
|
||||
void eval_init(void);
|
||||
void eval_clear(void);
|
||||
char_u *func_name(void *cookie);
|
||||
linenr_T *func_breakpoint(void *cookie);
|
||||
int *func_dbg_tick(void *cookie);
|
||||
int func_level(void *cookie);
|
||||
int current_func_returned(void);
|
||||
void set_internal_string_var(char_u *name, char_u *value);
|
||||
int var_redir_start(char_u *name, int append);
|
||||
void var_redir_str(char_u *value, int value_len);
|
||||
void var_redir_stop(void);
|
||||
int eval_charconvert(char_u *enc_from, char_u *enc_to, char_u *
|
||||
fname_from,
|
||||
char_u *fname_to);
|
||||
int eval_printexpr(char_u *fname, char_u *args);
|
||||
void eval_diff(char_u *origfile, char_u *newfile, char_u *outfile);
|
||||
void eval_patch(char_u *origfile, char_u *difffile, char_u *outfile);
|
||||
int eval_to_bool(char_u *arg, int *error, char_u **nextcmd, int skip);
|
||||
char_u *eval_to_string_skip(char_u *arg, char_u **nextcmd, int skip);
|
||||
int skip_expr(char_u **pp);
|
||||
char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert);
|
||||
char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd,
|
||||
int use_sandbox);
|
||||
int eval_to_number(char_u *expr);
|
||||
list_T *eval_spell_expr(char_u *badword, char_u *expr);
|
||||
int get_spellword(list_T *list, char_u **pp);
|
||||
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
||||
int call_vim_function(char_u *func, int argc, char_u **argv, int safe,
|
||||
int str_arg_only,
|
||||
typval_T *rettv);
|
||||
long call_func_retnr(char_u *func, int argc, char_u **argv, int safe);
|
||||
void *call_func_retstr(char_u *func, int argc, char_u **argv, int safe);
|
||||
void *call_func_retlist(char_u *func, int argc, char_u **argv, int safe);
|
||||
void *save_funccal(void);
|
||||
void restore_funccal(void *vfc);
|
||||
void prof_child_enter(proftime_T *tm);
|
||||
void prof_child_exit(proftime_T *tm);
|
||||
int eval_foldexpr(char_u *arg, int *cp);
|
||||
void ex_let(exarg_T *eap);
|
||||
void list_add_watch(list_T *l, listwatch_T *lw);
|
||||
void list_rem_watch(list_T *l, listwatch_T *lwrem);
|
||||
void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip);
|
||||
int next_for_item(void *fi_void, char_u *arg);
|
||||
void free_for_info(void *fi_void);
|
||||
void set_context_for_expression(expand_T *xp, char_u *arg,
|
||||
cmdidx_T cmdidx);
|
||||
void ex_call(exarg_T *eap);
|
||||
void ex_unlet(exarg_T *eap);
|
||||
void ex_lockvar(exarg_T *eap);
|
||||
int do_unlet(char_u *name, int forceit);
|
||||
void del_menutrans_vars(void);
|
||||
char_u *get_user_var_name(expand_T *xp, int idx);
|
||||
list_T *list_alloc(void);
|
||||
void list_unref(list_T *l);
|
||||
void list_free(list_T *l, int recurse);
|
||||
listitem_T *listitem_alloc(void);
|
||||
void listitem_free(listitem_T *item);
|
||||
void listitem_remove(list_T *l, listitem_T *item);
|
||||
dictitem_T *dict_lookup(hashitem_T *hi);
|
||||
listitem_T *list_find(list_T *l, long n);
|
||||
char_u *list_find_str(list_T *l, long idx);
|
||||
void list_append(list_T *l, listitem_T *item);
|
||||
void list_append_tv(list_T *l, typval_T *tv);
|
||||
void list_append_dict(list_T *list, dict_T *dict);
|
||||
void list_append_string(list_T *l, char_u *str, int len);
|
||||
int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
|
||||
void list_remove(list_T *l, listitem_T *item, listitem_T *item2);
|
||||
void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
|
||||
int garbage_collect(void);
|
||||
void set_ref_in_ht(hashtab_T *ht, int copyID);
|
||||
void set_ref_in_list(list_T *l, int copyID);
|
||||
void set_ref_in_item(typval_T *tv, int copyID);
|
||||
dict_T *dict_alloc(void);
|
||||
void dict_unref(dict_T *d);
|
||||
void dict_free(dict_T *d, int recurse);
|
||||
dictitem_T *dictitem_alloc(char_u *key);
|
||||
void dictitem_free(dictitem_T *item);
|
||||
int dict_add(dict_T *d, dictitem_T *item);
|
||||
int dict_add_nr_str(dict_T *d, char *key, long nr, char_u *str);
|
||||
int dict_add_list(dict_T *d, char *key, list_T *list);
|
||||
dictitem_T *dict_find(dict_T *d, char_u *key, int len);
|
||||
char_u *get_dict_string(dict_T *d, char_u *key, int save);
|
||||
long get_dict_number(dict_T *d, char_u *key);
|
||||
char_u *get_function_name(expand_T *xp, int idx);
|
||||
char_u *get_expr_name(expand_T *xp, int idx);
|
||||
int func_call(char_u *name, typval_T *args, dict_T *selfdict,
|
||||
typval_T *rettv);
|
||||
void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
|
||||
float_T vim_round(float_T f);
|
||||
long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir,
|
||||
char_u *skip, int flags, pos_T *match_pos,
|
||||
linenr_T lnum_stop,
|
||||
long time_limit);
|
||||
void set_vim_var_nr(int idx, long val);
|
||||
long get_vim_var_nr(int idx);
|
||||
char_u *get_vim_var_str(int idx);
|
||||
list_T *get_vim_var_list(int idx);
|
||||
void set_vim_var_char(int c);
|
||||
void set_vcount(long count, long count1, int set_prevcount);
|
||||
void set_vim_var_string(int idx, char_u *val, int len);
|
||||
void set_vim_var_list(int idx, list_T *val);
|
||||
void set_reg_var(int c);
|
||||
char_u *v_exception(char_u *oldval);
|
||||
char_u *v_throwpoint(char_u *oldval);
|
||||
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg);
|
||||
void free_tv(typval_T *varp);
|
||||
void clear_tv(typval_T *varp);
|
||||
long get_tv_number_chk(typval_T *varp, int *denote);
|
||||
char_u *get_tv_string_chk(typval_T *varp);
|
||||
char_u *get_var_value(char_u *name);
|
||||
void new_script_vars(scid_T id);
|
||||
void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope);
|
||||
void unref_var_dict(dict_T *dict);
|
||||
void vars_clear(hashtab_T *ht);
|
||||
void copy_tv(typval_T *from, typval_T *to);
|
||||
void ex_echo(exarg_T *eap);
|
||||
void ex_echohl(exarg_T *eap);
|
||||
void ex_execute(exarg_T *eap);
|
||||
void ex_function(exarg_T *eap);
|
||||
void free_all_functions(void);
|
||||
int translated_function_exists(char_u *name);
|
||||
char_u *get_expanded_name(char_u *name, int check);
|
||||
void func_dump_profile(FILE *fd);
|
||||
char_u *get_user_func_name(expand_T *xp, int idx);
|
||||
void ex_delfunction(exarg_T *eap);
|
||||
void func_unref(char_u *name);
|
||||
void func_ref(char_u *name);
|
||||
void ex_return(exarg_T *eap);
|
||||
int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv);
|
||||
void discard_pending_return(void *rettv);
|
||||
char_u *get_return_cmd(void *rettv);
|
||||
char_u *get_func_line(int c, void *cookie, int indent);
|
||||
void func_line_start(void *cookie);
|
||||
void func_line_exec(void *cookie);
|
||||
void func_line_end(void *cookie);
|
||||
int func_has_ended(void *cookie);
|
||||
int func_has_abort(void *cookie);
|
||||
int read_viminfo_varlist(vir_T *virp, int writing);
|
||||
void write_viminfo_varlist(FILE *fp);
|
||||
int store_session_globals(FILE *fd);
|
||||
void last_set_msg(scid_T scriptID);
|
||||
void ex_oldfiles(exarg_T *eap);
|
||||
int modify_fname(char_u *src, int *usedlen, char_u **fnamep,
|
||||
char_u **bufp,
|
||||
int *fnamelen);
|
||||
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub,
|
||||
char_u *flags);
|
||||
|
||||
#endif /* NEOVIM_EVAL_H */
|
||||
116
src/nvim/eval_defs.h
Normal file
116
src/nvim/eval_defs.h
Normal file
@@ -0,0 +1,116 @@
|
||||
#ifndef NEOVIM_EVAL_DEFS_H
|
||||
#define NEOVIM_EVAL_DEFS_H
|
||||
|
||||
#include "hashtab.h"
|
||||
|
||||
typedef int varnumber_T;
|
||||
typedef double float_T;
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
|
||||
/*
|
||||
* Structure to hold an internal variable without a name.
|
||||
*/
|
||||
typedef struct {
|
||||
char v_type; /* see below: VAR_NUMBER, VAR_STRING, etc. */
|
||||
char v_lock; /* see below: VAR_LOCKED, VAR_FIXED */
|
||||
union {
|
||||
varnumber_T v_number; /* number value */
|
||||
float_T v_float; /* floating number value */
|
||||
char_u *v_string; /* string value (can be NULL!) */
|
||||
list_T *v_list; /* list value (can be NULL!) */
|
||||
dict_T *v_dict; /* dict value (can be NULL!) */
|
||||
} vval;
|
||||
} typval_T;
|
||||
|
||||
/* Values for "v_type". */
|
||||
#define VAR_UNKNOWN 0
|
||||
#define VAR_NUMBER 1 /* "v_number" is used */
|
||||
#define VAR_STRING 2 /* "v_string" is used */
|
||||
#define VAR_FUNC 3 /* "v_string" is function name */
|
||||
#define VAR_LIST 4 /* "v_list" is used */
|
||||
#define VAR_DICT 5 /* "v_dict" is used */
|
||||
#define VAR_FLOAT 6 /* "v_float" is used */
|
||||
|
||||
/* Values for "dv_scope". */
|
||||
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||
allowed to mask existing functions */
|
||||
|
||||
/* Values for "v_lock". */
|
||||
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
|
||||
#define VAR_FIXED 2 /* locked forever */
|
||||
|
||||
/*
|
||||
* Structure to hold an item of a list: an internal variable without a name.
|
||||
*/
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; /* next item in list */
|
||||
listitem_T *li_prev; /* previous item in list */
|
||||
typval_T li_tv; /* type and value of the variable */
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct used by those that are using an item in a list.
|
||||
*/
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; /* item being watched */
|
||||
listwatch_T *lw_next; /* next watcher */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to hold info about a list.
|
||||
*/
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; /* first item, NULL if none */
|
||||
listitem_T *lv_last; /* last item, NULL if none */
|
||||
int lv_refcount; /* reference count */
|
||||
int lv_len; /* number of items */
|
||||
listwatch_T *lv_watch; /* first watcher, NULL if none */
|
||||
int lv_idx; /* cached index of an item */
|
||||
listitem_T *lv_idx_item; /* when not NULL item at index "lv_idx" */
|
||||
int lv_copyID; /* ID used by deepcopy() */
|
||||
list_T *lv_copylist; /* copied list used by deepcopy() */
|
||||
char lv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
|
||||
list_T *lv_used_next; /* next list in used lists list */
|
||||
list_T *lv_used_prev; /* previous list in used lists list */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to hold an item of a Dictionary.
|
||||
* Also used for a variable.
|
||||
* The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
*/
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; /* type and value of the variable */
|
||||
char_u di_flags; /* flags (only used for variable) */
|
||||
char_u di_key[1]; /* key (actually longer!) */
|
||||
};
|
||||
|
||||
typedef struct dictitem_S dictitem_T;
|
||||
|
||||
#define DI_FLAGS_RO 1 /* "di_flags" value: read-only variable */
|
||||
#define DI_FLAGS_RO_SBX 2 /* "di_flags" value: read-only in the sandbox */
|
||||
#define DI_FLAGS_FIX 4 /* "di_flags" value: fixed variable, not allocated */
|
||||
#define DI_FLAGS_LOCK 8 /* "di_flags" value: locked variable */
|
||||
|
||||
/*
|
||||
* Structure to hold info about a Dictionary.
|
||||
*/
|
||||
struct dictvar_S {
|
||||
char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
|
||||
char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */
|
||||
int dv_refcount; /* reference count */
|
||||
int dv_copyID; /* ID used by deepcopy() */
|
||||
hashtab_T dv_hashtab; /* hashtab that refers to the items */
|
||||
dict_T *dv_copydict; /* copied dict used by deepcopy() */
|
||||
dict_T *dv_used_next; /* next dict in used dicts list */
|
||||
dict_T *dv_used_prev; /* previous dict in used dicts list */
|
||||
};
|
||||
|
||||
#endif // NEOVIM_EVAL_DEFS_H
|
||||
6374
src/nvim/ex_cmds.c
Normal file
6374
src/nvim/ex_cmds.c
Normal file
File diff suppressed because it is too large
Load Diff
75
src/nvim/ex_cmds.h
Normal file
75
src/nvim/ex_cmds.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef NEOVIM_EX_CMDS_H
|
||||
#define NEOVIM_EX_CMDS_H
|
||||
/* ex_cmds.c */
|
||||
|
||||
void do_ascii(exarg_T *eap);
|
||||
void ex_align(exarg_T *eap);
|
||||
void ex_sort(exarg_T *eap);
|
||||
void ex_retab(exarg_T *eap);
|
||||
int do_move(linenr_T line1, linenr_T line2, linenr_T dest);
|
||||
void ex_copy(linenr_T line1, linenr_T line2, linenr_T n);
|
||||
void free_prev_shellcmd(void);
|
||||
void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in,
|
||||
int do_out);
|
||||
void do_shell(char_u *cmd, int flags);
|
||||
char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp);
|
||||
void append_redir(char_u *buf, int buflen, char_u *opt, char_u *fname);
|
||||
int viminfo_error(char *errnum, char *message, char_u *line);
|
||||
int read_viminfo(char_u *file, int flags);
|
||||
void write_viminfo(char_u *file, int forceit);
|
||||
int viminfo_readline(vir_T *virp);
|
||||
char_u *viminfo_readstring(vir_T *virp, int off, int convert);
|
||||
void viminfo_writestring(FILE *fd, char_u *p);
|
||||
void do_fixdel(exarg_T *eap);
|
||||
void print_line_no_prefix(linenr_T lnum, int use_number, int list);
|
||||
void print_line(linenr_T lnum, int use_number, int list);
|
||||
int rename_buffer(char_u *new_fname);
|
||||
void ex_file(exarg_T *eap);
|
||||
void ex_update(exarg_T *eap);
|
||||
void ex_write(exarg_T *eap);
|
||||
int do_write(exarg_T *eap);
|
||||
int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *
|
||||
ffname,
|
||||
int other);
|
||||
void ex_wnext(exarg_T *eap);
|
||||
void do_wqall(exarg_T *eap);
|
||||
int not_writing(void);
|
||||
int getfile(int fnum, char_u *ffname, char_u *sfname, int setpm,
|
||||
linenr_T lnum,
|
||||
int forceit);
|
||||
int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap,
|
||||
linenr_T newlnum, int flags,
|
||||
win_T *oldwin);
|
||||
void ex_append(exarg_T *eap);
|
||||
void ex_change(exarg_T *eap);
|
||||
void ex_z(exarg_T *eap);
|
||||
int check_restricted(void);
|
||||
int check_secure(void);
|
||||
void do_sub(exarg_T *eap);
|
||||
int do_sub_msg(int count_only);
|
||||
void ex_global(exarg_T *eap);
|
||||
void global_exe(char_u *cmd);
|
||||
int read_viminfo_sub_string(vir_T *virp, int force);
|
||||
void write_viminfo_sub_string(FILE *fp);
|
||||
void free_old_sub(void);
|
||||
int prepare_tagpreview(int undo_sync);
|
||||
void ex_help(exarg_T *eap);
|
||||
char_u *check_help_lang(char_u *arg);
|
||||
int help_heuristic(char_u *matched_string, int offset, int wrong_case);
|
||||
int find_help_tags(char_u *arg, int *num_matches, char_u ***matches,
|
||||
int keep_lang);
|
||||
void fix_help_buffer(void);
|
||||
void ex_exusage(exarg_T *eap);
|
||||
void ex_viusage(exarg_T *eap);
|
||||
void ex_helptags(exarg_T *eap);
|
||||
void ex_sign(exarg_T *eap);
|
||||
int sign_get_attr(int typenr, int line);
|
||||
char_u *sign_get_text(int typenr);
|
||||
void *sign_get_image(int typenr);
|
||||
char_u *sign_typenr2name(int typenr);
|
||||
void free_signs(void);
|
||||
char_u *get_sign_name(expand_T *xp, int idx);
|
||||
void set_context_in_sign_cmd(expand_T *xp, char_u *arg);
|
||||
void ex_drop(exarg_T *eap);
|
||||
|
||||
#endif /* NEOVIM_EX_CMDS_H */
|
||||
3541
src/nvim/ex_cmds2.c
Normal file
3541
src/nvim/ex_cmds2.c
Normal file
File diff suppressed because it is too large
Load Diff
95
src/nvim/ex_cmds2.h
Normal file
95
src/nvim/ex_cmds2.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef NEOVIM_EX_CMDS2_H
|
||||
#define NEOVIM_EX_CMDS2_H
|
||||
/* ex_cmds2.c */
|
||||
void do_debug(char_u *cmd);
|
||||
void ex_debug(exarg_T *eap);
|
||||
void dbg_check_breakpoint(exarg_T *eap);
|
||||
int dbg_check_skipped(exarg_T *eap);
|
||||
void ex_breakadd(exarg_T *eap);
|
||||
void ex_debuggreedy(exarg_T *eap);
|
||||
void ex_breakdel(exarg_T *eap);
|
||||
void ex_breaklist(exarg_T *eap);
|
||||
linenr_T dbg_find_breakpoint(int file, char_u *fname, linenr_T after);
|
||||
int has_profiling(int file, char_u *fname, int *fp);
|
||||
void dbg_breakpoint(char_u *name, linenr_T lnum);
|
||||
void profile_start(proftime_T *tm);
|
||||
void profile_end(proftime_T *tm);
|
||||
void profile_sub(proftime_T *tm, proftime_T *tm2);
|
||||
char *profile_msg(proftime_T *tm);
|
||||
void profile_setlimit(long msec, proftime_T *tm);
|
||||
int profile_passed_limit(proftime_T *tm);
|
||||
void profile_zero(proftime_T *tm);
|
||||
void profile_divide(proftime_T *tm, int count, proftime_T *tm2);
|
||||
void profile_add(proftime_T *tm, proftime_T *tm2);
|
||||
void profile_self(proftime_T *self, proftime_T *total,
|
||||
proftime_T *children);
|
||||
void profile_get_wait(proftime_T *tm);
|
||||
void profile_sub_wait(proftime_T *tm, proftime_T *tma);
|
||||
int profile_equal(proftime_T *tm1, proftime_T *tm2);
|
||||
int profile_cmp(const proftime_T *tm1, const proftime_T *tm2);
|
||||
void ex_profile(exarg_T *eap);
|
||||
char_u *get_profile_name(expand_T *xp, int idx);
|
||||
void set_context_in_profile_cmd(expand_T *xp, char_u *arg);
|
||||
void profile_dump(void);
|
||||
void script_prof_save(proftime_T *tm);
|
||||
void script_prof_restore(proftime_T *tm);
|
||||
void prof_inchar_enter(void);
|
||||
void prof_inchar_exit(void);
|
||||
int prof_def_func(void);
|
||||
int autowrite(buf_T *buf, int forceit);
|
||||
void autowrite_all(void);
|
||||
int check_changed(buf_T *buf, int flags);
|
||||
void dialog_changed(buf_T *buf, int checkall);
|
||||
int can_abandon(buf_T *buf, int forceit);
|
||||
int check_changed_any(int hidden);
|
||||
int check_fname(void);
|
||||
int buf_write_all(buf_T *buf, int forceit);
|
||||
void get_arglist(garray_T *gap, char_u *str);
|
||||
int get_arglist_exp(char_u *str, int *fcountp, char_u ***fnamesp,
|
||||
int wig);
|
||||
void check_arg_idx(win_T *win);
|
||||
void ex_args(exarg_T *eap);
|
||||
void ex_previous(exarg_T *eap);
|
||||
void ex_rewind(exarg_T *eap);
|
||||
void ex_last(exarg_T *eap);
|
||||
void ex_argument(exarg_T *eap);
|
||||
void do_argfile(exarg_T *eap, int argn);
|
||||
void ex_next(exarg_T *eap);
|
||||
void ex_argedit(exarg_T *eap);
|
||||
void ex_argadd(exarg_T *eap);
|
||||
void ex_argdelete(exarg_T *eap);
|
||||
void ex_listdo(exarg_T *eap);
|
||||
void ex_compiler(exarg_T *eap);
|
||||
void ex_runtime(exarg_T *eap);
|
||||
int source_runtime(char_u *name, int all);
|
||||
int do_in_runtimepath(char_u *name, int all,
|
||||
void (*callback)(char_u *fname, void *ck),
|
||||
void *cookie);
|
||||
void ex_options(exarg_T *eap);
|
||||
void ex_source(exarg_T *eap);
|
||||
linenr_T *source_breakpoint(void *cookie);
|
||||
int *source_dbg_tick(void *cookie);
|
||||
int source_level(void *cookie);
|
||||
int do_source(char_u *fname, int check_other, int is_vimrc);
|
||||
void ex_scriptnames(exarg_T *eap);
|
||||
void scriptnames_slash_adjust(void);
|
||||
char_u *get_scriptname(scid_T id);
|
||||
void free_scriptnames(void);
|
||||
char *fgets_cr(char *s, int n, FILE *stream);
|
||||
char_u *getsourceline(int c, void *cookie, int indent);
|
||||
void script_line_start(void);
|
||||
void script_line_exec(void);
|
||||
void script_line_end(void);
|
||||
void ex_scriptencoding(exarg_T *eap);
|
||||
void ex_finish(exarg_T *eap);
|
||||
void do_finish(exarg_T *eap, int reanimate);
|
||||
int source_finished(char_u *(*fgetline)(int, void *, int), void *cookie);
|
||||
void ex_checktime(exarg_T *eap);
|
||||
char_u *get_mess_lang(void);
|
||||
void set_lang_var(void);
|
||||
void ex_language(exarg_T *eap);
|
||||
void free_locales(void);
|
||||
char_u *get_lang_arg(expand_T *xp, int idx);
|
||||
char_u *get_locales(expand_T *xp, int idx);
|
||||
|
||||
#endif /* NEOVIM_EX_CMDS2_H */
|
||||
1191
src/nvim/ex_cmds_defs.h
Normal file
1191
src/nvim/ex_cmds_defs.h
Normal file
File diff suppressed because it is too large
Load Diff
9109
src/nvim/ex_docmd.c
Normal file
9109
src/nvim/ex_docmd.c
Normal file
File diff suppressed because it is too large
Load Diff
69
src/nvim/ex_docmd.h
Normal file
69
src/nvim/ex_docmd.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef NEOVIM_EX_DOCMD_H
|
||||
#define NEOVIM_EX_DOCMD_H
|
||||
/* ex_docmd.c */
|
||||
void do_exmode(int improved);
|
||||
int do_cmdline_cmd(char_u *cmd);
|
||||
int do_cmdline(char_u *cmdline, char_u *
|
||||
(*fgetline)(int, void *, int), void *cookie,
|
||||
int flags);
|
||||
int getline_equal(char_u *
|
||||
(*fgetline)(int, void *, int), void *cookie, char_u *
|
||||
(*func)(int, void *, int));
|
||||
void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
|
||||
int checkforcmd(char_u **pp, char *cmd, int len);
|
||||
int modifier_len(char_u *cmd);
|
||||
int cmd_exists(char_u *name);
|
||||
char_u *set_one_cmd_context(expand_T *xp, char_u *buff);
|
||||
char_u *skip_range(char_u *cmd, int *ctx);
|
||||
void ex_ni(exarg_T *eap);
|
||||
int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp);
|
||||
void separate_nextcmd(exarg_T *eap);
|
||||
int ends_excmd(int c);
|
||||
char_u *find_nextcmd(char_u *p);
|
||||
char_u *check_nextcmd(char_u *p);
|
||||
char_u *get_command_name(expand_T *xp, int idx);
|
||||
void ex_comclear(exarg_T *eap);
|
||||
void ex_may_print(exarg_T *eap);
|
||||
void uc_clear(garray_T *gap);
|
||||
char_u *get_user_commands(expand_T *xp, int idx);
|
||||
char_u *get_user_cmd_flags(expand_T *xp, int idx);
|
||||
char_u *get_user_cmd_nargs(expand_T *xp, int idx);
|
||||
char_u *get_user_cmd_complete(expand_T *xp, int idx);
|
||||
int parse_compl_arg(char_u *value, int vallen, int *complp, long *argt,
|
||||
char_u **compl_arg);
|
||||
void not_exiting(void);
|
||||
void tabpage_close(int forceit);
|
||||
void tabpage_close_other(tabpage_T *tp, int forceit);
|
||||
void ex_all(exarg_T *eap);
|
||||
void alist_clear(alist_T *al);
|
||||
void alist_init(alist_T *al);
|
||||
void alist_unlink(alist_T *al);
|
||||
void alist_new(void);
|
||||
void alist_expand(int *fnum_list, int fnum_len);
|
||||
void alist_set(alist_T *al, int count, char_u **files, int use_curbuf,
|
||||
int *fnum_list,
|
||||
int fnum_len);
|
||||
void alist_add(alist_T *al, char_u *fname, int set_fnum);
|
||||
void alist_slash_adjust(void);
|
||||
void ex_splitview(exarg_T *eap);
|
||||
void tabpage_new(void);
|
||||
void do_exedit(exarg_T *eap, win_T *old_curwin);
|
||||
void free_cd_dir(void);
|
||||
void post_chdir(int local);
|
||||
void ex_cd(exarg_T *eap);
|
||||
void do_sleep(long msec);
|
||||
int vim_mkdir_emsg(char_u *name, int prot);
|
||||
FILE *open_exfile(char_u *fname, int forceit, char *mode);
|
||||
void update_topline_cursor(void);
|
||||
void exec_normal_cmd(char_u *cmd, int remap, int silent);
|
||||
int find_cmdline_var(char_u *src, int *usedlen);
|
||||
char_u *eval_vars(char_u *src, char_u *srcstart, int *usedlen,
|
||||
linenr_T *lnump, char_u **errormsg,
|
||||
int *escaped);
|
||||
char_u *expand_sfile(char_u *arg);
|
||||
int put_eol(FILE *fd);
|
||||
int put_line(FILE *fd, char *s);
|
||||
void dialog_msg(char_u *buff, char *format, char_u *fname);
|
||||
char_u *get_behave_arg(expand_T *xp, int idx);
|
||||
|
||||
#endif /* NEOVIM_EX_DOCMD_H */
|
||||
2073
src/nvim/ex_eval.c
Normal file
2073
src/nvim/ex_eval.c
Normal file
File diff suppressed because it is too large
Load Diff
159
src/nvim/ex_eval.h
Normal file
159
src/nvim/ex_eval.h
Normal file
@@ -0,0 +1,159 @@
|
||||
#ifndef NEOVIM_EX_EVAL_H
|
||||
#define NEOVIM_EX_EVAL_H
|
||||
|
||||
/*
|
||||
* A list used for saving values of "emsg_silent". Used by ex_try() to save the
|
||||
* value of "emsg_silent" if it was non-zero. When this is done, the CSF_SILENT
|
||||
* flag below is set.
|
||||
*/
|
||||
|
||||
typedef struct eslist_elem eslist_T;
|
||||
struct eslist_elem {
|
||||
int saved_emsg_silent; /* saved value of "emsg_silent" */
|
||||
eslist_T *next; /* next element on the list */
|
||||
};
|
||||
|
||||
/*
|
||||
* For conditional commands a stack is kept of nested conditionals.
|
||||
* When cs_idx < 0, there is no conditional command.
|
||||
*/
|
||||
#define CSTACK_LEN 50
|
||||
|
||||
struct condstack {
|
||||
short cs_flags[CSTACK_LEN]; /* CSF_ flags */
|
||||
char cs_pending[CSTACK_LEN]; /* CSTP_: what's pending in ":finally"*/
|
||||
union {
|
||||
void *csp_rv[CSTACK_LEN]; /* return typeval for pending return */
|
||||
void *csp_ex[CSTACK_LEN]; /* exception for pending throw */
|
||||
} cs_pend;
|
||||
void *cs_forinfo[CSTACK_LEN]; /* info used by ":for" */
|
||||
int cs_line[CSTACK_LEN]; /* line nr of ":while"/":for" line */
|
||||
int cs_idx; /* current entry, or -1 if none */
|
||||
int cs_looplevel; /* nr of nested ":while"s and ":for"s */
|
||||
int cs_trylevel; /* nr of nested ":try"s */
|
||||
eslist_T *cs_emsg_silent_list; /* saved values of "emsg_silent" */
|
||||
char cs_lflags; /* loop flags: CSL_ flags */
|
||||
};
|
||||
# define cs_rettv cs_pend.csp_rv
|
||||
# define cs_exception cs_pend.csp_ex
|
||||
|
||||
/* There is no CSF_IF, the lack of CSF_WHILE, CSF_FOR and CSF_TRY means ":if"
|
||||
* was used. */
|
||||
# define CSF_TRUE 0x0001 /* condition was TRUE */
|
||||
# define CSF_ACTIVE 0x0002 /* current state is active */
|
||||
# define CSF_ELSE 0x0004 /* ":else" has been passed */
|
||||
# define CSF_WHILE 0x0008 /* is a ":while" */
|
||||
# define CSF_FOR 0x0010 /* is a ":for" */
|
||||
|
||||
# define CSF_TRY 0x0100 /* is a ":try" */
|
||||
# define CSF_FINALLY 0x0200 /* ":finally" has been passed */
|
||||
# define CSF_THROWN 0x0400 /* exception thrown to this try conditional */
|
||||
# define CSF_CAUGHT 0x0800 /* exception caught by this try conditional */
|
||||
# define CSF_SILENT 0x1000 /* "emsg_silent" reset by ":try" */
|
||||
/* Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset
|
||||
* (an ":if"), and CSF_SILENT is only used when CSF_TRY is set. */
|
||||
|
||||
/*
|
||||
* What's pending for being reactivated at the ":endtry" of this try
|
||||
* conditional:
|
||||
*/
|
||||
# define CSTP_NONE 0 /* nothing pending in ":finally" clause */
|
||||
# define CSTP_ERROR 1 /* an error is pending */
|
||||
# define CSTP_INTERRUPT 2 /* an interrupt is pending */
|
||||
# define CSTP_THROW 4 /* a throw is pending */
|
||||
# define CSTP_BREAK 8 /* ":break" is pending */
|
||||
# define CSTP_CONTINUE 16 /* ":continue" is pending */
|
||||
# define CSTP_RETURN 24 /* ":return" is pending */
|
||||
# define CSTP_FINISH 32 /* ":finish" is pending */
|
||||
|
||||
/*
|
||||
* Flags for the cs_lflags item in struct condstack.
|
||||
*/
|
||||
# define CSL_HAD_LOOP 1 /* just found ":while" or ":for" */
|
||||
# define CSL_HAD_ENDLOOP 2 /* just found ":endwhile" or ":endfor" */
|
||||
# define CSL_HAD_CONT 4 /* just found ":continue" */
|
||||
# define CSL_HAD_FINA 8 /* just found ":finally" */
|
||||
|
||||
/*
|
||||
* A list of error messages that can be converted to an exception. "throw_msg"
|
||||
* is only set in the first element of the list. Usually, it points to the
|
||||
* original message stored in that element, but sometimes it points to a later
|
||||
* message in the list. See cause_errthrow() below.
|
||||
*/
|
||||
struct msglist {
|
||||
char_u *msg; /* original message */
|
||||
char_u *throw_msg; /* msg to throw: usually original one */
|
||||
struct msglist *next; /* next of several messages in a row */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing an exception.
|
||||
* (don't use "struct exception", it's used by the math library).
|
||||
*/
|
||||
typedef struct vim_exception except_T;
|
||||
struct vim_exception {
|
||||
int type; /* exception type */
|
||||
char_u *value; /* exception value */
|
||||
struct msglist *messages; /* message(s) causing error exception */
|
||||
char_u *throw_name; /* name of the throw point */
|
||||
linenr_T throw_lnum; /* line number of the throw point */
|
||||
except_T *caught; /* next exception on the caught stack */
|
||||
};
|
||||
|
||||
/*
|
||||
* The exception types.
|
||||
*/
|
||||
#define ET_USER 0 /* exception caused by ":throw" command */
|
||||
#define ET_ERROR 1 /* error exception */
|
||||
#define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */
|
||||
|
||||
/*
|
||||
* Structure to save the error/interrupt/exception state between calls to
|
||||
* enter_cleanup() and leave_cleanup(). Must be allocated as an automatic
|
||||
* variable by the (common) caller of these functions.
|
||||
*/
|
||||
typedef struct cleanup_stuff cleanup_T;
|
||||
struct cleanup_stuff {
|
||||
int pending; /* error/interrupt/exception state */
|
||||
except_T *exception; /* exception value */
|
||||
};
|
||||
|
||||
/* ex_eval.c */
|
||||
int aborting(void);
|
||||
void update_force_abort(void);
|
||||
int should_abort(int retcode);
|
||||
int aborted_in_try(void);
|
||||
int cause_errthrow(char_u *mesg, int severe, int *ignore);
|
||||
void free_global_msglist(void);
|
||||
void do_errthrow(struct condstack *cstack, char_u *cmdname);
|
||||
int do_intthrow(struct condstack *cstack);
|
||||
char_u *get_exception_string(void *value, int type, char_u *cmdname,
|
||||
int *should_free);
|
||||
void discard_current_exception(void);
|
||||
void report_make_pending(int pending, void *value);
|
||||
void report_resume_pending(int pending, void *value);
|
||||
void report_discard_pending(int pending, void *value);
|
||||
void ex_if(exarg_T *eap);
|
||||
void ex_endif(exarg_T *eap);
|
||||
void ex_else(exarg_T *eap);
|
||||
void ex_while(exarg_T *eap);
|
||||
void ex_continue(exarg_T *eap);
|
||||
void ex_break(exarg_T *eap);
|
||||
void ex_endwhile(exarg_T *eap);
|
||||
void ex_throw(exarg_T *eap);
|
||||
void do_throw(struct condstack *cstack);
|
||||
void ex_try(exarg_T *eap);
|
||||
void ex_catch(exarg_T *eap);
|
||||
void ex_finally(exarg_T *eap);
|
||||
void ex_endtry(exarg_T *eap);
|
||||
void enter_cleanup(cleanup_T *csp);
|
||||
void leave_cleanup(cleanup_T *csp);
|
||||
int cleanup_conditionals(struct condstack *cstack, int searched_cond,
|
||||
int inclusive);
|
||||
void rewind_conditionals(struct condstack *cstack, int idx,
|
||||
int cond_type,
|
||||
int *cond_level);
|
||||
void ex_endfunction(exarg_T *eap);
|
||||
int has_loop_cmd(char_u *p);
|
||||
|
||||
#endif /* NEOVIM_EX_EVAL_H */
|
||||
5443
src/nvim/ex_getln.c
Normal file
5443
src/nvim/ex_getln.c
Normal file
File diff suppressed because it is too large
Load Diff
66
src/nvim/ex_getln.h
Normal file
66
src/nvim/ex_getln.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef NEOVIM_EX_GETLN_H
|
||||
#define NEOVIM_EX_GETLN_H
|
||||
/* ex_getln.c */
|
||||
char_u *getcmdline(int firstc, long count, int indent);
|
||||
char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr,
|
||||
int xp_context,
|
||||
char_u *xp_arg);
|
||||
int text_locked(void);
|
||||
void text_locked_msg(void);
|
||||
int curbuf_locked(void);
|
||||
int allbuf_locked(void);
|
||||
char_u *getexline(int c, void *cookie, int indent);
|
||||
char_u *getexmodeline(int promptc, void *cookie, int indent);
|
||||
void free_cmdline_buf(void);
|
||||
void putcmdline(int c, int shift);
|
||||
void unputcmdline(void);
|
||||
int put_on_cmdline(char_u *str, int len, int redraw);
|
||||
char_u *save_cmdline_alloc(void);
|
||||
void restore_cmdline_alloc(char_u *p);
|
||||
void cmdline_paste_str(char_u *s, int literally);
|
||||
void redrawcmdline(void);
|
||||
void redrawcmd(void);
|
||||
void compute_cmdrow(void);
|
||||
void gotocmdline(int clr);
|
||||
char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options,
|
||||
int mode);
|
||||
void ExpandInit(expand_T *xp);
|
||||
void ExpandCleanup(expand_T *xp);
|
||||
void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u *
|
||||
*files,
|
||||
int options);
|
||||
char_u *vim_strsave_fnameescape(char_u *fname, int shell);
|
||||
void tilde_replace(char_u *orig_pat, int num_files, char_u **files);
|
||||
char_u *sm_gettail(char_u *s);
|
||||
char_u *addstar(char_u *fname, int len, int context);
|
||||
void set_cmd_context(expand_T *xp, char_u *str, int len, int col);
|
||||
int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount,
|
||||
char_u ***matches);
|
||||
int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file,
|
||||
char_u ***file, char_u *((*func)(expand_T *, int)),
|
||||
int escaped);
|
||||
char_u *globpath(char_u *path, char_u *file, int expand_options);
|
||||
void init_history(void);
|
||||
int get_histtype(char_u *name);
|
||||
void add_to_history(int histype, char_u *new_entry, int in_map, int sep);
|
||||
int get_history_idx(int histype);
|
||||
char_u *get_cmdline_str(void);
|
||||
int get_cmdline_pos(void);
|
||||
int set_cmdline_pos(int pos);
|
||||
int get_cmdline_type(void);
|
||||
char_u *get_history_entry(int histype, int idx);
|
||||
int clr_history(int histype);
|
||||
int del_history_entry(int histype, char_u *str);
|
||||
int del_history_idx(int histype, int idx);
|
||||
void remove_key_from_history(void);
|
||||
int get_list_range(char_u **str, int *num1, int *num2);
|
||||
void ex_history(exarg_T *eap);
|
||||
void prepare_viminfo_history(int asklen, int writing);
|
||||
int read_viminfo_history(vir_T *virp, int writing);
|
||||
void finish_viminfo_history(void);
|
||||
void write_viminfo_history(FILE *fp, int merge);
|
||||
void cmd_pchar(int c, int offset);
|
||||
int cmd_gchar(int offset);
|
||||
char_u *script_get(exarg_T *eap, char_u *cmd);
|
||||
|
||||
#endif /* NEOVIM_EX_GETLN_H */
|
||||
2994
src/nvim/farsi.c
Normal file
2994
src/nvim/farsi.c
Normal file
File diff suppressed because it is too large
Load Diff
183
src/nvim/farsi.h
Normal file
183
src/nvim/farsi.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/// @file farsi.h
|
||||
///
|
||||
/// Farsi characters are categorized into following types:
|
||||
///
|
||||
/// TyA (for capital letter representation)
|
||||
/// TyB (for types that look like _X e.g. AYN)
|
||||
/// TyC (for types that look like X_ e.g. YE_)
|
||||
/// TyD (for types that look like _X_ e.g. _AYN_)
|
||||
/// TyE (for types that look like X e.g. RE)
|
||||
|
||||
#ifndef NEOVIM_FARSI_H
|
||||
#define NEOVIM_FARSI_H
|
||||
|
||||
#include "normal.h"
|
||||
#include "types.h"
|
||||
|
||||
// Farsi character set definition
|
||||
|
||||
// Begin of the non-standard part
|
||||
|
||||
#define TEE_ 0x80
|
||||
#define ALEF_U_H_ 0x81
|
||||
#define ALEF_ 0x82
|
||||
#define _BE 0x83
|
||||
#define _PE 0x84
|
||||
#define _TE 0x85
|
||||
#define _SE 0x86
|
||||
#define _JIM 0x87
|
||||
#define _CHE 0x88
|
||||
#define _HE_J 0x89
|
||||
#define _XE 0x8a
|
||||
#define _SIN 0x8b
|
||||
#define _SHIN 0x8c
|
||||
#define _SAD 0x8d
|
||||
#define _ZAD 0x8e
|
||||
#define _AYN 0x8f
|
||||
#define _AYN_ 0x90
|
||||
#define AYN_ 0x91
|
||||
#define _GHAYN 0x92
|
||||
#define _GHAYN_ 0x93
|
||||
#define GHAYN_ 0x94
|
||||
#define _FE 0x95
|
||||
#define _GHAF 0x96
|
||||
#define _KAF 0x97
|
||||
#define _GAF 0x98
|
||||
#define _LAM 0x99
|
||||
#define LA 0x9a
|
||||
#define _MIM 0x9b
|
||||
#define _NOON 0x9c
|
||||
#define _HE 0x9d
|
||||
#define _HE_ 0x9e
|
||||
#define _YE 0x9f
|
||||
#define _IE 0xec
|
||||
#define IE_ 0xed
|
||||
#define IE 0xfb
|
||||
#define _YEE 0xee
|
||||
#define YEE_ 0xef
|
||||
#define YE_ 0xff
|
||||
|
||||
// End of the non-standard part
|
||||
|
||||
// Standard part
|
||||
|
||||
#define F_BLANK 0xa0 // Farsi ' ' (SP) character
|
||||
#define F_PSP 0xa1 // PSP for capitalizing of a character
|
||||
#define F_PCN 0xa2 // PCN for redefining of the hamye meaning
|
||||
#define F_EXCL 0xa3 // Farsi ! character
|
||||
#define F_CURRENCY 0xa4 // Farsi Rial character
|
||||
#define F_PERCENT 0xa5 // Farsi % character
|
||||
#define F_PERIOD 0xa6 // Farsi '.' character
|
||||
#define F_COMMA 0xa7 // Farsi ',' character
|
||||
#define F_LPARENT 0xa8 // Farsi '(' character
|
||||
#define F_RPARENT 0xa9 // Farsi ')' character
|
||||
#define F_MUL 0xaa // Farsi 'x' character
|
||||
#define F_PLUS 0xab // Farsi '+' character
|
||||
#define F_BCOMMA 0xac // Farsi comma character
|
||||
#define F_MINUS 0xad // Farsi '-' character
|
||||
#define F_DIVIDE 0xae // Farsi divide (/) character
|
||||
#define F_SLASH 0xaf // Farsi '/' character
|
||||
|
||||
#define FARSI_0 0xb0
|
||||
#define FARSI_1 0xb1
|
||||
#define FARSI_2 0xb2
|
||||
#define FARSI_3 0xb3
|
||||
#define FARSI_4 0xb4
|
||||
#define FARSI_5 0xb5
|
||||
#define FARSI_6 0xb6
|
||||
#define FARSI_7 0xb7
|
||||
#define FARSI_8 0xb8
|
||||
#define FARSI_9 0xb9
|
||||
|
||||
#define F_DCOLON 0xba // Farsi ':' character
|
||||
#define F_SEMICOLON 0xbb // Farsi ';' character
|
||||
#define F_GREATER 0xbc // Farsi '>' character
|
||||
#define F_EQUALS 0xbd // Farsi '=' character
|
||||
#define F_LESS 0xbe // Farsi '<' character
|
||||
#define F_QUESTION 0xbf // Farsi ? character
|
||||
|
||||
#define ALEF_A 0xc0
|
||||
#define ALEF 0xc1
|
||||
#define HAMZE 0xc2
|
||||
#define BE 0xc3
|
||||
#define PE 0xc4
|
||||
#define TE 0xc5
|
||||
#define SE 0xc6
|
||||
#define JIM 0xc7
|
||||
#define CHE 0xc8
|
||||
#define HE_J 0xc9
|
||||
#define XE 0xca
|
||||
#define DAL 0xcb
|
||||
#define ZAL 0xcc
|
||||
#define RE 0xcd
|
||||
#define ZE 0xce
|
||||
#define JE 0xcf
|
||||
#define SIN 0xd0
|
||||
#define SHIN 0xd1
|
||||
#define SAD 0xd2
|
||||
#define ZAD 0xd3
|
||||
#define _TA 0xd4
|
||||
#define _ZA 0xd5
|
||||
#define AYN 0xd6
|
||||
#define GHAYN 0xd7
|
||||
#define FE 0xd8
|
||||
#define GHAF 0xd9
|
||||
#define KAF 0xda
|
||||
#define GAF 0xdb
|
||||
#define LAM 0xdc
|
||||
#define MIM 0xdd
|
||||
#define NOON 0xde
|
||||
#define WAW 0xdf
|
||||
#define F_HE 0xe0 // F_ added for name clash with Perl
|
||||
#define YE 0xe1
|
||||
#define TEE 0xfc
|
||||
#define _KAF_H 0xfd
|
||||
#define YEE 0xfe
|
||||
|
||||
#define F_LBRACK 0xe2 // Farsi '[' character
|
||||
#define F_RBRACK 0xe3 // Farsi ']' character
|
||||
#define F_LBRACE 0xe4 // Farsi '{' character
|
||||
#define F_RBRACE 0xe5 // Farsi '}' character
|
||||
#define F_LQUOT 0xe6 // Farsi left quotation character
|
||||
#define F_RQUOT 0xe7 // Farsi right quotation character
|
||||
#define F_STAR 0xe8 // Farsi '*' character
|
||||
#define F_UNDERLINE 0xe9 // Farsi '_' character
|
||||
#define F_PIPE 0xea // Farsi '|' character
|
||||
#define F_BSLASH 0xeb // Farsi '\' character
|
||||
|
||||
#define MAD 0xf0
|
||||
#define JAZR 0xf1
|
||||
#define OW 0xf2
|
||||
#define MAD_N 0xf3
|
||||
#define JAZR_N 0xf4
|
||||
#define OW_OW 0xf5
|
||||
#define TASH 0xf6
|
||||
#define OO 0xf7
|
||||
#define ALEF_U_H 0xf8
|
||||
#define WAW_H 0xf9
|
||||
#define ALEF_D_H 0xfa
|
||||
|
||||
// definitions for the window dependent functions (w_farsi).
|
||||
#define W_CONV 0x1
|
||||
#define W_R_L 0x2
|
||||
|
||||
// special Farsi text messages
|
||||
extern const char_u farsi_text_1[];
|
||||
extern const char_u farsi_text_2[];
|
||||
extern const char_u farsi_text_3[];
|
||||
extern const char_u farsi_text_5[];
|
||||
|
||||
int toF_TyA(int c);
|
||||
int fkmap(int c);
|
||||
void conv_to_pvim(void);
|
||||
void conv_to_pstd(void);
|
||||
char_u *lrswap(char_u *ibuf);
|
||||
char_u *lrFswap(char_u *cmdbuf, int len);
|
||||
char_u *lrF_sub(char_u *ibuf);
|
||||
int cmdl_fkmap(int c);
|
||||
int F_isalpha(int c);
|
||||
int F_isdigit(int c);
|
||||
int F_ischar(int c);
|
||||
void farsi_fkey(cmdarg_T *cap);
|
||||
|
||||
#endif // NEOVIM_FARSI_H
|
||||
1565
src/nvim/file_search.c
Normal file
1565
src/nvim/file_search.c
Normal file
File diff suppressed because it is too large
Load Diff
23
src/nvim/file_search.h
Normal file
23
src/nvim/file_search.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef NEOVIM_FILE_SEARCH_H
|
||||
#define NEOVIM_FILE_SEARCH_H
|
||||
|
||||
void *vim_findfile_init(char_u *path, char_u *filename, char_u *
|
||||
stopdirs, int level, int free_visited,
|
||||
int find_what, void *search_ctx_arg,
|
||||
int tagfile,
|
||||
char_u *rel_fname);
|
||||
char_u *vim_findfile_stopdir(char_u *buf);
|
||||
void vim_findfile_cleanup(void *ctx);
|
||||
char_u *vim_findfile(void *search_ctx_arg);
|
||||
void vim_findfile_free_visited(void *search_ctx_arg);
|
||||
char_u *find_file_in_path(char_u *ptr, int len, int options, int first,
|
||||
char_u *rel_fname);
|
||||
void free_findfile(void);
|
||||
char_u *find_directory_in_path(char_u *ptr, int len, int options,
|
||||
char_u *rel_fname);
|
||||
char_u *find_file_in_path_option(char_u *ptr, int len, int options,
|
||||
int first, char_u *path_option,
|
||||
int find_what, char_u *rel_fname,
|
||||
char_u *suffixes);
|
||||
|
||||
#endif /* NEOVIM_FILE_SEARCH_H */
|
||||
8148
src/nvim/fileio.c
Normal file
8148
src/nvim/fileio.c
Normal file
File diff suppressed because it is too large
Load Diff
94
src/nvim/fileio.h
Normal file
94
src/nvim/fileio.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef NEOVIM_FILEIO_H
|
||||
#define NEOVIM_FILEIO_H
|
||||
|
||||
#include "buffer_defs.h"
|
||||
#include "os/os.h"
|
||||
|
||||
/*
|
||||
* Struct to save values in before executing autocommands for a buffer that is
|
||||
* not the current buffer. Without FEAT_AUTOCMD only "curbuf" is remembered.
|
||||
*/
|
||||
typedef struct {
|
||||
buf_T *save_curbuf; /* saved curbuf */
|
||||
int use_aucmd_win; /* using aucmd_win */
|
||||
win_T *save_curwin; /* saved curwin */
|
||||
win_T *new_curwin; /* new curwin */
|
||||
buf_T *new_curbuf; /* new curbuf */
|
||||
char_u *globaldir; /* saved value of globaldir */
|
||||
} aco_save_T;
|
||||
|
||||
/* fileio.c */
|
||||
void filemess(buf_T *buf, char_u *name, char_u *s, int attr);
|
||||
int readfile(char_u *fname, char_u *sfname, linenr_T from,
|
||||
linenr_T lines_to_skip, linenr_T lines_to_read, exarg_T *eap,
|
||||
int flags);
|
||||
void prep_exarg(exarg_T *eap, buf_T *buf);
|
||||
void set_file_options(int set_options, exarg_T *eap);
|
||||
void set_forced_fenc(exarg_T *eap);
|
||||
int prepare_crypt_read(FILE *fp);
|
||||
char_u *prepare_crypt_write(buf_T *buf, int *lenp);
|
||||
int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start,
|
||||
linenr_T end, exarg_T *eap, int append, int forceit,
|
||||
int reset_changed,
|
||||
int filtering);
|
||||
void msg_add_fname(buf_T *buf, char_u *fname);
|
||||
void msg_add_lines(int insert_space, long lnum, off_t nchars);
|
||||
void shorten_fnames(int force);
|
||||
char_u *modname(char_u *fname, char_u *ext, int prepend_dot);
|
||||
int vim_fgets(char_u *buf, int size, FILE *fp);
|
||||
int tag_fgets(char_u *buf, int size, FILE *fp);
|
||||
int vim_rename(char_u *from, char_u *to);
|
||||
int check_timestamps(int focus);
|
||||
int buf_check_timestamp(buf_T *buf, int focus);
|
||||
void buf_reload(buf_T *buf, int orig_mode);
|
||||
void buf_store_file_info(buf_T *buf, FileInfo *file_info);
|
||||
void write_lnum_adjust(linenr_T offset);
|
||||
void vim_deltempdir(void);
|
||||
char_u *vim_tempname(int extra_char);
|
||||
void forward_slash(char_u *fname);
|
||||
void aubuflocal_remove(buf_T *buf);
|
||||
int au_has_group(char_u *name);
|
||||
void do_augroup(char_u *arg, int del_group);
|
||||
void free_all_autocmds(void);
|
||||
int check_ei(void);
|
||||
char_u *au_event_disable(char *what);
|
||||
void au_event_restore(char_u *old_ei);
|
||||
void do_autocmd(char_u *arg, int forceit);
|
||||
int do_doautocmd(char_u *arg, int do_msg);
|
||||
void ex_doautoall(exarg_T *eap);
|
||||
int check_nomodeline(char_u **argp);
|
||||
void aucmd_prepbuf(aco_save_T *aco, buf_T *buf);
|
||||
void aucmd_restbuf(aco_save_T *aco);
|
||||
int apply_autocmds(event_T event, char_u *fname, char_u *fname_io,
|
||||
int force,
|
||||
buf_T *buf);
|
||||
int apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io,
|
||||
int force, buf_T *buf,
|
||||
int *retval);
|
||||
int has_cursorhold(void);
|
||||
int trigger_cursorhold(void);
|
||||
int has_cursormoved(void);
|
||||
int has_cursormovedI(void);
|
||||
int has_textchanged(void);
|
||||
int has_textchangedI(void);
|
||||
int has_insertcharpre(void);
|
||||
void block_autocmds(void);
|
||||
void unblock_autocmds(void);
|
||||
char_u *getnextac(int c, void *cookie, int indent);
|
||||
int has_autocmd(event_T event, char_u *sfname, buf_T *buf);
|
||||
char_u *get_augroup_name(expand_T *xp, int idx);
|
||||
char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd);
|
||||
char_u *get_event_name(expand_T *xp, int idx);
|
||||
int autocmd_supported(char_u *name);
|
||||
int au_exists(char_u *arg);
|
||||
int match_file_pat(char_u *pattern, regprog_T *prog, char_u *fname,
|
||||
char_u *sfname, char_u *tail,
|
||||
int allow_dirs);
|
||||
int match_file_list(char_u *list, char_u *sfname, char_u *ffname);
|
||||
char_u *file_pat_to_reg_pat(char_u *pat, char_u *pat_end,
|
||||
char *allow_dirs,
|
||||
int no_bslash);
|
||||
long read_eintr(int fd, void *buf, size_t bufsize);
|
||||
long write_eintr(int fd, void *buf, size_t bufsize);
|
||||
|
||||
#endif /* NEOVIM_FILEIO_H */
|
||||
3033
src/nvim/fold.c
Normal file
3033
src/nvim/fold.c
Normal file
File diff suppressed because it is too large
Load Diff
65
src/nvim/fold.h
Normal file
65
src/nvim/fold.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef NEOVIM_FOLD_H
|
||||
#define NEOVIM_FOLD_H
|
||||
|
||||
/*
|
||||
* Info used to pass info about a fold from the fold-detection code to the
|
||||
* code that displays the foldcolumn.
|
||||
*/
|
||||
typedef struct foldinfo {
|
||||
int fi_level; /* level of the fold; when this is zero the
|
||||
other fields are invalid */
|
||||
int fi_lnum; /* line number where fold starts */
|
||||
int fi_low_level; /* lowest fold level that starts in the same
|
||||
line */
|
||||
} foldinfo_T;
|
||||
|
||||
void copyFoldingState(win_T *wp_from, win_T *wp_to);
|
||||
int hasAnyFolding(win_T *win);
|
||||
int hasFolding(linenr_T lnum, linenr_T *firstp, linenr_T *lastp);
|
||||
int hasFoldingWin(win_T *win, linenr_T lnum, linenr_T *firstp,
|
||||
linenr_T *lastp, int cache,
|
||||
foldinfo_T *infop);
|
||||
int foldLevel(linenr_T lnum);
|
||||
int lineFolded(win_T *win, linenr_T lnum);
|
||||
long foldedCount(win_T *win, linenr_T lnum, foldinfo_T *infop);
|
||||
int foldmethodIsManual(win_T *wp);
|
||||
int foldmethodIsIndent(win_T *wp);
|
||||
int foldmethodIsExpr(win_T *wp);
|
||||
int foldmethodIsMarker(win_T *wp);
|
||||
int foldmethodIsSyntax(win_T *wp);
|
||||
int foldmethodIsDiff(win_T *wp);
|
||||
void closeFold(linenr_T lnum, long count);
|
||||
void closeFoldRecurse(linenr_T lnum);
|
||||
void opFoldRange(linenr_T first, linenr_T last, int opening,
|
||||
int recurse,
|
||||
int had_visual);
|
||||
void openFold(linenr_T lnum, long count);
|
||||
void openFoldRecurse(linenr_T lnum);
|
||||
void foldOpenCursor(void);
|
||||
void newFoldLevel(void);
|
||||
void foldCheckClose(void);
|
||||
int foldManualAllowed(int create);
|
||||
void foldCreate(linenr_T start, linenr_T end);
|
||||
void deleteFold(linenr_T start, linenr_T end, int recursive,
|
||||
int had_visual);
|
||||
void clearFolding(win_T *win);
|
||||
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot);
|
||||
void foldUpdateAll(win_T *win);
|
||||
int foldMoveTo(int updown, int dir, long count);
|
||||
void foldInitWin(win_T *new_win);
|
||||
int find_wl_entry(win_T *win, linenr_T lnum);
|
||||
void foldAdjustVisual(void);
|
||||
void foldAdjustCursor(void);
|
||||
void cloneFoldGrowArray(garray_T *from, garray_T *to);
|
||||
void deleteFoldRecurse(garray_T *gap);
|
||||
void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2,
|
||||
long amount,
|
||||
long amount_after);
|
||||
int getDeepestNesting(void);
|
||||
char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
|
||||
foldinfo_T *foldinfo,
|
||||
char_u *buf);
|
||||
void foldtext_cleanup(char_u *str);
|
||||
int put_folds(FILE *fd, win_T *wp);
|
||||
|
||||
#endif /* NEOVIM_FOLD_H */
|
||||
110
src/nvim/func_attr.h
Normal file
110
src/nvim/func_attr.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef NEOVIM_FUNC_ATTR_H
|
||||
#define NEOVIM_FUNC_ATTR_H
|
||||
|
||||
// gcc and clang expose their version as follows:
|
||||
//
|
||||
// gcc 4.7.2:
|
||||
// __GNUC__ = 4
|
||||
// __GNUC_MINOR__ = 7
|
||||
// __GNUC_PATCHLEVEL = 2
|
||||
//
|
||||
// clang 3.4 (claims compat with gcc 4.2.1):
|
||||
// __GNUC__ = 4
|
||||
// __GNUC_MINOR__ = 2
|
||||
// __GNUC_PATCHLEVEL = 1
|
||||
// __clang__ = 1
|
||||
// __clang_major__ = 3
|
||||
// __clang_minor__ = 4
|
||||
//
|
||||
// To view the default defines of these compilers, you can perform:
|
||||
//
|
||||
// $ gcc -E -dM - </dev/null
|
||||
// $ echo | clang -dM -E -
|
||||
|
||||
#ifdef __GNUC__
|
||||
// place defines for all gnulikes here, for now that's gcc, clang and
|
||||
// intel.
|
||||
|
||||
// place these after the argument list of the function declaration
|
||||
// (not definition), like so:
|
||||
// void myfunc(void) FUNC_ATTR_ALWAYS_INLINE;
|
||||
#define FUNC_ATTR_MALLOC __attribute__((malloc))
|
||||
#define FUNC_ATTR_ALLOC_ALIGN(x) __attribute__((alloc_align(x)))
|
||||
#define FUNC_ATTR_PURE __attribute__ ((pure))
|
||||
#define FUNC_ATTR_CONST __attribute__((const))
|
||||
#define FUNC_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define FUNC_ATTR_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#define FUNC_ATTR_UNUSED __attribute__((unused))
|
||||
|
||||
#ifdef __clang__
|
||||
// clang only
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
// intel only
|
||||
#else
|
||||
#define GCC_VERSION \
|
||||
(__GNUC__ * 10000 + \
|
||||
__GNUC_MINOR__ * 100 + \
|
||||
__GNUC_PATCHLEVEL__)
|
||||
// gcc only
|
||||
#define FUNC_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
|
||||
#define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) __attribute__((alloc_size(x,y)))
|
||||
#define FUNC_ATTR_NONNULL_ALL __attribute__((nonnull))
|
||||
#define FUNC_ATTR_NONNULL_ARG(...) __attribute__((nonnull(__VA_ARGS__)))
|
||||
#if GCC_VERSION >= 40900
|
||||
#define FUNC_ATTR_NONNULL_RET __attribute__((returns_nonnull))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// define function attributes that haven't been defined for this specific
|
||||
// compiler.
|
||||
|
||||
#ifndef FUNC_ATTR_MALLOC
|
||||
#define FUNC_ATTR_MALLOC
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_ALLOC_SIZE
|
||||
#define FUNC_ATTR_ALLOC_SIZE(x)
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_ALLOC_SIZE_PROD
|
||||
#define FUNC_ATTR_ALLOC_SIZE_PROD(x,y)
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_ALLOC_ALIGN
|
||||
#define FUNC_ATTR_ALLOC_ALIGN(x)
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_PURE
|
||||
#define FUNC_ATTR_PURE
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_CONST
|
||||
#define FUNC_ATTR_CONST
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
#define FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_ALWAYS_INLINE
|
||||
#define FUNC_ATTR_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_UNUSED
|
||||
#define FUNC_ATTR_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_NONNULL_ALL
|
||||
#define FUNC_ATTR_NONNULL_ALL
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_NONNULL_ARG
|
||||
#define FUNC_ATTR_NONNULL_ARG(...)
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_NONNULL_RET
|
||||
#define FUNC_ATTR_NONNULL_RET
|
||||
#endif
|
||||
|
||||
#endif // NEOVIM_FUNC_ATTR_H
|
||||
197
src/nvim/garray.c
Normal file
197
src/nvim/garray.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/// @file garray.c
|
||||
///
|
||||
/// Functions for handling growing arrays.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "vim.h"
|
||||
#include "ascii.h"
|
||||
#include "misc2.h"
|
||||
#include "memory.h"
|
||||
#include "path.h"
|
||||
#include "garray.h"
|
||||
|
||||
// #include "globals.h"
|
||||
#include "memline.h"
|
||||
|
||||
/// Clear an allocated growing array.
|
||||
void ga_clear(garray_T *gap)
|
||||
{
|
||||
free(gap->ga_data);
|
||||
|
||||
// Initialize growing array without resetting itemsize or growsize
|
||||
gap->ga_data = NULL;
|
||||
gap->ga_maxlen = 0;
|
||||
gap->ga_len = 0;
|
||||
}
|
||||
|
||||
/// Clear a growing array that contains a list of strings.
|
||||
///
|
||||
/// @param gap
|
||||
void ga_clear_strings(garray_T *gap)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < gap->ga_len; ++i) {
|
||||
free(((char_u **)(gap->ga_data))[i]);
|
||||
}
|
||||
ga_clear(gap);
|
||||
}
|
||||
|
||||
/// Initialize a growing array.
|
||||
///
|
||||
/// @param gap
|
||||
/// @param itemsize
|
||||
/// @param growsize
|
||||
void ga_init(garray_T *gap, int itemsize, int growsize)
|
||||
{
|
||||
gap->ga_data = NULL;
|
||||
gap->ga_maxlen = 0;
|
||||
gap->ga_len = 0;
|
||||
gap->ga_itemsize = itemsize;
|
||||
gap->ga_growsize = growsize;
|
||||
}
|
||||
|
||||
/// Make room in growing array "gap" for at least "n" items.
|
||||
///
|
||||
/// @param gap
|
||||
/// @param n
|
||||
void ga_grow(garray_T *gap, int n)
|
||||
{
|
||||
if (gap->ga_maxlen - gap->ga_len >= n) {
|
||||
// the garray still has enough space, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
// the garray grows by at least growsize (do we have a MIN macro somewhere?)
|
||||
n = (n < gap->ga_growsize) ? gap->ga_growsize : n;
|
||||
|
||||
size_t new_size = (size_t)(gap->ga_itemsize * (gap->ga_len + n));
|
||||
size_t old_size = (size_t)(gap->ga_itemsize * gap->ga_maxlen);
|
||||
|
||||
// reallocate and clear the new memory
|
||||
char_u *pp = xrealloc(gap->ga_data, new_size);
|
||||
memset(pp + old_size, 0, new_size - old_size);
|
||||
|
||||
gap->ga_maxlen = gap->ga_len + n;
|
||||
gap->ga_data = pp;
|
||||
}
|
||||
|
||||
/// Sort "gap" and remove duplicate entries. "gap" is expected to contain a
|
||||
/// list of file names in allocated memory.
|
||||
///
|
||||
/// @param gap
|
||||
void ga_remove_duplicate_strings(garray_T *gap)
|
||||
{
|
||||
char_u **fnames = gap->ga_data;
|
||||
|
||||
// sort the growing array, which puts duplicates next to each other
|
||||
sort_strings(fnames, gap->ga_len);
|
||||
|
||||
// loop over the growing array in reverse
|
||||
for (int i = gap->ga_len - 1; i > 0; i--) {
|
||||
if (fnamecmp(fnames[i - 1], fnames[i]) == 0) {
|
||||
free(fnames[i]);
|
||||
|
||||
// close the gap (move all strings one slot lower)
|
||||
for (int j = i + 1; j < gap->ga_len; j++) {
|
||||
fnames[j - 1] = fnames[j];
|
||||
}
|
||||
|
||||
--gap->ga_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For a growing array that contains a list of strings: concatenate all the
|
||||
/// strings with sep as separator.
|
||||
///
|
||||
/// @param gap
|
||||
///
|
||||
/// @returns the concatenated strings
|
||||
char_u *ga_concat_strings_sep(const garray_T *gap, const char *sep)
|
||||
{
|
||||
const size_t nelem = (size_t) gap->ga_len;
|
||||
const char **strings = gap->ga_data;
|
||||
|
||||
if (nelem == 0) {
|
||||
return (char_u *) xstrdup("");
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
for (size_t i = 0; i < nelem; i++) {
|
||||
len += strlen(strings[i]);
|
||||
}
|
||||
|
||||
// add some space for the (num - 1) separators
|
||||
len += (nelem - 1) * strlen(sep);
|
||||
char *const ret = xmallocz(len);
|
||||
|
||||
char *s = ret;
|
||||
for (size_t i = 0; i < nelem - 1; i++) {
|
||||
s = xstpcpy(s, strings[i]);
|
||||
s = xstpcpy(s, sep);
|
||||
}
|
||||
s = xstpcpy(s, strings[nelem - 1]);
|
||||
|
||||
return (char_u *) ret;
|
||||
}
|
||||
|
||||
/// For a growing array that contains a list of strings: concatenate all the
|
||||
/// strings with a separating comma.
|
||||
///
|
||||
/// @param gap
|
||||
///
|
||||
/// @returns the concatenated strings
|
||||
char_u* ga_concat_strings(const garray_T *gap)
|
||||
{
|
||||
return ga_concat_strings_sep(gap, ",");
|
||||
}
|
||||
|
||||
/// Concatenate a string to a growarray which contains characters.
|
||||
///
|
||||
/// WARNING:
|
||||
/// - Does NOT copy the NUL at the end!
|
||||
/// - The parameter may not overlap with the growing array
|
||||
///
|
||||
/// @param gap
|
||||
/// @param s
|
||||
void ga_concat(garray_T *gap, const char_u *restrict s)
|
||||
{
|
||||
int len = (int)strlen((char *) s);
|
||||
ga_grow(gap, len);
|
||||
char *data = gap->ga_data;
|
||||
memcpy(data + gap->ga_len, s, (size_t) len);
|
||||
gap->ga_len += len;
|
||||
}
|
||||
|
||||
/// Append one byte to a growarray which contains bytes.
|
||||
///
|
||||
/// @param gap
|
||||
/// @param c
|
||||
void ga_append(garray_T *gap, char c)
|
||||
{
|
||||
ga_grow(gap, 1);
|
||||
char *str = gap->ga_data;
|
||||
str[gap->ga_len] = c;
|
||||
gap->ga_len++;
|
||||
}
|
||||
|
||||
#if defined(UNIX) || defined(WIN3264)
|
||||
|
||||
/// Append the text in "gap" below the cursor line and clear "gap".
|
||||
///
|
||||
/// @param gap
|
||||
void append_ga_line(garray_T *gap)
|
||||
{
|
||||
// Remove trailing CR.
|
||||
if ((gap->ga_len > 0)
|
||||
&& !curbuf->b_p_bin
|
||||
&& (((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)) {
|
||||
gap->ga_len--;
|
||||
}
|
||||
ga_append(gap, NUL);
|
||||
ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
|
||||
gap->ga_len = 0;
|
||||
}
|
||||
|
||||
#endif // if defined(UNIX) || defined(WIN3264)
|
||||
31
src/nvim/garray.h
Normal file
31
src/nvim/garray.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef NEOVIM_GARRAY_H
|
||||
#define NEOVIM_GARRAY_H
|
||||
|
||||
#include "func_attr.h"
|
||||
|
||||
/// Structure used for growing arrays.
|
||||
/// This is used to store information that only grows, is deleted all at
|
||||
/// once, and needs to be accessed by index. See ga_clear() and ga_grow().
|
||||
typedef struct growarray {
|
||||
int ga_len; // current number of items used
|
||||
int ga_maxlen; // maximum number of items possible
|
||||
int ga_itemsize; // sizeof(item)
|
||||
int ga_growsize; // number of items to grow each time
|
||||
void *ga_data; // pointer to the first item
|
||||
} garray_T;
|
||||
|
||||
#define GA_EMPTY { 0, 0, 0, 0, NULL }
|
||||
|
||||
void ga_clear(garray_T *gap);
|
||||
void ga_clear_strings(garray_T *gap);
|
||||
void ga_init(garray_T *gap, int itemsize, int growsize);
|
||||
void ga_grow(garray_T *gap, int n);
|
||||
char_u *ga_concat_strings_sep(const garray_T *gap, const char *sep)
|
||||
FUNC_ATTR_NONNULL_RET;
|
||||
char_u *ga_concat_strings(const garray_T *gap) FUNC_ATTR_NONNULL_RET;
|
||||
void ga_remove_duplicate_strings(garray_T *gap);
|
||||
void ga_concat(garray_T *gap, const char_u *restrict s);
|
||||
void ga_append(garray_T *gap, char c);
|
||||
void append_ga_line(garray_T *gap);
|
||||
|
||||
#endif // NEOVIM_GARRAY_H
|
||||
4333
src/nvim/getchar.c
Normal file
4333
src/nvim/getchar.c
Normal file
File diff suppressed because it is too large
Load Diff
77
src/nvim/getchar.h
Normal file
77
src/nvim/getchar.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef NEOVIM_GETCHAR_H
|
||||
#define NEOVIM_GETCHAR_H
|
||||
/* getchar.c */
|
||||
void free_buff(buffheader_T *buf);
|
||||
char_u *get_recorded(void);
|
||||
char_u *get_inserted(void);
|
||||
int stuff_empty(void);
|
||||
int readbuf1_empty(void);
|
||||
void typeahead_noflush(int c);
|
||||
void flush_buffers(int flush_typeahead);
|
||||
void ResetRedobuff(void);
|
||||
void CancelRedo(void);
|
||||
void saveRedobuff(void);
|
||||
void restoreRedobuff(void);
|
||||
void AppendToRedobuff(char_u *s);
|
||||
void AppendToRedobuffLit(char_u *str, int len);
|
||||
void AppendCharToRedobuff(int c);
|
||||
void AppendNumberToRedobuff(long n);
|
||||
void stuffReadbuff(char_u *s);
|
||||
void stuffReadbuffLen(char_u *s, long len);
|
||||
void stuffReadbuffSpec(char_u *s);
|
||||
void stuffcharReadbuff(int c);
|
||||
void stuffnumReadbuff(long n);
|
||||
int start_redo(long count, int old_redo);
|
||||
int start_redo_ins(void);
|
||||
void stop_redo_ins(void);
|
||||
int ins_typebuf(char_u *str, int noremap, int offset, int nottyped,
|
||||
int silent);
|
||||
void ins_char_typebuf(int c);
|
||||
int typebuf_changed(int tb_change_cnt);
|
||||
int typebuf_typed(void);
|
||||
int typebuf_maplen(void);
|
||||
void del_typebuf(int len, int offset);
|
||||
int alloc_typebuf(void);
|
||||
void free_typebuf(void);
|
||||
int save_typebuf(void);
|
||||
void save_typeahead(tasave_T *tp);
|
||||
void restore_typeahead(tasave_T *tp);
|
||||
void openscript(char_u *name, int directly);
|
||||
void close_all_scripts(void);
|
||||
int using_script(void);
|
||||
void before_blocking(void);
|
||||
void updatescript(int c);
|
||||
int vgetc(void);
|
||||
int safe_vgetc(void);
|
||||
int plain_vgetc(void);
|
||||
int vpeekc(void);
|
||||
int vpeekc_nomap(void);
|
||||
int vpeekc_any(void);
|
||||
int char_avail(void);
|
||||
void vungetc(int c);
|
||||
int inchar(char_u *buf, int maxlen, long wait_time, int tb_change_cnt);
|
||||
int fix_input_buffer(char_u *buf, int len, int script);
|
||||
int input_available(void);
|
||||
int do_map(int maptype, char_u *arg, int mode, int abbrev);
|
||||
int get_map_mode(char_u **cmdp, int forceit);
|
||||
void map_clear(char_u *cmdp, char_u *arg, int forceit, int abbr);
|
||||
void map_clear_int(buf_T *buf, int mode, int local, int abbr);
|
||||
char_u *map_mode_to_chars(int mode);
|
||||
int map_to_exists(char_u *str, char_u *modechars, int abbr);
|
||||
int map_to_exists_mode(char_u *rhs, int mode, int abbr);
|
||||
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg,
|
||||
int forceit, int isabbrev, int isunmap,
|
||||
cmdidx_T cmdidx);
|
||||
int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
|
||||
int check_abbr(int c, char_u *ptr, int col, int mincol);
|
||||
char_u *vim_strsave_escape_csi(char_u *p);
|
||||
void vim_unescape_csi(char_u *p);
|
||||
int makemap(FILE *fd, buf_T *buf);
|
||||
int put_escstr(FILE *fd, char_u *strstart, int what);
|
||||
void check_map_keycodes(void);
|
||||
char_u *check_map(char_u *keys, int mode, int exact, int ign_mod,
|
||||
int abbr, mapblock_T **mp_ptr,
|
||||
int *local_ptr);
|
||||
void add_map(char_u *map, int mode);
|
||||
|
||||
#endif /* NEOVIM_GETCHAR_H */
|
||||
1140
src/nvim/globals.h
Normal file
1140
src/nvim/globals.h
Normal file
File diff suppressed because it is too large
Load Diff
3175
src/nvim/hardcopy.c
Normal file
3175
src/nvim/hardcopy.c
Normal file
File diff suppressed because it is too large
Load Diff
93
src/nvim/hardcopy.h
Normal file
93
src/nvim/hardcopy.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef NEOVIM_HARDCOPY_H
|
||||
#define NEOVIM_HARDCOPY_H
|
||||
|
||||
/*
|
||||
* Structure to hold printing color and font attributes.
|
||||
*/
|
||||
typedef struct {
|
||||
long_u fg_color;
|
||||
long_u bg_color;
|
||||
int bold;
|
||||
int italic;
|
||||
int underline;
|
||||
int undercurl;
|
||||
} prt_text_attr_T;
|
||||
|
||||
/*
|
||||
* Structure passed back to the generic printer code.
|
||||
*/
|
||||
typedef struct {
|
||||
int n_collated_copies;
|
||||
int n_uncollated_copies;
|
||||
int duplex;
|
||||
int chars_per_line;
|
||||
int lines_per_page;
|
||||
int has_color;
|
||||
prt_text_attr_T number;
|
||||
int modec;
|
||||
int do_syntax;
|
||||
int user_abort;
|
||||
char_u *jobname;
|
||||
char_u *outfile;
|
||||
char_u *arguments;
|
||||
} prt_settings_T;
|
||||
|
||||
/*
|
||||
* Generic option table item, only used for printer at the moment.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int hasnum;
|
||||
long number;
|
||||
char_u *string; /* points into option string */
|
||||
int strlen;
|
||||
int present;
|
||||
} option_table_T;
|
||||
|
||||
#define OPT_PRINT_TOP 0
|
||||
#define OPT_PRINT_BOT 1
|
||||
#define OPT_PRINT_LEFT 2
|
||||
#define OPT_PRINT_RIGHT 3
|
||||
#define OPT_PRINT_HEADERHEIGHT 4
|
||||
#define OPT_PRINT_SYNTAX 5
|
||||
#define OPT_PRINT_NUMBER 6
|
||||
#define OPT_PRINT_WRAP 7
|
||||
#define OPT_PRINT_DUPLEX 8
|
||||
#define OPT_PRINT_PORTRAIT 9
|
||||
#define OPT_PRINT_PAPER 10
|
||||
#define OPT_PRINT_COLLATE 11
|
||||
#define OPT_PRINT_JOBSPLIT 12
|
||||
#define OPT_PRINT_FORMFEED 13
|
||||
#define OPT_PRINT_NUM_OPTIONS 14
|
||||
|
||||
/* For prt_get_unit(). */
|
||||
#define PRT_UNIT_NONE -1
|
||||
#define PRT_UNIT_PERC 0
|
||||
#define PRT_UNIT_INCH 1
|
||||
#define PRT_UNIT_MM 2
|
||||
#define PRT_UNIT_POINT 3
|
||||
#define PRT_UNIT_NAMES {"pc", "in", "mm", "pt"}
|
||||
|
||||
#define PRINT_NUMBER_WIDTH 8
|
||||
|
||||
char_u *parse_printoptions(void);
|
||||
char_u *parse_printmbfont(void);
|
||||
int prt_header_height(void);
|
||||
int prt_use_number(void);
|
||||
int prt_get_unit(int idx);
|
||||
void ex_hardcopy(exarg_T *eap);
|
||||
void mch_print_cleanup(void);
|
||||
int mch_print_init(prt_settings_T *psettings, char_u *jobname,
|
||||
int forceit);
|
||||
int mch_print_begin(prt_settings_T *psettings);
|
||||
void mch_print_end(prt_settings_T *psettings);
|
||||
int mch_print_end_page(void);
|
||||
int mch_print_begin_page(char_u *str);
|
||||
int mch_print_blank_page(void);
|
||||
void mch_print_start_line(int margin, int page_line);
|
||||
int mch_print_text_out(char_u *p, int len);
|
||||
void mch_print_set_font(int iBold, int iItalic, int iUnderline);
|
||||
void mch_print_set_bg(long_u bgcol);
|
||||
void mch_print_set_fg(long_u fgcol);
|
||||
|
||||
#endif /* NEOVIM_HARDCOPY_H */
|
||||
431
src/nvim/hashtab.c
Normal file
431
src/nvim/hashtab.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/// @file hashtab.c
|
||||
///
|
||||
/// Handling of a hashtable with Vim-specific properties.
|
||||
///
|
||||
/// Each item in a hashtable has a NUL terminated string key. A key can appear
|
||||
/// only once in the table.
|
||||
///
|
||||
/// A hash number is computed from the key for quick lookup. When the hashes
|
||||
/// of two different keys point to the same entry an algorithm is used to
|
||||
/// iterate over other entries in the table until the right one is found.
|
||||
/// To make the iteration work removed keys are different from entries where a
|
||||
/// key was never present.
|
||||
///
|
||||
/// The mechanism has been partly based on how Python Dictionaries are
|
||||
/// implemented. The algorithm is from Knuth Vol. 3, Sec. 6.4.
|
||||
///
|
||||
/// The hashtable grows to accommodate more entries when needed. At least 1/3
|
||||
/// of the entries is empty to keep the lookup efficient (at the cost of extra
|
||||
/// memory).
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "vim.h"
|
||||
#include "hashtab.h"
|
||||
#include "message.h"
|
||||
#include "memory.h"
|
||||
#include "misc2.h"
|
||||
|
||||
// Magic value for algorithm that walks through the array.
|
||||
#define PERTURB_SHIFT 5
|
||||
|
||||
static int hash_may_resize(hashtab_T *ht, int minitems);
|
||||
|
||||
|
||||
/// Initialize an empty hash table.
|
||||
///
|
||||
/// @param ht
|
||||
void hash_init(hashtab_T *ht)
|
||||
{
|
||||
// This zeroes all "ht_" entries and all the "hi_key" in "ht_smallarray".
|
||||
memset(ht, 0, sizeof(hashtab_T));
|
||||
ht->ht_array = ht->ht_smallarray;
|
||||
ht->ht_mask = HT_INIT_SIZE - 1;
|
||||
}
|
||||
|
||||
/// Free the array of a hash table. Does not free the items it contains!
|
||||
/// If "ht" is not freed then you should call hash_init() next!
|
||||
///
|
||||
/// @param ht
|
||||
void hash_clear(hashtab_T *ht)
|
||||
{
|
||||
if (ht->ht_array != ht->ht_smallarray) {
|
||||
free(ht->ht_array);
|
||||
}
|
||||
}
|
||||
|
||||
/// Free the array of a hash table and all the keys it contains. The keys must
|
||||
/// have been allocated. "off" is the offset from the start of the allocate
|
||||
/// memory to the location of the key (it's always positive).
|
||||
///
|
||||
/// @param ht
|
||||
/// @param off
|
||||
void hash_clear_all(hashtab_T *ht, int off)
|
||||
{
|
||||
long todo;
|
||||
hashitem_T *hi;
|
||||
|
||||
todo = (long)ht->ht_used;
|
||||
|
||||
for (hi = ht->ht_array; todo > 0; ++hi) {
|
||||
if (!HASHITEM_EMPTY(hi)) {
|
||||
free(hi->hi_key - off);
|
||||
todo--;
|
||||
}
|
||||
}
|
||||
hash_clear(ht);
|
||||
}
|
||||
|
||||
/// Find "key" in hashtable "ht". "key" must not be NULL.
|
||||
/// Always returns a pointer to a hashitem. If the item was not found then
|
||||
/// HASHITEM_EMPTY() is TRUE. The pointer is then the place where the key
|
||||
/// would be added.
|
||||
/// WARNING: The returned pointer becomes invalid when the hashtable is changed
|
||||
/// (adding, setting or removing an item)!
|
||||
///
|
||||
/// @param ht
|
||||
/// @param key
|
||||
///
|
||||
/// @return Pointer to the hashitem stored with the given key.
|
||||
hashitem_T* hash_find(hashtab_T *ht, char_u *key)
|
||||
{
|
||||
return hash_lookup(ht, key, hash_hash(key));
|
||||
}
|
||||
|
||||
/// Like hash_find(), but caller computes "hash".
|
||||
///
|
||||
/// @param ht
|
||||
/// @param key
|
||||
/// @param hash
|
||||
///
|
||||
/// @return Pointer to the hashitem stored with the given key.
|
||||
hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
|
||||
{
|
||||
hash_T perturb;
|
||||
hashitem_T *freeitem;
|
||||
hashitem_T *hi;
|
||||
unsigned idx;
|
||||
|
||||
#ifdef HT_DEBUG
|
||||
hash_count_lookup++;
|
||||
#endif // ifdef HT_DEBUG
|
||||
|
||||
// Quickly handle the most common situations:
|
||||
// - return if there is no item at all
|
||||
// - skip over a removed item
|
||||
// - return if the item matches
|
||||
idx = (unsigned)(hash & ht->ht_mask);
|
||||
hi = &ht->ht_array[idx];
|
||||
|
||||
if (hi->hi_key == NULL) {
|
||||
return hi;
|
||||
}
|
||||
|
||||
if (hi->hi_key == HI_KEY_REMOVED) {
|
||||
freeitem = hi;
|
||||
} else if ((hi->hi_hash == hash) && (STRCMP(hi->hi_key, key) == 0)) {
|
||||
return hi;
|
||||
} else {
|
||||
freeitem = NULL;
|
||||
}
|
||||
|
||||
// Need to search through the table to find the key. The algorithm
|
||||
// to step through the table starts with large steps, gradually becoming
|
||||
// smaller down to (1/4 table size + 1). This means it goes through all
|
||||
// table entries in the end.
|
||||
// When we run into a NULL key it's clear that the key isn't there.
|
||||
// Return the first available slot found (can be a slot of a removed
|
||||
// item).
|
||||
for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
|
||||
#ifdef HT_DEBUG
|
||||
// count a "miss" for hashtab lookup
|
||||
hash_count_perturb++;
|
||||
#endif // ifdef HT_DEBUG
|
||||
idx = 5 * idx + perturb + 1;
|
||||
hi = &ht->ht_array[idx & ht->ht_mask];
|
||||
|
||||
if (hi->hi_key == NULL) {
|
||||
return freeitem == NULL ? hi : freeitem;
|
||||
}
|
||||
|
||||
if ((hi->hi_hash == hash)
|
||||
&& (hi->hi_key != HI_KEY_REMOVED)
|
||||
&& (STRCMP(hi->hi_key, key) == 0)) {
|
||||
return hi;
|
||||
}
|
||||
|
||||
if ((hi->hi_key == HI_KEY_REMOVED) && (freeitem == NULL)) {
|
||||
freeitem = hi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Print the efficiency of hashtable lookups.
|
||||
/// Useful when trying different hash algorithms.
|
||||
/// Called when exiting.
|
||||
void hash_debug_results(void)
|
||||
{
|
||||
#ifdef HT_DEBUG
|
||||
fprintf(stderr, "\r\n\r\n\r\n\r\n");
|
||||
fprintf(stderr, "Number of hashtable lookups: %" PRId64 "\r\n",
|
||||
(int64_t)hash_count_lookup);
|
||||
fprintf(stderr, "Number of perturb loops: %" PRId64 "\r\n",
|
||||
(int64_t)hash_count_perturb);
|
||||
fprintf(stderr, "Percentage of perturb loops: %" PRId64 "%%\r\n",
|
||||
(int64_t)(hash_count_perturb * 100 / hash_count_lookup));
|
||||
#endif // ifdef HT_DEBUG
|
||||
}
|
||||
|
||||
/// Add item with key "key" to hashtable "ht".
|
||||
///
|
||||
/// @param ht
|
||||
/// @param key
|
||||
///
|
||||
/// @returns FAIL when out of memory or the key is already present.
|
||||
int hash_add(hashtab_T *ht, char_u *key)
|
||||
{
|
||||
hash_T hash = hash_hash(key);
|
||||
hashitem_T *hi = hash_lookup(ht, key, hash);
|
||||
if (!HASHITEM_EMPTY(hi)) {
|
||||
EMSG2(_(e_intern2), "hash_add()");
|
||||
return FAIL;
|
||||
}
|
||||
return hash_add_item(ht, hi, key, hash);
|
||||
}
|
||||
|
||||
/// Add item "hi" with "key" to hashtable "ht". "key" must not be NULL and
|
||||
/// "hi" must have been obtained with hash_lookup() and point to an empty item.
|
||||
/// "hi" is invalid after this!
|
||||
///
|
||||
/// @param ht
|
||||
/// @param hi
|
||||
/// @param key
|
||||
/// @param hash
|
||||
///
|
||||
/// @returns OK or FAIL (out of memory).
|
||||
int hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
|
||||
{
|
||||
// If resizing failed before and it fails again we can't add an item.
|
||||
if (ht->ht_error && (hash_may_resize(ht, 0) == FAIL)) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ht->ht_used++;
|
||||
if (hi->hi_key == NULL) {
|
||||
ht->ht_filled++;
|
||||
}
|
||||
hi->hi_key = key;
|
||||
hi->hi_hash = hash;
|
||||
|
||||
// When the space gets low may resize the array.
|
||||
return hash_may_resize(ht, 0);
|
||||
}
|
||||
|
||||
/// Remove item "hi" from hashtable "ht". "hi" must have been obtained with
|
||||
/// hash_lookup().
|
||||
///
|
||||
/// The caller must take care of freeing the item itself.
|
||||
///
|
||||
/// @param ht
|
||||
/// @param hi
|
||||
void hash_remove(hashtab_T *ht, hashitem_T *hi)
|
||||
{
|
||||
ht->ht_used--;
|
||||
hi->hi_key = HI_KEY_REMOVED;
|
||||
hash_may_resize(ht, 0);
|
||||
}
|
||||
|
||||
/// Lock a hashtable: prevent that ht_array changes.
|
||||
/// Don't use this when items are to be added!
|
||||
/// Must call hash_unlock() later.
|
||||
///
|
||||
/// @param ht
|
||||
void hash_lock(hashtab_T *ht)
|
||||
{
|
||||
ht->ht_locked++;
|
||||
}
|
||||
|
||||
/// Unlock a hashtable: allow ht_array changes again.
|
||||
/// Table will be resized (shrink) when necessary.
|
||||
/// This must balance a call to hash_lock().
|
||||
void hash_unlock(hashtab_T *ht)
|
||||
{
|
||||
ht->ht_locked--;
|
||||
(void)hash_may_resize(ht, 0);
|
||||
}
|
||||
|
||||
/// Shrink a hashtable when there is too much empty space.
|
||||
/// Grow a hashtable when there is not enough empty space.
|
||||
///
|
||||
/// @param ht
|
||||
/// @param minitems minimal number of items
|
||||
///
|
||||
/// @returns OK or FAIL (out of memory).
|
||||
static int hash_may_resize(hashtab_T *ht, int minitems)
|
||||
{
|
||||
hashitem_T temparray[HT_INIT_SIZE];
|
||||
hashitem_T *oldarray, *newarray;
|
||||
hashitem_T *olditem, *newitem;
|
||||
unsigned newi;
|
||||
int todo;
|
||||
long_u oldsize, newsize;
|
||||
long_u minsize;
|
||||
long_u newmask;
|
||||
hash_T perturb;
|
||||
|
||||
// Don't resize a locked table.
|
||||
if (ht->ht_locked > 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HT_DEBUG
|
||||
if (ht->ht_used > ht->ht_filled) {
|
||||
EMSG("hash_may_resize(): more used than filled");
|
||||
}
|
||||
|
||||
if (ht->ht_filled >= ht->ht_mask + 1) {
|
||||
EMSG("hash_may_resize(): table completely filled");
|
||||
}
|
||||
#endif // ifdef HT_DEBUG
|
||||
|
||||
if (minitems == 0) {
|
||||
// Return quickly for small tables with at least two NULL items. NULL
|
||||
// items are required for the lookup to decide a key isn't there.
|
||||
if ((ht->ht_filled < HT_INIT_SIZE - 1)
|
||||
&& (ht->ht_array == ht->ht_smallarray)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Grow or refill the array when it's more than 2/3 full (including
|
||||
// removed items, so that they get cleaned up).
|
||||
// Shrink the array when it's less than 1/5 full. When growing it is
|
||||
// at least 1/4 full (avoids repeated grow-shrink operations)
|
||||
oldsize = ht->ht_mask + 1;
|
||||
if ((ht->ht_filled * 3 < oldsize * 2) && (ht->ht_used > oldsize / 5)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (ht->ht_used > 1000) {
|
||||
// it's big, don't make too much room
|
||||
minsize = ht->ht_used * 2;
|
||||
} else {
|
||||
// make plenty of room
|
||||
minsize = ht->ht_used * 4;
|
||||
}
|
||||
} else {
|
||||
// Use specified size.
|
||||
if ((long_u)minitems < ht->ht_used) {
|
||||
// just in case...
|
||||
minitems = (int)ht->ht_used;
|
||||
}
|
||||
// array is up to 2/3 full
|
||||
minsize = minitems * 3 / 2;
|
||||
}
|
||||
|
||||
newsize = HT_INIT_SIZE;
|
||||
|
||||
while (newsize < minsize) {
|
||||
// make sure it's always a power of 2
|
||||
newsize <<= 1;
|
||||
if (newsize == 0) {
|
||||
// overflow
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (newsize == HT_INIT_SIZE) {
|
||||
// Use the small array inside the hashdict structure.
|
||||
newarray = ht->ht_smallarray;
|
||||
if (ht->ht_array == newarray) {
|
||||
// Moving from ht_smallarray to ht_smallarray! Happens when there
|
||||
// are many removed items. Copy the items to be able to clean up
|
||||
// removed items.
|
||||
memmove(temparray, newarray, sizeof(temparray));
|
||||
oldarray = temparray;
|
||||
} else {
|
||||
oldarray = ht->ht_array;
|
||||
}
|
||||
} else {
|
||||
// Allocate an array.
|
||||
newarray = (hashitem_T *)alloc((unsigned)(sizeof(hashitem_T) * newsize));
|
||||
|
||||
if (newarray == NULL) {
|
||||
// Out of memory. When there are NULL items still return OK.
|
||||
// Otherwise set ht_error, because lookup may result in a hang if
|
||||
// we add another item.
|
||||
if (ht->ht_filled < ht->ht_mask) {
|
||||
return OK;
|
||||
}
|
||||
ht->ht_error = TRUE;
|
||||
return FAIL;
|
||||
}
|
||||
oldarray = ht->ht_array;
|
||||
}
|
||||
memset(newarray, 0, (size_t)(sizeof(hashitem_T) * newsize));
|
||||
|
||||
// Move all the items from the old array to the new one, placing them in
|
||||
// the right spot. The new array won't have any removed items, thus this
|
||||
// is also a cleanup action.
|
||||
newmask = newsize - 1;
|
||||
todo = (int)ht->ht_used;
|
||||
|
||||
for (olditem = oldarray; todo > 0; ++olditem) {
|
||||
if (!HASHITEM_EMPTY(olditem)) {
|
||||
// The algorithm to find the spot to add the item is identical to
|
||||
// the algorithm to find an item in hash_lookup(). But we only
|
||||
// need to search for a NULL key, thus it's simpler.
|
||||
newi = (unsigned)(olditem->hi_hash & newmask);
|
||||
newitem = &newarray[newi];
|
||||
if (newitem->hi_key != NULL) {
|
||||
for (perturb = olditem->hi_hash;; perturb >>= PERTURB_SHIFT) {
|
||||
newi = 5 * newi + perturb + 1;
|
||||
newitem = &newarray[newi & newmask];
|
||||
if (newitem->hi_key == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*newitem = *olditem;
|
||||
todo--;
|
||||
}
|
||||
}
|
||||
|
||||
if (ht->ht_array != ht->ht_smallarray) {
|
||||
free(ht->ht_array);
|
||||
}
|
||||
ht->ht_array = newarray;
|
||||
ht->ht_mask = newmask;
|
||||
ht->ht_filled = ht->ht_used;
|
||||
ht->ht_error = FALSE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Get the hash number for a key.
|
||||
/// If you think you know a better hash function: Compile with HT_DEBUG set and
|
||||
/// run a script that uses hashtables a lot. Vim will then print statistics
|
||||
/// when exiting. Try that with the current hash algorithm and yours. The
|
||||
/// lower the percentage the better.
|
||||
///
|
||||
/// @param key
|
||||
///
|
||||
/// @return Hash number for the key.
|
||||
hash_T hash_hash(char_u *key)
|
||||
{
|
||||
hash_T hash;
|
||||
char_u *p;
|
||||
|
||||
if ((hash = *key) == 0) {
|
||||
// Empty keys are not allowed, but we don't want to crash if we get one.
|
||||
return (hash_T) 0;
|
||||
}
|
||||
p = key + 1;
|
||||
|
||||
// A simplistic algorithm that appears to do very well.
|
||||
// Suggested by George Reilly.
|
||||
while (*p != NUL) {
|
||||
hash = hash * 101 + *p++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
56
src/nvim/hashtab.h
Normal file
56
src/nvim/hashtab.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef NEOVIM_HASHTAB_H
|
||||
#define NEOVIM_HASHTAB_H
|
||||
|
||||
/* Item for a hashtable. "hi_key" can be one of three values:
|
||||
* NULL: Never been used
|
||||
* HI_KEY_REMOVED: Entry was removed
|
||||
* Otherwise: Used item, pointer to the actual key; this usually is
|
||||
* inside the item, subtract an offset to locate the item.
|
||||
* This reduces the size of hashitem by 1/3.
|
||||
*/
|
||||
typedef struct hashitem_S {
|
||||
long_u hi_hash; /* cached hash number of hi_key */
|
||||
char_u *hi_key;
|
||||
} hashitem_T;
|
||||
|
||||
/* The address of "hash_removed" is used as a magic number for hi_key to
|
||||
* indicate a removed item. */
|
||||
#define HI_KEY_REMOVED &hash_removed
|
||||
#define HASHITEM_EMPTY(hi) ((hi)->hi_key == NULL || (hi)->hi_key == \
|
||||
&hash_removed)
|
||||
|
||||
/* Initial size for a hashtable. Our items are relatively small and growing
|
||||
* is expensive, thus use 16 as a start. Must be a power of 2. */
|
||||
#define HT_INIT_SIZE 16
|
||||
|
||||
typedef struct hashtable_S {
|
||||
long_u ht_mask; /* mask used for hash value (nr of items in
|
||||
* array is "ht_mask" + 1) */
|
||||
long_u ht_used; /* number of items used */
|
||||
long_u ht_filled; /* number of items used + removed */
|
||||
int ht_locked; /* counter for hash_lock() */
|
||||
int ht_error; /* when set growing failed, can't add more
|
||||
items before growing works */
|
||||
hashitem_T *ht_array; /* points to the array, allocated when it's
|
||||
not "ht_smallarray" */
|
||||
hashitem_T ht_smallarray[HT_INIT_SIZE]; /* initial array */
|
||||
} hashtab_T;
|
||||
|
||||
typedef long_u hash_T; /* Type for hi_hash */
|
||||
|
||||
/* hashtab.c */
|
||||
void hash_init(hashtab_T *ht);
|
||||
void hash_clear(hashtab_T *ht);
|
||||
void hash_clear_all(hashtab_T *ht, int off);
|
||||
hashitem_T *hash_find(hashtab_T *ht, char_u *key);
|
||||
hashitem_T *hash_lookup(hashtab_T *ht, char_u *key, hash_T hash);
|
||||
void hash_debug_results(void);
|
||||
int hash_add(hashtab_T *ht, char_u *key);
|
||||
int hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key,
|
||||
hash_T hash);
|
||||
void hash_remove(hashtab_T *ht, hashitem_T *hi);
|
||||
void hash_lock(hashtab_T *ht);
|
||||
void hash_unlock(hashtab_T *ht);
|
||||
hash_T hash_hash(char_u *key);
|
||||
|
||||
#endif /* NEOVIM_HASHTAB_H */
|
||||
2167
src/nvim/if_cscope.c
Normal file
2167
src/nvim/if_cscope.c
Normal file
File diff suppressed because it is too large
Load Diff
16
src/nvim/if_cscope.h
Normal file
16
src/nvim/if_cscope.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef NEOVIM_IF_CSCOPE_H
|
||||
#define NEOVIM_IF_CSCOPE_H
|
||||
/* if_cscope.c */
|
||||
char_u *get_cscope_name(expand_T *xp, int idx);
|
||||
void set_context_in_cscope_cmd(expand_T *xp, char_u *arg,
|
||||
cmdidx_T cmdidx);
|
||||
void do_cscope(exarg_T *eap);
|
||||
void do_scscope(exarg_T *eap);
|
||||
void do_cstag(exarg_T *eap);
|
||||
int cs_fgets(char_u *buf, int size);
|
||||
void cs_free_tags(void);
|
||||
void cs_print_tags(void);
|
||||
int cs_connection(int num, char_u *dbpath, char_u *ppath);
|
||||
void cs_end(void);
|
||||
|
||||
#endif /* NEOVIM_IF_CSCOPE_H */
|
||||
71
src/nvim/if_cscope_defs.h
Normal file
71
src/nvim/if_cscope_defs.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef NEOVIM_IF_CSCOPE_DEFS_H
|
||||
#define NEOVIM_IF_CSCOPE_DEFS_H
|
||||
|
||||
/*
|
||||
* CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
|
||||
* Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
|
||||
*
|
||||
* The basic idea/structure of cscope for Vim was borrowed from Nvi.
|
||||
* There might be a few lines of code that look similar to what Nvi
|
||||
* has. If this is a problem and requires inclusion of the annoying
|
||||
* BSD license, then sue me; I'm not worth much anyway.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(UNIX)
|
||||
# include <sys/types.h> /* pid_t */
|
||||
# include <sys/stat.h> /* dev_t, ino_t */
|
||||
#else
|
||||
#endif
|
||||
|
||||
#define CSCOPE_SUCCESS 0
|
||||
#define CSCOPE_FAILURE -1
|
||||
|
||||
#define CSCOPE_DBFILE "cscope.out"
|
||||
#define CSCOPE_PROMPT ">> "
|
||||
|
||||
/*
|
||||
* s 0name Find this C symbol
|
||||
* g 1name Find this definition
|
||||
* d 2name Find functions called by this function
|
||||
* c 3name Find functions calling this function
|
||||
* t 4string find text string (cscope 12.9)
|
||||
* t 4name Find assignments to (cscope 13.3)
|
||||
* 5pattern change pattern -- NOT USED
|
||||
* e 6pattern Find this egrep pattern
|
||||
* f 7name Find this file
|
||||
* i 8name Find files #including this file
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char * name;
|
||||
int (*func)(exarg_T *eap);
|
||||
char * help;
|
||||
char * usage;
|
||||
int cansplit; /* if supports splitting window */
|
||||
} cscmd_T;
|
||||
|
||||
typedef struct csi {
|
||||
char * fname; /* cscope db name */
|
||||
char * ppath; /* path to prepend (the -P option) */
|
||||
char * flags; /* additional cscope flags/options (e.g, -p2) */
|
||||
#if defined(UNIX)
|
||||
pid_t pid; /* PID of the connected cscope process. */
|
||||
#endif
|
||||
uint64_t st_dev; /* ID of dev containing cscope db */
|
||||
uint64_t st_ino; /* inode number of cscope db */
|
||||
|
||||
FILE * fr_fp; /* from cscope: FILE. */
|
||||
FILE * to_fp; /* to cscope: FILE. */
|
||||
} csinfo_T;
|
||||
|
||||
typedef enum { Add, Find, Help, Kill, Reset, Show } csid_e;
|
||||
|
||||
typedef enum {
|
||||
Store,
|
||||
Get,
|
||||
Free,
|
||||
Print
|
||||
} mcmd_e;
|
||||
|
||||
#endif // NEOVIM_IF_CSCOPE_DEFS_H
|
||||
696
src/nvim/indent.c
Normal file
696
src/nvim/indent.c
Normal file
@@ -0,0 +1,696 @@
|
||||
#include "indent.h"
|
||||
#include "eval.h"
|
||||
#include "charset.h"
|
||||
#include "memline.h"
|
||||
#include "memory.h"
|
||||
#include "misc1.h"
|
||||
#include "misc2.h"
|
||||
#include "option.h"
|
||||
#include "regexp.h"
|
||||
#include "search.h"
|
||||
#include "undo.h"
|
||||
|
||||
static int lisp_match(char_u *p);
|
||||
|
||||
|
||||
// Count the size (in window cells) of the indent in the current line.
|
||||
int get_indent(void)
|
||||
{
|
||||
return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts);
|
||||
}
|
||||
|
||||
|
||||
// Count the size (in window cells) of the indent in line "lnum".
|
||||
int get_indent_lnum(linenr_T lnum)
|
||||
{
|
||||
return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts);
|
||||
}
|
||||
|
||||
|
||||
// Count the size (in window cells) of the indent in line "lnum" of buffer
|
||||
// "buf".
|
||||
int get_indent_buf(buf_T *buf, linenr_T lnum)
|
||||
{
|
||||
return get_indent_str(ml_get_buf(buf, lnum, false), (int)buf->b_p_ts);
|
||||
}
|
||||
|
||||
|
||||
// Count the size (in window cells) of the indent in line "ptr", with
|
||||
// 'tabstop' at "ts".
|
||||
int get_indent_str(char_u *ptr, int ts)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (; *ptr; ++ptr) {
|
||||
// Count a tab for what it is worth.
|
||||
if (*ptr == TAB) {
|
||||
count += ts - (count % ts);
|
||||
} else if (*ptr == ' ') {
|
||||
// Count a space for one.
|
||||
count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// Set the indent of the current line.
|
||||
// Leaves the cursor on the first non-blank in the line.
|
||||
// Caller must take care of undo.
|
||||
// "flags":
|
||||
// SIN_CHANGED: call changed_bytes() if the line was changed.
|
||||
// SIN_INSERT: insert the indent in front of the line.
|
||||
// SIN_UNDO: save line for undo before changing it.
|
||||
// @param size measured in spaces
|
||||
// Returns true if the line was changed.
|
||||
int set_indent(int size, int flags)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *newline;
|
||||
char_u *oldline;
|
||||
char_u *s;
|
||||
int todo;
|
||||
int ind_len; // Measured in characters.
|
||||
int line_len;
|
||||
int doit = false;
|
||||
int ind_done = 0; // Measured in spaces.
|
||||
int tab_pad;
|
||||
int retval = false;
|
||||
|
||||
// Number of initial whitespace chars when 'et' and 'pi' are both set.
|
||||
int orig_char_len = -1;
|
||||
|
||||
// First check if there is anything to do and compute the number of
|
||||
// characters needed for the indent.
|
||||
todo = size;
|
||||
ind_len = 0;
|
||||
p = oldline = ml_get_curline();
|
||||
|
||||
// Calculate the buffer size for the new indent, and check to see if it
|
||||
// isn't already set.
|
||||
// If 'expandtab' isn't set: use TABs; if both 'expandtab' and
|
||||
// 'preserveindent' are set count the number of characters at the
|
||||
// beginning of the line to be copied.
|
||||
if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) {
|
||||
// If 'preserveindent' is set then reuse as much as possible of
|
||||
// the existing indent structure for the new indent.
|
||||
if (!(flags & SIN_INSERT) && curbuf->b_p_pi) {
|
||||
ind_done = 0;
|
||||
|
||||
// Count as many characters as we can use.
|
||||
while (todo > 0 && vim_iswhite(*p)) {
|
||||
if (*p == TAB) {
|
||||
tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
// Stop if this tab will overshoot the target.
|
||||
if (todo < tab_pad) {
|
||||
break;
|
||||
}
|
||||
todo -= tab_pad;
|
||||
ind_len++;
|
||||
ind_done += tab_pad;
|
||||
} else {
|
||||
todo--;
|
||||
ind_len++;
|
||||
ind_done++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
// Set initial number of whitespace chars to copy if we are
|
||||
// preserving indent but expandtab is set.
|
||||
if (curbuf->b_p_et) {
|
||||
orig_char_len = ind_len;
|
||||
}
|
||||
|
||||
// Fill to next tabstop with a tab, if possible.
|
||||
tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
if ((todo >= tab_pad) && (orig_char_len == -1)) {
|
||||
doit = true;
|
||||
todo -= tab_pad;
|
||||
ind_len++;
|
||||
|
||||
// ind_done += tab_pad;
|
||||
}
|
||||
}
|
||||
|
||||
// Count tabs required for indent.
|
||||
while (todo >= (int)curbuf->b_p_ts) {
|
||||
if (*p != TAB) {
|
||||
doit = true;
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
todo -= (int)curbuf->b_p_ts;
|
||||
ind_len++;
|
||||
|
||||
// ind_done += (int)curbuf->b_p_ts;
|
||||
}
|
||||
}
|
||||
|
||||
// Count spaces required for indent.
|
||||
while (todo > 0) {
|
||||
if (*p != ' ') {
|
||||
doit = true;
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
todo--;
|
||||
ind_len++;
|
||||
|
||||
// ind_done++;
|
||||
}
|
||||
|
||||
// Return if the indent is OK already.
|
||||
if (!doit && !vim_iswhite(*p) && !(flags & SIN_INSERT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate memory for the new line.
|
||||
if (flags & SIN_INSERT) {
|
||||
p = oldline;
|
||||
} else {
|
||||
p = skipwhite(p);
|
||||
}
|
||||
line_len = (int)STRLEN(p) + 1;
|
||||
|
||||
// If 'preserveindent' and 'expandtab' are both set keep the original
|
||||
// characters and allocate accordingly. We will fill the rest with spaces
|
||||
// after the if (!curbuf->b_p_et) below.
|
||||
if (orig_char_len != -1) {
|
||||
newline = alloc(orig_char_len + size - ind_done + line_len);
|
||||
todo = size - ind_done;
|
||||
|
||||
// Set total length of indent in characters, which may have been
|
||||
// undercounted until now.
|
||||
ind_len = orig_char_len + todo;
|
||||
p = oldline;
|
||||
s = newline;
|
||||
|
||||
while (orig_char_len > 0) {
|
||||
*s++ = *p++;
|
||||
orig_char_len--;
|
||||
}
|
||||
|
||||
// Skip over any additional white space (useful when newindent is less
|
||||
// than old).
|
||||
while (vim_iswhite(*p)) {
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
todo = size;
|
||||
newline = alloc(ind_len + line_len);
|
||||
s = newline;
|
||||
}
|
||||
|
||||
// Put the characters in the new line.
|
||||
// if 'expandtab' isn't set: use TABs
|
||||
if (!curbuf->b_p_et) {
|
||||
// If 'preserveindent' is set then reuse as much as possible of
|
||||
// the existing indent structure for the new indent.
|
||||
if (!(flags & SIN_INSERT) && curbuf->b_p_pi) {
|
||||
p = oldline;
|
||||
ind_done = 0;
|
||||
|
||||
while (todo > 0 && vim_iswhite(*p)) {
|
||||
if (*p == TAB) {
|
||||
tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
// Stop if this tab will overshoot the target.
|
||||
if (todo < tab_pad) {
|
||||
break;
|
||||
}
|
||||
todo -= tab_pad;
|
||||
ind_done += tab_pad;
|
||||
} else {
|
||||
todo--;
|
||||
ind_done++;
|
||||
}
|
||||
*s++ = *p++;
|
||||
}
|
||||
|
||||
// Fill to next tabstop with a tab, if possible.
|
||||
tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
if (todo >= tab_pad) {
|
||||
*s++ = TAB;
|
||||
todo -= tab_pad;
|
||||
}
|
||||
p = skipwhite(p);
|
||||
}
|
||||
|
||||
while (todo >= (int)curbuf->b_p_ts) {
|
||||
*s++ = TAB;
|
||||
todo -= (int)curbuf->b_p_ts;
|
||||
}
|
||||
}
|
||||
|
||||
while (todo > 0) {
|
||||
*s++ = ' ';
|
||||
todo--;
|
||||
}
|
||||
memmove(s, p, (size_t)line_len);
|
||||
|
||||
// Replace the line (unless undo fails).
|
||||
if (!(flags & SIN_UNDO) || (u_savesub(curwin->w_cursor.lnum) == OK)) {
|
||||
ml_replace(curwin->w_cursor.lnum, newline, false);
|
||||
|
||||
if (flags & SIN_CHANGED) {
|
||||
changed_bytes(curwin->w_cursor.lnum, 0);
|
||||
}
|
||||
|
||||
// Correct saved cursor position if it is in this line.
|
||||
if (saved_cursor.lnum == curwin->w_cursor.lnum) {
|
||||
if (saved_cursor.col >= (colnr_T)(p - oldline)) {
|
||||
// Cursor was after the indent, adjust for the number of
|
||||
// bytes added/removed.
|
||||
saved_cursor.col += ind_len - (colnr_T)(p - oldline);
|
||||
|
||||
} else if (saved_cursor.col >= (colnr_T)(s - newline)) {
|
||||
// Cursor was in the indent, and is now after it, put it back
|
||||
// at the start of the indent (replacing spaces with TAB).
|
||||
saved_cursor.col = (colnr_T)(s - newline);
|
||||
}
|
||||
}
|
||||
retval = true;
|
||||
} else {
|
||||
free(newline);
|
||||
}
|
||||
curwin->w_cursor.col = ind_len;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// Copy the indent from ptr to the current line (and fill to size).
|
||||
// Leaves the cursor on the first non-blank in the line.
|
||||
// @return true if the line was changed.
|
||||
int copy_indent(int size, char_u *src)
|
||||
{
|
||||
char_u *p = NULL;
|
||||
char_u *line = NULL;
|
||||
char_u *s;
|
||||
int todo;
|
||||
int ind_len;
|
||||
int line_len = 0;
|
||||
int tab_pad;
|
||||
int ind_done;
|
||||
int round;
|
||||
|
||||
// Round 1: compute the number of characters needed for the indent
|
||||
// Round 2: copy the characters.
|
||||
for (round = 1; round <= 2; ++round) {
|
||||
todo = size;
|
||||
ind_len = 0;
|
||||
ind_done = 0;
|
||||
s = src;
|
||||
|
||||
// Count/copy the usable portion of the source line.
|
||||
while (todo > 0 && vim_iswhite(*s)) {
|
||||
if (*s == TAB) {
|
||||
tab_pad = (int)curbuf->b_p_ts
|
||||
- (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
// Stop if this tab will overshoot the target.
|
||||
if (todo < tab_pad) {
|
||||
break;
|
||||
}
|
||||
todo -= tab_pad;
|
||||
ind_done += tab_pad;
|
||||
} else {
|
||||
todo--;
|
||||
ind_done++;
|
||||
}
|
||||
ind_len++;
|
||||
|
||||
if (p != NULL) {
|
||||
*p++ = *s;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
// Fill to next tabstop with a tab, if possible.
|
||||
tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
|
||||
|
||||
if ((todo >= tab_pad) && !curbuf->b_p_et) {
|
||||
todo -= tab_pad;
|
||||
ind_len++;
|
||||
|
||||
if (p != NULL) {
|
||||
*p++ = TAB;
|
||||
}
|
||||
}
|
||||
|
||||
// Add tabs required for indent.
|
||||
while (todo >= (int)curbuf->b_p_ts && !curbuf->b_p_et) {
|
||||
todo -= (int)curbuf->b_p_ts;
|
||||
ind_len++;
|
||||
|
||||
if (p != NULL) {
|
||||
*p++ = TAB;
|
||||
}
|
||||
}
|
||||
|
||||
// Count/add spaces required for indent.
|
||||
while (todo > 0) {
|
||||
todo--;
|
||||
ind_len++;
|
||||
|
||||
if (p != NULL) {
|
||||
*p++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
// Allocate memory for the result: the copied indent, new indent
|
||||
// and the rest of the line.
|
||||
line_len = (int)STRLEN(ml_get_curline()) + 1;
|
||||
line = alloc(ind_len + line_len);
|
||||
p = line;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the original line
|
||||
memmove(p, ml_get_curline(), (size_t)line_len);
|
||||
|
||||
// Replace the line
|
||||
ml_replace(curwin->w_cursor.lnum, line, false);
|
||||
|
||||
// Put the cursor after the indent.
|
||||
curwin->w_cursor.col = ind_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Return the indent of the current line after a number. Return -1 if no
|
||||
// number was found. Used for 'n' in 'formatoptions': numbered list.
|
||||
// Since a pattern is used it can actually handle more than numbers.
|
||||
int get_number_indent(linenr_T lnum)
|
||||
{
|
||||
colnr_T col;
|
||||
pos_T pos;
|
||||
regmatch_T regmatch;
|
||||
int lead_len = 0; // Length of comment leader.
|
||||
|
||||
if (lnum > curbuf->b_ml.ml_line_count) {
|
||||
return -1;
|
||||
}
|
||||
pos.lnum = 0;
|
||||
|
||||
// In format_lines() (i.e. not insert mode), fo+=q is needed too...
|
||||
if ((State & INSERT) || has_format_option(FO_Q_COMS)) {
|
||||
lead_len = get_leader_len(ml_get(lnum), NULL, false, true);
|
||||
}
|
||||
regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
|
||||
|
||||
if (regmatch.regprog != NULL) {
|
||||
regmatch.rm_ic = false;
|
||||
|
||||
// vim_regexec() expects a pointer to a line. This lets us
|
||||
// start matching for the flp beyond any comment leader...
|
||||
if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) {
|
||||
pos.lnum = lnum;
|
||||
pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum));
|
||||
pos.coladd = 0;
|
||||
}
|
||||
vim_regfree(regmatch.regprog);
|
||||
}
|
||||
|
||||
if ((pos.lnum == 0) || (*ml_get_pos(&pos) == NUL)) {
|
||||
return -1;
|
||||
}
|
||||
getvcol(curwin, &pos, &col, NULL, NULL);
|
||||
return (int)col;
|
||||
}
|
||||
|
||||
|
||||
// When extra == 0: Return true if the cursor is before or on the first
|
||||
// non-blank in the line.
|
||||
// When extra == 1: Return true if the cursor is before the first non-blank in
|
||||
// the line.
|
||||
int inindent(int extra)
|
||||
{
|
||||
char_u *ptr;
|
||||
colnr_T col;
|
||||
|
||||
for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (col >= curwin->w_cursor.col + extra) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get indent level from 'indentexpr'.
|
||||
int get_expr_indent(void)
|
||||
{
|
||||
int indent;
|
||||
pos_T save_pos;
|
||||
colnr_T save_curswant;
|
||||
int save_set_curswant;
|
||||
int save_State;
|
||||
int use_sandbox = was_set_insecurely((char_u *)"indentexpr", OPT_LOCAL);
|
||||
|
||||
// Save and restore cursor position and curswant, in case it was changed
|
||||
// * via :normal commands.
|
||||
save_pos = curwin->w_cursor;
|
||||
save_curswant = curwin->w_curswant;
|
||||
save_set_curswant = curwin->w_set_curswant;
|
||||
set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
|
||||
|
||||
if (use_sandbox) {
|
||||
sandbox++;
|
||||
}
|
||||
textlock++;
|
||||
indent = eval_to_number(curbuf->b_p_inde);
|
||||
|
||||
if (use_sandbox) {
|
||||
sandbox--;
|
||||
}
|
||||
textlock--;
|
||||
|
||||
// Restore the cursor position so that 'indentexpr' doesn't need to.
|
||||
// Pretend to be in Insert mode, allow cursor past end of line for "o"
|
||||
// command.
|
||||
save_State = State;
|
||||
State = INSERT;
|
||||
curwin->w_cursor = save_pos;
|
||||
curwin->w_curswant = save_curswant;
|
||||
curwin->w_set_curswant = save_set_curswant;
|
||||
check_cursor();
|
||||
State = save_State;
|
||||
|
||||
// If there is an error, just keep the current indent.
|
||||
if (indent < 0) {
|
||||
indent = get_indent();
|
||||
}
|
||||
|
||||
return indent;
|
||||
}
|
||||
|
||||
|
||||
// When 'p' is present in 'cpoptions, a Vi compatible method is used.
|
||||
// The incompatible newer method is quite a bit better at indenting
|
||||
// code in lisp-like languages than the traditional one; it's still
|
||||
// mostly heuristics however -- Dirk van Deun, dirk@rave.org
|
||||
|
||||
// TODO(unknown):
|
||||
// Findmatch() should be adapted for lisp, also to make showmatch
|
||||
// work correctly: now (v5.3) it seems all C/C++ oriented:
|
||||
// - it does not recognize the #\( and #\) notations as character literals
|
||||
// - it doesn't know about comments starting with a semicolon
|
||||
// - it incorrectly interprets '(' as a character literal
|
||||
// All this messes up get_lisp_indent in some rare cases.
|
||||
// Update from Sergey Khorev:
|
||||
// I tried to fix the first two issues.
|
||||
int get_lisp_indent(void)
|
||||
{
|
||||
pos_T *pos, realpos, paren;
|
||||
int amount;
|
||||
char_u *that;
|
||||
colnr_T col;
|
||||
colnr_T firsttry;
|
||||
int parencount;
|
||||
int quotecount;
|
||||
int vi_lisp;
|
||||
|
||||
// Set vi_lisp to use the vi-compatible method.
|
||||
vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
|
||||
|
||||
realpos = curwin->w_cursor;
|
||||
curwin->w_cursor.col = 0;
|
||||
|
||||
if ((pos = findmatch(NULL, '(')) == NULL) {
|
||||
pos = findmatch(NULL, '[');
|
||||
} else {
|
||||
paren = *pos;
|
||||
pos = findmatch(NULL, '[');
|
||||
|
||||
if ((pos == NULL) || ltp(pos, &paren)) {
|
||||
pos = &paren;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != NULL) {
|
||||
// Extra trick: Take the indent of the first previous non-white
|
||||
// line that is at the same () level.
|
||||
amount = -1;
|
||||
parencount = 0;
|
||||
|
||||
while (--curwin->w_cursor.lnum >= pos->lnum) {
|
||||
if (linewhite(curwin->w_cursor.lnum)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (that = ml_get_curline(); *that != NUL; ++that) {
|
||||
if (*that == ';') {
|
||||
while (*(that + 1) != NUL) {
|
||||
that++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*that == '\\') {
|
||||
if (*(that + 1) != NUL) {
|
||||
that++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*that == '"') && (*(that + 1) != NUL)) {
|
||||
while (*++that && *that != '"') {
|
||||
// Skipping escaped characters in the string
|
||||
if (*that == '\\') {
|
||||
if (*++that == NUL) {
|
||||
break;
|
||||
}
|
||||
if (that[1] == NUL) {
|
||||
that++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((*that == '(') || (*that == '[')) {
|
||||
parencount++;
|
||||
} else if ((*that == ')') || (*that == ']')) {
|
||||
parencount--;
|
||||
}
|
||||
}
|
||||
|
||||
if (parencount == 0) {
|
||||
amount = get_indent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (amount == -1) {
|
||||
curwin->w_cursor.lnum = pos->lnum;
|
||||
curwin->w_cursor.col = pos->col;
|
||||
col = pos->col;
|
||||
|
||||
that = ml_get_curline();
|
||||
|
||||
if (vi_lisp && (get_indent() == 0)) {
|
||||
amount = 2;
|
||||
} else {
|
||||
amount = 0;
|
||||
|
||||
while (*that && col) {
|
||||
amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
|
||||
col--;
|
||||
}
|
||||
|
||||
// Some keywords require "body" indenting rules (the
|
||||
// non-standard-lisp ones are Scheme special forms):
|
||||
// (let ((a 1)) instead (let ((a 1))
|
||||
// (...)) of (...))
|
||||
if (!vi_lisp && ((*that == '(') || (*that == '['))
|
||||
&& lisp_match(that + 1)) {
|
||||
amount += 2;
|
||||
} else {
|
||||
that++;
|
||||
amount++;
|
||||
firsttry = amount;
|
||||
|
||||
while (vim_iswhite(*that)) {
|
||||
amount += lbr_chartabsize(that, (colnr_T)amount);
|
||||
that++;
|
||||
}
|
||||
|
||||
if (*that && (*that != ';')) {
|
||||
// Not a comment line.
|
||||
// Test *that != '(' to accommodate first let/do
|
||||
// argument if it is more than one line.
|
||||
if (!vi_lisp && (*that != '(') && (*that != '[')) {
|
||||
firsttry++;
|
||||
}
|
||||
|
||||
parencount = 0;
|
||||
quotecount = 0;
|
||||
|
||||
if (vi_lisp || ((*that != '"') && (*that != '\'')
|
||||
&& (*that != '#') && ((*that < '0') || (*that > '9')))) {
|
||||
while (*that && (!vim_iswhite(*that) || quotecount || parencount)
|
||||
&& (!((*that == '(' || *that == '[')
|
||||
&& !quotecount && !parencount && vi_lisp))) {
|
||||
if (*that == '"') {
|
||||
quotecount = !quotecount;
|
||||
}
|
||||
if (((*that == '(') || (*that == '[')) && !quotecount) {
|
||||
parencount++;
|
||||
}
|
||||
if (((*that == ')') || (*that == ']')) && !quotecount) {
|
||||
parencount--;
|
||||
}
|
||||
if ((*that == '\\') && (*(that + 1) != NUL)) {
|
||||
amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
|
||||
}
|
||||
|
||||
amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
|
||||
}
|
||||
}
|
||||
|
||||
while (vim_iswhite(*that)) {
|
||||
amount += lbr_chartabsize(that, (colnr_T)amount);
|
||||
that++;
|
||||
}
|
||||
|
||||
if (!*that || (*that == ';')) {
|
||||
amount = firsttry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
amount = 0; // No matching '(' or '[' found, use zero indent.
|
||||
}
|
||||
curwin->w_cursor = realpos;
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static int lisp_match(char_u *p)
|
||||
{
|
||||
char_u buf[LSIZE];
|
||||
int len;
|
||||
char_u *word = p_lispwords;
|
||||
|
||||
while (*word != NUL) {
|
||||
(void)copy_option_part(&word, buf, LSIZE, ",");
|
||||
len = (int)STRLEN(buf);
|
||||
|
||||
if ((STRNCMP(buf, p, len) == 0) && (p[len] == ' ')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
14
src/nvim/indent.h
Normal file
14
src/nvim/indent.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef NEOVIM_INDENT_H
|
||||
#define NEOVIM_INDENT_H
|
||||
#include "vim.h"
|
||||
int get_indent(void);
|
||||
int get_indent_lnum(linenr_T lnum);
|
||||
int get_indent_buf(buf_T *buf, linenr_T lnum);
|
||||
int get_indent_str(char_u *ptr, int ts);
|
||||
int set_indent(int size, int flags);
|
||||
int copy_indent(int size, char_u *src);
|
||||
int get_number_indent(linenr_T lnum);
|
||||
int inindent(int extra);
|
||||
int get_expr_indent(void);
|
||||
int get_lisp_indent(void);
|
||||
#endif // NEOVIM_INDENT_H
|
||||
3316
src/nvim/indent_c.c
Normal file
3316
src/nvim/indent_c.c
Normal file
File diff suppressed because it is too large
Load Diff
12
src/nvim/indent_c.h
Normal file
12
src/nvim/indent_c.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef NEOVIM_INDENT_C_H
|
||||
#define NEOVIM_INDENT_C_H
|
||||
#include "vim.h"
|
||||
int cin_islabel(void);
|
||||
int cin_iscase(char_u *s, int strict);
|
||||
int cin_isscopedecl(char_u *s);
|
||||
int cin_is_cinword(char_u *line);
|
||||
int get_c_indent(void);
|
||||
void do_c_expr_indent(void);
|
||||
void parse_cino(buf_T *buf);
|
||||
pos_T * find_start_comment(int ind_maxcomment);
|
||||
#endif
|
||||
777
src/nvim/keymap.c
Normal file
777
src/nvim/keymap.c
Normal file
@@ -0,0 +1,777 @@
|
||||
/************************************************************************
|
||||
* functions that use lookup tables for various things, generally to do with
|
||||
* special key codes.
|
||||
*/
|
||||
|
||||
#include "vim.h"
|
||||
#include "keymap.h"
|
||||
#include "charset.h"
|
||||
#include "edit.h"
|
||||
#include "term.h"
|
||||
|
||||
|
||||
/*
|
||||
* Some useful tables.
|
||||
*/
|
||||
|
||||
static struct modmasktable {
|
||||
short mod_mask; /* Bit-mask for particular key modifier */
|
||||
short mod_flag; /* Bit(s) for particular key modifier */
|
||||
char_u name; /* Single letter name of modifier */
|
||||
} mod_mask_table[] =
|
||||
{
|
||||
{MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M'},
|
||||
{MOD_MASK_META, MOD_MASK_META, (char_u)'T'},
|
||||
{MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C'},
|
||||
{MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S'},
|
||||
{MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'},
|
||||
{MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'},
|
||||
{MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'},
|
||||
/* 'A' must be the last one */
|
||||
{MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A'},
|
||||
{0, 0, NUL}
|
||||
};
|
||||
|
||||
/*
|
||||
* Shifted key terminal codes and their unshifted equivalent.
|
||||
* Don't add mouse codes here, they are handled separately!
|
||||
*/
|
||||
#define MOD_KEYS_ENTRY_SIZE 5
|
||||
|
||||
static char_u modifier_keys_table[] =
|
||||
{
|
||||
/* mod mask with modifier without modifier */
|
||||
MOD_MASK_SHIFT, '&', '9', '@', '1', /* begin */
|
||||
MOD_MASK_SHIFT, '&', '0', '@', '2', /* cancel */
|
||||
MOD_MASK_SHIFT, '*', '1', '@', '4', /* command */
|
||||
MOD_MASK_SHIFT, '*', '2', '@', '5', /* copy */
|
||||
MOD_MASK_SHIFT, '*', '3', '@', '6', /* create */
|
||||
MOD_MASK_SHIFT, '*', '4', 'k', 'D', /* delete char */
|
||||
MOD_MASK_SHIFT, '*', '5', 'k', 'L', /* delete line */
|
||||
MOD_MASK_SHIFT, '*', '7', '@', '7', /* end */
|
||||
MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', /* end */
|
||||
MOD_MASK_SHIFT, '*', '9', '@', '9', /* exit */
|
||||
MOD_MASK_SHIFT, '*', '0', '@', '0', /* find */
|
||||
MOD_MASK_SHIFT, '#', '1', '%', '1', /* help */
|
||||
MOD_MASK_SHIFT, '#', '2', 'k', 'h', /* home */
|
||||
MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', /* home */
|
||||
MOD_MASK_SHIFT, '#', '3', 'k', 'I', /* insert */
|
||||
MOD_MASK_SHIFT, '#', '4', 'k', 'l', /* left arrow */
|
||||
MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', /* left arrow */
|
||||
MOD_MASK_SHIFT, '%', 'a', '%', '3', /* message */
|
||||
MOD_MASK_SHIFT, '%', 'b', '%', '4', /* move */
|
||||
MOD_MASK_SHIFT, '%', 'c', '%', '5', /* next */
|
||||
MOD_MASK_SHIFT, '%', 'd', '%', '7', /* options */
|
||||
MOD_MASK_SHIFT, '%', 'e', '%', '8', /* previous */
|
||||
MOD_MASK_SHIFT, '%', 'f', '%', '9', /* print */
|
||||
MOD_MASK_SHIFT, '%', 'g', '%', '0', /* redo */
|
||||
MOD_MASK_SHIFT, '%', 'h', '&', '3', /* replace */
|
||||
MOD_MASK_SHIFT, '%', 'i', 'k', 'r', /* right arr. */
|
||||
MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', /* right arr. */
|
||||
MOD_MASK_SHIFT, '%', 'j', '&', '5', /* resume */
|
||||
MOD_MASK_SHIFT, '!', '1', '&', '6', /* save */
|
||||
MOD_MASK_SHIFT, '!', '2', '&', '7', /* suspend */
|
||||
MOD_MASK_SHIFT, '!', '3', '&', '8', /* undo */
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', /* up arrow */
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', /* down arrow */
|
||||
|
||||
/* vt100 F1 */
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1,
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2,
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3,
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4,
|
||||
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', /* F1 */
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', /* F10 */
|
||||
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A',
|
||||
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K',
|
||||
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q',
|
||||
MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R',
|
||||
|
||||
/* TAB pseudo code*/
|
||||
MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB,
|
||||
|
||||
NUL
|
||||
};
|
||||
|
||||
static struct key_name_entry {
|
||||
int key; /* Special key code or ascii value */
|
||||
char_u *name; /* Name of key */
|
||||
} key_names_table[] =
|
||||
{
|
||||
{' ', (char_u *)"Space"},
|
||||
{TAB, (char_u *)"Tab"},
|
||||
{K_TAB, (char_u *)"Tab"},
|
||||
{NL, (char_u *)"NL"},
|
||||
{NL, (char_u *)"NewLine"}, /* Alternative name */
|
||||
{NL, (char_u *)"LineFeed"}, /* Alternative name */
|
||||
{NL, (char_u *)"LF"}, /* Alternative name */
|
||||
{CAR, (char_u *)"CR"},
|
||||
{CAR, (char_u *)"Return"}, /* Alternative name */
|
||||
{CAR, (char_u *)"Enter"}, /* Alternative name */
|
||||
{K_BS, (char_u *)"BS"},
|
||||
{K_BS, (char_u *)"BackSpace"}, /* Alternative name */
|
||||
{ESC, (char_u *)"Esc"},
|
||||
{CSI, (char_u *)"CSI"},
|
||||
{K_CSI, (char_u *)"xCSI"},
|
||||
{'|', (char_u *)"Bar"},
|
||||
{'\\', (char_u *)"Bslash"},
|
||||
{K_DEL, (char_u *)"Del"},
|
||||
{K_DEL, (char_u *)"Delete"}, /* Alternative name */
|
||||
{K_KDEL, (char_u *)"kDel"},
|
||||
{K_UP, (char_u *)"Up"},
|
||||
{K_DOWN, (char_u *)"Down"},
|
||||
{K_LEFT, (char_u *)"Left"},
|
||||
{K_RIGHT, (char_u *)"Right"},
|
||||
{K_XUP, (char_u *)"xUp"},
|
||||
{K_XDOWN, (char_u *)"xDown"},
|
||||
{K_XLEFT, (char_u *)"xLeft"},
|
||||
{K_XRIGHT, (char_u *)"xRight"},
|
||||
|
||||
{K_F1, (char_u *)"F1"},
|
||||
{K_F2, (char_u *)"F2"},
|
||||
{K_F3, (char_u *)"F3"},
|
||||
{K_F4, (char_u *)"F4"},
|
||||
{K_F5, (char_u *)"F5"},
|
||||
{K_F6, (char_u *)"F6"},
|
||||
{K_F7, (char_u *)"F7"},
|
||||
{K_F8, (char_u *)"F8"},
|
||||
{K_F9, (char_u *)"F9"},
|
||||
{K_F10, (char_u *)"F10"},
|
||||
|
||||
{K_F11, (char_u *)"F11"},
|
||||
{K_F12, (char_u *)"F12"},
|
||||
{K_F13, (char_u *)"F13"},
|
||||
{K_F14, (char_u *)"F14"},
|
||||
{K_F15, (char_u *)"F15"},
|
||||
{K_F16, (char_u *)"F16"},
|
||||
{K_F17, (char_u *)"F17"},
|
||||
{K_F18, (char_u *)"F18"},
|
||||
{K_F19, (char_u *)"F19"},
|
||||
{K_F20, (char_u *)"F20"},
|
||||
|
||||
{K_F21, (char_u *)"F21"},
|
||||
{K_F22, (char_u *)"F22"},
|
||||
{K_F23, (char_u *)"F23"},
|
||||
{K_F24, (char_u *)"F24"},
|
||||
{K_F25, (char_u *)"F25"},
|
||||
{K_F26, (char_u *)"F26"},
|
||||
{K_F27, (char_u *)"F27"},
|
||||
{K_F28, (char_u *)"F28"},
|
||||
{K_F29, (char_u *)"F29"},
|
||||
{K_F30, (char_u *)"F30"},
|
||||
|
||||
{K_F31, (char_u *)"F31"},
|
||||
{K_F32, (char_u *)"F32"},
|
||||
{K_F33, (char_u *)"F33"},
|
||||
{K_F34, (char_u *)"F34"},
|
||||
{K_F35, (char_u *)"F35"},
|
||||
{K_F36, (char_u *)"F36"},
|
||||
{K_F37, (char_u *)"F37"},
|
||||
|
||||
{K_XF1, (char_u *)"xF1"},
|
||||
{K_XF2, (char_u *)"xF2"},
|
||||
{K_XF3, (char_u *)"xF3"},
|
||||
{K_XF4, (char_u *)"xF4"},
|
||||
|
||||
{K_HELP, (char_u *)"Help"},
|
||||
{K_UNDO, (char_u *)"Undo"},
|
||||
{K_INS, (char_u *)"Insert"},
|
||||
{K_INS, (char_u *)"Ins"}, /* Alternative name */
|
||||
{K_KINS, (char_u *)"kInsert"},
|
||||
{K_HOME, (char_u *)"Home"},
|
||||
{K_KHOME, (char_u *)"kHome"},
|
||||
{K_XHOME, (char_u *)"xHome"},
|
||||
{K_ZHOME, (char_u *)"zHome"},
|
||||
{K_END, (char_u *)"End"},
|
||||
{K_KEND, (char_u *)"kEnd"},
|
||||
{K_XEND, (char_u *)"xEnd"},
|
||||
{K_ZEND, (char_u *)"zEnd"},
|
||||
{K_PAGEUP, (char_u *)"PageUp"},
|
||||
{K_PAGEDOWN, (char_u *)"PageDown"},
|
||||
{K_KPAGEUP, (char_u *)"kPageUp"},
|
||||
{K_KPAGEDOWN, (char_u *)"kPageDown"},
|
||||
|
||||
{K_KPLUS, (char_u *)"kPlus"},
|
||||
{K_KMINUS, (char_u *)"kMinus"},
|
||||
{K_KDIVIDE, (char_u *)"kDivide"},
|
||||
{K_KMULTIPLY, (char_u *)"kMultiply"},
|
||||
{K_KENTER, (char_u *)"kEnter"},
|
||||
{K_KPOINT, (char_u *)"kPoint"},
|
||||
|
||||
{K_K0, (char_u *)"k0"},
|
||||
{K_K1, (char_u *)"k1"},
|
||||
{K_K2, (char_u *)"k2"},
|
||||
{K_K3, (char_u *)"k3"},
|
||||
{K_K4, (char_u *)"k4"},
|
||||
{K_K5, (char_u *)"k5"},
|
||||
{K_K6, (char_u *)"k6"},
|
||||
{K_K7, (char_u *)"k7"},
|
||||
{K_K8, (char_u *)"k8"},
|
||||
{K_K9, (char_u *)"k9"},
|
||||
|
||||
{'<', (char_u *)"lt"},
|
||||
|
||||
{K_MOUSE, (char_u *)"Mouse"},
|
||||
{K_NETTERM_MOUSE, (char_u *)"NetMouse"},
|
||||
{K_DEC_MOUSE, (char_u *)"DecMouse"},
|
||||
#ifdef FEAT_MOUSE_JSB
|
||||
{K_JSBTERM_MOUSE, (char_u *)"JsbMouse"},
|
||||
#endif
|
||||
{K_URXVT_MOUSE, (char_u *)"UrxvtMouse"},
|
||||
{K_SGR_MOUSE, (char_u *)"SgrMouse"},
|
||||
{K_LEFTMOUSE, (char_u *)"LeftMouse"},
|
||||
{K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"},
|
||||
{K_LEFTDRAG, (char_u *)"LeftDrag"},
|
||||
{K_LEFTRELEASE, (char_u *)"LeftRelease"},
|
||||
{K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"},
|
||||
{K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
|
||||
{K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
|
||||
{K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
|
||||
{K_RIGHTMOUSE, (char_u *)"RightMouse"},
|
||||
{K_RIGHTDRAG, (char_u *)"RightDrag"},
|
||||
{K_RIGHTRELEASE, (char_u *)"RightRelease"},
|
||||
{K_MOUSEDOWN, (char_u *)"ScrollWheelUp"},
|
||||
{K_MOUSEUP, (char_u *)"ScrollWheelDown"},
|
||||
{K_MOUSELEFT, (char_u *)"ScrollWheelRight"},
|
||||
{K_MOUSERIGHT, (char_u *)"ScrollWheelLeft"},
|
||||
{K_MOUSEDOWN, (char_u *)"MouseDown"}, /* OBSOLETE: Use */
|
||||
{K_MOUSEUP, (char_u *)"MouseUp"}, /* ScrollWheelXXX instead */
|
||||
{K_X1MOUSE, (char_u *)"X1Mouse"},
|
||||
{K_X1DRAG, (char_u *)"X1Drag"},
|
||||
{K_X1RELEASE, (char_u *)"X1Release"},
|
||||
{K_X2MOUSE, (char_u *)"X2Mouse"},
|
||||
{K_X2DRAG, (char_u *)"X2Drag"},
|
||||
{K_X2RELEASE, (char_u *)"X2Release"},
|
||||
{K_DROP, (char_u *)"Drop"},
|
||||
{K_ZERO, (char_u *)"Nul"},
|
||||
{K_SNR, (char_u *)"SNR"},
|
||||
{K_PLUG, (char_u *)"Plug"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / \
|
||||
sizeof(struct key_name_entry))
|
||||
|
||||
static struct mousetable {
|
||||
int pseudo_code; /* Code for pseudo mouse event */
|
||||
int button; /* Which mouse button is it? */
|
||||
int is_click; /* Is it a mouse button click event? */
|
||||
int is_drag; /* Is it a mouse drag event? */
|
||||
} mouse_table[] =
|
||||
{
|
||||
{(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE},
|
||||
{(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE},
|
||||
{(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE},
|
||||
{(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE},
|
||||
{(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE},
|
||||
{(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE},
|
||||
{(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE},
|
||||
{(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE},
|
||||
{(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE},
|
||||
{(int)KE_X1MOUSE, MOUSE_X1, TRUE, FALSE},
|
||||
{(int)KE_X1DRAG, MOUSE_X1, FALSE, TRUE},
|
||||
{(int)KE_X1RELEASE, MOUSE_X1, FALSE, FALSE},
|
||||
{(int)KE_X2MOUSE, MOUSE_X2, TRUE, FALSE},
|
||||
{(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE},
|
||||
{(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE},
|
||||
/* DRAG without CLICK */
|
||||
{(int)KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE},
|
||||
/* RELEASE without CLICK */
|
||||
{(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
|
||||
* modifier name ('S' for Shift, 'C' for Ctrl etc).
|
||||
*/
|
||||
int name_to_mod_mask(int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
c = TOUPPER_ASC(c);
|
||||
for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
|
||||
if (c == mod_mask_table[i].name)
|
||||
return mod_mask_table[i].mod_flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if if there is a special key code for "key" that includes the
|
||||
* modifiers specified.
|
||||
*/
|
||||
int simplify_key(int key, int *modifiers)
|
||||
{
|
||||
int i;
|
||||
int key0;
|
||||
int key1;
|
||||
|
||||
if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT)) {
|
||||
/* TAB is a special case */
|
||||
if (key == TAB && (*modifiers & MOD_MASK_SHIFT)) {
|
||||
*modifiers &= ~MOD_MASK_SHIFT;
|
||||
return K_S_TAB;
|
||||
}
|
||||
key0 = KEY2TERMCAP0(key);
|
||||
key1 = KEY2TERMCAP1(key);
|
||||
for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
|
||||
if (key0 == modifier_keys_table[i + 3]
|
||||
&& key1 == modifier_keys_table[i + 4]
|
||||
&& (*modifiers & modifier_keys_table[i])) {
|
||||
*modifiers &= ~modifier_keys_table[i];
|
||||
return TERMCAP2KEY(modifier_keys_table[i + 1],
|
||||
modifier_keys_table[i + 2]);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change <xHome> to <Home>, <xUp> to <Up>, etc.
|
||||
*/
|
||||
int handle_x_keys(int key)
|
||||
{
|
||||
switch (key) {
|
||||
case K_XUP: return K_UP;
|
||||
case K_XDOWN: return K_DOWN;
|
||||
case K_XLEFT: return K_LEFT;
|
||||
case K_XRIGHT: return K_RIGHT;
|
||||
case K_XHOME: return K_HOME;
|
||||
case K_ZHOME: return K_HOME;
|
||||
case K_XEND: return K_END;
|
||||
case K_ZEND: return K_END;
|
||||
case K_XF1: return K_F1;
|
||||
case K_XF2: return K_F2;
|
||||
case K_XF3: return K_F3;
|
||||
case K_XF4: return K_F4;
|
||||
case K_S_XF1: return K_S_F1;
|
||||
case K_S_XF2: return K_S_F2;
|
||||
case K_S_XF3: return K_S_F3;
|
||||
case K_S_XF4: return K_S_F4;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string which contains the name of the given key when the given
|
||||
* modifiers are down.
|
||||
*/
|
||||
char_u *get_special_key_name(int c, int modifiers)
|
||||
{
|
||||
static char_u string[MAX_KEY_NAME_LEN + 1];
|
||||
|
||||
int i, idx;
|
||||
int table_idx;
|
||||
char_u *s;
|
||||
|
||||
string[0] = '<';
|
||||
idx = 1;
|
||||
|
||||
/* Key that stands for a normal character. */
|
||||
if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
|
||||
c = KEY2TERMCAP1(c);
|
||||
|
||||
/*
|
||||
* Translate shifted special keys into unshifted keys and set modifier.
|
||||
* Same for CTRL and ALT modifiers.
|
||||
*/
|
||||
if (IS_SPECIAL(c)) {
|
||||
for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
|
||||
if ( KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
|
||||
&& (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2]) {
|
||||
modifiers |= modifier_keys_table[i];
|
||||
c = TERMCAP2KEY(modifier_keys_table[i + 3],
|
||||
modifier_keys_table[i + 4]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* try to find the key in the special key table */
|
||||
table_idx = find_special_key_in_table(c);
|
||||
|
||||
/*
|
||||
* When not a known special key, and not a printable character, try to
|
||||
* extract modifiers.
|
||||
*/
|
||||
if (c > 0
|
||||
&& (*mb_char2len)(c) == 1
|
||||
) {
|
||||
if (table_idx < 0
|
||||
&& (!vim_isprintc(c) || (c & 0x7f) == ' ')
|
||||
&& (c & 0x80)) {
|
||||
c &= 0x7f;
|
||||
modifiers |= MOD_MASK_ALT;
|
||||
/* try again, to find the un-alted key in the special key table */
|
||||
table_idx = find_special_key_in_table(c);
|
||||
}
|
||||
if (table_idx < 0 && !vim_isprintc(c) && c < ' ') {
|
||||
c += '@';
|
||||
modifiers |= MOD_MASK_CTRL;
|
||||
}
|
||||
}
|
||||
|
||||
/* translate the modifier into a string */
|
||||
for (i = 0; mod_mask_table[i].name != 'A'; i++)
|
||||
if ((modifiers & mod_mask_table[i].mod_mask)
|
||||
== mod_mask_table[i].mod_flag) {
|
||||
string[idx++] = mod_mask_table[i].name;
|
||||
string[idx++] = (char_u)'-';
|
||||
}
|
||||
|
||||
if (table_idx < 0) { /* unknown special key, may output t_xx */
|
||||
if (IS_SPECIAL(c)) {
|
||||
string[idx++] = 't';
|
||||
string[idx++] = '_';
|
||||
string[idx++] = KEY2TERMCAP0(c);
|
||||
string[idx++] = KEY2TERMCAP1(c);
|
||||
}
|
||||
/* Not a special key, only modifiers, output directly */
|
||||
else {
|
||||
if (has_mbyte && (*mb_char2len)(c) > 1)
|
||||
idx += (*mb_char2bytes)(c, string + idx);
|
||||
else if (vim_isprintc(c))
|
||||
string[idx++] = c;
|
||||
else {
|
||||
s = transchar(c);
|
||||
while (*s)
|
||||
string[idx++] = *s++;
|
||||
}
|
||||
}
|
||||
} else { /* use name of special key */
|
||||
STRCPY(string + idx, key_names_table[table_idx].name);
|
||||
idx = (int)STRLEN(string);
|
||||
}
|
||||
string[idx++] = '>';
|
||||
string[idx] = NUL;
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try translating a <> name at (*srcp)[] to dst[].
|
||||
* Return the number of characters added to dst[], zero for no match.
|
||||
* If there is a match, srcp is advanced to after the <> name.
|
||||
* dst[] must be big enough to hold the result (up to six characters)!
|
||||
*/
|
||||
int
|
||||
trans_special (
|
||||
char_u **srcp,
|
||||
char_u *dst,
|
||||
int keycode /* prefer key code, e.g. K_DEL instead of DEL */
|
||||
)
|
||||
{
|
||||
int modifiers = 0;
|
||||
int key;
|
||||
int dlen = 0;
|
||||
|
||||
key = find_special_key(srcp, &modifiers, keycode, FALSE);
|
||||
if (key == 0)
|
||||
return 0;
|
||||
|
||||
/* Put the appropriate modifier in a string */
|
||||
if (modifiers != 0) {
|
||||
dst[dlen++] = K_SPECIAL;
|
||||
dst[dlen++] = KS_MODIFIER;
|
||||
dst[dlen++] = modifiers;
|
||||
}
|
||||
|
||||
if (IS_SPECIAL(key)) {
|
||||
dst[dlen++] = K_SPECIAL;
|
||||
dst[dlen++] = KEY2TERMCAP0(key);
|
||||
dst[dlen++] = KEY2TERMCAP1(key);
|
||||
} else if (has_mbyte && !keycode)
|
||||
dlen += (*mb_char2bytes)(key, dst + dlen);
|
||||
else if (keycode)
|
||||
dlen = (int)(add_char2buf(key, dst + dlen) - dst);
|
||||
else
|
||||
dst[dlen++] = key;
|
||||
|
||||
return dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try translating a <> name at (*srcp)[], return the key and modifiers.
|
||||
* srcp is advanced to after the <> name.
|
||||
* returns 0 if there is no match.
|
||||
*/
|
||||
int
|
||||
find_special_key (
|
||||
char_u **srcp,
|
||||
int *modp,
|
||||
int keycode, /* prefer key code, e.g. K_DEL instead of DEL */
|
||||
int keep_x_key /* don't translate xHome to Home key */
|
||||
)
|
||||
{
|
||||
char_u *last_dash;
|
||||
char_u *end_of_name;
|
||||
char_u *src;
|
||||
char_u *bp;
|
||||
int modifiers;
|
||||
int bit;
|
||||
int key;
|
||||
unsigned long n;
|
||||
int l;
|
||||
|
||||
src = *srcp;
|
||||
if (src[0] != '<')
|
||||
return 0;
|
||||
|
||||
/* Find end of modifier list */
|
||||
last_dash = src;
|
||||
for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++) {
|
||||
if (*bp == '-') {
|
||||
last_dash = bp;
|
||||
if (bp[1] != NUL) {
|
||||
if (has_mbyte)
|
||||
l = mb_ptr2len(bp + 1);
|
||||
else
|
||||
l = 1;
|
||||
if (bp[l + 1] == '>')
|
||||
bp += l; /* anything accepted, like <C-?> */
|
||||
}
|
||||
}
|
||||
if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
|
||||
bp += 3; /* skip t_xx, xx may be '-' or '>' */
|
||||
else if (STRNICMP(bp, "char-", 5) == 0) {
|
||||
vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL);
|
||||
bp += l + 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*bp == '>') { /* found matching '>' */
|
||||
end_of_name = bp + 1;
|
||||
|
||||
/* Which modifiers are given? */
|
||||
modifiers = 0x0;
|
||||
for (bp = src + 1; bp < last_dash; bp++) {
|
||||
if (*bp != '-') {
|
||||
bit = name_to_mod_mask(*bp);
|
||||
if (bit == 0x0)
|
||||
break; /* Illegal modifier name */
|
||||
modifiers |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Legal modifier name.
|
||||
*/
|
||||
if (bp >= last_dash) {
|
||||
if (STRNICMP(last_dash + 1, "char-", 5) == 0
|
||||
&& VIM_ISDIGIT(last_dash[6])) {
|
||||
/* <Char-123> or <Char-033> or <Char-0x33> */
|
||||
vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
|
||||
key = (int)n;
|
||||
} else {
|
||||
/*
|
||||
* Modifier with single letter, or special key name.
|
||||
*/
|
||||
if (has_mbyte)
|
||||
l = mb_ptr2len(last_dash + 1);
|
||||
else
|
||||
l = 1;
|
||||
if (modifiers != 0 && last_dash[l + 1] == '>')
|
||||
key = PTR2CHAR(last_dash + 1);
|
||||
else {
|
||||
key = get_special_key_code(last_dash + 1);
|
||||
if (!keep_x_key)
|
||||
key = handle_x_keys(key);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_special_key_code() may return NUL for invalid
|
||||
* special key name.
|
||||
*/
|
||||
if (key != NUL) {
|
||||
/*
|
||||
* Only use a modifier when there is no special key code that
|
||||
* includes the modifier.
|
||||
*/
|
||||
key = simplify_key(key, &modifiers);
|
||||
|
||||
if (!keycode) {
|
||||
/* don't want keycode, use single byte code */
|
||||
if (key == K_BS)
|
||||
key = BS;
|
||||
else if (key == K_DEL || key == K_KDEL)
|
||||
key = DEL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal Key with modifier: Try to make a single byte code.
|
||||
*/
|
||||
if (!IS_SPECIAL(key))
|
||||
key = extract_modifiers(key, &modifiers);
|
||||
|
||||
*modp = modifiers;
|
||||
*srcp = end_of_name;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to include modifiers in the key.
|
||||
* Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
|
||||
*/
|
||||
int extract_modifiers(int key, int *modp)
|
||||
{
|
||||
int modifiers = *modp;
|
||||
|
||||
if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) {
|
||||
key = TOUPPER_ASC(key);
|
||||
modifiers &= ~MOD_MASK_SHIFT;
|
||||
}
|
||||
if ((modifiers & MOD_MASK_CTRL)
|
||||
&& ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
|
||||
) {
|
||||
key = Ctrl_chr(key);
|
||||
modifiers &= ~MOD_MASK_CTRL;
|
||||
/* <C-@> is <Nul> */
|
||||
if (key == 0)
|
||||
key = K_ZERO;
|
||||
}
|
||||
if ((modifiers & MOD_MASK_ALT) && key < 0x80
|
||||
&& !enc_dbcs /* avoid creating a lead byte */
|
||||
) {
|
||||
key |= 0x80;
|
||||
modifiers &= ~MOD_MASK_ALT; /* remove the META modifier */
|
||||
}
|
||||
|
||||
*modp = modifiers;
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find key "c" in the special key table.
|
||||
* Return the index when found, -1 when not found.
|
||||
*/
|
||||
int find_special_key_in_table(int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; key_names_table[i].name != NULL; i++)
|
||||
if (c == key_names_table[i].key)
|
||||
break;
|
||||
if (key_names_table[i].name == NULL)
|
||||
i = -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the special key with the given name (the given string does not have to
|
||||
* end with NUL, the name is assumed to end before the first non-idchar).
|
||||
* If the name starts with "t_" the next two characters are interpreted as a
|
||||
* termcap name.
|
||||
* Return the key code, or 0 if not found.
|
||||
*/
|
||||
int get_special_key_code(char_u *name)
|
||||
{
|
||||
char_u *table_name;
|
||||
char_u string[3];
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* If it's <t_xx> we get the code for xx from the termcap
|
||||
*/
|
||||
if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL) {
|
||||
string[0] = name[2];
|
||||
string[1] = name[3];
|
||||
string[2] = NUL;
|
||||
if (add_termcap_entry(string, FALSE) == OK)
|
||||
return TERMCAP2KEY(name[2], name[3]);
|
||||
} else
|
||||
for (i = 0; key_names_table[i].name != NULL; i++) {
|
||||
table_name = key_names_table[i].name;
|
||||
for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
|
||||
if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
|
||||
break;
|
||||
if (!vim_isIDc(name[j]) && table_name[j] == NUL)
|
||||
return key_names_table[i].key;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char_u *get_key_name(int i)
|
||||
{
|
||||
if (i >= (int)KEY_NAMES_TABLE_LEN)
|
||||
return NULL;
|
||||
return key_names_table[i].name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the given mouse code to return the relevant information in the other
|
||||
* arguments. Return which button is down or was released.
|
||||
*/
|
||||
int get_mouse_button(int code, int *is_click, int *is_drag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; mouse_table[i].pseudo_code; i++)
|
||||
if (code == mouse_table[i].pseudo_code) {
|
||||
*is_click = mouse_table[i].is_click;
|
||||
*is_drag = mouse_table[i].is_drag;
|
||||
return mouse_table[i].button;
|
||||
}
|
||||
return 0; /* Shouldn't get here */
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
|
||||
* the given information about which mouse button is down, and whether the
|
||||
* mouse was clicked, dragged or released.
|
||||
*/
|
||||
int
|
||||
get_pseudo_mouse_code (
|
||||
int button, /* eg MOUSE_LEFT */
|
||||
int is_click,
|
||||
int is_drag
|
||||
)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; mouse_table[i].pseudo_code; i++)
|
||||
if (button == mouse_table[i].button
|
||||
&& is_click == mouse_table[i].is_click
|
||||
&& is_drag == mouse_table[i].is_drag) {
|
||||
return mouse_table[i].pseudo_code;
|
||||
}
|
||||
return (int)KE_IGNORE; /* not recognized, ignore it */
|
||||
}
|
||||
515
src/nvim/keymap.h
Normal file
515
src/nvim/keymap.h
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* VIM - Vi IMproved by Bram Moolenaar
|
||||
*
|
||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||
*/
|
||||
|
||||
#ifndef NEOVIM_KEYMAP_H
|
||||
#define NEOVIM_KEYMAP_H
|
||||
|
||||
/*
|
||||
* Keycode definitions for special keys.
|
||||
*
|
||||
* Any special key code sequences are replaced by these codes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For MSDOS some keys produce codes larger than 0xff. They are split into two
|
||||
* chars, the first one is K_NUL (same value used in term_defs.h).
|
||||
*/
|
||||
#define K_NUL (0xce) /* for MSDOS: special key follows */
|
||||
|
||||
/*
|
||||
* K_SPECIAL is the first byte of a special key code and is always followed by
|
||||
* two bytes.
|
||||
* The second byte can have any value. ASCII is used for normal termcap
|
||||
* entries, 0x80 and higher for special keys, see below.
|
||||
* The third byte is guaranteed to be between 0x02 and 0x7f.
|
||||
*/
|
||||
|
||||
#define K_SPECIAL (0x80)
|
||||
|
||||
/*
|
||||
* Positive characters are "normal" characters.
|
||||
* Negative characters are special key codes. Only characters below -0x200
|
||||
* are used to so that the absolute value can't be mistaken for a single-byte
|
||||
* character.
|
||||
*/
|
||||
#define IS_SPECIAL(c) ((c) < 0)
|
||||
|
||||
/*
|
||||
* Characters 0x0100 - 0x01ff have a special meaning for abbreviations.
|
||||
* Multi-byte characters also have ABBR_OFF added, thus are above 0x0200.
|
||||
*/
|
||||
#define ABBR_OFF 0x100
|
||||
|
||||
/*
|
||||
* NUL cannot be in the input string, therefore it is replaced by
|
||||
* K_SPECIAL KS_ZERO KE_FILLER
|
||||
*/
|
||||
#define KS_ZERO 255
|
||||
|
||||
/*
|
||||
* K_SPECIAL cannot be in the input string, therefore it is replaced by
|
||||
* K_SPECIAL KS_SPECIAL KE_FILLER
|
||||
*/
|
||||
#define KS_SPECIAL 254
|
||||
|
||||
/*
|
||||
* KS_EXTRA is used for keys that have no termcap name
|
||||
* K_SPECIAL KS_EXTRA KE_xxx
|
||||
*/
|
||||
#define KS_EXTRA 253
|
||||
|
||||
/*
|
||||
* KS_MODIFIER is used when a modifier is given for a (special) key
|
||||
* K_SPECIAL KS_MODIFIER bitmask
|
||||
*/
|
||||
#define KS_MODIFIER 252
|
||||
|
||||
/*
|
||||
* These are used for the GUI
|
||||
* K_SPECIAL KS_xxx KE_FILLER
|
||||
*/
|
||||
#define KS_MOUSE 251
|
||||
#define KS_MENU 250
|
||||
#define KS_VER_SCROLLBAR 249
|
||||
#define KS_HOR_SCROLLBAR 248
|
||||
|
||||
/*
|
||||
* These are used for DEC mouse
|
||||
*/
|
||||
#define KS_NETTERM_MOUSE 247
|
||||
#define KS_DEC_MOUSE 246
|
||||
|
||||
/*
|
||||
* Used for switching Select mode back on after a mapping or menu.
|
||||
*/
|
||||
#define KS_SELECT 245
|
||||
#define K_SELECT_STRING (char_u *)"\200\365X"
|
||||
|
||||
/*
|
||||
* Used for tearing off a menu.
|
||||
*/
|
||||
#define KS_TEAROFF 244
|
||||
|
||||
/* Used for JSB term mouse. */
|
||||
#define KS_JSBTERM_MOUSE 243
|
||||
|
||||
/* Used a termcap entry that produces a normal character. */
|
||||
#define KS_KEY 242
|
||||
|
||||
/* Used for the qnx pterm mouse. */
|
||||
#define KS_PTERM_MOUSE 241
|
||||
|
||||
/* Used for click in a tab pages label. */
|
||||
#define KS_TABLINE 240
|
||||
|
||||
/* Used for menu in a tab pages line. */
|
||||
#define KS_TABMENU 239
|
||||
|
||||
/* Used for the urxvt mouse. */
|
||||
#define KS_URXVT_MOUSE 238
|
||||
|
||||
/* Used for the sgr mouse. */
|
||||
#define KS_SGR_MOUSE 237
|
||||
|
||||
/*
|
||||
* Filler used after KS_SPECIAL and others
|
||||
*/
|
||||
#define KE_FILLER ('X')
|
||||
|
||||
/*
|
||||
* translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back
|
||||
*/
|
||||
#define TERMCAP2KEY(a, b) (-((a) + ((int)(b) << 8)))
|
||||
#define KEY2TERMCAP0(x) ((-(x)) & 0xff)
|
||||
#define KEY2TERMCAP1(x) (((unsigned)(-(x)) >> 8) & 0xff)
|
||||
|
||||
/*
|
||||
* get second or third byte when translating special key code into three bytes
|
||||
*/
|
||||
#define K_SECOND(c) ((c) == K_SPECIAL ? KS_SPECIAL : (c) == \
|
||||
NUL ? KS_ZERO : KEY2TERMCAP0(c))
|
||||
|
||||
#define K_THIRD(c) (((c) == K_SPECIAL || (c) == \
|
||||
NUL) ? KE_FILLER : KEY2TERMCAP1(c))
|
||||
|
||||
/*
|
||||
* get single int code from second byte after K_SPECIAL
|
||||
*/
|
||||
#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \
|
||||
KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b))
|
||||
|
||||
/*
|
||||
* Codes for keys that do not have a termcap name.
|
||||
*
|
||||
* K_SPECIAL KS_EXTRA KE_xxx
|
||||
*/
|
||||
enum key_extra {
|
||||
KE_NAME = 3 /* name of this terminal entry */
|
||||
|
||||
, KE_S_UP /* shift-up */
|
||||
, KE_S_DOWN /* shift-down */
|
||||
|
||||
, KE_S_F1 /* shifted function keys */
|
||||
, KE_S_F2
|
||||
, KE_S_F3
|
||||
, KE_S_F4
|
||||
, KE_S_F5
|
||||
, KE_S_F6
|
||||
, KE_S_F7
|
||||
, KE_S_F8
|
||||
, KE_S_F9
|
||||
, KE_S_F10
|
||||
|
||||
, KE_S_F11
|
||||
, KE_S_F12
|
||||
, KE_S_F13
|
||||
, KE_S_F14
|
||||
, KE_S_F15
|
||||
, KE_S_F16
|
||||
, KE_S_F17
|
||||
, KE_S_F18
|
||||
, KE_S_F19
|
||||
, KE_S_F20
|
||||
|
||||
, KE_S_F21
|
||||
, KE_S_F22
|
||||
, KE_S_F23
|
||||
, KE_S_F24
|
||||
, KE_S_F25
|
||||
, KE_S_F26
|
||||
, KE_S_F27
|
||||
, KE_S_F28
|
||||
, KE_S_F29
|
||||
, KE_S_F30
|
||||
|
||||
, KE_S_F31
|
||||
, KE_S_F32
|
||||
, KE_S_F33
|
||||
, KE_S_F34
|
||||
, KE_S_F35
|
||||
, KE_S_F36
|
||||
, KE_S_F37
|
||||
|
||||
, KE_MOUSE /* mouse event start */
|
||||
|
||||
/*
|
||||
* Symbols for pseudo keys which are translated from the real key symbols
|
||||
* above.
|
||||
*/
|
||||
, KE_LEFTMOUSE /* Left mouse button click */
|
||||
, KE_LEFTDRAG /* Drag with left mouse button down */
|
||||
, KE_LEFTRELEASE /* Left mouse button release */
|
||||
, KE_MIDDLEMOUSE /* Middle mouse button click */
|
||||
, KE_MIDDLEDRAG /* Drag with middle mouse button down */
|
||||
, KE_MIDDLERELEASE /* Middle mouse button release */
|
||||
, KE_RIGHTMOUSE /* Right mouse button click */
|
||||
, KE_RIGHTDRAG /* Drag with right mouse button down */
|
||||
, KE_RIGHTRELEASE /* Right mouse button release */
|
||||
|
||||
, KE_IGNORE /* Ignored mouse drag/release */
|
||||
|
||||
, KE_TAB /* unshifted TAB key */
|
||||
, KE_S_TAB_OLD /* shifted TAB key (no longer used) */
|
||||
|
||||
, KE_XF1 /* extra vt100 function keys for xterm */
|
||||
, KE_XF2
|
||||
, KE_XF3
|
||||
, KE_XF4
|
||||
, KE_XEND /* extra (vt100) end key for xterm */
|
||||
, KE_ZEND /* extra (vt100) end key for xterm */
|
||||
, KE_XHOME /* extra (vt100) home key for xterm */
|
||||
, KE_ZHOME /* extra (vt100) home key for xterm */
|
||||
, KE_XUP /* extra vt100 cursor keys for xterm */
|
||||
, KE_XDOWN
|
||||
, KE_XLEFT
|
||||
, KE_XRIGHT
|
||||
|
||||
, KE_LEFTMOUSE_NM /* non-mappable Left mouse button click */
|
||||
, KE_LEFTRELEASE_NM /* non-mappable left mouse button release */
|
||||
|
||||
, KE_S_XF1 /* extra vt100 shifted function keys for xterm */
|
||||
, KE_S_XF2
|
||||
, KE_S_XF3
|
||||
, KE_S_XF4
|
||||
|
||||
/* NOTE: The scroll wheel events are inverted: i.e. UP is the same as
|
||||
* moving the actual scroll wheel down, LEFT is the same as moving the
|
||||
* scroll wheel right. */
|
||||
, KE_MOUSEDOWN /* scroll wheel pseudo-button Down */
|
||||
, KE_MOUSEUP /* scroll wheel pseudo-button Up */
|
||||
, KE_MOUSELEFT /* scroll wheel pseudo-button Left */
|
||||
, KE_MOUSERIGHT /* scroll wheel pseudo-button Right */
|
||||
|
||||
, KE_KINS /* keypad Insert key */
|
||||
, KE_KDEL /* keypad Delete key */
|
||||
|
||||
, KE_CSI /* CSI typed directly */
|
||||
, KE_SNR /* <SNR> */
|
||||
, KE_PLUG /* <Plug> */
|
||||
, KE_CMDWIN /* open command-line window from Command-line Mode */
|
||||
|
||||
, KE_C_LEFT /* control-left */
|
||||
, KE_C_RIGHT /* control-right */
|
||||
, KE_C_HOME /* control-home */
|
||||
, KE_C_END /* control-end */
|
||||
|
||||
, KE_X1MOUSE /* X1/X2 mouse-buttons */
|
||||
, KE_X1DRAG
|
||||
, KE_X1RELEASE
|
||||
, KE_X2MOUSE
|
||||
, KE_X2DRAG
|
||||
, KE_X2RELEASE
|
||||
|
||||
, KE_DROP /* DnD data is available */
|
||||
, KE_CURSORHOLD /* CursorHold event */
|
||||
, KE_NOP /* doesn't do something */
|
||||
, KE_FOCUSGAINED /* focus gained */
|
||||
, KE_FOCUSLOST /* focus lost */
|
||||
, KE_EVENT // event
|
||||
};
|
||||
|
||||
/*
|
||||
* the three byte codes are replaced with the following int when using vgetc()
|
||||
*/
|
||||
#define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER)
|
||||
|
||||
#define K_UP TERMCAP2KEY('k', 'u')
|
||||
#define K_DOWN TERMCAP2KEY('k', 'd')
|
||||
#define K_LEFT TERMCAP2KEY('k', 'l')
|
||||
#define K_RIGHT TERMCAP2KEY('k', 'r')
|
||||
#define K_S_UP TERMCAP2KEY(KS_EXTRA, KE_S_UP)
|
||||
#define K_S_DOWN TERMCAP2KEY(KS_EXTRA, KE_S_DOWN)
|
||||
#define K_S_LEFT TERMCAP2KEY('#', '4')
|
||||
#define K_C_LEFT TERMCAP2KEY(KS_EXTRA, KE_C_LEFT)
|
||||
#define K_S_RIGHT TERMCAP2KEY('%', 'i')
|
||||
#define K_C_RIGHT TERMCAP2KEY(KS_EXTRA, KE_C_RIGHT)
|
||||
#define K_S_HOME TERMCAP2KEY('#', '2')
|
||||
#define K_C_HOME TERMCAP2KEY(KS_EXTRA, KE_C_HOME)
|
||||
#define K_S_END TERMCAP2KEY('*', '7')
|
||||
#define K_C_END TERMCAP2KEY(KS_EXTRA, KE_C_END)
|
||||
#define K_TAB TERMCAP2KEY(KS_EXTRA, KE_TAB)
|
||||
#define K_S_TAB TERMCAP2KEY('k', 'B')
|
||||
|
||||
/* extra set of function keys F1-F4, for vt100 compatible xterm */
|
||||
#define K_XF1 TERMCAP2KEY(KS_EXTRA, KE_XF1)
|
||||
#define K_XF2 TERMCAP2KEY(KS_EXTRA, KE_XF2)
|
||||
#define K_XF3 TERMCAP2KEY(KS_EXTRA, KE_XF3)
|
||||
#define K_XF4 TERMCAP2KEY(KS_EXTRA, KE_XF4)
|
||||
|
||||
/* extra set of cursor keys for vt100 compatible xterm */
|
||||
#define K_XUP TERMCAP2KEY(KS_EXTRA, KE_XUP)
|
||||
#define K_XDOWN TERMCAP2KEY(KS_EXTRA, KE_XDOWN)
|
||||
#define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT)
|
||||
#define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT)
|
||||
|
||||
#define K_F1 TERMCAP2KEY('k', '1') /* function keys */
|
||||
#define K_F2 TERMCAP2KEY('k', '2')
|
||||
#define K_F3 TERMCAP2KEY('k', '3')
|
||||
#define K_F4 TERMCAP2KEY('k', '4')
|
||||
#define K_F5 TERMCAP2KEY('k', '5')
|
||||
#define K_F6 TERMCAP2KEY('k', '6')
|
||||
#define K_F7 TERMCAP2KEY('k', '7')
|
||||
#define K_F8 TERMCAP2KEY('k', '8')
|
||||
#define K_F9 TERMCAP2KEY('k', '9')
|
||||
#define K_F10 TERMCAP2KEY('k', ';')
|
||||
|
||||
#define K_F11 TERMCAP2KEY('F', '1')
|
||||
#define K_F12 TERMCAP2KEY('F', '2')
|
||||
#define K_F13 TERMCAP2KEY('F', '3')
|
||||
#define K_F14 TERMCAP2KEY('F', '4')
|
||||
#define K_F15 TERMCAP2KEY('F', '5')
|
||||
#define K_F16 TERMCAP2KEY('F', '6')
|
||||
#define K_F17 TERMCAP2KEY('F', '7')
|
||||
#define K_F18 TERMCAP2KEY('F', '8')
|
||||
#define K_F19 TERMCAP2KEY('F', '9')
|
||||
#define K_F20 TERMCAP2KEY('F', 'A')
|
||||
|
||||
#define K_F21 TERMCAP2KEY('F', 'B')
|
||||
#define K_F22 TERMCAP2KEY('F', 'C')
|
||||
#define K_F23 TERMCAP2KEY('F', 'D')
|
||||
#define K_F24 TERMCAP2KEY('F', 'E')
|
||||
#define K_F25 TERMCAP2KEY('F', 'F')
|
||||
#define K_F26 TERMCAP2KEY('F', 'G')
|
||||
#define K_F27 TERMCAP2KEY('F', 'H')
|
||||
#define K_F28 TERMCAP2KEY('F', 'I')
|
||||
#define K_F29 TERMCAP2KEY('F', 'J')
|
||||
#define K_F30 TERMCAP2KEY('F', 'K')
|
||||
|
||||
#define K_F31 TERMCAP2KEY('F', 'L')
|
||||
#define K_F32 TERMCAP2KEY('F', 'M')
|
||||
#define K_F33 TERMCAP2KEY('F', 'N')
|
||||
#define K_F34 TERMCAP2KEY('F', 'O')
|
||||
#define K_F35 TERMCAP2KEY('F', 'P')
|
||||
#define K_F36 TERMCAP2KEY('F', 'Q')
|
||||
#define K_F37 TERMCAP2KEY('F', 'R')
|
||||
|
||||
/* extra set of shifted function keys F1-F4, for vt100 compatible xterm */
|
||||
#define K_S_XF1 TERMCAP2KEY(KS_EXTRA, KE_S_XF1)
|
||||
#define K_S_XF2 TERMCAP2KEY(KS_EXTRA, KE_S_XF2)
|
||||
#define K_S_XF3 TERMCAP2KEY(KS_EXTRA, KE_S_XF3)
|
||||
#define K_S_XF4 TERMCAP2KEY(KS_EXTRA, KE_S_XF4)
|
||||
|
||||
#define K_S_F1 TERMCAP2KEY(KS_EXTRA, KE_S_F1) /* shifted func. keys */
|
||||
#define K_S_F2 TERMCAP2KEY(KS_EXTRA, KE_S_F2)
|
||||
#define K_S_F3 TERMCAP2KEY(KS_EXTRA, KE_S_F3)
|
||||
#define K_S_F4 TERMCAP2KEY(KS_EXTRA, KE_S_F4)
|
||||
#define K_S_F5 TERMCAP2KEY(KS_EXTRA, KE_S_F5)
|
||||
#define K_S_F6 TERMCAP2KEY(KS_EXTRA, KE_S_F6)
|
||||
#define K_S_F7 TERMCAP2KEY(KS_EXTRA, KE_S_F7)
|
||||
#define K_S_F8 TERMCAP2KEY(KS_EXTRA, KE_S_F8)
|
||||
#define K_S_F9 TERMCAP2KEY(KS_EXTRA, KE_S_F9)
|
||||
#define K_S_F10 TERMCAP2KEY(KS_EXTRA, KE_S_F10)
|
||||
|
||||
#define K_S_F11 TERMCAP2KEY(KS_EXTRA, KE_S_F11)
|
||||
#define K_S_F12 TERMCAP2KEY(KS_EXTRA, KE_S_F12)
|
||||
/* K_S_F13 to K_S_F37 are currently not used */
|
||||
|
||||
#define K_HELP TERMCAP2KEY('%', '1')
|
||||
#define K_UNDO TERMCAP2KEY('&', '8')
|
||||
|
||||
#define K_BS TERMCAP2KEY('k', 'b')
|
||||
|
||||
#define K_INS TERMCAP2KEY('k', 'I')
|
||||
#define K_KINS TERMCAP2KEY(KS_EXTRA, KE_KINS)
|
||||
#define K_DEL TERMCAP2KEY('k', 'D')
|
||||
#define K_KDEL TERMCAP2KEY(KS_EXTRA, KE_KDEL)
|
||||
#define K_HOME TERMCAP2KEY('k', 'h')
|
||||
#define K_KHOME TERMCAP2KEY('K', '1') /* keypad home (upper left) */
|
||||
#define K_XHOME TERMCAP2KEY(KS_EXTRA, KE_XHOME)
|
||||
#define K_ZHOME TERMCAP2KEY(KS_EXTRA, KE_ZHOME)
|
||||
#define K_END TERMCAP2KEY('@', '7')
|
||||
#define K_KEND TERMCAP2KEY('K', '4') /* keypad end (lower left) */
|
||||
#define K_XEND TERMCAP2KEY(KS_EXTRA, KE_XEND)
|
||||
#define K_ZEND TERMCAP2KEY(KS_EXTRA, KE_ZEND)
|
||||
#define K_PAGEUP TERMCAP2KEY('k', 'P')
|
||||
#define K_PAGEDOWN TERMCAP2KEY('k', 'N')
|
||||
#define K_KPAGEUP TERMCAP2KEY('K', '3') /* keypad pageup (upper R.) */
|
||||
#define K_KPAGEDOWN TERMCAP2KEY('K', '5') /* keypad pagedown (lower R.) */
|
||||
|
||||
#define K_KPLUS TERMCAP2KEY('K', '6') /* keypad plus */
|
||||
#define K_KMINUS TERMCAP2KEY('K', '7') /* keypad minus */
|
||||
#define K_KDIVIDE TERMCAP2KEY('K', '8') /* keypad / */
|
||||
#define K_KMULTIPLY TERMCAP2KEY('K', '9') /* keypad * */
|
||||
#define K_KENTER TERMCAP2KEY('K', 'A') /* keypad Enter */
|
||||
#define K_KPOINT TERMCAP2KEY('K', 'B') /* keypad . or ,*/
|
||||
|
||||
#define K_K0 TERMCAP2KEY('K', 'C') /* keypad 0 */
|
||||
#define K_K1 TERMCAP2KEY('K', 'D') /* keypad 1 */
|
||||
#define K_K2 TERMCAP2KEY('K', 'E') /* keypad 2 */
|
||||
#define K_K3 TERMCAP2KEY('K', 'F') /* keypad 3 */
|
||||
#define K_K4 TERMCAP2KEY('K', 'G') /* keypad 4 */
|
||||
#define K_K5 TERMCAP2KEY('K', 'H') /* keypad 5 */
|
||||
#define K_K6 TERMCAP2KEY('K', 'I') /* keypad 6 */
|
||||
#define K_K7 TERMCAP2KEY('K', 'J') /* keypad 7 */
|
||||
#define K_K8 TERMCAP2KEY('K', 'K') /* keypad 8 */
|
||||
#define K_K9 TERMCAP2KEY('K', 'L') /* keypad 9 */
|
||||
|
||||
#define K_MOUSE TERMCAP2KEY(KS_MOUSE, KE_FILLER)
|
||||
#define K_MENU TERMCAP2KEY(KS_MENU, KE_FILLER)
|
||||
#define K_VER_SCROLLBAR TERMCAP2KEY(KS_VER_SCROLLBAR, KE_FILLER)
|
||||
#define K_HOR_SCROLLBAR TERMCAP2KEY(KS_HOR_SCROLLBAR, KE_FILLER)
|
||||
|
||||
#define K_NETTERM_MOUSE TERMCAP2KEY(KS_NETTERM_MOUSE, KE_FILLER)
|
||||
#define K_DEC_MOUSE TERMCAP2KEY(KS_DEC_MOUSE, KE_FILLER)
|
||||
#define K_JSBTERM_MOUSE TERMCAP2KEY(KS_JSBTERM_MOUSE, KE_FILLER)
|
||||
#define K_PTERM_MOUSE TERMCAP2KEY(KS_PTERM_MOUSE, KE_FILLER)
|
||||
#define K_URXVT_MOUSE TERMCAP2KEY(KS_URXVT_MOUSE, KE_FILLER)
|
||||
#define K_SGR_MOUSE TERMCAP2KEY(KS_SGR_MOUSE, KE_FILLER)
|
||||
|
||||
#define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER)
|
||||
#define K_TEAROFF TERMCAP2KEY(KS_TEAROFF, KE_FILLER)
|
||||
|
||||
#define K_TABLINE TERMCAP2KEY(KS_TABLINE, KE_FILLER)
|
||||
#define K_TABMENU TERMCAP2KEY(KS_TABMENU, KE_FILLER)
|
||||
|
||||
/*
|
||||
* Symbols for pseudo keys which are translated from the real key symbols
|
||||
* above.
|
||||
*/
|
||||
#define K_LEFTMOUSE TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE)
|
||||
#define K_LEFTMOUSE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE_NM)
|
||||
#define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG)
|
||||
#define K_LEFTRELEASE TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE)
|
||||
#define K_LEFTRELEASE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE_NM)
|
||||
#define K_MIDDLEMOUSE TERMCAP2KEY(KS_EXTRA, KE_MIDDLEMOUSE)
|
||||
#define K_MIDDLEDRAG TERMCAP2KEY(KS_EXTRA, KE_MIDDLEDRAG)
|
||||
#define K_MIDDLERELEASE TERMCAP2KEY(KS_EXTRA, KE_MIDDLERELEASE)
|
||||
#define K_RIGHTMOUSE TERMCAP2KEY(KS_EXTRA, KE_RIGHTMOUSE)
|
||||
#define K_RIGHTDRAG TERMCAP2KEY(KS_EXTRA, KE_RIGHTDRAG)
|
||||
#define K_RIGHTRELEASE TERMCAP2KEY(KS_EXTRA, KE_RIGHTRELEASE)
|
||||
#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE)
|
||||
#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE)
|
||||
#define K_X1DRAG TERMCAP2KEY(KS_EXTRA, KE_X1DRAG)
|
||||
#define K_X1RELEASE TERMCAP2KEY(KS_EXTRA, KE_X1RELEASE)
|
||||
#define K_X2MOUSE TERMCAP2KEY(KS_EXTRA, KE_X2MOUSE)
|
||||
#define K_X2DRAG TERMCAP2KEY(KS_EXTRA, KE_X2DRAG)
|
||||
#define K_X2RELEASE TERMCAP2KEY(KS_EXTRA, KE_X2RELEASE)
|
||||
|
||||
#define K_IGNORE TERMCAP2KEY(KS_EXTRA, KE_IGNORE)
|
||||
#define K_NOP TERMCAP2KEY(KS_EXTRA, KE_NOP)
|
||||
|
||||
#define K_MOUSEDOWN TERMCAP2KEY(KS_EXTRA, KE_MOUSEDOWN)
|
||||
#define K_MOUSEUP TERMCAP2KEY(KS_EXTRA, KE_MOUSEUP)
|
||||
#define K_MOUSELEFT TERMCAP2KEY(KS_EXTRA, KE_MOUSELEFT)
|
||||
#define K_MOUSERIGHT TERMCAP2KEY(KS_EXTRA, KE_MOUSERIGHT)
|
||||
|
||||
#define K_CSI TERMCAP2KEY(KS_EXTRA, KE_CSI)
|
||||
#define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR)
|
||||
#define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG)
|
||||
#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
|
||||
|
||||
#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP)
|
||||
#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
|
||||
#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
|
||||
|
||||
#define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
|
||||
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
||||
|
||||
/* Bits for modifier mask */
|
||||
/* 0x01 cannot be used, because the modifier must be 0x02 or higher */
|
||||
#define MOD_MASK_SHIFT 0x02
|
||||
#define MOD_MASK_CTRL 0x04
|
||||
#define MOD_MASK_ALT 0x08 /* aka META */
|
||||
#define MOD_MASK_META 0x10 /* META when it's different from ALT */
|
||||
#define MOD_MASK_2CLICK 0x20 /* use MOD_MASK_MULTI_CLICK */
|
||||
#define MOD_MASK_3CLICK 0x40 /* use MOD_MASK_MULTI_CLICK */
|
||||
#define MOD_MASK_4CLICK 0x60 /* use MOD_MASK_MULTI_CLICK */
|
||||
|
||||
#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK| \
|
||||
MOD_MASK_4CLICK)
|
||||
|
||||
/*
|
||||
* The length of the longest special key name, including modifiers.
|
||||
* Current longest is <M-C-S-T-4-MiddleRelease> (length includes '<' and '>').
|
||||
*/
|
||||
#define MAX_KEY_NAME_LEN 25
|
||||
|
||||
/* Maximum length of a special key event as tokens. This includes modifiers.
|
||||
* The longest event is something like <M-C-S-T-4-LeftDrag> which would be the
|
||||
* following string of tokens:
|
||||
*
|
||||
* <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KT_LEFTDRAG>.
|
||||
*
|
||||
* This is a total of 6 tokens, and is currently the longest one possible.
|
||||
*/
|
||||
#define MAX_KEY_CODE_LEN 6
|
||||
|
||||
int name_to_mod_mask(int c);
|
||||
int simplify_key(int key, int *modifiers);
|
||||
int handle_x_keys(int key);
|
||||
char_u *get_special_key_name(int c, int modifiers);
|
||||
int trans_special(char_u **srcp, char_u *dst, int keycode);
|
||||
int find_special_key(char_u **srcp, int *modp, int keycode,
|
||||
int keep_x_key);
|
||||
int extract_modifiers(int key, int *modp);
|
||||
int find_special_key_in_table(int c);
|
||||
int get_special_key_code(char_u *name);
|
||||
char_u *get_key_name(int i);
|
||||
int get_mouse_button(int code, int *is_click, int *is_drag);
|
||||
int get_pseudo_mouse_code(int button, int is_click, int is_drag);
|
||||
|
||||
#endif /* NEOVIM_KEYMAP_H */
|
||||
632
src/nvim/lib/khash.h
Normal file
632
src/nvim/lib/khash.h
Normal file
@@ -0,0 +1,632 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
An example:
|
||||
|
||||
#include "khash.h"
|
||||
KHASH_MAP_INIT_INT(32, char)
|
||||
int main() {
|
||||
int ret, is_missing;
|
||||
khiter_t k;
|
||||
khash_t(32) *h = kh_init(32);
|
||||
k = kh_put(32, h, 5, &ret);
|
||||
kh_value(h, k) = 10;
|
||||
k = kh_get(32, h, 10);
|
||||
is_missing = (k == kh_end(h));
|
||||
k = kh_get(32, h, 5);
|
||||
kh_del(32, h, k);
|
||||
for (k = kh_begin(h); k != kh_end(h); ++k)
|
||||
if (kh_exist(h, k)) kh_value(h, k) = 1;
|
||||
kh_destroy(32, h);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
2013-05-02 (0.2.8):
|
||||
|
||||
* Use quadratic probing. When the capacity is power of 2, stepping function
|
||||
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
|
||||
hashing on cache performance and is more robust than linear probing.
|
||||
|
||||
In theory, double hashing should be more robust than quadratic probing.
|
||||
However, my implementation is probably not for large hash tables, because
|
||||
the second hash function is closely tied to the first hash function,
|
||||
which reduce the effectiveness of double hashing.
|
||||
|
||||
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
|
||||
|
||||
2011-12-29 (0.2.7):
|
||||
|
||||
* Minor code clean up; no actual effect.
|
||||
|
||||
2011-09-16 (0.2.6):
|
||||
|
||||
* The capacity is a power of 2. This seems to dramatically improve the
|
||||
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
|
||||
|
||||
- http://code.google.com/p/ulib/
|
||||
- http://nothings.org/computer/judy/
|
||||
|
||||
* Allow to optionally use linear probing which usually has better
|
||||
performance for random input. Double hashing is still the default as it
|
||||
is more robust to certain non-random input.
|
||||
|
||||
* Added Wang's integer hash function (not used by default). This hash
|
||||
function is more robust to certain non-random input.
|
||||
|
||||
2011-02-14 (0.2.5):
|
||||
|
||||
* Allow to declare global functions.
|
||||
|
||||
2009-09-26 (0.2.4):
|
||||
|
||||
* Improve portability
|
||||
|
||||
2008-09-19 (0.2.3):
|
||||
|
||||
* Corrected the example
|
||||
* Improved interfaces
|
||||
|
||||
2008-09-11 (0.2.2):
|
||||
|
||||
* Improved speed a little in kh_put()
|
||||
|
||||
2008-09-10 (0.2.1):
|
||||
|
||||
* Added kh_clear()
|
||||
* Fixed a compiling error
|
||||
|
||||
2008-09-02 (0.2.0):
|
||||
|
||||
* Changed to token concatenation which increases flexibility.
|
||||
|
||||
2008-08-31 (0.1.2):
|
||||
|
||||
* Fixed a bug in kh_get(), which has not been tested previously.
|
||||
|
||||
2008-08-31 (0.1.1):
|
||||
|
||||
* Added destructor
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __AC_KHASH_H
|
||||
#define __AC_KHASH_H
|
||||
|
||||
/*!
|
||||
@header
|
||||
|
||||
Generic hash table library.
|
||||
*/
|
||||
|
||||
#define AC_VERSION_KHASH_H "0.2.8"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "func_attr.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* compiler specific configuration */
|
||||
|
||||
#if UINT_MAX == 0xffffffffu
|
||||
typedef unsigned int khint32_t;
|
||||
#elif ULONG_MAX == 0xffffffffu
|
||||
typedef unsigned long khint32_t;
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == ULLONG_MAX
|
||||
typedef unsigned long khint64_t;
|
||||
#else
|
||||
typedef unsigned long long khint64_t;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define kh_inline __inline
|
||||
#else
|
||||
#define kh_inline inline
|
||||
#endif
|
||||
|
||||
typedef khint32_t khint_t;
|
||||
typedef khint_t khiter_t;
|
||||
|
||||
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
|
||||
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
|
||||
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
|
||||
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
|
||||
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
|
||||
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
|
||||
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
|
||||
|
||||
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
|
||||
|
||||
#ifndef kroundup32
|
||||
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
|
||||
#endif
|
||||
|
||||
#ifndef kcalloc
|
||||
#define kcalloc(N,Z) xcalloc(N,Z)
|
||||
#endif
|
||||
#ifndef kmalloc
|
||||
#define kmalloc(Z) xmalloc(Z)
|
||||
#endif
|
||||
#ifndef krealloc
|
||||
#define krealloc(P,Z) xrealloc(P,Z)
|
||||
#endif
|
||||
#ifndef kfree
|
||||
#define kfree(P) free(P)
|
||||
#endif
|
||||
|
||||
static const double __ac_HASH_UPPER = 0.77;
|
||||
|
||||
#define __KHASH_TYPE(name, khkey_t, khval_t) \
|
||||
typedef struct { \
|
||||
khint_t n_buckets, size, n_occupied, upper_bound; \
|
||||
khint32_t *flags; \
|
||||
khkey_t *keys; \
|
||||
khval_t *vals; \
|
||||
} kh_##name##_t;
|
||||
|
||||
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
|
||||
extern kh_##name##_t *kh_init_##name(void); \
|
||||
extern void kh_destroy_##name(kh_##name##_t *h); \
|
||||
extern void kh_clear_##name(kh_##name##_t *h); \
|
||||
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
|
||||
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
|
||||
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
|
||||
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
|
||||
|
||||
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
SCOPE kh_##name##_t *kh_init_##name(void) { \
|
||||
return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \
|
||||
} \
|
||||
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
|
||||
{ \
|
||||
if (h) { \
|
||||
kfree((void *)h->keys); kfree(h->flags); \
|
||||
kfree((void *)h->vals); \
|
||||
kfree(h); \
|
||||
} \
|
||||
} \
|
||||
SCOPE void kh_clear_##name(kh_##name##_t *h) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE void kh_clear_##name(kh_##name##_t *h) \
|
||||
{ \
|
||||
if (h && h->flags) { \
|
||||
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
|
||||
h->size = h->n_occupied = 0; \
|
||||
} \
|
||||
} \
|
||||
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
|
||||
{ \
|
||||
if (h->n_buckets) { \
|
||||
khint_t k, i, last, mask, step = 0; \
|
||||
mask = h->n_buckets - 1; \
|
||||
k = __hash_func(key); i = k & mask; \
|
||||
last = i; \
|
||||
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
|
||||
i = (i + (++step)) & mask; \
|
||||
if (i == last) return h->n_buckets; \
|
||||
} \
|
||||
return __ac_iseither(h->flags, i)? h->n_buckets : i; \
|
||||
} else return 0; \
|
||||
} \
|
||||
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
|
||||
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
|
||||
khint32_t *new_flags = 0; \
|
||||
khint_t j = 1; \
|
||||
{ \
|
||||
kroundup32(new_n_buckets); \
|
||||
if (new_n_buckets < 4) new_n_buckets = 4; \
|
||||
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
|
||||
else { /* hash table size to be changed (shrink or expand); rehash */ \
|
||||
new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
|
||||
if (!new_flags) return -1; \
|
||||
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
|
||||
if (h->n_buckets < new_n_buckets) { /* expand */ \
|
||||
khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
|
||||
if (!new_keys) return -1; \
|
||||
h->keys = new_keys; \
|
||||
if (kh_is_map) { \
|
||||
khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
|
||||
if (!new_vals) return -1; \
|
||||
h->vals = new_vals; \
|
||||
} \
|
||||
} /* otherwise shrink */ \
|
||||
} \
|
||||
} \
|
||||
if (j) { /* rehashing is needed */ \
|
||||
for (j = 0; j != h->n_buckets; ++j) { \
|
||||
if (__ac_iseither(h->flags, j) == 0) { \
|
||||
khkey_t key = h->keys[j]; \
|
||||
khval_t val; \
|
||||
khint_t new_mask; \
|
||||
new_mask = new_n_buckets - 1; \
|
||||
if (kh_is_map) val = h->vals[j]; \
|
||||
__ac_set_isdel_true(h->flags, j); \
|
||||
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
|
||||
khint_t k, i, step = 0; \
|
||||
k = __hash_func(key); \
|
||||
i = k & new_mask; \
|
||||
while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
|
||||
__ac_set_isempty_false(new_flags, i); \
|
||||
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
|
||||
{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
|
||||
if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
|
||||
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
|
||||
} else { /* write the element and jump out of the loop */ \
|
||||
h->keys[i] = key; \
|
||||
if (kh_is_map) h->vals[i] = val; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
|
||||
h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
|
||||
if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
|
||||
} \
|
||||
kfree(h->flags); /* free the working space */ \
|
||||
h->flags = new_flags; \
|
||||
h->n_buckets = new_n_buckets; \
|
||||
h->n_occupied = h->size; \
|
||||
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
{ \
|
||||
khint_t x; \
|
||||
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
|
||||
if (h->n_buckets > (h->size<<1)) { \
|
||||
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
|
||||
*ret = -1; return h->n_buckets; \
|
||||
} \
|
||||
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
|
||||
*ret = -1; return h->n_buckets; \
|
||||
} \
|
||||
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
|
||||
{ \
|
||||
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
|
||||
x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
|
||||
if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
|
||||
else { \
|
||||
last = i; \
|
||||
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
|
||||
if (__ac_isdel(h->flags, i)) site = i; \
|
||||
i = (i + (++step)) & mask; \
|
||||
if (i == last) { x = site; break; } \
|
||||
} \
|
||||
if (x == h->n_buckets) { \
|
||||
if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
|
||||
else x = i; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
|
||||
h->keys[x] = key; \
|
||||
__ac_set_isboth_false(h->flags, x); \
|
||||
++h->size; ++h->n_occupied; \
|
||||
*ret = 1; \
|
||||
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
|
||||
h->keys[x] = key; \
|
||||
__ac_set_isboth_false(h->flags, x); \
|
||||
++h->size; \
|
||||
*ret = 2; \
|
||||
} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
|
||||
return x; \
|
||||
} \
|
||||
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
|
||||
{ \
|
||||
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
|
||||
__ac_set_isdel_true(h->flags, x); \
|
||||
--h->size; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define KHASH_DECLARE(name, khkey_t, khval_t) \
|
||||
__KHASH_TYPE(name, khkey_t, khval_t) \
|
||||
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
|
||||
|
||||
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
__KHASH_TYPE(name, khkey_t, khval_t) \
|
||||
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
|
||||
|
||||
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
|
||||
|
||||
/* --- BEGIN OF HASH FUNCTIONS --- */
|
||||
|
||||
/*! @function
|
||||
@abstract Integer hash function
|
||||
@param key The integer [khint32_t]
|
||||
@return The hash value [khint_t]
|
||||
*/
|
||||
#define kh_int_hash_func(key) (khint32_t)(key)
|
||||
/*! @function
|
||||
@abstract Integer comparison function
|
||||
*/
|
||||
#define kh_int_hash_equal(a, b) ((a) == (b))
|
||||
/*! @function
|
||||
@abstract 64-bit integer hash function
|
||||
@param key The integer [khint64_t]
|
||||
@return The hash value [khint_t]
|
||||
*/
|
||||
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
|
||||
/*! @function
|
||||
@abstract 64-bit integer comparison function
|
||||
*/
|
||||
#define kh_int64_hash_equal(a, b) ((a) == (b))
|
||||
/*! @function
|
||||
@abstract const char* hash function
|
||||
@param s Pointer to a null terminated string
|
||||
@return The hash value
|
||||
*/
|
||||
static kh_inline khint_t __ac_X31_hash_string(const char *s)
|
||||
{
|
||||
khint_t h = (khint_t)*s;
|
||||
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
|
||||
return h;
|
||||
}
|
||||
/*! @function
|
||||
@abstract Another interface to const char* hash function
|
||||
@param key Pointer to a null terminated string [const char*]
|
||||
@return The hash value [khint_t]
|
||||
*/
|
||||
#define kh_str_hash_func(key) __ac_X31_hash_string(key)
|
||||
/*! @function
|
||||
@abstract Const char* comparison function
|
||||
*/
|
||||
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
|
||||
|
||||
static kh_inline khint_t __ac_Wang_hash(khint_t key)
|
||||
{
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
#define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key)
|
||||
|
||||
/* --- END OF HASH FUNCTIONS --- */
|
||||
|
||||
/* Other convenient macros... */
|
||||
|
||||
/*!
|
||||
@abstract Type of the hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
*/
|
||||
#define khash_t(name) kh_##name##_t
|
||||
|
||||
/*! @function
|
||||
@abstract Initiate a hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@return Pointer to the hash table [khash_t(name)*]
|
||||
*/
|
||||
#define kh_init(name) kh_init_##name()
|
||||
|
||||
/*! @function
|
||||
@abstract Destroy a hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
*/
|
||||
#define kh_destroy(name, h) kh_destroy_##name(h)
|
||||
|
||||
/*! @function
|
||||
@abstract Reset a hash table without deallocating memory.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
*/
|
||||
#define kh_clear(name, h) kh_clear_##name(h)
|
||||
|
||||
/*! @function
|
||||
@abstract Resize a hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param s New size [khint_t]
|
||||
*/
|
||||
#define kh_resize(name, h, s) kh_resize_##name(h, s)
|
||||
|
||||
/*! @function
|
||||
@abstract Insert a key to the hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param k Key [type of keys]
|
||||
@param r Extra return code: -1 if the operation failed;
|
||||
0 if the key is present in the hash table;
|
||||
1 if the bucket is empty (never used); 2 if the element in
|
||||
the bucket has been deleted [int*]
|
||||
@return Iterator to the inserted element [khint_t]
|
||||
*/
|
||||
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
|
||||
|
||||
/*! @function
|
||||
@abstract Retrieve a key from the hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param k Key [type of keys]
|
||||
@return Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
|
||||
*/
|
||||
#define kh_get(name, h, k) kh_get_##name(h, k)
|
||||
|
||||
/*! @function
|
||||
@abstract Remove a key from the hash table.
|
||||
@param name Name of the hash table [symbol]
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param k Iterator to the element to be deleted [khint_t]
|
||||
*/
|
||||
#define kh_del(name, h, k) kh_del_##name(h, k)
|
||||
|
||||
/*! @function
|
||||
@abstract Test whether a bucket contains data.
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param x Iterator to the bucket [khint_t]
|
||||
@return 1 if containing data; 0 otherwise [int]
|
||||
*/
|
||||
#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
|
||||
|
||||
/*! @function
|
||||
@abstract Get key given an iterator
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param x Iterator to the bucket [khint_t]
|
||||
@return Key [type of keys]
|
||||
*/
|
||||
#define kh_key(h, x) ((h)->keys[x])
|
||||
|
||||
/*! @function
|
||||
@abstract Get value given an iterator
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param x Iterator to the bucket [khint_t]
|
||||
@return Value [type of values]
|
||||
@discussion For hash sets, calling this results in segfault.
|
||||
*/
|
||||
#define kh_val(h, x) ((h)->vals[x])
|
||||
|
||||
/*! @function
|
||||
@abstract Alias of kh_val()
|
||||
*/
|
||||
#define kh_value(h, x) ((h)->vals[x])
|
||||
|
||||
/*! @function
|
||||
@abstract Get the start iterator
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@return The start iterator [khint_t]
|
||||
*/
|
||||
#define kh_begin(h) (khint_t)(0)
|
||||
|
||||
/*! @function
|
||||
@abstract Get the end iterator
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@return The end iterator [khint_t]
|
||||
*/
|
||||
#define kh_end(h) ((h)->n_buckets)
|
||||
|
||||
/*! @function
|
||||
@abstract Get the number of elements in the hash table
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@return Number of elements in the hash table [khint_t]
|
||||
*/
|
||||
#define kh_size(h) ((h)->size)
|
||||
|
||||
/*! @function
|
||||
@abstract Get the number of buckets in the hash table
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@return Number of buckets in the hash table [khint_t]
|
||||
*/
|
||||
#define kh_n_buckets(h) ((h)->n_buckets)
|
||||
|
||||
/*! @function
|
||||
@abstract Iterate over the entries in the hash table
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param kvar Variable to which key will be assigned
|
||||
@param vvar Variable to which value will be assigned
|
||||
@param code Block of code to execute
|
||||
*/
|
||||
#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
|
||||
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
|
||||
if (!kh_exist(h,__i)) continue; \
|
||||
(kvar) = kh_key(h,__i); \
|
||||
(vvar) = kh_val(h,__i); \
|
||||
code; \
|
||||
} }
|
||||
|
||||
/*! @function
|
||||
@abstract Iterate over the values in the hash table
|
||||
@param h Pointer to the hash table [khash_t(name)*]
|
||||
@param vvar Variable to which value will be assigned
|
||||
@param code Block of code to execute
|
||||
*/
|
||||
#define kh_foreach_value(h, vvar, code) { khint_t __i; \
|
||||
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
|
||||
if (!kh_exist(h,__i)) continue; \
|
||||
(vvar) = kh_val(h,__i); \
|
||||
code; \
|
||||
} }
|
||||
|
||||
/* More conenient interfaces */
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash set containing integer keys
|
||||
@param name Name of the hash table [symbol]
|
||||
*/
|
||||
#define KHASH_SET_INIT_INT(name) \
|
||||
KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing integer keys
|
||||
@param name Name of the hash table [symbol]
|
||||
@param khval_t Type of values [type]
|
||||
*/
|
||||
#define KHASH_MAP_INIT_INT(name, khval_t) \
|
||||
KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing 64-bit integer keys
|
||||
@param name Name of the hash table [symbol]
|
||||
*/
|
||||
#define KHASH_SET_INIT_INT64(name) \
|
||||
KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing 64-bit integer keys
|
||||
@param name Name of the hash table [symbol]
|
||||
@param khval_t Type of values [type]
|
||||
*/
|
||||
#define KHASH_MAP_INIT_INT64(name, khval_t) \
|
||||
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
|
||||
|
||||
typedef const char *kh_cstr_t;
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing const char* keys
|
||||
@param name Name of the hash table [symbol]
|
||||
*/
|
||||
#define KHASH_SET_INIT_STR(name) \
|
||||
KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing const char* keys
|
||||
@param name Name of the hash table [symbol]
|
||||
@param khval_t Type of values [type]
|
||||
*/
|
||||
#define KHASH_MAP_INIT_STR(name, khval_t) \
|
||||
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
|
||||
|
||||
#endif /* __AC_KHASH_H */
|
||||
128
src/nvim/lib/klist.h
Normal file
128
src/nvim/lib/klist.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2008-2009, by Attractive Chaos <attractor@live.co.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _AC_KLIST_H
|
||||
#define _AC_KLIST_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "func_attr.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \
|
||||
typedef struct { \
|
||||
size_t cnt, n, max; \
|
||||
kmptype_t **buf; \
|
||||
} kmp_##name##_t; \
|
||||
static inline kmp_##name##_t *kmp_init_##name() { \
|
||||
return xcalloc(1, sizeof(kmp_##name##_t)); \
|
||||
} \
|
||||
static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \
|
||||
size_t k; \
|
||||
for (k = 0; k < mp->n; ++k) { \
|
||||
kmpfree_f(mp->buf[k]); free(mp->buf[k]); \
|
||||
} \
|
||||
free(mp->buf); free(mp); \
|
||||
} \
|
||||
static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \
|
||||
++mp->cnt; \
|
||||
if (mp->n == 0) return xcalloc(1, sizeof(kmptype_t)); \
|
||||
return mp->buf[--mp->n]; \
|
||||
} \
|
||||
static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \
|
||||
--mp->cnt; \
|
||||
if (mp->n == mp->max) { \
|
||||
mp->max = mp->max? mp->max<<1 : 16; \
|
||||
mp->buf = xrealloc(mp->buf, sizeof(void*) * mp->max); \
|
||||
} \
|
||||
mp->buf[mp->n++] = p; \
|
||||
}
|
||||
|
||||
#define kmempool_t(name) kmp_##name##_t
|
||||
#define kmp_init(name) kmp_init_##name()
|
||||
#define kmp_destroy(name, mp) kmp_destroy_##name(mp)
|
||||
#define kmp_alloc(name, mp) kmp_alloc_##name(mp)
|
||||
#define kmp_free(name, mp, p) kmp_free_##name(mp, p)
|
||||
|
||||
#define KLIST_INIT(name, kltype_t, kmpfree_t) \
|
||||
struct __kl1_##name { \
|
||||
kltype_t data; \
|
||||
struct __kl1_##name *next; \
|
||||
}; \
|
||||
typedef struct __kl1_##name kl1_##name; \
|
||||
KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \
|
||||
typedef struct { \
|
||||
kl1_##name *head, *tail; \
|
||||
kmp_##name##_t *mp; \
|
||||
size_t size; \
|
||||
} kl_##name##_t; \
|
||||
static inline kl_##name##_t *kl_init_##name() { \
|
||||
kl_##name##_t *kl = xcalloc(1, sizeof(kl_##name##_t)); \
|
||||
kl->mp = kmp_init(name); \
|
||||
kl->head = kl->tail = kmp_alloc(name, kl->mp); \
|
||||
kl->head->next = 0; \
|
||||
return kl; \
|
||||
} \
|
||||
static inline void kl_destroy_##name(kl_##name##_t *kl) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
static inline void kl_destroy_##name(kl_##name##_t *kl) { \
|
||||
kl1_##name *p; \
|
||||
for (p = kl->head; p != kl->tail; p = p->next) \
|
||||
kmp_free(name, kl->mp, p); \
|
||||
kmp_free(name, kl->mp, p); \
|
||||
kmp_destroy(name, kl->mp); \
|
||||
free(kl); \
|
||||
} \
|
||||
static inline kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \
|
||||
kl1_##name *q, *p = kmp_alloc(name, kl->mp); \
|
||||
q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \
|
||||
++kl->size; \
|
||||
return &q->data; \
|
||||
} \
|
||||
static inline int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \
|
||||
kl1_##name *p; \
|
||||
if (kl->head->next == 0) return -1; \
|
||||
--kl->size; \
|
||||
p = kl->head; kl->head = kl->head->next; \
|
||||
if (d) *d = p->data; \
|
||||
kmp_free(name, kl->mp, p); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define kliter_t(name) kl1_##name
|
||||
#define klist_t(name) kl_##name##_t
|
||||
#define kl_val(iter) ((iter)->data)
|
||||
#define kl_next(iter) ((iter)->next)
|
||||
#define kl_begin(kl) ((kl)->head)
|
||||
#define kl_end(kl) ((kl)->tail)
|
||||
|
||||
#define kl_init(name) kl_init_##name()
|
||||
#define kl_destroy(name, kl) kl_destroy_##name(kl)
|
||||
#define kl_pushp(name, kl) kl_pushp_##name(kl)
|
||||
#define kl_shift(name, kl, d) kl_shift_##name(kl, d)
|
||||
#define kl_empty(kl) ((kl)->size == 0)
|
||||
|
||||
#endif
|
||||
147
src/nvim/log.c
Normal file
147
src/nvim/log.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "misc1.h"
|
||||
#include "types.h"
|
||||
#include "os/os.h"
|
||||
#include "os/time.h"
|
||||
|
||||
#define USR_LOG_FILE "$HOME/.nvimlog"
|
||||
|
||||
|
||||
static FILE *open_log_file(void);
|
||||
static bool do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num,
|
||||
const char* fmt, ...);
|
||||
static bool v_do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num,
|
||||
const char* fmt, va_list args);
|
||||
|
||||
bool do_log(int log_level, const char *func_name, int line_num,
|
||||
const char* fmt, ...)
|
||||
{
|
||||
FILE *log_file = open_log_file();
|
||||
|
||||
if (log_file == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool ret = v_do_log_to_file(log_file, log_level, func_name, line_num, fmt,
|
||||
args);
|
||||
va_end(args);
|
||||
|
||||
if (log_file != stderr && log_file != stdout) {
|
||||
fclose(log_file);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Open the log file for appending.
|
||||
///
|
||||
/// @return The FILE* specified by the USR_LOG_FILE path or stderr in case of
|
||||
/// error
|
||||
static FILE *open_log_file(void)
|
||||
{
|
||||
static bool opening_log_file = false;
|
||||
|
||||
// check if it's a recursive call
|
||||
if (opening_log_file) {
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__,
|
||||
"Trying to LOG() recursively! Please fix it.");
|
||||
return stderr;
|
||||
}
|
||||
|
||||
// expand USR_LOG_FILE and open the file
|
||||
FILE *log_file;
|
||||
opening_log_file = true;
|
||||
{
|
||||
static char expanded_log_file_path[MAXPATHL + 1];
|
||||
|
||||
expand_env((char_u *)USR_LOG_FILE, (char_u *)expanded_log_file_path,
|
||||
MAXPATHL);
|
||||
// if the log file path expansion failed then fall back to stderr
|
||||
if (strcmp(USR_LOG_FILE, expanded_log_file_path) == 0) {
|
||||
goto open_log_file_error;
|
||||
}
|
||||
|
||||
log_file = fopen(expanded_log_file_path, "a");
|
||||
if (log_file == NULL) {
|
||||
goto open_log_file_error;
|
||||
}
|
||||
}
|
||||
opening_log_file = false;
|
||||
|
||||
return log_file;
|
||||
|
||||
open_log_file_error:
|
||||
opening_log_file = false;
|
||||
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__,
|
||||
"Couldn't open USR_LOG_FILE, logging to stderr! This may be "
|
||||
"caused by attempting to LOG() before initialization "
|
||||
"functions are called (e.g. init_homedir()).");
|
||||
return stderr;
|
||||
}
|
||||
|
||||
static bool do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num,
|
||||
const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool ret = v_do_log_to_file(log_file, log_level, func_name, line_num, fmt,
|
||||
args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool v_do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num,
|
||||
const char* fmt, va_list args)
|
||||
{
|
||||
static const char *log_levels[] = {
|
||||
[DEBUG_LOG_LEVEL] = "debug",
|
||||
[INFO_LOG_LEVEL] = "info",
|
||||
[WARNING_LOG_LEVEL] = "warning",
|
||||
[ERROR_LOG_LEVEL] = "error"
|
||||
};
|
||||
assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL);
|
||||
|
||||
// format current timestamp in local time
|
||||
struct tm local_time;
|
||||
if (os_get_localtime(&local_time) == NULL) {
|
||||
return false;
|
||||
}
|
||||
char date_time[20];
|
||||
if (strftime(date_time, sizeof(date_time), "%Y/%m/%d %H:%M:%S",
|
||||
&local_time) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// print the log message prefixed by the current timestamp and pid
|
||||
int64_t pid = os_get_pid();
|
||||
if (fprintf(log_file, "%s [%s @ %s:%d] %" PRId64 " - ", date_time,
|
||||
log_levels[log_level], func_name, line_num, pid) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (vfprintf(log_file, fmt, args) < 0) {
|
||||
return false;
|
||||
}
|
||||
fputc('\n', log_file);
|
||||
if (fflush(log_file) == EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
57
src/nvim/log.h
Normal file
57
src/nvim/log.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef NEOVIM_LOG_H
|
||||
#define NEOVIM_LOG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "func_attr.h"
|
||||
|
||||
#define DEBUG_LOG_LEVEL 0
|
||||
#define INFO_LOG_LEVEL 1
|
||||
#define WARNING_LOG_LEVEL 2
|
||||
#define ERROR_LOG_LEVEL 3
|
||||
|
||||
bool do_log(int log_level, const char *func_name, int line_num,
|
||||
const char* fmt, ...) FUNC_ATTR_UNUSED;
|
||||
|
||||
#define DLOG(...)
|
||||
#define ILOG(...)
|
||||
#define WLOG(...)
|
||||
#define ELOG(...)
|
||||
|
||||
// Logging is disabled if NDEBUG or DISABLE_LOG is defined.
|
||||
#ifdef NDEBUG
|
||||
# define DISABLE_LOG
|
||||
#endif
|
||||
|
||||
// MIN_LOG_LEVEL can be defined during compilation to adjust the desired level
|
||||
// of logging. DEBUG_LOG_LEVEL is used by default.
|
||||
#ifndef MIN_LOG_LEVEL
|
||||
# define MIN_LOG_LEVEL DEBUG_LOG_LEVEL
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_LOG
|
||||
|
||||
# if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
||||
# undef DLOG
|
||||
# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, __VA_ARGS__)
|
||||
# endif
|
||||
|
||||
# if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
||||
# undef ILOG
|
||||
# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, __VA_ARGS__)
|
||||
# endif
|
||||
|
||||
# if MIN_LOG_LEVEL <= WARNING_LOG_LEVEL
|
||||
# undef WLOG
|
||||
# define WLOG(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, __VA_ARGS__)
|
||||
# endif
|
||||
|
||||
# if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL
|
||||
# undef ELOG
|
||||
# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, __VA_ARGS__)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // NEOVIM_LOG_H
|
||||
|
||||
151
src/nvim/macros.h
Normal file
151
src/nvim/macros.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef NEOVIM_MACROS_H
|
||||
#define NEOVIM_MACROS_H
|
||||
|
||||
/*
|
||||
* VIM - Vi IMproved by Bram Moolenaar
|
||||
*
|
||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* macros.h: macro definitions for often used code
|
||||
*/
|
||||
|
||||
/*
|
||||
* Position comparisons
|
||||
*/
|
||||
# define lt(a, b) (((a).lnum != (b).lnum) \
|
||||
? (a).lnum < (b).lnum \
|
||||
: (a).col != (b).col \
|
||||
? (a).col < (b).col \
|
||||
: (a).coladd < (b).coladd)
|
||||
# define ltp(a, b) (((a)->lnum != (b)->lnum) \
|
||||
? (a)->lnum < (b)->lnum \
|
||||
: (a)->col != (b)->col \
|
||||
? (a)->col < (b)->col \
|
||||
: (a)->coladd < (b)->coladd)
|
||||
# define equalpos(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col) && \
|
||||
((a).coladd == (b).coladd))
|
||||
# define clearpos(a) {(a)->lnum = 0; (a)->col = 0; (a)->coladd = 0; }
|
||||
|
||||
#define ltoreq(a, b) (lt(a, b) || equalpos(a, b))
|
||||
|
||||
/*
|
||||
* lineempty() - return TRUE if the line is empty
|
||||
*/
|
||||
#define lineempty(p) (*ml_get(p) == NUL)
|
||||
|
||||
/*
|
||||
* bufempty() - return TRUE if the current buffer is empty
|
||||
*/
|
||||
#define bufempty() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == \
|
||||
NUL)
|
||||
|
||||
/*
|
||||
* toupper() and tolower() that use the current locale.
|
||||
* Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
|
||||
* range 0 - 255. toupper()/tolower() on some systems can't handle others.
|
||||
* Note: It is often better to use vim_tolower() and vim_toupper(), because many
|
||||
* toupper() and tolower() implementations only work for ASCII.
|
||||
*/
|
||||
#define TOUPPER_LOC toupper
|
||||
#define TOLOWER_LOC tolower
|
||||
|
||||
/* toupper() and tolower() for ASCII only and ignore the current locale. */
|
||||
# define TOUPPER_ASC(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) - ('a' - 'A'))
|
||||
# define TOLOWER_ASC(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) + ('a' - 'A'))
|
||||
|
||||
/* Use our own isdigit() replacement, because on MS-Windows isdigit() returns
|
||||
* non-zero for superscript 1. Also avoids that isdigit() crashes for numbers
|
||||
* below 0 and above 255. */
|
||||
#define VIM_ISDIGIT(c) ((unsigned)(c) - '0' < 10)
|
||||
|
||||
/* Like isalpha() but reject non-ASCII characters. Can't be used with a
|
||||
* special key (negative value). */
|
||||
# define ASCII_ISLOWER(c) ((unsigned)(c) - 'a' < 26)
|
||||
# define ASCII_ISUPPER(c) ((unsigned)(c) - 'A' < 26)
|
||||
# define ASCII_ISALPHA(c) (ASCII_ISUPPER(c) || ASCII_ISLOWER(c))
|
||||
# define ASCII_ISALNUM(c) (ASCII_ISALPHA(c) || VIM_ISDIGIT(c))
|
||||
|
||||
/* macro version of chartab().
|
||||
* Only works with values 0-255!
|
||||
* Doesn't work for UTF-8 mode with chars >= 0x80. */
|
||||
#define CHARSIZE(c) (chartab[c] & CT_CELL_MASK)
|
||||
|
||||
/*
|
||||
* Adjust chars in a language according to 'langmap' option.
|
||||
* NOTE that there is no noticeable overhead if 'langmap' is not set.
|
||||
* When set the overhead for characters < 256 is small.
|
||||
* Don't apply 'langmap' if the character comes from the Stuff buffer.
|
||||
* The do-while is just to ignore a ';' after the macro.
|
||||
*/
|
||||
# define LANGMAP_ADJUST(c, condition) \
|
||||
do { \
|
||||
if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0) \
|
||||
{ \
|
||||
if ((c) < 256) \
|
||||
c = langmap_mapchar[c]; \
|
||||
else \
|
||||
c = langmap_adjust_mb(c); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* vim_isbreak() is used very often if 'linebreak' is set, use a macro to make
|
||||
* it work fast.
|
||||
*/
|
||||
#define vim_isbreak(c) (breakat_flags[(char_u)(c)])
|
||||
|
||||
# define mch_fopen(n, p) fopen((n), (p))
|
||||
# define mch_open(n, m, p) open((n), (m), (p))
|
||||
|
||||
/* mch_open_rw(): invoke mch_open() with third argument for user R/W. */
|
||||
#if defined(UNIX) /* open in rw------- mode */
|
||||
# define mch_open_rw(n, f) mch_open((n), (f), (mode_t)0600)
|
||||
#else
|
||||
# define mch_open_rw(n, f) mch_open((n), (f), 0)
|
||||
#endif
|
||||
|
||||
#ifdef STARTUPTIME
|
||||
# define TIME_MSG(s) { if (time_fd != NULL) time_msg(s, NULL); }
|
||||
#else
|
||||
# define TIME_MSG(s)
|
||||
#endif
|
||||
|
||||
# define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG))
|
||||
|
||||
# define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2))
|
||||
|
||||
/* Whether to draw the vertical bar on the right side of the cell. */
|
||||
# define CURSOR_BAR_RIGHT (curwin->w_p_rl && (!(State & CMDLINE) || cmdmsg_rl))
|
||||
|
||||
/*
|
||||
* mb_ptr_adv(): advance a pointer to the next character, taking care of
|
||||
* multi-byte characters if needed.
|
||||
* mb_ptr_back(): backup a pointer to the previous character, taking care of
|
||||
* multi-byte characters if needed.
|
||||
* MB_COPY_CHAR(f, t): copy one char from "f" to "t" and advance the pointers.
|
||||
* PTR2CHAR(): get character from pointer.
|
||||
*/
|
||||
/* Get the length of the character p points to */
|
||||
# define MB_PTR2LEN(p) (has_mbyte ? (*mb_ptr2len)(p) : 1)
|
||||
/* Advance multi-byte pointer, skip over composing chars. */
|
||||
# define mb_ptr_adv(p) p += has_mbyte ? (*mb_ptr2len)(p) : 1
|
||||
/* Advance multi-byte pointer, do not skip over composing chars. */
|
||||
# define mb_cptr_adv(p) p += \
|
||||
enc_utf8 ? utf_ptr2len(p) : has_mbyte ? (*mb_ptr2len)(p) : 1
|
||||
/* Backup multi-byte pointer. */
|
||||
# define mb_ptr_back(s, p) p -= has_mbyte ? ((*mb_head_off)(s, p - 1) + 1) : 1
|
||||
/* get length of multi-byte char, not including composing chars */
|
||||
# define mb_cptr2len(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p))
|
||||
|
||||
# define MB_COPY_CHAR(f, \
|
||||
t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++
|
||||
# define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
|
||||
# define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1)
|
||||
# define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p))
|
||||
|
||||
# define RESET_BINDING(wp) (wp)->w_p_scb = FALSE; (wp)->w_p_crb = FALSE
|
||||
|
||||
#endif // NEOVIM_MACROS_H
|
||||
2367
src/nvim/main.c
Normal file
2367
src/nvim/main.c
Normal file
File diff suppressed because it is too large
Load Diff
16
src/nvim/main.h
Normal file
16
src/nvim/main.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef NEOVIM_MAIN_H
|
||||
#define NEOVIM_MAIN_H
|
||||
|
||||
#include "normal.h"
|
||||
|
||||
void main_loop(int cmdwin, int noexmode);
|
||||
void getout(int exitval);
|
||||
int process_env(char_u *env, int is_viminit);
|
||||
void mainerr_arg_missing(char_u *str);
|
||||
void time_push(void *tv_rel, void *tv_start);
|
||||
void time_pop(void *tp);
|
||||
void time_msg(char *mesg, void *tv_start);
|
||||
char_u *eval_client_expr_to_string(char_u *expr);
|
||||
char_u *serverConvert(char_u *client_enc, char_u *data, char_u **tofree);
|
||||
|
||||
#endif /* NEOVIM_MAIN_H */
|
||||
91
src/nvim/map.c
Normal file
91
src/nvim/map.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "map.h"
|
||||
#include "map_defs.h"
|
||||
#include "vim.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "lib/khash.h"
|
||||
|
||||
typedef struct {
|
||||
void *ptr;
|
||||
} Value;
|
||||
|
||||
KHASH_MAP_INIT_STR(Map, Value)
|
||||
|
||||
struct map {
|
||||
khash_t(Map) *table;
|
||||
};
|
||||
|
||||
Map *map_new()
|
||||
{
|
||||
Map *rv = xmalloc(sizeof(Map));
|
||||
rv->table = kh_init(Map);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void map_free(Map *map)
|
||||
{
|
||||
kh_clear(Map, map->table);
|
||||
kh_destroy(Map, map->table);
|
||||
free(map);
|
||||
}
|
||||
|
||||
void *map_get(Map *map, const char *key)
|
||||
{
|
||||
khiter_t k;
|
||||
|
||||
if ((k = kh_get(Map, map->table, key)) == kh_end(map->table)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return kh_val(map->table, k).ptr;
|
||||
}
|
||||
|
||||
bool map_has(Map *map, const char *key)
|
||||
{
|
||||
return map_get(map, key) != NULL;
|
||||
}
|
||||
|
||||
void *map_put(Map *map, const char *key, void *value)
|
||||
{
|
||||
int ret;
|
||||
void *rv = NULL;
|
||||
khiter_t k = kh_put(Map, map->table, key, &ret);
|
||||
Value val = {.ptr = value};
|
||||
|
||||
if (!ret) {
|
||||
// key present, return the current value
|
||||
rv = kh_val(map->table, k).ptr;
|
||||
kh_del(Map, map->table, k);
|
||||
}
|
||||
|
||||
kh_val(map->table, k) = val;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void *map_del(Map *map, const char *key)
|
||||
{
|
||||
void *rv = NULL;
|
||||
khiter_t k;
|
||||
|
||||
if ((k = kh_get(Map, map->table, key)) != kh_end(map->table)) {
|
||||
rv = kh_val(map->table, k).ptr;
|
||||
kh_del(Map, map->table, k);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void map_foreach(Map *map, key_value_cb cb)
|
||||
{
|
||||
const char *key;
|
||||
Value value;
|
||||
|
||||
kh_foreach(map->table, key, value, {
|
||||
cb(map, (const char *)key, value.ptr);
|
||||
});
|
||||
}
|
||||
|
||||
57
src/nvim/map.h
Normal file
57
src/nvim/map.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// General-purpose string->pointer associative array with a simple API
|
||||
#ifndef NEOVIM_MAP_H
|
||||
#define NEOVIM_MAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "map_defs.h"
|
||||
|
||||
/// Creates a new `Map` instance
|
||||
///
|
||||
/// @return a pointer to the new instance
|
||||
Map *map_new(void);
|
||||
|
||||
/// Frees memory for a `Map` instance
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
void map_free(Map *map);
|
||||
|
||||
/// Gets the value corresponding to a key in a `Map` instance
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return The value if the key exists in the map, or NULL if it doesn't
|
||||
void *map_get(Map *map, const char *key);
|
||||
|
||||
/// Checks if a key exists in the map
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return true if the key exists, false otherwise
|
||||
bool map_has(Map *map, const char *key);
|
||||
|
||||
/// Set the value corresponding to a key in a `Map` instance and returns
|
||||
/// the old value.
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @param value A value
|
||||
/// @return The current value if exists or NULL otherwise
|
||||
void *map_put(Map *map, const char *key, void *value);
|
||||
|
||||
/// Deletes the value corresponding to a key in a `Map` instance and returns
|
||||
/// the old value.
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return The current value if exists or NULL otherwise
|
||||
void *map_del(Map *map, const char *key);
|
||||
|
||||
/// Iterates through each key/value pair in the map
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param cb A function that will be called for each key/value
|
||||
void map_foreach(Map *map, key_value_cb cb);
|
||||
|
||||
#endif /* NEOVIM_MAP_H */
|
||||
|
||||
14
src/nvim/map_defs.h
Normal file
14
src/nvim/map_defs.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef NEOVIM_MAP_DEFS_H
|
||||
#define NEOVIM_MAP_DEFS_H
|
||||
|
||||
typedef struct map Map;
|
||||
|
||||
/// Callback for iterating through each key/value pair in a map
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @param value A value
|
||||
typedef void (*key_value_cb)(Map *map, const char *key, void *value);
|
||||
|
||||
#endif /* NEOVIM_MAP_DEFS_H */
|
||||
|
||||
1539
src/nvim/mark.c
Normal file
1539
src/nvim/mark.c
Normal file
File diff suppressed because it is too large
Load Diff
42
src/nvim/mark.h
Normal file
42
src/nvim/mark.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef NEOVIM_MARK_H
|
||||
#define NEOVIM_MARK_H
|
||||
|
||||
#include "buffer_defs.h"
|
||||
#include "mark_defs.h"
|
||||
#include "pos.h"
|
||||
|
||||
/* mark.c */
|
||||
int setmark(int c);
|
||||
int setmark_pos(int c, pos_T *pos, int fnum);
|
||||
void setpcmark(void);
|
||||
void checkpcmark(void);
|
||||
pos_T *movemark(int count);
|
||||
pos_T *movechangelist(int count);
|
||||
pos_T *getmark_buf(buf_T *buf, int c, int changefile);
|
||||
pos_T *getmark(int c, int changefile);
|
||||
pos_T *getmark_buf_fnum(buf_T *buf, int c, int changefile, int *fnum);
|
||||
pos_T *getnextmark(pos_T *startpos, int dir, int begin_line);
|
||||
void fmarks_check_names(buf_T *buf);
|
||||
int check_mark(pos_T *pos);
|
||||
void clrallmarks(buf_T *buf);
|
||||
char_u *fm_getname(fmark_T *fmark, int lead_len);
|
||||
void do_marks(exarg_T *eap);
|
||||
void ex_delmarks(exarg_T *eap);
|
||||
void ex_jumps(exarg_T *eap);
|
||||
void ex_changes(exarg_T *eap);
|
||||
void mark_adjust(linenr_T line1, linenr_T line2, long amount,
|
||||
long amount_after);
|
||||
void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount,
|
||||
long col_amount);
|
||||
void copy_jumplist(win_T *from, win_T *to);
|
||||
void free_jumplist(win_T *wp);
|
||||
void set_last_cursor(win_T *win);
|
||||
void free_all_marks(void);
|
||||
int read_viminfo_filemark(vir_T *virp, int force);
|
||||
void write_viminfo_filemarks(FILE *fp);
|
||||
int removable(char_u *name);
|
||||
int write_viminfo_marks(FILE *fp_out);
|
||||
void copy_viminfo_marks(vir_T *virp, FILE *fp_out, int count, int eof,
|
||||
int flags);
|
||||
|
||||
#endif /* NEOVIM_MARK_H */
|
||||
29
src/nvim/mark_defs.h
Normal file
29
src/nvim/mark_defs.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef NEOVIM_MARK_DEFS_H
|
||||
#define NEOVIM_MARK_DEFS_H
|
||||
|
||||
#include "pos.h"
|
||||
|
||||
/*
|
||||
* marks: positions in a file
|
||||
* (a normal mark is a lnum/col pair, the same as a file position)
|
||||
*/
|
||||
|
||||
/* (Note: for EBCDIC there are more than 26, because there are gaps in the
|
||||
* alphabet coding. To minimize changes to the code, I decided to just
|
||||
* increase the number of possible marks. */
|
||||
#define NMARKS ('z' - 'a' + 1) /* max. # of named marks */
|
||||
#define JUMPLISTSIZE 100 /* max. # of marks in jump list */
|
||||
#define TAGSTACKSIZE 20 /* max. # of tags in tag stack */
|
||||
|
||||
typedef struct filemark {
|
||||
pos_T mark; /* cursor position */
|
||||
int fnum; /* file number */
|
||||
} fmark_T;
|
||||
|
||||
/* Xtended file mark: also has a file name */
|
||||
typedef struct xfilemark {
|
||||
fmark_T fmark;
|
||||
char_u *fname; /* file name, used when fnum == 0 */
|
||||
} xfmark_T;
|
||||
|
||||
#endif // NEOVIM_MARK_DEFS_H
|
||||
4041
src/nvim/mbyte.c
Normal file
4041
src/nvim/mbyte.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/nvim/mbyte.h
Normal file
87
src/nvim/mbyte.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef NEOVIM_MBYTE_H
|
||||
#define NEOVIM_MBYTE_H
|
||||
/* mbyte.c */
|
||||
int enc_canon_props(char_u *name);
|
||||
char_u *mb_init(void);
|
||||
int bomb_size(void);
|
||||
void remove_bom(char_u *s);
|
||||
int mb_get_class(char_u *p);
|
||||
int mb_get_class_buf(char_u *p, buf_T *buf);
|
||||
int dbcs_class(unsigned lead, unsigned trail);
|
||||
int latin_char2len(int c);
|
||||
int latin_char2bytes(int c, char_u *buf);
|
||||
int latin_ptr2len(char_u *p);
|
||||
int latin_ptr2len_len(char_u *p, int size);
|
||||
int utf_char2cells(int c);
|
||||
int latin_ptr2cells(char_u *p);
|
||||
int utf_ptr2cells(char_u *p);
|
||||
int dbcs_ptr2cells(char_u *p);
|
||||
int latin_ptr2cells_len(char_u *p, int size);
|
||||
int latin_char2cells(int c);
|
||||
int mb_string2cells(char_u *p, int len);
|
||||
int latin_off2cells(unsigned off, unsigned max_off);
|
||||
int dbcs_off2cells(unsigned off, unsigned max_off);
|
||||
int utf_off2cells(unsigned off, unsigned max_off);
|
||||
int latin_ptr2char(char_u *p);
|
||||
int utf_ptr2char(char_u *p);
|
||||
int mb_ptr2char_adv(char_u **pp);
|
||||
int mb_cptr2char_adv(char_u **pp);
|
||||
int arabic_combine(int one, int two);
|
||||
int arabic_maycombine(int two);
|
||||
int utf_composinglike(char_u *p1, char_u *p2);
|
||||
int utfc_ptr2char(char_u *p, int *pcc);
|
||||
int utfc_ptr2char_len(char_u *p, int *pcc, int maxlen);
|
||||
int utfc_char2bytes(int off, char_u *buf);
|
||||
int utf_ptr2len(char_u *p);
|
||||
int utf_byte2len(int b);
|
||||
int utf_ptr2len_len(char_u *p, int size);
|
||||
int utfc_ptr2len(char_u *p);
|
||||
int utfc_ptr2len_len(char_u *p, int size);
|
||||
int utf_char2len(int c);
|
||||
int utf_char2bytes(int c, char_u *buf);
|
||||
int utf_iscomposing(int c);
|
||||
int utf_printable(int c);
|
||||
int utf_class(int c);
|
||||
int utf_fold(int a);
|
||||
int utf_toupper(int a);
|
||||
int utf_islower(int a);
|
||||
int utf_tolower(int a);
|
||||
int utf_isupper(int a);
|
||||
int mb_strnicmp(char_u *s1, char_u *s2, size_t nn);
|
||||
void show_utf8(void);
|
||||
int latin_head_off(char_u *base, char_u *p);
|
||||
int dbcs_head_off(char_u *base, char_u *p);
|
||||
int dbcs_screen_head_off(char_u *base, char_u *p);
|
||||
int utf_head_off(char_u *base, char_u *p);
|
||||
void mb_copy_char(char_u **fp, char_u **tp);
|
||||
int mb_off_next(char_u *base, char_u *p);
|
||||
int mb_tail_off(char_u *base, char_u *p);
|
||||
void utf_find_illegal(void);
|
||||
void mb_adjust_cursor(void);
|
||||
void mb_adjustpos(buf_T *buf, pos_T *lp);
|
||||
char_u *mb_prevptr(char_u *line, char_u *p);
|
||||
int mb_charlen(char_u *str);
|
||||
int mb_charlen_len(char_u *str, int len);
|
||||
char_u *mb_unescape(char_u **pp);
|
||||
int mb_lefthalve(int row, int col);
|
||||
int mb_fix_col(int col, int row);
|
||||
char_u *enc_skip(char_u *p);
|
||||
char_u *enc_canonize(char_u *enc);
|
||||
char_u *enc_locale(void);
|
||||
void *my_iconv_open(char_u *to, char_u *from);
|
||||
int iconv_enabled(int verbose);
|
||||
void iconv_end(void);
|
||||
void im_set_active(int active);
|
||||
int im_get_status(void);
|
||||
int convert_setup(vimconv_T *vcp, char_u *from, char_u *to);
|
||||
int convert_setup_ext(vimconv_T *vcp, char_u *from,
|
||||
int from_unicode_is_utf8, char_u *to,
|
||||
int to_unicode_is_utf8);
|
||||
int convert_input(char_u *ptr, int len, int maxlen);
|
||||
int convert_input_safe(char_u *ptr, int len, int maxlen, char_u **restp,
|
||||
int *restlenp);
|
||||
char_u *string_convert(vimconv_T *vcp, char_u *ptr, int *lenp);
|
||||
char_u *string_convert_ext(vimconv_T *vcp, char_u *ptr, int *lenp,
|
||||
int *unconvlenp);
|
||||
|
||||
#endif /* NEOVIM_MBYTE_H */
|
||||
1260
src/nvim/memfile.c
Normal file
1260
src/nvim/memfile.c
Normal file
File diff suppressed because it is too large
Load Diff
25
src/nvim/memfile.h
Normal file
25
src/nvim/memfile.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef NEOVIM_MEMFILE_H
|
||||
#define NEOVIM_MEMFILE_H
|
||||
|
||||
#include "buffer_defs.h"
|
||||
#include "memfile_defs.h"
|
||||
|
||||
/* memfile.c */
|
||||
memfile_T *mf_open(char_u *fname, int flags);
|
||||
int mf_open_file(memfile_T *mfp, char_u *fname);
|
||||
void mf_close(memfile_T *mfp, int del_file);
|
||||
void mf_close_file(buf_T *buf, int getlines);
|
||||
void mf_new_page_size(memfile_T *mfp, unsigned new_size);
|
||||
bhdr_T *mf_new(memfile_T *mfp, int negative, int page_count);
|
||||
bhdr_T *mf_get(memfile_T *mfp, blocknr_T nr, int page_count);
|
||||
void mf_put(memfile_T *mfp, bhdr_T *hp, int dirty, int infile);
|
||||
void mf_free(memfile_T *mfp, bhdr_T *hp);
|
||||
int mf_sync(memfile_T *mfp, int flags);
|
||||
void mf_set_dirty(memfile_T *mfp);
|
||||
int mf_release_all(void);
|
||||
blocknr_T mf_trans_del(memfile_T *mfp, blocknr_T old_nr);
|
||||
void mf_set_ffname(memfile_T *mfp);
|
||||
void mf_fullname(memfile_T *mfp);
|
||||
int mf_need_trans(memfile_T *mfp);
|
||||
|
||||
#endif /* NEOVIM_MEMFILE_H */
|
||||
107
src/nvim/memfile_defs.h
Normal file
107
src/nvim/memfile_defs.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#ifndef NEOVIM_MEMFILE_DEFS_H
|
||||
#define NEOVIM_MEMFILE_DEFS_H
|
||||
|
||||
typedef struct block_hdr bhdr_T;
|
||||
typedef long blocknr_T;
|
||||
|
||||
/*
|
||||
* mf_hashtab_T is a chained hashtable with blocknr_T key and arbitrary
|
||||
* structures as items. This is an intrusive data structure: we require
|
||||
* that items begin with mf_hashitem_T which contains the key and linked
|
||||
* list pointers. List of items in each bucket is doubly-linked.
|
||||
*/
|
||||
|
||||
typedef struct mf_hashitem_S mf_hashitem_T;
|
||||
|
||||
struct mf_hashitem_S {
|
||||
mf_hashitem_T *mhi_next;
|
||||
mf_hashitem_T *mhi_prev;
|
||||
blocknr_T mhi_key;
|
||||
};
|
||||
|
||||
#define MHT_INIT_SIZE 64
|
||||
|
||||
typedef struct mf_hashtab_S {
|
||||
long_u mht_mask; /* mask used for hash value (nr of items
|
||||
* in array is "mht_mask" + 1) */
|
||||
long_u mht_count; /* nr of items inserted into hashtable */
|
||||
mf_hashitem_T **mht_buckets; /* points to mht_small_buckets or
|
||||
*dynamically allocated array */
|
||||
mf_hashitem_T *mht_small_buckets[MHT_INIT_SIZE]; /* initial buckets */
|
||||
char mht_fixed; /* non-zero value forbids growth */
|
||||
} mf_hashtab_T;
|
||||
|
||||
/*
|
||||
* for each (previously) used block in the memfile there is one block header.
|
||||
*
|
||||
* The block may be linked in the used list OR in the free list.
|
||||
* The used blocks are also kept in hash lists.
|
||||
*
|
||||
* The used list is a doubly linked list, most recently used block first.
|
||||
* The blocks in the used list have a block of memory allocated.
|
||||
* mf_used_count is the number of pages in the used list.
|
||||
* The hash lists are used to quickly find a block in the used list.
|
||||
* The free list is a single linked list, not sorted.
|
||||
* The blocks in the free list have no block of memory allocated and
|
||||
* the contents of the block in the file (if any) is irrelevant.
|
||||
*/
|
||||
|
||||
struct block_hdr {
|
||||
mf_hashitem_T bh_hashitem; /* header for hash table and key */
|
||||
#define bh_bnum bh_hashitem.mhi_key /* block number, part of bh_hashitem */
|
||||
|
||||
bhdr_T *bh_next; /* next block_hdr in free or used list */
|
||||
bhdr_T *bh_prev; /* previous block_hdr in used list */
|
||||
char_u *bh_data; /* pointer to memory (for used block) */
|
||||
int bh_page_count; /* number of pages in this block */
|
||||
|
||||
#define BH_DIRTY 1
|
||||
#define BH_LOCKED 2
|
||||
char bh_flags; /* BH_DIRTY or BH_LOCKED */
|
||||
};
|
||||
|
||||
/*
|
||||
* when a block with a negative number is flushed to the file, it gets
|
||||
* a positive number. Because the reference to the block is still the negative
|
||||
* number, we remember the translation to the new positive number in the
|
||||
* double linked trans lists. The structure is the same as the hash lists.
|
||||
*/
|
||||
typedef struct nr_trans NR_TRANS;
|
||||
|
||||
struct nr_trans {
|
||||
mf_hashitem_T nt_hashitem; /* header for hash table and key */
|
||||
#define nt_old_bnum nt_hashitem.mhi_key /* old, negative, number */
|
||||
|
||||
blocknr_T nt_new_bnum; /* new, positive, number */
|
||||
};
|
||||
|
||||
#define MF_SEED_LEN 8
|
||||
|
||||
struct memfile {
|
||||
char_u *mf_fname; /* name of the file */
|
||||
char_u *mf_ffname; /* idem, full path */
|
||||
int mf_fd; /* file descriptor */
|
||||
bhdr_T *mf_free_first; /* first block_hdr in free list */
|
||||
bhdr_T *mf_used_first; /* mru block_hdr in used list */
|
||||
bhdr_T *mf_used_last; /* lru block_hdr in used list */
|
||||
unsigned mf_used_count; /* number of pages in used list */
|
||||
unsigned mf_used_count_max; /* maximum number of pages in memory */
|
||||
mf_hashtab_T mf_hash; /* hash lists */
|
||||
mf_hashtab_T mf_trans; /* trans lists */
|
||||
blocknr_T mf_blocknr_max; /* highest positive block number + 1*/
|
||||
blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */
|
||||
blocknr_T mf_neg_count; /* number of negative blocks numbers */
|
||||
blocknr_T mf_infile_count; /* number of pages in the file */
|
||||
unsigned mf_page_size; /* number of bytes in a page */
|
||||
int mf_dirty; /* TRUE if there are dirty blocks */
|
||||
buf_T *mf_buffer; /* bufer this memfile is for */
|
||||
char_u mf_seed[MF_SEED_LEN]; /* seed for encryption */
|
||||
|
||||
/* Values for key, method and seed used for reading data blocks when
|
||||
* updating for a newly set key or method. Only when mf_old_key != NULL. */
|
||||
char_u *mf_old_key;
|
||||
int mf_old_cm;
|
||||
char_u mf_old_seed[MF_SEED_LEN];
|
||||
};
|
||||
|
||||
#endif // NEOVIM_MEMFILE_DEFS_H
|
||||
4378
src/nvim/memline.c
Normal file
4378
src/nvim/memline.c
Normal file
File diff suppressed because it is too large
Load Diff
47
src/nvim/memline.h
Normal file
47
src/nvim/memline.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef NEOVIM_MEMLINE_H
|
||||
#define NEOVIM_MEMLINE_H
|
||||
|
||||
#include "types.h"
|
||||
#include "func_attr.h"
|
||||
|
||||
int ml_open(buf_T *buf);
|
||||
void ml_set_crypt_key(buf_T *buf, char_u *old_key, int old_cm);
|
||||
void ml_setname(buf_T *buf);
|
||||
void ml_open_files(void);
|
||||
void ml_open_file(buf_T *buf);
|
||||
void check_need_swap(int newfile);
|
||||
void ml_close(buf_T *buf, int del_file);
|
||||
void ml_close_all(int del_file);
|
||||
void ml_close_notmod(void);
|
||||
void ml_timestamp(buf_T *buf);
|
||||
void ml_recover(void);
|
||||
int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
|
||||
void ml_sync_all(int check_file, int check_char);
|
||||
void ml_preserve(buf_T *buf, int message);
|
||||
char_u *ml_get(linenr_T lnum);
|
||||
char_u *ml_get_pos(pos_T *pos);
|
||||
char_u *ml_get_curline(void);
|
||||
char_u *ml_get_cursor(void);
|
||||
char_u *ml_get_buf(buf_T *buf, linenr_T lnum, int will_change);
|
||||
int ml_line_alloced(void);
|
||||
int ml_append(linenr_T lnum, char_u *line, colnr_T len, int newfile);
|
||||
int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len,
|
||||
int newfile);
|
||||
int ml_replace(linenr_T lnum, char_u *line, int copy);
|
||||
int ml_delete(linenr_T lnum, int message);
|
||||
void ml_setmarked(linenr_T lnum);
|
||||
linenr_T ml_firstmarked(void);
|
||||
void ml_clearmarked(void);
|
||||
int resolve_symlink(char_u *fname, char_u *buf);
|
||||
char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf,
|
||||
char_u *dir_name);
|
||||
char_u *get_file_in_dir(char_u *fname, char_u *dname);
|
||||
void ml_setflags(buf_T *buf);
|
||||
char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_t offset,
|
||||
unsigned size) FUNC_ATTR_NONNULL_RET;
|
||||
void ml_decrypt_data(memfile_T *mfp, char_u *data, off_t offset,
|
||||
unsigned size);
|
||||
long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
|
||||
void goto_byte(long cnt);
|
||||
|
||||
#endif /* NEOVIM_MEMLINE_H */
|
||||
59
src/nvim/memline_defs.h
Normal file
59
src/nvim/memline_defs.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef NEOVIM_MEMLINE_DEFS_H
|
||||
#define NEOVIM_MEMLINE_DEFS_H
|
||||
|
||||
#include "memfile_defs.h"
|
||||
|
||||
/*
|
||||
* When searching for a specific line, we remember what blocks in the tree
|
||||
* are the branches leading to that block. This is stored in ml_stack. Each
|
||||
* entry is a pointer to info in a block (may be data block or pointer block)
|
||||
*/
|
||||
typedef struct info_pointer {
|
||||
blocknr_T ip_bnum; /* block number */
|
||||
linenr_T ip_low; /* lowest lnum in this block */
|
||||
linenr_T ip_high; /* highest lnum in this block */
|
||||
int ip_index; /* index for block with current lnum */
|
||||
} infoptr_T; /* block/index pair */
|
||||
|
||||
typedef struct ml_chunksize {
|
||||
int mlcs_numlines;
|
||||
long mlcs_totalsize;
|
||||
} chunksize_T;
|
||||
|
||||
/* Flags when calling ml_updatechunk() */
|
||||
|
||||
#define ML_CHNK_ADDLINE 1
|
||||
#define ML_CHNK_DELLINE 2
|
||||
#define ML_CHNK_UPDLINE 3
|
||||
|
||||
/*
|
||||
* the memline structure holds all the information about a memline
|
||||
*/
|
||||
typedef struct memline {
|
||||
linenr_T ml_line_count; /* number of lines in the buffer */
|
||||
|
||||
memfile_T *ml_mfp; /* pointer to associated memfile */
|
||||
|
||||
#define ML_EMPTY 1 /* empty buffer */
|
||||
#define ML_LINE_DIRTY 2 /* cached line was changed and allocated */
|
||||
#define ML_LOCKED_DIRTY 4 /* ml_locked was changed */
|
||||
#define ML_LOCKED_POS 8 /* ml_locked needs positive block number */
|
||||
int ml_flags;
|
||||
|
||||
infoptr_T *ml_stack; /* stack of pointer blocks (array of IPTRs) */
|
||||
int ml_stack_top; /* current top if ml_stack */
|
||||
int ml_stack_size; /* total number of entries in ml_stack */
|
||||
|
||||
linenr_T ml_line_lnum; /* line number of cached line, 0 if not valid */
|
||||
char_u *ml_line_ptr; /* pointer to cached line */
|
||||
|
||||
bhdr_T *ml_locked; /* block used by last ml_get */
|
||||
linenr_T ml_locked_low; /* first line in ml_locked */
|
||||
linenr_T ml_locked_high; /* last line in ml_locked */
|
||||
int ml_locked_lineadd; /* number of lines inserted in ml_locked */
|
||||
chunksize_T *ml_chunksize;
|
||||
int ml_numchunks;
|
||||
int ml_usedchunks;
|
||||
} memline_T;
|
||||
|
||||
#endif // NEOVIM_MEMLINE_DEFS_H
|
||||
388
src/nvim/memory.c
Normal file
388
src/nvim/memory.c
Normal file
@@ -0,0 +1,388 @@
|
||||
// Various routines dealing with allocation and deallocation of memory.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vim.h"
|
||||
#include "misc2.h"
|
||||
#include "file_search.h"
|
||||
#include "blowfish.h"
|
||||
#include "buffer.h"
|
||||
#include "charset.h"
|
||||
#include "diff.h"
|
||||
#include "edit.h"
|
||||
#include "eval.h"
|
||||
#include "ex_cmds.h"
|
||||
#include "ex_docmd.h"
|
||||
#include "ex_getln.h"
|
||||
#include "fileio.h"
|
||||
#include "fold.h"
|
||||
#include "getchar.h"
|
||||
#include "mark.h"
|
||||
#include "mbyte.h"
|
||||
#include "memfile.h"
|
||||
#include "memline.h"
|
||||
#include "memory.h"
|
||||
#include "message.h"
|
||||
#include "misc1.h"
|
||||
#include "move.h"
|
||||
#include "option.h"
|
||||
#include "ops.h"
|
||||
#include "os_unix.h"
|
||||
#include "path.h"
|
||||
#include "quickfix.h"
|
||||
#include "regexp.h"
|
||||
#include "screen.h"
|
||||
#include "search.h"
|
||||
#include "spell.h"
|
||||
#include "syntax.h"
|
||||
#include "tag.h"
|
||||
#include "term.h"
|
||||
#include "ui.h"
|
||||
#include "window.h"
|
||||
#include "os/os.h"
|
||||
|
||||
static void try_to_free_memory();
|
||||
|
||||
/*
|
||||
* Note: if unsigned is 16 bits we can only allocate up to 64K with alloc().
|
||||
*/
|
||||
char_u *alloc(unsigned size)
|
||||
{
|
||||
return xmalloc(size);
|
||||
}
|
||||
|
||||
/// Try to free memory. Used when trying to recover from out of memory errors.
|
||||
/// @see {xmalloc}
|
||||
static void try_to_free_memory()
|
||||
{
|
||||
static bool trying_to_free = false;
|
||||
// avoid recursive calls
|
||||
if (trying_to_free)
|
||||
return;
|
||||
trying_to_free = true;
|
||||
|
||||
// free any scrollback text
|
||||
clear_sb_text();
|
||||
// Try to save all buffers and release as many blocks as possible
|
||||
mf_release_all();
|
||||
// cleanup recursive lists/dicts
|
||||
garbage_collect();
|
||||
|
||||
trying_to_free = false;
|
||||
}
|
||||
|
||||
void *try_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
|
||||
if (!ret && !size) {
|
||||
ret = malloc(1);
|
||||
}
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = malloc(size);
|
||||
if (!ret && !size) {
|
||||
ret = malloc(1);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *verbose_try_malloc(size_t size)
|
||||
{
|
||||
void *ret = try_malloc(size);
|
||||
if (!ret) {
|
||||
do_outofmem_msg((long_u)size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size)
|
||||
{
|
||||
void *ret = try_malloc(size);
|
||||
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xcalloc(size_t count, size_t size)
|
||||
{
|
||||
void *ret = calloc(count, size);
|
||||
|
||||
if (!ret && (!count || !size))
|
||||
ret = calloc(1, 1);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = calloc(count, size);
|
||||
if (!ret && (!count || !size))
|
||||
ret = calloc(1, 1);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
||||
if (!ret && !size)
|
||||
ret = realloc(ptr, 1);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = realloc(ptr, size);
|
||||
if (!ret && !size)
|
||||
ret = realloc(ptr, 1);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmallocz(size_t size)
|
||||
{
|
||||
size_t total_size = size + 1;
|
||||
void *ret;
|
||||
|
||||
if (total_size < size) {
|
||||
OUT_STR("Vim: Data too large to fit into virtual memory space\n");
|
||||
preserve_exit();
|
||||
}
|
||||
|
||||
ret = xmalloc(total_size);
|
||||
((char*)ret)[size] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmemdupz(const void *data, size_t len)
|
||||
{
|
||||
return memcpy(xmallocz(len), data, len);
|
||||
}
|
||||
|
||||
char *xstpcpy(char *restrict dst, const char *restrict src)
|
||||
{
|
||||
const size_t len = strlen(src);
|
||||
return (char *)memcpy(dst, src, len + 1) + len;
|
||||
}
|
||||
|
||||
char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen)
|
||||
{
|
||||
const char *p = memchr(src, '\0', maxlen);
|
||||
if (p) {
|
||||
size_t srclen = (size_t)(p - src);
|
||||
memcpy(dst, src, srclen);
|
||||
memset(dst + srclen, 0, maxlen - srclen);
|
||||
return dst + srclen;
|
||||
} else {
|
||||
memcpy(dst, src, maxlen);
|
||||
return dst + maxlen;
|
||||
}
|
||||
}
|
||||
|
||||
char * xstrdup(const char *str)
|
||||
{
|
||||
char *ret = strdup(str);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = strdup(str);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *xstrndup(const char *str, size_t len)
|
||||
{
|
||||
char *p = memchr(str, '\0', len);
|
||||
return xmemdupz(str, p ? (size_t)(p - str) : len);
|
||||
}
|
||||
|
||||
char *xmemdup(const char *data, size_t len)
|
||||
{
|
||||
return memcpy(xmalloc(len), data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid repeating the error message many times (they take 1 second each).
|
||||
* Did_outofmem_msg is reset when a character is read.
|
||||
*/
|
||||
void do_outofmem_msg(long_u size)
|
||||
{
|
||||
if (!did_outofmem_msg) {
|
||||
/* Don't hide this message */
|
||||
emsg_silent = 0;
|
||||
|
||||
/* Must come first to avoid coming back here when printing the error
|
||||
* message fails, e.g. when setting v:errmsg. */
|
||||
did_outofmem_msg = TRUE;
|
||||
|
||||
EMSGU(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), size);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EXITFREE) || defined(PROTO)
|
||||
|
||||
/*
|
||||
* Free everything that we allocated.
|
||||
* Can be used to detect memory leaks, e.g., with ccmalloc.
|
||||
* NOTE: This is tricky! Things are freed that functions depend on. Don't be
|
||||
* surprised if Vim crashes...
|
||||
* Some things can't be freed, esp. things local to a library function.
|
||||
*/
|
||||
void free_all_mem(void)
|
||||
{
|
||||
buf_T *buf, *nextbuf;
|
||||
static int entered = FALSE;
|
||||
|
||||
/* When we cause a crash here it is caught and Vim tries to exit cleanly.
|
||||
* Don't try freeing everything again. */
|
||||
if (entered)
|
||||
return;
|
||||
entered = TRUE;
|
||||
|
||||
block_autocmds(); /* don't want to trigger autocommands here */
|
||||
|
||||
/* Close all tabs and windows. Reset 'equalalways' to avoid redraws. */
|
||||
p_ea = FALSE;
|
||||
if (first_tabpage->tp_next != NULL)
|
||||
do_cmdline_cmd((char_u *)"tabonly!");
|
||||
if (firstwin != lastwin)
|
||||
do_cmdline_cmd((char_u *)"only!");
|
||||
|
||||
/* Free all spell info. */
|
||||
spell_free_all();
|
||||
|
||||
/* Clear user commands (before deleting buffers). */
|
||||
ex_comclear(NULL);
|
||||
|
||||
/* Clear menus. */
|
||||
do_cmdline_cmd((char_u *)"aunmenu *");
|
||||
do_cmdline_cmd((char_u *)"menutranslate clear");
|
||||
|
||||
/* Clear mappings, abbreviations, breakpoints. */
|
||||
do_cmdline_cmd((char_u *)"lmapclear");
|
||||
do_cmdline_cmd((char_u *)"xmapclear");
|
||||
do_cmdline_cmd((char_u *)"mapclear");
|
||||
do_cmdline_cmd((char_u *)"mapclear!");
|
||||
do_cmdline_cmd((char_u *)"abclear");
|
||||
do_cmdline_cmd((char_u *)"breakdel *");
|
||||
do_cmdline_cmd((char_u *)"profdel *");
|
||||
do_cmdline_cmd((char_u *)"set keymap=");
|
||||
|
||||
free_titles();
|
||||
free_findfile();
|
||||
|
||||
/* Obviously named calls. */
|
||||
free_all_autocmds();
|
||||
clear_termcodes();
|
||||
free_all_options();
|
||||
free_all_marks();
|
||||
alist_clear(&global_alist);
|
||||
free_homedir();
|
||||
free_users();
|
||||
free_search_patterns();
|
||||
free_old_sub();
|
||||
free_last_insert();
|
||||
free_prev_shellcmd();
|
||||
free_regexp_stuff();
|
||||
free_tag_stuff();
|
||||
free_cd_dir();
|
||||
free_signs();
|
||||
set_expr_line(NULL);
|
||||
diff_clear(curtab);
|
||||
clear_sb_text(); /* free any scrollback text */
|
||||
|
||||
/* Free some global vars. */
|
||||
free(last_cmdline);
|
||||
free(new_last_cmdline);
|
||||
set_keep_msg(NULL, 0);
|
||||
|
||||
/* Clear cmdline history. */
|
||||
p_hi = 0;
|
||||
init_history();
|
||||
|
||||
{
|
||||
win_T *win;
|
||||
tabpage_T *tab;
|
||||
|
||||
qf_free_all(NULL);
|
||||
/* Free all location lists */
|
||||
FOR_ALL_TAB_WINDOWS(tab, win)
|
||||
qf_free_all(win);
|
||||
}
|
||||
|
||||
/* Close all script inputs. */
|
||||
close_all_scripts();
|
||||
|
||||
/* Destroy all windows. Must come before freeing buffers. */
|
||||
win_free_all();
|
||||
|
||||
/* Free all buffers. Reset 'autochdir' to avoid accessing things that
|
||||
* were freed already. */
|
||||
p_acd = FALSE;
|
||||
for (buf = firstbuf; buf != NULL; ) {
|
||||
nextbuf = buf->b_next;
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, FALSE);
|
||||
if (buf_valid(buf))
|
||||
buf = nextbuf; /* didn't work, try next one */
|
||||
else
|
||||
buf = firstbuf;
|
||||
}
|
||||
|
||||
free_cmdline_buf();
|
||||
|
||||
/* Clear registers. */
|
||||
clear_registers();
|
||||
ResetRedobuff();
|
||||
ResetRedobuff();
|
||||
|
||||
|
||||
/* highlight info */
|
||||
free_highlight();
|
||||
|
||||
reset_last_sourcing();
|
||||
|
||||
free_tabpage(first_tabpage);
|
||||
first_tabpage = NULL;
|
||||
|
||||
# ifdef UNIX
|
||||
/* Machine-specific free. */
|
||||
mch_free_mem();
|
||||
# endif
|
||||
|
||||
/* message history */
|
||||
for (;; )
|
||||
if (delete_first_msg() == FAIL)
|
||||
break;
|
||||
|
||||
eval_clear();
|
||||
|
||||
free_termoptions();
|
||||
|
||||
/* screenlines (can't display anything now!) */
|
||||
free_screenlines();
|
||||
|
||||
clear_hl_tables();
|
||||
|
||||
free(NameBuff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
149
src/nvim/memory.h
Normal file
149
src/nvim/memory.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef NEOVIM_MEMORY_H
|
||||
#define NEOVIM_MEMORY_H
|
||||
|
||||
#include "func_attr.h"
|
||||
#include "types.h"
|
||||
#include "vim.h"
|
||||
|
||||
char_u *alloc(unsigned size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1);
|
||||
|
||||
/// malloc() wrapper
|
||||
///
|
||||
/// try_malloc() is a malloc() wrapper that tries to free some memory before
|
||||
/// trying again.
|
||||
///
|
||||
/// @see {try_to_free_memory}
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. NULL if out of memory
|
||||
void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1);
|
||||
|
||||
/// try_malloc() wrapper that shows an out-of-memory error message to the user
|
||||
/// before returning NULL
|
||||
///
|
||||
/// @see {try_malloc}
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. NULL if out of memory
|
||||
void *verbose_try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1);
|
||||
|
||||
/// malloc() wrapper that never returns NULL
|
||||
///
|
||||
/// xmalloc() succeeds or gracefully aborts when out of memory.
|
||||
/// Before aborting try to free some memory and call malloc again.
|
||||
///
|
||||
/// @see {try_to_free_memory}
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. Never NULL
|
||||
void *xmalloc(size_t size)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// calloc() wrapper
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param count
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. Never NULL
|
||||
void *xcalloc(size_t count, size_t size)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// realloc() wrapper
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param size
|
||||
/// @return pointer to reallocated space. Never NULL
|
||||
void *xrealloc(void *ptr, size_t size)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// xmalloc() wrapper that allocates size + 1 bytes and zeroes the last byte
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. Never NULL
|
||||
void *xmallocz(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// Allocates (len + 1) bytes of memory, duplicates `len` bytes of
|
||||
/// `data` to the allocated memory, zero terminates the allocated memory,
|
||||
/// and returns a pointer to the allocated memory. If the allocation fails,
|
||||
/// the program dies.
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param data Pointer to the data that will be copied
|
||||
/// @param len number of bytes that will be copied
|
||||
void *xmemdupz(const void *data, size_t len) FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// strdup() wrapper
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param str 0-terminated string that will be copied
|
||||
/// @return pointer to a copy of the string
|
||||
char * xstrdup(const char *str)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// strndup() wrapper
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param str 0-terminated string that will be copied
|
||||
/// @return pointer to a copy of the string
|
||||
char * xstrndup(const char *str, size_t len)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// The xstpcpy() function shall copy the string pointed to by src (including
|
||||
/// the terminating NUL character) into the array pointed to by dst.
|
||||
///
|
||||
/// The xstpcpy() function shall return a pointer to the terminating NUL
|
||||
/// character copied into the dst buffer. This is the only difference with
|
||||
/// strcpy(), which returns dst.
|
||||
///
|
||||
/// WARNING: If copying takes place between objects that overlap, the behavior is
|
||||
/// undefined.
|
||||
///
|
||||
/// This is the Neovim version of stpcpy(3) as defined in POSIX 2008. We
|
||||
/// don't require that supported platforms implement POSIX 2008, so we
|
||||
/// implement our own version.
|
||||
///
|
||||
/// @param dst
|
||||
/// @param src
|
||||
char *xstpcpy(char *restrict dst, const char *restrict src);
|
||||
|
||||
/// The xstpncpy() function shall copy not more than n bytes (bytes that follow
|
||||
/// a NUL character are not copied) from the array pointed to by src to the
|
||||
/// array pointed to by dst.
|
||||
///
|
||||
/// If a NUL character is written to the destination, the xstpncpy() function
|
||||
/// shall return the address of the first such NUL character. Otherwise, it
|
||||
/// shall return &dst[maxlen].
|
||||
///
|
||||
/// WARNING: If copying takes place between objects that overlap, the behavior is
|
||||
/// undefined.
|
||||
///
|
||||
/// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than
|
||||
/// maxlen, zeroes will be written to the remaining bytes.
|
||||
///
|
||||
/// TODO(aktau): I don't see a good reason to have this last behaviour, and
|
||||
/// it is potentially wasteful. Could we perhaps deviate from the standard
|
||||
/// and not zero the rest of the buffer?
|
||||
///
|
||||
/// @param dst
|
||||
/// @param src
|
||||
/// @param maxlen
|
||||
char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen);
|
||||
|
||||
/// Duplicates a chunk of memory using xmalloc
|
||||
///
|
||||
/// @see {xmalloc}
|
||||
/// @param data pointer to the chunk
|
||||
/// @param len size of the chunk
|
||||
/// @return a pointer
|
||||
char *xmemdup(const char *data, size_t len)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET;
|
||||
|
||||
/// Old low level memory allocation function.
|
||||
///
|
||||
/// @deprecated use xmalloc() directly instead
|
||||
/// @param size
|
||||
/// @return pointer to allocated space. Never NULL
|
||||
char_u *lalloc(long_u size, int message) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1);
|
||||
|
||||
void do_outofmem_msg(long_u size);
|
||||
void free_all_mem(void);
|
||||
|
||||
#endif
|
||||
1616
src/nvim/menu.c
Normal file
1616
src/nvim/menu.c
Normal file
File diff suppressed because it is too large
Load Diff
65
src/nvim/menu.h
Normal file
65
src/nvim/menu.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef NEOVIM_MENU_H
|
||||
#define NEOVIM_MENU_H
|
||||
|
||||
/* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */
|
||||
#define MENU_INDEX_INVALID -1
|
||||
#define MENU_INDEX_NORMAL 0
|
||||
#define MENU_INDEX_VISUAL 1
|
||||
#define MENU_INDEX_SELECT 2
|
||||
#define MENU_INDEX_OP_PENDING 3
|
||||
#define MENU_INDEX_INSERT 4
|
||||
#define MENU_INDEX_CMDLINE 5
|
||||
#define MENU_INDEX_TIP 6
|
||||
#define MENU_MODES 7
|
||||
|
||||
/* Menu modes */
|
||||
#define MENU_NORMAL_MODE (1 << MENU_INDEX_NORMAL)
|
||||
#define MENU_VISUAL_MODE (1 << MENU_INDEX_VISUAL)
|
||||
#define MENU_SELECT_MODE (1 << MENU_INDEX_SELECT)
|
||||
#define MENU_OP_PENDING_MODE (1 << MENU_INDEX_OP_PENDING)
|
||||
#define MENU_INSERT_MODE (1 << MENU_INDEX_INSERT)
|
||||
#define MENU_CMDLINE_MODE (1 << MENU_INDEX_CMDLINE)
|
||||
#define MENU_TIP_MODE (1 << MENU_INDEX_TIP)
|
||||
#define MENU_ALL_MODES ((1 << MENU_INDEX_TIP) - 1)
|
||||
/*note MENU_INDEX_TIP is not a 'real' mode*/
|
||||
|
||||
/* Start a menu name with this to not include it on the main menu bar */
|
||||
#define MNU_HIDDEN_CHAR ']'
|
||||
|
||||
typedef struct VimMenu vimmenu_T;
|
||||
|
||||
struct VimMenu {
|
||||
int modes; /* Which modes is this menu visible for? */
|
||||
int enabled; /* for which modes the menu is enabled */
|
||||
char_u *name; /* Name of menu, possibly translated */
|
||||
char_u *dname; /* Displayed Name ("name" without '&') */
|
||||
char_u *en_name; /* "name" untranslated, NULL when "name"
|
||||
* was not translated */
|
||||
char_u *en_dname; /* "dname" untranslated, NULL when "dname"
|
||||
* was not translated */
|
||||
int mnemonic; /* mnemonic key (after '&') */
|
||||
char_u *actext; /* accelerator text (after TAB) */
|
||||
int priority; /* Menu order priority */
|
||||
char_u *strings[MENU_MODES]; /* Mapped string for each mode */
|
||||
int noremap[MENU_MODES]; /* A REMAP_ flag for each mode */
|
||||
char silent[MENU_MODES]; /* A silent flag for each mode */
|
||||
vimmenu_T *children; /* Children of sub-menu */
|
||||
vimmenu_T *parent; /* Parent of menu */
|
||||
vimmenu_T *next; /* Next item in menu */
|
||||
};
|
||||
|
||||
void ex_menu(exarg_T *eap);
|
||||
char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg,
|
||||
int forceit);
|
||||
char_u *get_menu_name(expand_T *xp, int idx);
|
||||
char_u *get_menu_names(expand_T *xp, int idx);
|
||||
char_u *menu_name_skip(char_u *name);
|
||||
int menu_is_menubar(char_u *name);
|
||||
int menu_is_popup(char_u *name);
|
||||
int menu_is_toolbar(char_u *name);
|
||||
int menu_is_separator(char_u *name);
|
||||
void ex_emenu(exarg_T *eap);
|
||||
vimmenu_T *gui_find_menu(char_u *path_name);
|
||||
void ex_menutranslate(exarg_T *eap);
|
||||
|
||||
#endif /* NEOVIM_MENU_H */
|
||||
3881
src/nvim/message.c
Normal file
3881
src/nvim/message.c
Normal file
File diff suppressed because it is too large
Load Diff
85
src/nvim/message.h
Normal file
85
src/nvim/message.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef NEOVIM_MESSAGE_H
|
||||
#define NEOVIM_MESSAGE_H
|
||||
/* message.c */
|
||||
int msg(char_u *s);
|
||||
int verb_msg(char_u *s);
|
||||
int msg_attr(char_u *s, int attr);
|
||||
int msg_attr_keep(char_u *s, int attr, int keep);
|
||||
char_u *msg_strtrunc(char_u *s, int force);
|
||||
void trunc_string(char_u *s, char_u *buf, int room, int buflen);
|
||||
void reset_last_sourcing(void);
|
||||
void msg_source(int attr);
|
||||
int emsg_not_now(void);
|
||||
int emsg(char_u *s);
|
||||
int emsg2(char_u *s, char_u *a1);
|
||||
void emsg_invreg(int name);
|
||||
char_u *msg_trunc_attr(char_u *s, int force, int attr);
|
||||
char_u *msg_may_trunc(int force, char_u *s);
|
||||
int delete_first_msg(void);
|
||||
void ex_messages(exarg_T *eap);
|
||||
void msg_end_prompt(void);
|
||||
void wait_return(int redraw);
|
||||
void set_keep_msg(char_u *s, int attr);
|
||||
void set_keep_msg_from_hist(void);
|
||||
void msg_start(void);
|
||||
void msg_starthere(void);
|
||||
void msg_putchar(int c);
|
||||
void msg_putchar_attr(int c, int attr);
|
||||
void msg_outnum(long n);
|
||||
void msg_home_replace(char_u *fname);
|
||||
void msg_home_replace_hl(char_u *fname);
|
||||
int msg_outtrans(char_u *str);
|
||||
int msg_outtrans_attr(char_u *str, int attr);
|
||||
int msg_outtrans_len(char_u *str, int len);
|
||||
char_u *msg_outtrans_one(char_u *p, int attr);
|
||||
int msg_outtrans_len_attr(char_u *msgstr, int len, int attr);
|
||||
void msg_make(char_u *arg);
|
||||
int msg_outtrans_special(char_u *strstart, int from);
|
||||
char_u *str2special_save(char_u *str, int is_lhs);
|
||||
char_u *str2special(char_u **sp, int from);
|
||||
void str2specialbuf(char_u *sp, char_u *buf, int len);
|
||||
void msg_prt_line(char_u *s, int list);
|
||||
void msg_puts(char_u *s);
|
||||
void msg_puts_title(char_u *s);
|
||||
void msg_puts_long_attr(char_u *longstr, int attr);
|
||||
void msg_puts_long_len_attr(char_u *longstr, int len, int attr);
|
||||
void msg_puts_attr(char_u *s, int attr);
|
||||
void may_clear_sb_text(void);
|
||||
void clear_sb_text(void);
|
||||
void show_sb_text(void);
|
||||
void msg_sb_eol(void);
|
||||
int msg_use_printf(void);
|
||||
#ifdef USE_MCH_ERRMSG
|
||||
void mch_errmsg(char *str);
|
||||
void mch_msg(char *str);
|
||||
#endif
|
||||
void msg_moremsg(int full);
|
||||
void repeat_message(void);
|
||||
void msg_clr_eos(void);
|
||||
void msg_clr_eos_force(void);
|
||||
void msg_clr_cmdline(void);
|
||||
int msg_end(void);
|
||||
void msg_check(void);
|
||||
int redirecting(void);
|
||||
void verbose_enter(void);
|
||||
void verbose_leave(void);
|
||||
void verbose_enter_scroll(void);
|
||||
void verbose_leave_scroll(void);
|
||||
void verbose_stop(void);
|
||||
int verbose_open(void);
|
||||
void give_warning(char_u *message, int hl);
|
||||
void msg_advance(int col);
|
||||
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons,
|
||||
int dfltbutton, char_u *textfield,
|
||||
int ex_cmd);
|
||||
void display_confirm_msg(void);
|
||||
int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt);
|
||||
int vim_dialog_yesnocancel(int type, char_u *title, char_u *message,
|
||||
int dflt);
|
||||
int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message,
|
||||
int dflt);
|
||||
char_u *do_browse(int flags, char_u *title, char_u *dflt, char_u *ext,
|
||||
char_u *initdir, char_u *filter,
|
||||
buf_T *buf);
|
||||
|
||||
#endif /* NEOVIM_MESSAGE_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user