Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
V
Vim
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Someone-Else
Vim
Commits
ca8a4dfe
Commit
ca8a4dfe
authored
14 years ago
by
Bram Moolenaar
Browse files
Options
Downloads
Patches
Plain Diff
Move many more common Python items to if_py_both.c.
parent
3b1c4856
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/if_py_both.h
+1093
-0
1093 additions, 0 deletions
src/if_py_both.h
src/if_python.c
+48
-1190
48 additions, 1190 deletions
src/if_python.c
src/if_python3.c
+18
-1161
18 additions, 1161 deletions
src/if_python3.c
with
1159 additions
and
2351 deletions
src/if_py_both.h
+
1093
−
0
View file @
ca8a4dfe
...
...
@@ -51,6 +51,8 @@ static struct PyMethodDef OutputMethods[] = {
{
NULL
,
NULL
,
0
,
NULL
}
};
#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
/*************/
/* Output buffer management
...
...
@@ -254,3 +256,1094 @@ VimErrorCheck(void)
return
0
;
}
/* Vim module - Implementation
*/
static
PyObject
*
VimCommand
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
char
*
cmd
;
PyObject
*
result
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
cmd
))
return
NULL
;
PyErr_Clear
();
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
do_cmdline_cmd
((
char_u
*
)
cmd
);
update_screen
(
VALID
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
VimErrorCheck
())
result
=
NULL
;
else
result
=
Py_None
;
Py_XINCREF
(
result
);
return
result
;
}
#ifdef FEAT_EVAL
/*
* Function to translate a typval_T into a PyObject; this will recursively
* translate lists/dictionaries into their Python equivalents.
*
* The depth parameter is to avoid infinite recursion, set it to 1 when
* you call VimToPython.
*/
static
PyObject
*
VimToPython
(
typval_T
*
our_tv
,
int
depth
,
PyObject
*
lookupDict
)
{
PyObject
*
result
;
PyObject
*
newObj
;
char
ptrBuf
[
NUMBUFLEN
];
/* Avoid infinite recursion */
if
(
depth
>
100
)
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
return
result
;
}
/* Check if we run into a recursive loop. The item must be in lookupDict
* then and we can use it again. */
if
((
our_tv
->
v_type
==
VAR_LIST
&&
our_tv
->
vval
.
v_list
!=
NULL
)
||
(
our_tv
->
v_type
==
VAR_DICT
&&
our_tv
->
vval
.
v_dict
!=
NULL
))
{
sprintf
(
ptrBuf
,
PRINTF_DECIMAL_LONG_U
,
our_tv
->
v_type
==
VAR_LIST
?
(
long_u
)
our_tv
->
vval
.
v_list
:
(
long_u
)
our_tv
->
vval
.
v_dict
);
result
=
PyDict_GetItemString
(
lookupDict
,
ptrBuf
);
if
(
result
!=
NULL
)
{
Py_INCREF
(
result
);
return
result
;
}
}
if
(
our_tv
->
v_type
==
VAR_STRING
)
{
result
=
Py_BuildValue
(
"s"
,
our_tv
->
vval
.
v_string
);
}
else
if
(
our_tv
->
v_type
==
VAR_NUMBER
)
{
char
buf
[
NUMBUFLEN
];
/* For backwards compatibility numbers are stored as strings. */
sprintf
(
buf
,
"%ld"
,
(
long
)
our_tv
->
vval
.
v_number
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# ifdef FEAT_FLOAT
else
if
(
our_tv
->
v_type
==
VAR_FLOAT
)
{
char
buf
[
NUMBUFLEN
];
sprintf
(
buf
,
"%f"
,
our_tv
->
vval
.
v_float
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# endif
else
if
(
our_tv
->
v_type
==
VAR_LIST
)
{
list_T
*
list
=
our_tv
->
vval
.
v_list
;
listitem_T
*
curr
;
result
=
PyList_New
(
0
);
if
(
list
!=
NULL
)
{
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
curr
=
list
->
lv_first
;
curr
!=
NULL
;
curr
=
curr
->
li_next
)
{
newObj
=
VimToPython
(
&
curr
->
li_tv
,
depth
+
1
,
lookupDict
);
PyList_Append
(
result
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
else
if
(
our_tv
->
v_type
==
VAR_DICT
)
{
result
=
PyDict_New
();
if
(
our_tv
->
vval
.
v_dict
!=
NULL
)
{
hashtab_T
*
ht
=
&
our_tv
->
vval
.
v_dict
->
dv_hashtab
;
long_u
todo
=
ht
->
ht_used
;
hashitem_T
*
hi
;
dictitem_T
*
di
;
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
hi
=
ht
->
ht_array
;
todo
>
0
;
++
hi
)
{
if
(
!
HASHITEM_EMPTY
(
hi
))
{
--
todo
;
di
=
dict_lookup
(
hi
);
newObj
=
VimToPython
(
&
di
->
di_tv
,
depth
+
1
,
lookupDict
);
PyDict_SetItemString
(
result
,
(
char
*
)
hi
->
hi_key
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
}
else
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
}
return
result
;
}
#endif
static
PyObject
*
VimEval
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
#ifdef FEAT_EVAL
char
*
expr
;
typval_T
*
our_tv
;
PyObject
*
result
;
PyObject
*
lookup_dict
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
expr
))
return
NULL
;
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
our_tv
=
eval_expr
((
char_u
*
)
expr
,
NULL
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
our_tv
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid expression"
));
return
NULL
;
}
/* Convert the Vim type into a Python type. Create a dictionary that's
* used to check for recursive loops. */
lookup_dict
=
PyDict_New
();
result
=
VimToPython
(
our_tv
,
1
,
lookup_dict
);
Py_DECREF
(
lookup_dict
);
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
free_tv
(
our_tv
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
return
result
;
#else
PyErr_SetVim
(
_
(
"expressions disabled at compile time"
));
return
NULL
;
#endif
}
/*
* Vim module - Definitions
*/
static
struct
PyMethodDef
VimMethods
[]
=
{
/* name, function, calling, documentation */
{
"command"
,
VimCommand
,
1
,
"Execute a Vim ex-mode command"
},
{
"eval"
,
VimEval
,
1
,
"Evaluate an expression using Vim evaluator"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
typedef
struct
{
PyObject_HEAD
buf_T
*
buf
;
}
BufferObject
;
#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
/*
* Buffer list object - Implementation
*/
static
PyInt
BufListLength
(
PyObject
*
self
UNUSED
)
{
buf_T
*
b
=
firstbuf
;
PyInt
n
=
0
;
while
(
b
)
{
++
n
;
b
=
b
->
b_next
;
}
return
n
;
}
static
PyObject
*
BufListItem
(
PyObject
*
self
UNUSED
,
PyInt
n
)
{
buf_T
*
b
;
for
(
b
=
firstbuf
;
b
;
b
=
b
->
b_next
,
--
n
)
{
if
(
n
==
0
)
return
BufferNew
(
b
);
}
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such buffer"
));
return
NULL
;
}
typedef
struct
{
PyObject_HEAD
win_T
*
win
;
}
WindowObject
;
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
static
int
CheckWindow
(
WindowObject
*
this
)
{
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted window"
));
return
-
1
;
}
return
0
;
}
static
int
WindowSetattr
(
PyObject
*
,
char
*
,
PyObject
*
);
static
PyObject
*
WindowRepr
(
PyObject
*
);
static
int
WindowSetattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
val
)
{
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
if
(
CheckWindow
(
this
))
return
-
1
;
if
(
strcmp
(
name
,
"buffer"
)
==
0
)
{
PyErr_SetString
(
PyExc_TypeError
,
_
(
"readonly attribute"
));
return
-
1
;
}
else
if
(
strcmp
(
name
,
"cursor"
)
==
0
)
{
long
lnum
;
long
col
;
long
len
;
if
(
!
PyArg_Parse
(
val
,
"(ll)"
,
&
lnum
,
&
col
))
return
-
1
;
if
(
lnum
<=
0
||
lnum
>
this
->
win
->
w_buffer
->
b_ml
.
ml_line_count
)
{
PyErr_SetVim
(
_
(
"cursor position outside buffer"
));
return
-
1
;
}
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
/* When column is out of range silently correct it. */
len
=
(
long
)
STRLEN
(
ml_get_buf
(
this
->
win
->
w_buffer
,
lnum
,
FALSE
));
if
(
col
>
len
)
col
=
len
;
this
->
win
->
w_cursor
.
lnum
=
lnum
;
this
->
win
->
w_cursor
.
col
=
col
;
#ifdef FEAT_VIRTUALEDIT
this
->
win
->
w_cursor
.
coladd
=
0
;
#endif
update_screen
(
VALID
);
return
0
;
}
else
if
(
strcmp
(
name
,
"height"
)
==
0
)
{
int
height
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
height
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setheight
(
height
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#ifdef FEAT_VERTSPLIT
else
if
(
strcmp
(
name
,
"width"
)
==
0
)
{
int
width
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
width
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setwidth
(
width
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#endif
else
{
PyErr_SetString
(
PyExc_AttributeError
,
name
);
return
-
1
;
}
}
static
PyObject
*
WindowRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
vim_snprintf
(
repr
,
100
,
_
(
"<window object (deleted) at %p>"
),
(
self
));
return
PyString_FromString
(
repr
);
}
else
{
int
i
=
0
;
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
&&
w
!=
this
->
win
;
w
=
W_NEXT
(
w
))
++
i
;
if
(
w
==
NULL
)
vim_snprintf
(
repr
,
100
,
_
(
"<window object (unknown) at %p>"
),
(
self
));
else
vim_snprintf
(
repr
,
100
,
_
(
"<window %d>"
),
i
);
return
PyString_FromString
(
repr
);
}
}
/*
* Window list object - Implementation
*/
static
PyInt
WinListLength
(
PyObject
*
self
UNUSED
)
{
win_T
*
w
=
firstwin
;
PyInt
n
=
0
;
while
(
w
!=
NULL
)
{
++
n
;
w
=
W_NEXT
(
w
);
}
return
n
;
}
static
PyObject
*
WinListItem
(
PyObject
*
self
UNUSED
,
PyInt
n
)
{
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
;
w
=
W_NEXT
(
w
),
--
n
)
if
(
n
==
0
)
return
WindowNew
(
w
);
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such window"
));
return
NULL
;
}
/* Convert a Python string into a Vim line.
*
* The result is in allocated memory. All internal nulls are replaced by
* newline characters. It is an error for the string to contain newline
* characters.
*
* On errors, the Python exception data is set, and NULL is returned.
*/
static
char
*
StringToLine
(
PyObject
*
obj
)
{
const
char
*
str
;
char
*
save
;
PyInt
len
;
PyInt
i
;
char
*
p
;
if
(
obj
==
NULL
||
!
PyString_Check
(
obj
))
{
PyErr_BadArgument
();
return
NULL
;
}
str
=
PyString_AsString
(
obj
);
len
=
PyString_Size
(
obj
);
/*
* Error checking: String must not contain newlines, as we
* are replacing a single line, and we must replace it with
* a single line.
* A trailing newline is removed, so that append(f.readlines()) works.
*/
p
=
memchr
(
str
,
'\n'
,
len
);
if
(
p
!=
NULL
)
{
if
(
p
==
str
+
len
-
1
)
--
len
;
else
{
PyErr_SetVim
(
_
(
"string cannot contain newlines"
));
return
NULL
;
}
}
/* Create a copy of the string, with internal nulls replaced by
* newline characters, as is the vim convention.
*/
save
=
(
char
*
)
alloc
((
unsigned
)(
len
+
1
));
if
(
save
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
for
(
i
=
0
;
i
<
len
;
++
i
)
{
if
(
str
[
i
]
==
'\0'
)
save
[
i
]
=
'\n'
;
else
save
[
i
]
=
str
[
i
];
}
save
[
i
]
=
'\0'
;
return
save
;
}
/* Get a line from the specified buffer. The line number is
* in Vim format (1-based). The line is returned as a Python
* string object.
*/
static
PyObject
*
GetBufferLine
(
buf_T
*
buf
,
PyInt
n
)
{
return
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)
n
,
FALSE
));
}
/* Get a list of lines from the specified buffer. The line numbers
* are in Vim format (1-based). The range is from lo up to, but not
* including, hi. The list is returned as a Python list of string objects.
*/
static
PyObject
*
GetBufferLineList
(
buf_T
*
buf
,
PyInt
lo
,
PyInt
hi
)
{
PyInt
i
;
PyInt
n
=
hi
-
lo
;
PyObject
*
list
=
PyList_New
(
n
);
if
(
list
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
n
;
++
i
)
{
PyObject
*
str
=
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)(
lo
+
i
),
FALSE
));
/* Error check - was the Python string creation OK? */
if
(
str
==
NULL
)
{
Py_DECREF
(
list
);
return
NULL
;
}
/* Set the list item */
if
(
PyList_SetItem
(
list
,
i
,
str
))
{
Py_DECREF
(
str
);
Py_DECREF
(
list
);
return
NULL
;
}
}
/* The ownership of the Python list is passed to the caller (ie,
* the caller should Py_DECREF() the object when it is finished
* with it).
*/
return
list
;
}
/*
* 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
py_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
();
}
/* Replace a line in the specified buffer. The line number is
* in Vim format (1-based). The replacement line is given as
* a Python string object. The object is checked for validity
* and correct format. Errors are returned as a value of FAIL.
* The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
SetBufferLine
(
buf_T
*
buf
,
PyInt
n
,
PyObject
*
line
,
PyInt
*
len_change
)
{
/* First of all, we check the thpe of the supplied Python object.
* There are three cases:
* 1. NULL, or None - this is a deletion.
* 2. A string - this is a replacement.
* 3. Anything else - this is an error.
*/
if
(
line
==
Py_None
||
line
==
NULL
)
{
buf_T
*
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savedel
((
linenr_T
)
n
,
1L
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_delete
((
linenr_T
)
n
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot delete line"
));
else
{
if
(
buf
==
curwin
->
w_buffer
)
py_fix_cursor
((
linenr_T
)
n
,
(
linenr_T
)
n
+
1
,
(
linenr_T
)
-
1
);
deleted_lines_mark
((
linenr_T
)
n
,
1L
);
}
curbuf
=
savebuf
;
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
-
1
;
return
OK
;
}
else
if
(
PyString_Check
(
line
))
{
char
*
save
=
StringToLine
(
line
);
buf_T
*
savebuf
=
curbuf
;
if
(
save
==
NULL
)
return
FAIL
;
/* We do not need to free "save" if ml_replace() consumes it. */
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savesub
((
linenr_T
)
n
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot save undo information"
));
vim_free
(
save
);
}
else
if
(
ml_replace
((
linenr_T
)
n
,
(
char_u
*
)
save
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot replace line"
));
vim_free
(
save
);
}
else
changed_bytes
((
linenr_T
)
n
,
0
);
curbuf
=
savebuf
;
/* Check that the cursor is not beyond the end of the line now. */
if
(
buf
==
curwin
->
w_buffer
)
check_cursor_col
();
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
0
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/* Insert a number of lines into the specified buffer after the specifed line.
* The line number is in Vim format (1-based). The lines to be inserted are
* given as a Python list of string objects or as a single string. The lines
* to be added are checked for validity and correct format. Errors are
* returned as a value of FAIL. The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
InsertBufferLines
(
buf_T
*
buf
,
PyInt
n
,
PyObject
*
lines
,
PyInt
*
len_change
)
{
/* First of all, we check the type of the supplied Python object.
* It must be a string or a list, or the call is in error.
*/
if
(
PyString_Check
(
lines
))
{
char
*
str
=
StringToLine
(
lines
);
buf_T
*
savebuf
;
if
(
str
==
NULL
)
return
FAIL
;
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_append
((
linenr_T
)
n
,
(
char_u
*
)
str
,
0
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot insert line"
));
else
appended_lines_mark
((
linenr_T
)
n
,
1L
);
vim_free
(
str
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
1
;
return
OK
;
}
else
if
(
PyList_Check
(
lines
))
{
PyInt
i
;
PyInt
size
=
PyList_Size
(
lines
);
char
**
array
;
buf_T
*
savebuf
;
array
=
(
char
**
)
alloc
((
unsigned
)(
size
*
sizeof
(
char
*
)));
if
(
array
==
NULL
)
{
PyErr_NoMemory
();
return
FAIL
;
}
for
(
i
=
0
;
i
<
size
;
++
i
)
{
PyObject
*
line
=
PyList_GetItem
(
lines
,
i
);
array
[
i
]
=
StringToLine
(
line
);
if
(
array
[
i
]
==
NULL
)
{
while
(
i
)
vim_free
(
array
[
--
i
]);
vim_free
(
array
);
return
FAIL
;
}
}
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
{
for
(
i
=
0
;
i
<
size
;
++
i
)
{
if
(
ml_append
((
linenr_T
)(
n
+
i
),
(
char_u
*
)
array
[
i
],
0
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot insert line"
));
/* Free the rest of the lines */
while
(
i
<
size
)
vim_free
(
array
[
i
++
]);
break
;
}
vim_free
(
array
[
i
]);
}
if
(
i
>
0
)
appended_lines_mark
((
linenr_T
)
n
,
(
long
)
i
);
}
/* Free the array of lines. All of its contents have now
* been freed.
*/
vim_free
(
array
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
size
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/*
* Common routines for buffers and line ranges
* -------------------------------------------
*/
static
int
CheckBuffer
(
BufferObject
*
this
)
{
if
(
this
->
buf
==
INVALID_BUFFER_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted buffer"
));
return
-
1
;
}
return
0
;
}
static
PyObject
*
RBItem
(
BufferObject
*
self
,
PyInt
n
,
PyInt
start
,
PyInt
end
)
{
if
(
CheckBuffer
(
self
))
return
NULL
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
NULL
;
}
return
GetBufferLine
(
self
->
buf
,
n
+
start
);
}
static
PyObject
*
RBSlice
(
BufferObject
*
self
,
PyInt
lo
,
PyInt
hi
,
PyInt
start
,
PyInt
end
)
{
PyInt
size
;
if
(
CheckBuffer
(
self
))
return
NULL
;
size
=
end
-
start
+
1
;
if
(
lo
<
0
)
lo
=
0
;
else
if
(
lo
>
size
)
lo
=
size
;
if
(
hi
<
0
)
hi
=
0
;
if
(
hi
<
lo
)
hi
=
lo
;
else
if
(
hi
>
size
)
hi
=
size
;
return
GetBufferLineList
(
self
->
buf
,
lo
+
start
,
hi
+
start
);
}
static
PyInt
RBAsItem
(
BufferObject
*
self
,
PyInt
n
,
PyObject
*
val
,
PyInt
start
,
PyInt
end
,
PyInt
*
new_end
)
{
PyInt
len_change
;
if
(
CheckBuffer
(
self
))
return
-
1
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
-
1
;
}
if
(
SetBufferLine
(
self
->
buf
,
n
+
start
,
val
,
&
len_change
)
==
FAIL
)
return
-
1
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
return
0
;
}
static
PyObject
*
RBAppend
(
BufferObject
*
self
,
PyObject
*
args
,
PyInt
start
,
PyInt
end
,
PyInt
*
new_end
)
{
PyObject
*
lines
;
PyInt
len_change
;
PyInt
max
;
PyInt
n
;
if
(
CheckBuffer
(
self
))
return
NULL
;
max
=
n
=
end
-
start
+
1
;
if
(
!
PyArg_ParseTuple
(
args
,
"O|n"
,
&
lines
,
&
n
))
return
NULL
;
if
(
n
<
0
||
n
>
max
)
{
PyErr_SetString
(
PyExc_ValueError
,
_
(
"line number out of range"
));
return
NULL
;
}
if
(
InsertBufferLines
(
self
->
buf
,
n
+
start
-
1
,
lines
,
&
len_change
)
==
FAIL
)
return
NULL
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/* Buffer object - Definitions
*/
typedef
struct
{
PyObject_HEAD
BufferObject
*
buf
;
PyInt
start
;
PyInt
end
;
}
RangeObject
;
static
PyObject
*
RangeNew
(
buf_T
*
buf
,
PyInt
start
,
PyInt
end
)
{
BufferObject
*
bufr
;
RangeObject
*
self
;
self
=
PyObject_NEW
(
RangeObject
,
&
RangeType
);
if
(
self
==
NULL
)
return
NULL
;
bufr
=
(
BufferObject
*
)
BufferNew
(
buf
);
if
(
bufr
==
NULL
)
{
Py_DECREF
(
self
);
return
NULL
;
}
Py_INCREF
(
bufr
);
self
->
buf
=
bufr
;
self
->
start
=
start
;
self
->
end
=
end
;
return
(
PyObject
*
)(
self
);
}
static
PyObject
*
BufferAppend
(
PyObject
*
self
,
PyObject
*
args
)
{
return
RBAppend
((
BufferObject
*
)(
self
),
args
,
1
,
(
PyInt
)((
BufferObject
*
)(
self
))
->
buf
->
b_ml
.
ml_line_count
,
NULL
);
}
static
PyObject
*
BufferMark
(
PyObject
*
self
,
PyObject
*
args
)
{
pos_T
*
posp
;
char
*
pmark
;
char
mark
;
buf_T
*
curbuf_save
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
pmark
))
return
NULL
;
mark
=
*
pmark
;
curbuf_save
=
curbuf
;
curbuf
=
((
BufferObject
*
)(
self
))
->
buf
;
posp
=
getmark
(
mark
,
FALSE
);
curbuf
=
curbuf_save
;
if
(
posp
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid mark name"
));
return
NULL
;
}
/* Ckeck for keyboard interrupt */
if
(
VimErrorCheck
())
return
NULL
;
if
(
posp
->
lnum
<=
0
)
{
/* Or raise an error? */
Py_INCREF
(
Py_None
);
return
Py_None
;
}
return
Py_BuildValue
(
"(ll)"
,
(
long
)(
posp
->
lnum
),
(
long
)(
posp
->
col
));
}
static
PyObject
*
BufferRange
(
PyObject
*
self
,
PyObject
*
args
)
{
PyInt
start
;
PyInt
end
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"nn"
,
&
start
,
&
end
))
return
NULL
;
return
RangeNew
(((
BufferObject
*
)(
self
))
->
buf
,
start
,
end
);
}
static
struct
PyMethodDef
BufferMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
BufferAppend
,
1
,
"Append data to Vim buffer"
},
{
"mark"
,
BufferMark
,
1
,
"Return (row,col) representing position of named mark"
},
{
"range"
,
BufferRange
,
1
,
"Return a range object which represents the part of the given buffer between line numbers s and e"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PyObject
*
RangeAppend
(
PyObject
*
self
,
PyObject
*
args
)
{
return
RBAppend
(((
RangeObject
*
)(
self
))
->
buf
,
args
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
,
&
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyInt
RangeLength
(
PyObject
*
self
)
{
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
if
(
CheckBuffer
(((
RangeObject
*
)(
self
))
->
buf
))
return
-
1
;
/* ??? */
return
(((
RangeObject
*
)(
self
))
->
end
-
((
RangeObject
*
)(
self
))
->
start
+
1
);
}
static
PyObject
*
RangeItem
(
PyObject
*
self
,
PyInt
n
)
{
return
RBItem
(((
RangeObject
*
)(
self
))
->
buf
,
n
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyObject
*
RangeRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
RangeObject
*
this
=
(
RangeObject
*
)(
self
);
if
(
this
->
buf
->
buf
==
INVALID_BUFFER_VALUE
)
{
vim_snprintf
(
repr
,
100
,
"<range object (for deleted buffer) at %p>"
,
(
self
));
return
PyString_FromString
(
repr
);
}
else
{
char
*
name
=
(
char
*
)
this
->
buf
->
buf
->
b_fname
;
int
len
;
if
(
name
==
NULL
)
name
=
""
;
len
=
(
int
)
strlen
(
name
);
if
(
len
>
45
)
name
=
name
+
(
45
-
len
);
vim_snprintf
(
repr
,
100
,
"<range %s%s (%d:%d)>"
,
len
>
45
?
"..."
:
""
,
name
,
this
->
start
,
this
->
end
);
return
PyString_FromString
(
repr
);
}
}
static
PyObject
*
RangeSlice
(
PyObject
*
self
,
PyInt
lo
,
PyInt
hi
)
{
return
RBSlice
(((
RangeObject
*
)(
self
))
->
buf
,
lo
,
hi
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
/*
* Line range object - Definitions
*/
static
struct
PyMethodDef
RangeMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
RangeAppend
,
1
,
"Append data to the Vim range"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
This diff is collapsed.
Click to expand it.
src/if_python.c
+
48
−
1190
View file @
ca8a4dfe
...
...
@@ -390,13 +390,12 @@ python_enabled(int verbose)
return
python_runtime_link_init
(
DYNAMIC_PYTHON_DLL
,
verbose
)
==
OK
;
}
/* Load the standard Python exceptions - don't import the symbols from the
/*
* Load the standard Python exceptions - don't import the symbols from the
* DLL, as this can cause errors (importing data symbols is not reliable).
*/
static
void
get_exceptions
__ARGS
((
void
));
static
void
get_exceptions
()
get_exceptions
(
void
)
{
PyObject
*
exmod
=
PyImport_ImportModule
(
"exceptions"
);
PyObject
*
exdict
=
PyModule_GetDict
(
exmod
);
...
...
@@ -414,6 +413,12 @@ get_exceptions()
}
#endif
/* DYNAMIC_PYTHON */
static
PyObject
*
BufferNew
(
buf_T
*
);
static
PyObject
*
WindowNew
(
win_T
*
);
static
PyObject
*
LineToString
(
const
char
*
);
static
PyTypeObject
RangeType
;
/*
* Include the code shared with if_python3.c
*/
...
...
@@ -424,7 +429,6 @@ get_exceptions()
* Internal function prototypes.
*/
static
void
DoPythonCommand
(
exarg_T
*
,
const
char
*
);
static
PyInt
RangeStart
;
static
PyInt
RangeEnd
;
...
...
@@ -435,17 +439,9 @@ static int PythonMod_Init(void);
/* Utility functions for the vim/python interface
* ----------------------------------------------
*/
static
PyObject
*
GetBufferLine
(
buf_T
*
,
PyInt
);
static
PyObject
*
GetBufferLineList
(
buf_T
*
,
PyInt
,
PyInt
);
static
int
SetBufferLine
(
buf_T
*
,
PyInt
,
PyObject
*
,
PyInt
*
);
static
int
SetBufferLineList
(
buf_T
*
,
PyInt
,
PyInt
,
PyObject
*
,
PyInt
*
);
static
int
InsertBufferLines
(
buf_T
*
,
PyInt
,
PyObject
*
,
PyInt
*
);
static
PyObject
*
LineToString
(
const
char
*
);
static
char
*
StringToLine
(
PyObject
*
);
#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
/******************************************************
* 1. Python interpreter main program.
...
...
@@ -734,11 +730,6 @@ ex_pyfile(exarg_T *eap)
/* Implementation functions
*/
static
PyObject
*
OutputGetattr
(
PyObject
*
,
char
*
);
static
int
OutputSetattr
(
PyObject
*
,
char
*
,
PyObject
*
);
/*************/
static
PyObject
*
OutputGetattr
(
PyObject
*
self
,
char
*
name
)
{
...
...
@@ -786,52 +777,21 @@ PythonIO_Init(void)
* 3. Implementation of the Vim module for Python
*/
/* Vim module - Implementation functions
* -------------------------------------
*/
static
PyObject
*
VimCommand
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
VimEval
(
PyObject
*
,
PyObject
*
);
/* Window type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
win_T
*
win
;
}
WindowObject
;
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
#define WindowType_Check(obj) ((obj)->ob_type == &WindowType)
static
PyObject
*
WindowNew
(
win_T
*
);
static
void
WindowDestructor
(
PyObject
*
);
static
PyObject
*
WindowGetattr
(
PyObject
*
,
char
*
);
static
int
WindowSetattr
(
PyObject
*
,
char
*
,
PyObject
*
);
static
PyObject
*
WindowRepr
(
PyObject
*
);
/* Buffer type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
buf_T
*
buf
;
}
BufferObject
;
#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
#define BufferType_Check(obj) ((obj)->ob_type == &BufferType)
static
PyObject
*
BufferNew
(
buf_T
*
);
static
void
BufferDestructor
(
PyObject
*
);
static
PyObject
*
BufferGetattr
(
PyObject
*
,
char
*
);
static
PyObject
*
BufferRepr
(
PyObject
*
);
...
...
@@ -842,53 +802,15 @@ static PyObject *BufferSlice(PyObject *, PyInt, PyInt);
static
PyInt
BufferAssItem
(
PyObject
*
,
PyInt
,
PyObject
*
);
static
PyInt
BufferAssSlice
(
PyObject
*
,
PyInt
,
PyInt
,
PyObject
*
);
static
PyObject
*
BufferAppend
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
BufferMark
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
BufferRange
(
PyObject
*
,
PyObject
*
);
/* Line range type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
BufferObject
*
buf
;
PyInt
start
;
PyInt
end
;
}
RangeObject
;
#define RangeType_Check(obj) ((obj)->ob_type == &RangeType)
static
PyObject
*
RangeNew
(
buf_T
*
,
PyInt
,
PyInt
);
static
void
RangeDestructor
(
PyObject
*
);
static
PyObject
*
RangeGetattr
(
PyObject
*
,
char
*
);
static
PyObject
*
RangeRepr
(
PyObject
*
);
static
PyInt
RangeLength
(
PyObject
*
);
static
PyObject
*
RangeItem
(
PyObject
*
,
PyInt
);
static
PyObject
*
RangeSlice
(
PyObject
*
,
PyInt
,
PyInt
);
static
PyInt
RangeAssItem
(
PyObject
*
,
PyInt
,
PyObject
*
);
static
PyInt
RangeAssSlice
(
PyObject
*
,
PyInt
,
PyInt
,
PyObject
*
);
static
PyObject
*
RangeAppend
(
PyObject
*
,
PyObject
*
);
/* Window list type - Implementation functions
* -------------------------------------------
*/
static
PyInt
WinListLength
(
PyObject
*
);
static
PyObject
*
WinListItem
(
PyObject
*
,
PyInt
);
/* Buffer list type - Implementation functions
* -------------------------------------------
*/
static
PyInt
BufListLength
(
PyObject
*
);
static
PyObject
*
BufListItem
(
PyObject
*
,
PyInt
);
/* Current objects type - Implementation functions
* -----------------------------------------------
*/
...
...
@@ -896,286 +818,10 @@ static PyObject *BufListItem(PyObject *, PyInt);
static
PyObject
*
CurrentGetattr
(
PyObject
*
,
char
*
);
static
int
CurrentSetattr
(
PyObject
*
,
char
*
,
PyObject
*
);
/* Vim module - Definitions
*/
static
struct
PyMethodDef
VimMethods
[]
=
{
/* name, function, calling, documentation */
{
"command"
,
VimCommand
,
1
,
"Execute a Vim ex-mode command"
},
{
"eval"
,
VimEval
,
1
,
"Evaluate an expression using Vim evaluator"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
/* Vim module - Implementation
*/
static
PyObject
*
VimCommand
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
char
*
cmd
;
PyObject
*
result
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
cmd
))
return
NULL
;
PyErr_Clear
();
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
do_cmdline_cmd
((
char_u
*
)
cmd
);
update_screen
(
VALID
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
VimErrorCheck
())
result
=
NULL
;
else
result
=
Py_None
;
Py_XINCREF
(
result
);
return
result
;
}
#ifdef FEAT_EVAL
/*
* Function to translate a typval_T into a PyObject; this will recursively
* translate lists/dictionaries into their Python equivalents.
*
* The depth parameter is to avoid infinite recursion, set it to 1 when
* you call VimToPython.
*/
static
PyObject
*
VimToPython
(
typval_T
*
our_tv
,
int
depth
,
PyObject
*
lookupDict
)
{
PyObject
*
result
;
PyObject
*
newObj
;
char
ptrBuf
[
NUMBUFLEN
];
/* Avoid infinite recursion */
if
(
depth
>
100
)
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
return
result
;
}
/* Check if we run into a recursive loop. The item must be in lookupDict
* then and we can use it again. */
if
((
our_tv
->
v_type
==
VAR_LIST
&&
our_tv
->
vval
.
v_list
!=
NULL
)
||
(
our_tv
->
v_type
==
VAR_DICT
&&
our_tv
->
vval
.
v_dict
!=
NULL
))
{
sprintf
(
ptrBuf
,
PRINTF_DECIMAL_LONG_U
,
our_tv
->
v_type
==
VAR_LIST
?
(
long_u
)
our_tv
->
vval
.
v_list
:
(
long_u
)
our_tv
->
vval
.
v_dict
);
result
=
PyDict_GetItemString
(
lookupDict
,
ptrBuf
);
if
(
result
!=
NULL
)
{
Py_INCREF
(
result
);
return
result
;
}
}
if
(
our_tv
->
v_type
==
VAR_STRING
)
{
result
=
Py_BuildValue
(
"s"
,
our_tv
->
vval
.
v_string
);
}
else
if
(
our_tv
->
v_type
==
VAR_NUMBER
)
{
char
buf
[
NUMBUFLEN
];
/* For backwards compatibility numbers are stored as strings. */
sprintf
(
buf
,
"%ld"
,
(
long
)
our_tv
->
vval
.
v_number
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# ifdef FEAT_FLOAT
else
if
(
our_tv
->
v_type
==
VAR_FLOAT
)
{
char
buf
[
NUMBUFLEN
];
sprintf
(
buf
,
"%f"
,
our_tv
->
vval
.
v_float
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# endif
else
if
(
our_tv
->
v_type
==
VAR_LIST
)
{
list_T
*
list
=
our_tv
->
vval
.
v_list
;
listitem_T
*
curr
;
result
=
PyList_New
(
0
);
if
(
list
!=
NULL
)
{
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
curr
=
list
->
lv_first
;
curr
!=
NULL
;
curr
=
curr
->
li_next
)
{
newObj
=
VimToPython
(
&
curr
->
li_tv
,
depth
+
1
,
lookupDict
);
PyList_Append
(
result
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
else
if
(
our_tv
->
v_type
==
VAR_DICT
)
{
result
=
PyDict_New
();
if
(
our_tv
->
vval
.
v_dict
!=
NULL
)
{
hashtab_T
*
ht
=
&
our_tv
->
vval
.
v_dict
->
dv_hashtab
;
long_u
todo
=
ht
->
ht_used
;
hashitem_T
*
hi
;
dictitem_T
*
di
;
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
hi
=
ht
->
ht_array
;
todo
>
0
;
++
hi
)
{
if
(
!
HASHITEM_EMPTY
(
hi
))
{
--
todo
;
di
=
dict_lookup
(
hi
);
newObj
=
VimToPython
(
&
di
->
di_tv
,
depth
+
1
,
lookupDict
);
PyDict_SetItemString
(
result
,
(
char
*
)
hi
->
hi_key
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
}
else
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
}
return
result
;
}
#endif
static
PyObject
*
VimEval
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
#ifdef FEAT_EVAL
char
*
expr
;
typval_T
*
our_tv
;
PyObject
*
result
;
PyObject
*
lookup_dict
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
expr
))
return
NULL
;
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
our_tv
=
eval_expr
((
char_u
*
)
expr
,
NULL
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
our_tv
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid expression"
));
return
NULL
;
}
/* Convert the Vim type into a Python type. Create a dictionary that's
* used to check for recursive loops. */
lookup_dict
=
PyDict_New
();
result
=
VimToPython
(
our_tv
,
1
,
lookup_dict
);
Py_DECREF
(
lookup_dict
);
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
free_tv
(
our_tv
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
return
result
;
#else
PyErr_SetVim
(
_
(
"expressions disabled at compile time"
));
return
NULL
;
#endif
}
/* Common routines for buffers and line ranges
* -------------------------------------------
*/
static
int
CheckBuffer
(
BufferObject
*
this
)
{
if
(
this
->
buf
==
INVALID_BUFFER_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted buffer"
));
return
-
1
;
}
return
0
;
}
static
PyObject
*
RBItem
(
BufferObject
*
self
,
PyInt
n
,
PyInt
start
,
PyInt
end
)
{
if
(
CheckBuffer
(
self
))
return
NULL
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
NULL
;
}
return
GetBufferLine
(
self
->
buf
,
n
+
start
);
}
static
PyObject
*
RBSlice
(
BufferObject
*
self
,
PyInt
lo
,
PyInt
hi
,
PyInt
start
,
PyInt
end
)
{
PyInt
size
;
if
(
CheckBuffer
(
self
))
return
NULL
;
size
=
end
-
start
+
1
;
if
(
lo
<
0
)
lo
=
0
;
else
if
(
lo
>
size
)
lo
=
size
;
if
(
hi
<
0
)
hi
=
0
;
if
(
hi
<
lo
)
hi
=
lo
;
else
if
(
hi
>
size
)
hi
=
size
;
return
GetBufferLineList
(
self
->
buf
,
lo
+
start
,
hi
+
start
);
}
static
PyInt
RBAssItem
(
BufferObject
*
self
,
PyInt
n
,
PyObject
*
val
,
PyInt
start
,
PyInt
end
,
PyInt
*
new_end
)
{
PyInt
len_change
;
if
(
CheckBuffer
(
self
))
return
-
1
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
-
1
;
}
if
(
SetBufferLine
(
self
->
buf
,
n
+
start
,
val
,
&
len_change
)
==
FAIL
)
return
-
1
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
return
0
;
}
static
PyInt
RBAssSlice
(
BufferObject
*
self
,
PyInt
lo
,
PyInt
hi
,
PyObject
*
val
,
PyInt
start
,
PyInt
end
,
PyInt
*
new_end
)
{
...
...
@@ -1200,7 +846,8 @@ RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, P
else
if
(
hi
>
size
)
hi
=
size
;
if
(
SetBufferLineList
(
self
->
buf
,
lo
+
start
,
hi
+
start
,
val
,
&
len_change
)
==
FAIL
)
if
(
SetBufferLineList
(
self
->
buf
,
lo
+
start
,
hi
+
start
,
val
,
&
len_change
)
==
FAIL
)
return
-
1
;
if
(
new_end
)
...
...
@@ -1209,50 +856,6 @@ RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, P
return
0
;
}
static
PyObject
*
RBAppend
(
BufferObject
*
self
,
PyObject
*
args
,
PyInt
start
,
PyInt
end
,
PyInt
*
new_end
)
{
PyObject
*
lines
;
PyInt
len_change
;
PyInt
max
;
PyInt
n
;
if
(
CheckBuffer
(
self
))
return
NULL
;
max
=
n
=
end
-
start
+
1
;
if
(
!
PyArg_ParseTuple
(
args
,
"O|"
Py_ssize_t_fmt
,
&
lines
,
&
n
))
return
NULL
;
if
(
n
<
0
||
n
>
max
)
{
PyErr_SetString
(
PyExc_ValueError
,
_
(
"line number out of range"
));
return
NULL
;
}
if
(
InsertBufferLines
(
self
->
buf
,
n
+
start
-
1
,
lines
,
&
len_change
)
==
FAIL
)
return
NULL
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/* Buffer object - Definitions
*/
static
struct
PyMethodDef
BufferMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
BufferAppend
,
1
,
"Append data to Vim buffer"
},
{
"mark"
,
BufferMark
,
1
,
"Return (row,col) representing position of named mark"
},
{
"range"
,
BufferRange
,
1
,
"Return a range object which represents the part of the given buffer between line numbers s and e"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PySequenceMethods
BufferAsSeq
=
{
(
PyInquiry
)
BufferLength
,
/* sq_length, len(x) */
(
binaryfunc
)
0
,
/* BufferConcat, */
/* sq_concat, x+y */
...
...
@@ -1412,7 +1015,7 @@ BufferSlice(PyObject *self, PyInt lo, PyInt hi)
static
PyInt
BufferAssItem
(
PyObject
*
self
,
PyInt
n
,
PyObject
*
val
)
{
return
RBAs
s
Item
((
BufferObject
*
)(
self
),
n
,
val
,
1
,
return
RBAsItem
((
BufferObject
*
)(
self
),
n
,
val
,
1
,
(
PyInt
)((
BufferObject
*
)(
self
))
->
buf
->
b_ml
.
ml_line_count
,
NULL
);
}
...
...
@@ -1425,218 +1028,43 @@ BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
NULL
);
}
static
PyObject
*
BufferAppend
(
PyObject
*
self
,
PyObject
*
args
)
static
PySequenceMethods
RangeAsSeq
=
{
(
PyInquiry
)
RangeLength
,
/* sq_length, len(x) */
(
binaryfunc
)
0
,
/* RangeConcat, */
/* sq_concat, x+y */
(
PyIntArgFunc
)
0
,
/* RangeRepeat, */
/* sq_repeat, x*n */
(
PyIntArgFunc
)
RangeItem
,
/* sq_item, x[i] */
(
PyIntIntArgFunc
)
RangeSlice
,
/* sq_slice, x[i:j] */
(
PyIntObjArgProc
)
RangeAssItem
,
/* sq_ass_item, x[i]=v */
(
PyIntIntObjArgProc
)
RangeAssSlice
,
/* sq_ass_slice, x[i:j]=v */
};
/* Line range object - Implementation
*/
static
void
RangeDestructor
(
PyObject
*
self
)
{
return
RBAppend
((
BufferObject
*
)(
self
),
args
,
1
,
(
PyInt
)((
BufferObject
*
)(
self
))
->
buf
->
b_ml
.
ml_line_count
,
NULL
);
Py_DECREF
(((
RangeObject
*
)(
self
))
->
buf
);
Py_DECREF
(
self
);
}
static
PyObject
*
BufferMark
(
PyObject
*
self
,
PyObject
*
args
)
RangeGetattr
(
PyObject
*
self
,
char
*
name
)
{
pos_T
*
posp
;
char
mark
;
buf_T
*
curbuf_save
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"c"
,
&
mark
))
return
NULL
;
curbuf_save
=
curbuf
;
curbuf
=
((
BufferObject
*
)(
self
))
->
buf
;
posp
=
getmark
(
mark
,
FALSE
);
curbuf
=
curbuf_save
;
if
(
posp
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid mark name"
));
return
NULL
;
}
/* Ckeck for keyboard interrupt */
if
(
VimErrorCheck
())
return
NULL
;
if
(
posp
->
lnum
<=
0
)
{
/* Or raise an error? */
Py_INCREF
(
Py_None
);
return
Py_None
;
}
return
Py_BuildValue
(
"(ll)"
,
(
long
)(
posp
->
lnum
),
(
long
)(
posp
->
col
));
}
static
PyObject
*
BufferRange
(
PyObject
*
self
,
PyObject
*
args
)
{
PyInt
start
;
PyInt
end
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
Py_ssize_t_fmt
Py_ssize_t_fmt
,
&
start
,
&
end
))
return
NULL
;
return
RangeNew
(((
BufferObject
*
)(
self
))
->
buf
,
start
,
end
);
}
/* Line range object - Definitions
*/
static
struct
PyMethodDef
RangeMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
RangeAppend
,
1
,
"Append data to the Vim range"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PySequenceMethods
RangeAsSeq
=
{
(
PyInquiry
)
RangeLength
,
/* sq_length, len(x) */
(
binaryfunc
)
0
,
/* RangeConcat, */
/* sq_concat, x+y */
(
PyIntArgFunc
)
0
,
/* RangeRepeat, */
/* sq_repeat, x*n */
(
PyIntArgFunc
)
RangeItem
,
/* sq_item, x[i] */
(
PyIntIntArgFunc
)
RangeSlice
,
/* sq_slice, x[i:j] */
(
PyIntObjArgProc
)
RangeAssItem
,
/* sq_ass_item, x[i]=v */
(
PyIntIntObjArgProc
)
RangeAssSlice
,
/* sq_ass_slice, x[i:j]=v */
};
static
PyTypeObject
RangeType
=
{
PyObject_HEAD_INIT
(
0
)
0
,
"range"
,
sizeof
(
RangeObject
),
0
,
(
destructor
)
RangeDestructor
,
/* tp_dealloc, refcount==0 */
(
printfunc
)
0
,
/* tp_print, print x */
(
getattrfunc
)
RangeGetattr
,
/* tp_getattr, x.attr */
(
setattrfunc
)
0
,
/* tp_setattr, x.attr=v */
(
cmpfunc
)
0
,
/* tp_compare, x>y */
(
reprfunc
)
RangeRepr
,
/* tp_repr, `x`, print x */
0
,
/* as number */
&
RangeAsSeq
,
/* as sequence */
0
,
/* as mapping */
(
hashfunc
)
0
,
/* tp_hash, dict(x) */
(
ternaryfunc
)
0
,
/* tp_call, x() */
(
reprfunc
)
0
,
/* tp_str, str(x) */
};
/* Line range object - Implementation
*/
static
PyObject
*
RangeNew
(
buf_T
*
buf
,
PyInt
start
,
PyInt
end
)
{
BufferObject
*
bufr
;
RangeObject
*
self
;
self
=
PyObject_NEW
(
RangeObject
,
&
RangeType
);
if
(
self
==
NULL
)
return
NULL
;
bufr
=
(
BufferObject
*
)
BufferNew
(
buf
);
if
(
bufr
==
NULL
)
{
Py_DECREF
(
self
);
return
NULL
;
}
Py_INCREF
(
bufr
);
self
->
buf
=
bufr
;
self
->
start
=
start
;
self
->
end
=
end
;
return
(
PyObject
*
)(
self
);
}
static
void
RangeDestructor
(
PyObject
*
self
)
{
Py_DECREF
(((
RangeObject
*
)(
self
))
->
buf
);
Py_DECREF
(
self
);
}
static
PyObject
*
RangeGetattr
(
PyObject
*
self
,
char
*
name
)
{
if
(
strcmp
(
name
,
"start"
)
==
0
)
return
Py_BuildValue
(
Py_ssize_t_fmt
,
((
RangeObject
*
)(
self
))
->
start
-
1
);
else
if
(
strcmp
(
name
,
"end"
)
==
0
)
return
Py_BuildValue
(
Py_ssize_t_fmt
,
((
RangeObject
*
)(
self
))
->
end
-
1
);
else
return
Py_FindMethod
(
RangeMethods
,
self
,
name
);
}
static
PyObject
*
RangeRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
RangeObject
*
this
=
(
RangeObject
*
)(
self
);
if
(
this
->
buf
->
buf
==
INVALID_BUFFER_VALUE
)
{
vim_snprintf
(
repr
,
100
,
"<range object (for deleted buffer) at %p>"
,
(
self
));
return
PyString_FromString
(
repr
);
}
else
{
char
*
name
=
(
char
*
)
this
->
buf
->
buf
->
b_fname
;
int
len
;
if
(
name
==
NULL
)
name
=
""
;
len
=
(
int
)
strlen
(
name
);
if
(
len
>
45
)
name
=
name
+
(
45
-
len
);
vim_snprintf
(
repr
,
100
,
"<range %s%s (%d:%d)>"
,
len
>
45
?
"..."
:
""
,
name
,
this
->
start
,
this
->
end
);
return
PyString_FromString
(
repr
);
}
}
if
(
strcmp
(
name
,
"start"
)
==
0
)
return
Py_BuildValue
(
Py_ssize_t_fmt
,
((
RangeObject
*
)(
self
))
->
start
-
1
);
else
if
(
strcmp
(
name
,
"end"
)
==
0
)
return
Py_BuildValue
(
Py_ssize_t_fmt
,
((
RangeObject
*
)(
self
))
->
end
-
1
);
else
return
Py_FindMethod
(
RangeMethods
,
self
,
name
);
}
/****************/
static
PyInt
RangeLength
(
PyObject
*
self
)
{
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
if
(
CheckBuffer
(((
RangeObject
*
)(
self
))
->
buf
))
return
-
1
;
/* ??? */
return
(((
RangeObject
*
)(
self
))
->
end
-
((
RangeObject
*
)(
self
))
->
start
+
1
);
}
static
PyObject
*
RangeItem
(
PyObject
*
self
,
PyInt
n
)
{
return
RBItem
(((
RangeObject
*
)(
self
))
->
buf
,
n
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyObject
*
RangeSlice
(
PyObject
*
self
,
PyInt
lo
,
PyInt
hi
)
{
return
RBSlice
(((
RangeObject
*
)(
self
))
->
buf
,
lo
,
hi
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyInt
RangeAssItem
(
PyObject
*
self
,
PyInt
n
,
PyObject
*
val
)
{
return
RBAs
s
Item
(((
RangeObject
*
)(
self
))
->
buf
,
n
,
val
,
return
RBAsItem
(((
RangeObject
*
)(
self
))
->
buf
,
n
,
val
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
,
&
((
RangeObject
*
)(
self
))
->
end
);
...
...
@@ -1651,23 +1079,13 @@ RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
&
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyObject
*
RangeAppend
(
PyObject
*
self
,
PyObject
*
args
)
{
return
RBAppend
(((
RangeObject
*
)(
self
))
->
buf
,
args
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
,
&
((
RangeObject
*
)(
self
))
->
end
);
}
/* Buffer list object - Definitions
*/
typedef
struct
{
PyObject_HEAD
}
BufListObject
;
}
BufListObject
;
static
PySequenceMethods
BufListAsSeq
=
{
(
PyInquiry
)
BufListLength
,
/* sq_length, len(x) */
...
...
@@ -1702,39 +1120,6 @@ static PyTypeObject BufListType = {
(
reprfunc
)
0
,
/* tp_str, str(x) */
};
/* Buffer list object - Implementation
*/
static
PyInt
BufListLength
(
PyObject
*
self
UNUSED
)
{
buf_T
*
b
=
firstbuf
;
PyInt
n
=
0
;
while
(
b
)
{
++
n
;
b
=
b
->
b_next
;
}
return
n
;
}
static
PyObject
*
BufListItem
(
PyObject
*
self
UNUSED
,
PyInt
n
)
{
buf_T
*
b
;
for
(
b
=
firstbuf
;
b
;
b
=
b
->
b_next
,
--
n
)
{
if
(
n
==
0
)
return
BufferNew
(
b
);
}
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such buffer"
));
return
NULL
;
}
/* Window object - Definitions
*/
...
...
@@ -1814,18 +1199,6 @@ WindowDestructor(PyObject *self)
Py_DECREF
(
self
);
}
static
int
CheckWindow
(
WindowObject
*
this
)
{
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted window"
));
return
-
1
;
}
return
0
;
}
static
PyObject
*
WindowGetattr
(
PyObject
*
self
,
char
*
name
)
{
...
...
@@ -1854,134 +1227,6 @@ WindowGetattr(PyObject *self, char *name)
return
Py_FindMethod
(
WindowMethods
,
self
,
name
);
}
static
int
WindowSetattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
val
)
{
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
if
(
CheckWindow
(
this
))
return
-
1
;
if
(
strcmp
(
name
,
"buffer"
)
==
0
)
{
PyErr_SetString
(
PyExc_TypeError
,
_
(
"readonly attribute"
));
return
-
1
;
}
else
if
(
strcmp
(
name
,
"cursor"
)
==
0
)
{
long
lnum
;
long
col
;
long
len
;
if
(
!
PyArg_Parse
(
val
,
"(ll)"
,
&
lnum
,
&
col
))
return
-
1
;
if
(
lnum
<=
0
||
lnum
>
this
->
win
->
w_buffer
->
b_ml
.
ml_line_count
)
{
PyErr_SetVim
(
_
(
"cursor position outside buffer"
));
return
-
1
;
}
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
/* When column is out of range silently correct it. */
len
=
(
long
)
STRLEN
(
ml_get_buf
(
this
->
win
->
w_buffer
,
lnum
,
FALSE
));
if
(
col
>
len
)
col
=
len
;
this
->
win
->
w_cursor
.
lnum
=
lnum
;
this
->
win
->
w_cursor
.
col
=
col
;
#ifdef FEAT_VIRTUALEDIT
this
->
win
->
w_cursor
.
coladd
=
0
;
#endif
update_screen
(
VALID
);
return
0
;
}
else
if
(
strcmp
(
name
,
"height"
)
==
0
)
{
int
height
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
height
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setheight
(
height
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#ifdef FEAT_VERTSPLIT
else
if
(
strcmp
(
name
,
"width"
)
==
0
)
{
int
width
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
width
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setwidth
(
width
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#endif
else
{
PyErr_SetString
(
PyExc_AttributeError
,
name
);
return
-
1
;
}
}
static
PyObject
*
WindowRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
vim_snprintf
(
repr
,
100
,
_
(
"<window object (deleted) at %p>"
),
(
self
));
return
PyString_FromString
(
repr
);
}
else
{
int
i
=
0
;
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
&&
w
!=
this
->
win
;
w
=
W_NEXT
(
w
))
++
i
;
if
(
w
==
NULL
)
vim_snprintf
(
repr
,
100
,
_
(
"<window object (unknown) at %p>"
),
(
self
));
else
vim_snprintf
(
repr
,
100
,
_
(
"<window %d>"
),
i
);
return
PyString_FromString
(
repr
);
}
}
/* Window list object - Definitions
*/
...
...
@@ -2024,44 +1269,13 @@ static PyTypeObject WinListType = {
(
reprfunc
)
0
,
/* tp_str, str(x) */
};
/* Window list object - Implementation
*/
static
PyInt
WinListLength
(
PyObject
*
self
UNUSED
)
{
win_T
*
w
=
firstwin
;
PyInt
n
=
0
;
while
(
w
!=
NULL
)
{
++
n
;
w
=
W_NEXT
(
w
);
}
return
n
;
}
static
PyObject
*
WinListItem
(
PyObject
*
self
UNUSED
,
PyInt
n
)
{
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
;
w
=
W_NEXT
(
w
),
--
n
)
if
(
n
==
0
)
return
WindowNew
(
w
);
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such window"
));
return
NULL
;
}
/* Current items object - Definitions
*/
typedef
struct
{
PyObject_HEAD
}
CurrentObject
;
}
CurrentObject
;
static
PyTypeObject
CurrentType
=
{
PyObject_HEAD_INIT
(
0
)
...
...
@@ -2206,178 +1420,6 @@ PythonMod_Init(void)
* 4. Utility functions for handling the interface between Vim and Python.
*/
/* Get a line from the specified buffer. The line number is
* in Vim format (1-based). The line is returned as a Python
* string object.
*/
static
PyObject
*
GetBufferLine
(
buf_T
*
buf
,
PyInt
n
)
{
return
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)
n
,
FALSE
));
}
/* Get a list of lines from the specified buffer. The line numbers
* are in Vim format (1-based). The range is from lo up to, but not
* including, hi. The list is returned as a Python list of string objects.
*/
static
PyObject
*
GetBufferLineList
(
buf_T
*
buf
,
PyInt
lo
,
PyInt
hi
)
{
PyInt
i
;
PyInt
n
=
hi
-
lo
;
PyObject
*
list
=
PyList_New
(
n
);
if
(
list
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
n
;
++
i
)
{
PyObject
*
str
=
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)(
lo
+
i
),
FALSE
));
/* Error check - was the Python string creation OK? */
if
(
str
==
NULL
)
{
Py_DECREF
(
list
);
return
NULL
;
}
/* Set the list item */
if
(
PyList_SetItem
(
list
,
i
,
str
))
{
Py_DECREF
(
str
);
Py_DECREF
(
list
);
return
NULL
;
}
}
/* The ownership of the Python list is passed to the caller (ie,
* the caller should Py_DECREF() the object when it is finished
* with it).
*/
return
list
;
}
/*
* 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
py_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
();
}
/* Replace a line in the specified buffer. The line number is
* in Vim format (1-based). The replacement line is given as
* a Python string object. The object is checked for validity
* and correct format. Errors are returned as a value of FAIL.
* The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
SetBufferLine
(
buf_T
*
buf
,
PyInt
n
,
PyObject
*
line
,
PyInt
*
len_change
)
{
/* First of all, we check the thpe of the supplied Python object.
* There are three cases:
* 1. NULL, or None - this is a deletion.
* 2. A string - this is a replacement.
* 3. Anything else - this is an error.
*/
if
(
line
==
Py_None
||
line
==
NULL
)
{
buf_T
*
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savedel
((
linenr_T
)
n
,
1L
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_delete
((
linenr_T
)
n
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot delete line"
));
else
{
if
(
buf
==
curwin
->
w_buffer
)
py_fix_cursor
((
linenr_T
)
n
,
(
linenr_T
)
n
+
1
,
(
linenr_T
)
-
1
);
deleted_lines_mark
((
linenr_T
)
n
,
1L
);
}
curbuf
=
savebuf
;
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
-
1
;
return
OK
;
}
else
if
(
PyString_Check
(
line
))
{
char
*
save
=
StringToLine
(
line
);
buf_T
*
savebuf
=
curbuf
;
if
(
save
==
NULL
)
return
FAIL
;
/* We do not need to free "save" if ml_replace() consumes it. */
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savesub
((
linenr_T
)
n
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot save undo information"
));
vim_free
(
save
);
}
else
if
(
ml_replace
((
linenr_T
)
n
,
(
char_u
*
)
save
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot replace line"
));
vim_free
(
save
);
}
else
changed_bytes
((
linenr_T
)
n
,
0
);
curbuf
=
savebuf
;
/* Check that the cursor is not beyond the end of the line now. */
if
(
buf
==
curwin
->
w_buffer
)
check_cursor_col
();
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
0
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/* Replace a range of lines in the specified buffer. The line numbers are in
* Vim format (1-based). The range is from lo up to, but not including, hi.
* The replacement lines are given as a Python list of string objects. The
...
...
@@ -2566,131 +1608,6 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
}
}
/* Insert a number of lines into the specified buffer after the specifed line.
* The line number is in Vim format (1-based). The lines to be inserted are
* given as a Python list of string objects or as a single string. The lines
* to be added are checked for validity and correct format. Errors are
* returned as a value of FAIL. The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
InsertBufferLines
(
buf_T
*
buf
,
PyInt
n
,
PyObject
*
lines
,
PyInt
*
len_change
)
{
/* First of all, we check the type of the supplied Python object.
* It must be a string or a list, or the call is in error.
*/
if
(
PyString_Check
(
lines
))
{
char
*
str
=
StringToLine
(
lines
);
buf_T
*
savebuf
;
if
(
str
==
NULL
)
return
FAIL
;
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_append
((
linenr_T
)
n
,
(
char_u
*
)
str
,
0
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot insert line"
));
else
appended_lines_mark
((
linenr_T
)
n
,
1L
);
vim_free
(
str
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
1
;
return
OK
;
}
else
if
(
PyList_Check
(
lines
))
{
PyInt
i
;
PyInt
size
=
PyList_Size
(
lines
);
char
**
array
;
buf_T
*
savebuf
;
array
=
(
char
**
)
alloc
((
unsigned
)(
size
*
sizeof
(
char
*
)));
if
(
array
==
NULL
)
{
PyErr_NoMemory
();
return
FAIL
;
}
for
(
i
=
0
;
i
<
size
;
++
i
)
{
PyObject
*
line
=
PyList_GetItem
(
lines
,
i
);
array
[
i
]
=
StringToLine
(
line
);
if
(
array
[
i
]
==
NULL
)
{
while
(
i
)
vim_free
(
array
[
--
i
]);
vim_free
(
array
);
return
FAIL
;
}
}
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
{
for
(
i
=
0
;
i
<
size
;
++
i
)
{
if
(
ml_append
((
linenr_T
)(
n
+
i
),
(
char_u
*
)
array
[
i
],
0
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot insert line"
));
/* Free the rest of the lines */
while
(
i
<
size
)
vim_free
(
array
[
i
++
]);
break
;
}
vim_free
(
array
[
i
]);
}
if
(
i
>
0
)
appended_lines_mark
((
linenr_T
)
n
,
(
long
)
i
);
}
/* Free the array of lines. All of its contents have now
* been freed.
*/
vim_free
(
array
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
size
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/* Convert a Vim line into a Python string.
* All internal newlines are replaced by null characters.
*
...
...
@@ -2727,73 +1644,6 @@ LineToString(const char *str)
return
result
;
}
/* Convert a Python string into a Vim line.
*
* The result is in allocated memory. All internal nulls are replaced by
* newline characters. It is an error for the string to contain newline
* characters.
*
* On errors, the Python exception data is set, and NULL is returned.
*/
static
char
*
StringToLine
(
PyObject
*
obj
)
{
const
char
*
str
;
char
*
save
;
PyInt
len
;
PyInt
i
;
char
*
p
;
if
(
obj
==
NULL
||
!
PyString_Check
(
obj
))
{
PyErr_BadArgument
();
return
NULL
;
}
str
=
PyString_AsString
(
obj
);
len
=
PyString_Size
(
obj
);
/*
* Error checking: String must not contain newlines, as we
* are replacing a single line, and we must replace it with
* a single line.
* A trailing newline is removed, so that append(f.readlines()) works.
*/
p
=
memchr
(
str
,
'\n'
,
len
);
if
(
p
!=
NULL
)
{
if
(
p
==
str
+
len
-
1
)
--
len
;
else
{
PyErr_SetVim
(
_
(
"string cannot contain newlines"
));
return
NULL
;
}
}
/* Create a copy of the string, with internal nulls replaced by
* newline characters, as is the vim convention.
*/
save
=
(
char
*
)
alloc
((
unsigned
)(
len
+
1
));
if
(
save
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
for
(
i
=
0
;
i
<
len
;
++
i
)
{
if
(
str
[
i
]
==
'\0'
)
save
[
i
]
=
'\n'
;
else
save
[
i
]
=
str
[
i
];
}
save
[
i
]
=
'\0'
;
return
save
;
}
/* Don't generate a prototype for the next function, it generates an error on
* newer Python versions. */
...
...
@@ -2814,4 +1664,12 @@ init_structs(void)
OutputType
.
tp_basicsize
=
sizeof
(
OutputObject
);
OutputType
.
tp_getattr
=
OutputGetattr
;
OutputType
.
tp_setattr
=
OutputSetattr
;
vim_memset
(
&
RangeType
,
0
,
sizeof
(
RangeType
));
RangeType
.
tp_name
=
"range"
;
RangeType
.
tp_basicsize
=
sizeof
(
RangeObject
);
RangeType
.
tp_dealloc
=
RangeDestructor
;
RangeType
.
tp_getattr
=
RangeGetattr
;
RangeType
.
tp_repr
=
RangeRepr
;
RangeType
.
tp_as_sequence
=
&
RangeAsSeq
;
}
This diff is collapsed.
Click to expand it.
src/if_python3.c
+
18
−
1161
View file @
ca8a4dfe
...
...
@@ -69,6 +69,10 @@
static
void
init_structs
(
void
);
#define PyInt Py_ssize_t
#define PyString_Check(obj) PyUnicode_Check(obj)
#define PyString_AsString(obj) _PyUnicode_AsString(obj)
#define PyString_Size(obj) PyUnicode_GET_SIZE(obj)
#define PyString_FromString(repr) PyUnicode_FromString(repr)
#if defined(DYNAMIC_PYTHON3)
...
...
@@ -424,6 +428,12 @@ get_py3_exceptions()
}
#endif
/* DYNAMIC_PYTHON3 */
static
PyObject
*
BufferNew
(
buf_T
*
);
static
PyObject
*
WindowNew
(
win_T
*
);
static
PyObject
*
LineToString
(
const
char
*
);
static
PyTypeObject
RangeType
;
/*
* Include the code shared with if_python.c
*/
...
...
@@ -455,36 +465,19 @@ call_PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
* Internal function prototypes.
*/
static
void
DoPy3Command
(
exarg_T
*
,
const
char
*
);
static
Py_ssize_t
RangeStart
;
static
Py_ssize_t
RangeEnd
;
static
void
PythonIO_Flush
(
void
);
static
int
PythonIO_Init
(
void
);
static
void
PythonIO_Fini
(
void
);
PyMODINIT_FUNC
Py3Init_vim
(
void
);
/* Utility functions for the vim/python interface
* ----------------------------------------------
*/
static
PyObject
*
GetBufferLine
(
buf_T
*
,
Py_ssize_t
);
static
int
SetBufferLine
(
buf_T
*
,
Py_ssize_t
,
PyObject
*
,
Py_ssize_t
*
);
static
int
InsertBufferLines
(
buf_T
*
,
Py_ssize_t
,
PyObject
*
,
Py_ssize_t
*
);
static
PyObject
*
GetBufferLineList
(
buf_T
*
buf
,
Py_ssize_t
lo
,
Py_ssize_t
hi
);
static
PyObject
*
LineToString
(
const
char
*
);
static
char
*
StringToLine
(
PyObject
*
);
#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
/******************************************************
* 1. Python interpreter main program.
*/
static
int
py3initialised
=
0
;
static
PyGILState_STATE
pygilstate
=
PyGILState_UNLOCKED
;
void
...
...
@@ -732,11 +725,6 @@ ex_py3file(exarg_T *eap)
/* Implementation functions
*/
static
PyObject
*
OutputGetattro
(
PyObject
*
,
PyObject
*
);
static
int
OutputSetattro
(
PyObject
*
,
PyObject
*
,
PyObject
*
);
/*************/
static
PyObject
*
OutputGetattro
(
PyObject
*
self
,
PyObject
*
nameobj
)
{
...
...
@@ -797,439 +785,37 @@ PythonIO_Fini(void)
* 3. Implementation of the Vim module for Python
*/
/* Vim module - Implementation functions
* -------------------------------------
*/
static
PyObject
*
VimCommand
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
VimEval
(
PyObject
*
,
PyObject
*
);
/* Window type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
win_T
*
win
;
}
WindowObject
;
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
#define WindowType_Check(obj) ((obj)->ob_base.ob_type == &WindowType)
static
PyObject
*
WindowNew
(
win_T
*
);
static
void
WindowDestructor
(
PyObject
*
);
static
PyObject
*
WindowGetattro
(
PyObject
*
,
PyObject
*
);
static
int
WindowSetattro
(
PyObject
*
,
PyObject
*
,
PyObject
*
);
static
PyObject
*
WindowRepr
(
PyObject
*
);
/* Buffer type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
buf_T
*
buf
;
}
BufferObject
;
#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
#define BufferType_Check(obj) ((obj)->ob_base.ob_type == &BufferType)
static
PyObject
*
BufferNew
(
buf_T
*
);
static
void
BufferDestructor
(
PyObject
*
);
static
PyObject
*
BufferGetattro
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
BufferRepr
(
PyObject
*
);
static
Py_ssize_t
BufferLength
(
PyObject
*
);
static
PyObject
*
BufferItem
(
PyObject
*
,
Py_ssize_t
);
static
Py_ssize_t
BufferAsItem
(
PyObject
*
,
Py_ssize_t
,
PyObject
*
);
static
PyObject
*
BufferSubscript
(
PyObject
*
self
,
PyObject
*
idx
);
static
PyObject
*
BufferAppend
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
BufferMark
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
BufferRange
(
PyObject
*
,
PyObject
*
);
/* Line range type - Implementation functions
* --------------------------------------
*/
typedef
struct
{
PyObject_HEAD
BufferObject
*
buf
;
Py_ssize_t
start
;
Py_ssize_t
end
;
}
RangeObject
;
#define RangeType_Check(obj) ((obj)->ob_base.ob_type == &RangeType)
static
PyObject
*
RangeNew
(
buf_T
*
,
Py_ssize_t
,
Py_ssize_t
);
static
void
RangeDestructor
(
PyObject
*
);
static
PyObject
*
RangeGetattro
(
PyObject
*
,
PyObject
*
);
static
PyObject
*
RangeRepr
(
PyObject
*
);
static
PyObject
*
RangeSubscript
(
PyObject
*
self
,
PyObject
*
idx
);
static
Py_ssize_t
RangeLength
(
PyObject
*
);
static
PyObject
*
RangeItem
(
PyObject
*
,
Py_ssize_t
);
static
Py_ssize_t
RangeAsItem
(
PyObject
*
,
Py_ssize_t
,
PyObject
*
);
static
PyObject
*
RangeAppend
(
PyObject
*
,
PyObject
*
);
/* Window list type - Implementation functions
* -------------------------------------------
*/
static
Py_ssize_t
WinListLength
(
PyObject
*
);
static
PyObject
*
WinListItem
(
PyObject
*
,
Py_ssize_t
);
/* Buffer list type - Implementation functions
* -------------------------------------------
*/
static
Py_ssize_t
BufListLength
(
PyObject
*
);
static
PyObject
*
BufListItem
(
PyObject
*
,
Py_ssize_t
);
/* Current objects type - Implementation functions
* -----------------------------------------------
*/
static
PyObject
*
CurrentGetattro
(
PyObject
*
,
PyObject
*
);
static
int
CurrentSetattro
(
PyObject
*
,
PyObject
*
,
PyObject
*
);
/* Vim module - Definitions
*/
static
struct
PyMethodDef
VimMethods
[]
=
{
/* name, function, calling, documentation */
{
"command"
,
VimCommand
,
1
,
"Execute a Vim ex-mode command"
},
{
"eval"
,
VimEval
,
1
,
"Evaluate an expression using Vim evaluator"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
/* Vim module - Implementation
*/
static
PyObject
*
VimCommand
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
char
*
cmd
;
PyObject
*
result
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
cmd
))
return
NULL
;
PyErr_Clear
();
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
do_cmdline_cmd
((
char_u
*
)
cmd
);
update_screen
(
VALID
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
VimErrorCheck
())
result
=
NULL
;
else
result
=
Py_None
;
Py_XINCREF
(
result
);
return
result
;
}
#ifdef FEAT_EVAL
/*
* Function to translate a typval_T into a PyObject; this will recursively
* translate lists/dictionaries into their Python equivalents.
*
* The depth parameter is to avoid infinite recursion, set it to 1 when
* you call VimToPython.
*/
static
PyObject
*
VimToPython
(
typval_T
*
our_tv
,
int
depth
,
PyObject
*
lookupDict
)
{
PyObject
*
result
;
PyObject
*
newObj
;
char
ptrBuf
[
NUMBUFLEN
];
/* Avoid infinite recursion */
if
(
depth
>
100
)
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
return
result
;
}
/* Check if we run into a recursive loop. The item must be in lookupDict
* then and we can use it again. */
if
((
our_tv
->
v_type
==
VAR_LIST
&&
our_tv
->
vval
.
v_list
!=
NULL
)
||
(
our_tv
->
v_type
==
VAR_DICT
&&
our_tv
->
vval
.
v_dict
!=
NULL
))
{
sprintf
(
ptrBuf
,
PRINTF_DECIMAL_LONG_U
,
our_tv
->
v_type
==
VAR_LIST
?
(
long_u
)
our_tv
->
vval
.
v_list
:
(
long_u
)
our_tv
->
vval
.
v_dict
);
result
=
PyDict_GetItemString
(
lookupDict
,
ptrBuf
);
if
(
result
!=
NULL
)
{
Py_INCREF
(
result
);
return
result
;
}
}
if
(
our_tv
->
v_type
==
VAR_STRING
)
{
result
=
Py_BuildValue
(
"s"
,
our_tv
->
vval
.
v_string
);
}
else
if
(
our_tv
->
v_type
==
VAR_NUMBER
)
{
char
buf
[
NUMBUFLEN
];
/* For backwards compatibility numbers are stored as strings. */
sprintf
(
buf
,
"%ld"
,
(
long
)
our_tv
->
vval
.
v_number
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# ifdef FEAT_FLOAT
else
if
(
our_tv
->
v_type
==
VAR_FLOAT
)
{
char
buf
[
NUMBUFLEN
];
sprintf
(
buf
,
"%f"
,
our_tv
->
vval
.
v_float
);
result
=
Py_BuildValue
(
"s"
,
buf
);
}
# endif
else
if
(
our_tv
->
v_type
==
VAR_LIST
)
{
list_T
*
list
=
our_tv
->
vval
.
v_list
;
listitem_T
*
curr
;
result
=
PyList_New
(
0
);
if
(
list
!=
NULL
)
{
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
curr
=
list
->
lv_first
;
curr
!=
NULL
;
curr
=
curr
->
li_next
)
{
newObj
=
VimToPython
(
&
curr
->
li_tv
,
depth
+
1
,
lookupDict
);
PyList_Append
(
result
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
else
if
(
our_tv
->
v_type
==
VAR_DICT
)
{
result
=
PyDict_New
();
if
(
our_tv
->
vval
.
v_dict
!=
NULL
)
{
hashtab_T
*
ht
=
&
our_tv
->
vval
.
v_dict
->
dv_hashtab
;
long_u
todo
=
ht
->
ht_used
;
hashitem_T
*
hi
;
dictitem_T
*
di
;
PyDict_SetItemString
(
lookupDict
,
ptrBuf
,
result
);
for
(
hi
=
ht
->
ht_array
;
todo
>
0
;
++
hi
)
{
if
(
!
HASHITEM_EMPTY
(
hi
))
{
--
todo
;
di
=
dict_lookup
(
hi
);
newObj
=
VimToPython
(
&
di
->
di_tv
,
depth
+
1
,
lookupDict
);
PyDict_SetItemString
(
result
,
(
char
*
)
hi
->
hi_key
,
newObj
);
Py_DECREF
(
newObj
);
}
}
}
}
else
{
Py_INCREF
(
Py_None
);
result
=
Py_None
;
}
return
result
;
}
#endif
static
PyObject
*
VimEval
(
PyObject
*
self
UNUSED
,
PyObject
*
args
)
{
#ifdef FEAT_EVAL
char
*
expr
;
typval_T
*
our_tv
;
PyObject
*
result
;
PyObject
*
lookup_dict
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
expr
))
return
NULL
;
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
our_tv
=
eval_expr
((
char_u
*
)
expr
,
NULL
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
if
(
our_tv
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid expression"
));
return
NULL
;
}
/* Convert the Vim type into a Python type. Create a dictionary that's
* used to check for recursive loops. */
lookup_dict
=
PyDict_New
();
result
=
VimToPython
(
our_tv
,
1
,
lookup_dict
);
Py_DECREF
(
lookup_dict
);
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim
();
free_tv
(
our_tv
);
Python_Release_Vim
();
Py_END_ALLOW_THREADS
return
result
;
#else
PyErr_SetVim
(
_
(
"expressions disabled at compile time"
));
return
NULL
;
#endif
}
/* Common routines for buffers and line ranges
* -------------------------------------------
*/
static
int
CheckBuffer
(
BufferObject
*
this
)
{
if
(
this
->
buf
==
INVALID_BUFFER_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted buffer"
));
return
-
1
;
}
return
0
;
}
static
PyObject
*
RBItem
(
BufferObject
*
self
,
Py_ssize_t
n
,
Py_ssize_t
start
,
Py_ssize_t
end
)
{
if
(
CheckBuffer
(
self
))
return
NULL
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
NULL
;
}
return
GetBufferLine
(
self
->
buf
,
n
+
start
);
}
static
PyObject
*
RBSlice
(
BufferObject
*
self
,
Py_ssize_t
lo
,
Py_ssize_t
hi
,
Py_ssize_t
start
,
Py_ssize_t
end
)
{
Py_ssize_t
size
;
if
(
CheckBuffer
(
self
))
return
NULL
;
size
=
end
-
start
+
1
;
if
(
lo
<
0
)
lo
=
0
;
else
if
(
lo
>
size
)
lo
=
size
;
if
(
hi
<
0
)
hi
=
0
;
if
(
hi
<
lo
)
hi
=
lo
;
else
if
(
hi
>
size
)
hi
=
size
;
return
GetBufferLineList
(
self
->
buf
,
lo
+
start
,
hi
+
start
);
}
static
Py_ssize_t
RBAsItem
(
BufferObject
*
self
,
Py_ssize_t
n
,
PyObject
*
val
,
Py_ssize_t
start
,
Py_ssize_t
end
,
Py_ssize_t
*
new_end
)
{
Py_ssize_t
len_change
;
if
(
CheckBuffer
(
self
))
return
-
1
;
if
(
n
<
0
||
n
>
end
-
start
)
{
PyErr_SetString
(
PyExc_IndexError
,
_
(
"line number out of range"
));
return
-
1
;
}
if
(
SetBufferLine
(
self
->
buf
,
n
+
start
,
val
,
&
len_change
)
==
FAIL
)
return
-
1
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
return
0
;
}
static
PyObject
*
RBAppend
(
BufferObject
*
self
,
PyObject
*
args
,
Py_ssize_t
start
,
Py_ssize_t
end
,
Py_ssize_t
*
new_end
)
{
PyObject
*
lines
;
Py_ssize_t
len_change
;
Py_ssize_t
max
;
Py_ssize_t
n
;
if
(
CheckBuffer
(
self
))
return
NULL
;
max
=
n
=
end
-
start
+
1
;
if
(
!
PyArg_ParseTuple
(
args
,
"O|n"
,
&
lines
,
&
n
))
return
NULL
;
if
(
n
<
0
||
n
>
max
)
{
PyErr_SetString
(
PyExc_ValueError
,
_
(
"line number out of range"
));
return
NULL
;
}
if
(
InsertBufferLines
(
self
->
buf
,
n
+
start
-
1
,
lines
,
&
len_change
)
==
FAIL
)
return
NULL
;
if
(
new_end
)
*
new_end
=
end
+
len_change
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/* Buffer object - Definitions
*/
static
struct
PyMethodDef
BufferMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
BufferAppend
,
1
,
"Append data to Vim buffer"
},
{
"mark"
,
BufferMark
,
1
,
"Return (row,col) representing position of named mark"
},
{
"range"
,
BufferRange
,
1
,
"Return a range object which represents the part of the given buffer between line numbers s and e"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PySequenceMethods
BufferAsSeq
=
{
(
lenfunc
)
BufferLength
,
/* sq_length, len(x) */
(
binaryfunc
)
0
,
/* sq_concat, x+y */
...
...
@@ -1407,78 +993,6 @@ BufferSubscript(PyObject *self, PyObject* idx)
}
}
static
PyObject
*
BufferAppend
(
PyObject
*
self
,
PyObject
*
args
)
{
return
RBAppend
((
BufferObject
*
)(
self
),
args
,
1
,
(
Py_ssize_t
)((
BufferObject
*
)(
self
))
->
buf
->
b_ml
.
ml_line_count
,
NULL
);
}
static
PyObject
*
BufferMark
(
PyObject
*
self
,
PyObject
*
args
)
{
pos_T
*
posp
;
char
*
pmark
;
//test
char
mark
;
buf_T
*
curbuf_save
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"s"
,
&
pmark
))
//test: "c"->"s"
return
NULL
;
mark
=
*
pmark
;
//test
curbuf_save
=
curbuf
;
curbuf
=
((
BufferObject
*
)(
self
))
->
buf
;
posp
=
getmark
(
mark
,
FALSE
);
curbuf
=
curbuf_save
;
if
(
posp
==
NULL
)
{
PyErr_SetVim
(
_
(
"invalid mark name"
));
return
NULL
;
}
/* Ckeck for keyboard interrupt */
if
(
VimErrorCheck
())
return
NULL
;
if
(
posp
->
lnum
<=
0
)
{
/* Or raise an error? */
Py_INCREF
(
Py_None
);
return
Py_None
;
}
return
Py_BuildValue
(
"(ll)"
,
(
long
)(
posp
->
lnum
),
(
long
)(
posp
->
col
));
}
static
PyObject
*
BufferRange
(
PyObject
*
self
,
PyObject
*
args
)
{
Py_ssize_t
start
;
Py_ssize_t
end
;
if
(
CheckBuffer
((
BufferObject
*
)(
self
)))
return
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"nn"
,
&
start
,
&
end
))
return
NULL
;
return
RangeNew
(((
BufferObject
*
)(
self
))
->
buf
,
start
,
end
);
}
/* Line range object - Definitions
*/
static
struct
PyMethodDef
RangeMethods
[]
=
{
/* name, function, calling, documentation */
{
"append"
,
RangeAppend
,
1
,
"Append data to the Vim range"
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PySequenceMethods
RangeAsSeq
=
{
(
lenfunc
)
RangeLength
,
/* sq_length, len(x) */
(
binaryfunc
)
0
,
/* RangeConcat, sq_concat, x+y */
...
...
@@ -1498,40 +1012,14 @@ PyMappingMethods RangeAsMapping = {
/* mp_ass_subscript */
(
objobjargproc
)
0
,
};
static
PyTypeObject
RangeType
;
/* Line range object - Implementation
*/
static
PyObject
*
Range
New
(
buf_T
*
buf
,
Py_ssize_t
start
,
Py_ssize_t
end
)
static
void
Range
Destructor
(
PyObject
*
self
)
{
BufferObject
*
bufr
;
RangeObject
*
self
;
self
=
PyObject_NEW
(
RangeObject
,
&
RangeType
);
if
(
self
==
NULL
)
return
NULL
;
bufr
=
(
BufferObject
*
)
BufferNew
(
buf
);
if
(
bufr
==
NULL
)
{
Py_DECREF
(
self
);
return
NULL
;
}
Py_INCREF
(
bufr
);
self
->
buf
=
bufr
;
self
->
start
=
start
;
self
->
end
=
end
;
return
(
PyObject
*
)(
self
);
}
static
void
RangeDestructor
(
PyObject
*
self
)
{
Py_DECREF
(((
RangeObject
*
)(
self
))
->
buf
);
}
Py_DECREF
(((
RangeObject
*
)(
self
))
->
buf
);
}
static
PyObject
*
RangeGetattro
(
PyObject
*
self
,
PyObject
*
nameobj
)
...
...
@@ -1548,58 +1036,8 @@ RangeGetattro(PyObject *self, PyObject *nameobj)
return
PyObject_GenericGetAttr
(
self
,
nameobj
);
}
static
PyObject
*
RangeRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
RangeObject
*
this
=
(
RangeObject
*
)(
self
);
if
(
this
->
buf
->
buf
==
INVALID_BUFFER_VALUE
)
{
vim_snprintf
(
repr
,
100
,
"<range object (for deleted buffer) at %p>"
,
(
self
));
return
PyUnicode_FromString
(
repr
);
}
else
{
char
*
name
=
(
char
*
)
this
->
buf
->
buf
->
b_fname
;
int
len
;
if
(
name
==
NULL
)
name
=
""
;
len
=
(
int
)
strlen
(
name
);
if
(
len
>
45
)
name
=
name
+
(
45
-
len
);
vim_snprintf
(
repr
,
100
,
"<range %s%s (%d:%d)>"
,
len
>
45
?
"..."
:
""
,
name
,
this
->
start
,
this
->
end
);
return
PyUnicode_FromString
(
repr
);
}
}
/****************/
static
Py_ssize_t
RangeLength
(
PyObject
*
self
)
{
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
if
(
CheckBuffer
(((
RangeObject
*
)(
self
))
->
buf
))
return
-
1
;
/* ??? */
return
(((
RangeObject
*
)(
self
))
->
end
-
((
RangeObject
*
)(
self
))
->
start
+
1
);
}
static
PyObject
*
RangeItem
(
PyObject
*
self
,
Py_ssize_t
n
)
{
return
RBItem
(((
RangeObject
*
)(
self
))
->
buf
,
n
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
static
Py_ssize_t
RangeAsItem
(
PyObject
*
self
,
Py_ssize_t
n
,
PyObject
*
val
)
{
...
...
@@ -1609,14 +1047,6 @@ RangeAsItem(PyObject *self, Py_ssize_t n, PyObject *val)
&
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyObject
*
RangeSlice
(
PyObject
*
self
,
Py_ssize_t
lo
,
Py_ssize_t
hi
)
{
return
RBSlice
(((
RangeObject
*
)(
self
))
->
buf
,
lo
,
hi
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
);
}
static
PyObject
*
RangeSubscript
(
PyObject
*
self
,
PyObject
*
idx
)
{
...
...
@@ -1639,23 +1069,13 @@ RangeSubscript(PyObject *self, PyObject* idx)
}
}
static
PyObject
*
RangeAppend
(
PyObject
*
self
,
PyObject
*
args
)
{
return
RBAppend
(((
RangeObject
*
)(
self
))
->
buf
,
args
,
((
RangeObject
*
)(
self
))
->
start
,
((
RangeObject
*
)(
self
))
->
end
,
&
((
RangeObject
*
)(
self
))
->
end
);
}
/* Buffer list object - Definitions
*/
typedef
struct
{
PyObject_HEAD
}
BufListObject
;
}
BufListObject
;
static
PySequenceMethods
BufListAsSeq
=
{
(
lenfunc
)
BufListLength
,
/* sq_length, len(x) */
...
...
@@ -1672,39 +1092,6 @@ static PySequenceMethods BufListAsSeq = {
static
PyTypeObject
BufListType
;
/* Buffer list object - Implementation
*/
static
Py_ssize_t
BufListLength
(
PyObject
*
self
UNUSED
)
{
buf_T
*
b
=
firstbuf
;
Py_ssize_t
n
=
0
;
while
(
b
)
{
++
n
;
b
=
b
->
b_next
;
}
return
n
;
}
static
PyObject
*
BufListItem
(
PyObject
*
self
UNUSED
,
Py_ssize_t
n
)
{
buf_T
*
b
;
for
(
b
=
firstbuf
;
b
;
b
=
b
->
b_next
,
--
n
)
{
if
(
n
==
0
)
return
BufferNew
(
b
);
}
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such buffer"
));
return
NULL
;
}
/* Window object - Definitions
*/
...
...
@@ -1761,18 +1148,6 @@ WindowDestructor(PyObject *self)
this
->
win
->
w_python3_ref
=
NULL
;
}
static
int
CheckWindow
(
WindowObject
*
this
)
{
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
PyErr_SetVim
(
_
(
"attempt to refer to deleted window"
));
return
-
1
;
}
return
0
;
}
static
PyObject
*
WindowGetattro
(
PyObject
*
self
,
PyObject
*
nameobj
)
{
...
...
@@ -1809,134 +1184,12 @@ WindowGetattro(PyObject *self, PyObject *nameobj)
static
int
WindowSetattro
(
PyObject
*
self
,
PyObject
*
nameobj
,
PyObject
*
val
)
{
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
char
*
name
=
""
;
if
(
PyUnicode_Check
(
nameobj
))
name
=
_PyUnicode_AsString
(
nameobj
);
if
(
CheckWindow
(
this
))
return
-
1
;
if
(
strcmp
(
name
,
"buffer"
)
==
0
)
{
PyErr_SetString
(
PyExc_TypeError
,
_
(
"readonly attribute"
));
return
-
1
;
}
else
if
(
strcmp
(
name
,
"cursor"
)
==
0
)
{
long
lnum
;
long
col
;
long
len
;
if
(
!
PyArg_Parse
(
val
,
"(ll)"
,
&
lnum
,
&
col
))
return
-
1
;
if
(
lnum
<=
0
||
lnum
>
this
->
win
->
w_buffer
->
b_ml
.
ml_line_count
)
{
PyErr_SetVim
(
_
(
"cursor position outside buffer"
));
return
-
1
;
}
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
/* When column is out of range silently correct it. */
len
=
(
long
)
STRLEN
(
ml_get_buf
(
this
->
win
->
w_buffer
,
lnum
,
FALSE
));
if
(
col
>
len
)
col
=
len
;
this
->
win
->
w_cursor
.
lnum
=
lnum
;
this
->
win
->
w_cursor
.
col
=
col
;
#ifdef FEAT_VIRTUALEDIT
this
->
win
->
w_cursor
.
coladd
=
0
;
#endif
update_screen
(
VALID
);
return
0
;
}
else
if
(
strcmp
(
name
,
"height"
)
==
0
)
{
int
height
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
height
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setheight
(
height
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#ifdef FEAT_VERTSPLIT
else
if
(
strcmp
(
name
,
"width"
)
==
0
)
{
int
width
;
win_T
*
savewin
;
if
(
!
PyArg_Parse
(
val
,
"i"
,
&
width
))
return
-
1
;
#ifdef FEAT_GUI
need_mouse_correct
=
TRUE
;
#endif
savewin
=
curwin
;
curwin
=
this
->
win
;
win_setwidth
(
width
);
curwin
=
savewin
;
/* Check for keyboard interrupts */
if
(
VimErrorCheck
())
return
-
1
;
return
0
;
}
#endif
else
{
PyErr_SetString
(
PyExc_AttributeError
,
name
);
return
-
1
;
}
}
static
PyObject
*
WindowRepr
(
PyObject
*
self
)
{
static
char
repr
[
100
];
WindowObject
*
this
=
(
WindowObject
*
)(
self
);
if
(
this
->
win
==
INVALID_WINDOW_VALUE
)
{
vim_snprintf
(
repr
,
100
,
_
(
"<window object (deleted) at %p>"
),
(
self
));
return
PyUnicode_FromString
(
repr
);
}
else
{
int
i
=
0
;
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
&&
w
!=
this
->
win
;
w
=
W_NEXT
(
w
))
++
i
;
if
(
w
==
NULL
)
vim_snprintf
(
repr
,
100
,
_
(
"<window object (unknown) at %p>"
),
(
self
));
else
vim_snprintf
(
repr
,
100
,
_
(
"<window %d>"
),
i
);
return
PyUnicode_FromString
(
repr
);
}
return
WindowSetattr
(
self
,
name
,
val
);
}
/* Window list object - Definitions
...
...
@@ -1963,44 +1216,13 @@ static PySequenceMethods WinListAsSeq = {
static
PyTypeObject
WinListType
;
/* Window list object - Implementation
*/
static
Py_ssize_t
WinListLength
(
PyObject
*
self
UNUSED
)
{
win_T
*
w
=
firstwin
;
Py_ssize_t
n
=
0
;
while
(
w
!=
NULL
)
{
++
n
;
w
=
W_NEXT
(
w
);
}
return
n
;
}
static
PyObject
*
WinListItem
(
PyObject
*
self
UNUSED
,
Py_ssize_t
n
)
{
win_T
*
w
;
for
(
w
=
firstwin
;
w
!=
NULL
;
w
=
W_NEXT
(
w
),
--
n
)
if
(
n
==
0
)
return
WindowNew
(
w
);
PyErr_SetString
(
PyExc_IndexError
,
_
(
"no such window"
));
return
NULL
;
}
/* Current items object - Definitions
*/
typedef
struct
{
PyObject_HEAD
}
CurrentObject
;
}
CurrentObject
;
static
PyTypeObject
CurrentType
;
...
...
@@ -2137,304 +1359,6 @@ PyMODINIT_FUNC Py3Init_vim(void)
* 4. Utility functions for handling the interface between Vim and Python.
*/
/* Get a line from the specified buffer. The line number is
* in Vim format (1-based). The line is returned as a Python
* string object.
*/
static
PyObject
*
GetBufferLine
(
buf_T
*
buf
,
Py_ssize_t
n
)
{
return
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)
n
,
FALSE
));
}
/* Get a list of lines from the specified buffer. The line numbers
* are in Vim format (1-based). The range is from lo up to, but not
* including, hi. The list is returned as a Python list of string objects.
*/
static
PyObject
*
GetBufferLineList
(
buf_T
*
buf
,
Py_ssize_t
lo
,
Py_ssize_t
hi
)
{
Py_ssize_t
i
;
Py_ssize_t
n
=
hi
-
lo
;
PyObject
*
list
=
PyList_New
(
n
);
if
(
list
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
n
;
++
i
)
{
PyObject
*
str
=
LineToString
((
char
*
)
ml_get_buf
(
buf
,
(
linenr_T
)(
lo
+
i
),
FALSE
));
/* Error check - was the Python string creation OK? */
if
(
str
==
NULL
)
{
Py_DECREF
(
list
);
return
NULL
;
}
/* Set the list item */
if
(
PyList_SetItem
(
list
,
i
,
str
))
{
Py_DECREF
(
str
);
Py_DECREF
(
list
);
return
NULL
;
}
}
/* The ownership of the Python list is passed to the caller (ie,
* the caller should Py_DECREF() the object when it is finished
* with it).
*/
return
list
;
}
/*
* 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
py_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
();
}
/* Replace a line in the specified buffer. The line number is
* in Vim format (1-based). The replacement line is given as
* a Python string object. The object is checked for validity
* and correct format. Errors are returned as a value of FAIL.
* The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
SetBufferLine
(
buf_T
*
buf
,
Py_ssize_t
n
,
PyObject
*
line
,
Py_ssize_t
*
len_change
)
{
/* First of all, we check the thpe of the supplied Python object.
* There are three cases:
* 1. NULL, or None - this is a deletion.
* 2. A string - this is a replacement.
* 3. Anything else - this is an error.
*/
if
(
line
==
Py_None
||
line
==
NULL
)
{
buf_T
*
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savedel
((
linenr_T
)
n
,
1L
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_delete
((
linenr_T
)
n
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot delete line"
));
else
{
if
(
buf
==
curwin
->
w_buffer
)
py_fix_cursor
((
linenr_T
)
n
,
(
linenr_T
)
n
+
1
,
(
linenr_T
)
-
1
);
deleted_lines_mark
((
linenr_T
)
n
,
1L
);
}
curbuf
=
savebuf
;
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
-
1
;
return
OK
;
}
else
if
(
PyUnicode_Check
(
line
))
{
char
*
save
=
StringToLine
(
line
);
buf_T
*
savebuf
=
curbuf
;
if
(
save
==
NULL
)
return
FAIL
;
/* We do not need to free "save" if ml_replace() consumes it. */
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_savesub
((
linenr_T
)
n
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot save undo information"
));
vim_free
(
save
);
}
else
if
(
ml_replace
((
linenr_T
)
n
,
(
char_u
*
)
save
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot replace line"
));
vim_free
(
save
);
}
else
changed_bytes
((
linenr_T
)
n
,
0
);
curbuf
=
savebuf
;
/* Check that the cursor is not beyond the end of the line now. */
if
(
buf
==
curwin
->
w_buffer
)
check_cursor_col
();
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
0
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/* Insert a number of lines into the specified buffer after the specifed line.
* The line number is in Vim format (1-based). The lines to be inserted are
* given as a Python list of string objects or as a single string. The lines
* to be added are checked for validity and correct format. Errors are
* returned as a value of FAIL. The return value is OK on success.
* If OK is returned and len_change is not NULL, *len_change
* is set to the change in the buffer length.
*/
static
int
InsertBufferLines
(
buf_T
*
buf
,
Py_ssize_t
n
,
PyObject
*
lines
,
Py_ssize_t
*
len_change
)
{
/* First of all, we check the type of the supplied Python object.
* It must be a string or a list, or the call is in error.
*/
if
(
PyUnicode_Check
(
lines
))
{
char
*
str
=
StringToLine
(
lines
);
buf_T
*
savebuf
;
if
(
str
==
NULL
)
return
FAIL
;
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
if
(
ml_append
((
linenr_T
)
n
,
(
char_u
*
)
str
,
0
,
FALSE
)
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot insert line"
));
else
appended_lines_mark
((
linenr_T
)
n
,
1L
);
vim_free
(
str
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
1
;
return
OK
;
}
else
if
(
PyList_Check
(
lines
))
{
Py_ssize_t
i
;
Py_ssize_t
size
=
PyList_Size
(
lines
);
char
**
array
;
buf_T
*
savebuf
;
array
=
(
char
**
)
alloc
((
unsigned
)(
size
*
sizeof
(
char
*
)));
if
(
array
==
NULL
)
{
PyErr_NoMemory
();
return
FAIL
;
}
for
(
i
=
0
;
i
<
size
;
++
i
)
{
PyObject
*
line
=
PyList_GetItem
(
lines
,
i
);
array
[
i
]
=
StringToLine
(
line
);
if
(
array
[
i
]
==
NULL
)
{
while
(
i
)
vim_free
(
array
[
--
i
]);
vim_free
(
array
);
return
FAIL
;
}
}
savebuf
=
curbuf
;
PyErr_Clear
();
curbuf
=
buf
;
if
(
u_save
((
linenr_T
)
n
,
(
linenr_T
)(
n
+
1
))
==
FAIL
)
PyErr_SetVim
(
_
(
"cannot save undo information"
));
else
{
for
(
i
=
0
;
i
<
size
;
++
i
)
{
if
(
ml_append
((
linenr_T
)(
n
+
i
),
(
char_u
*
)
array
[
i
],
0
,
FALSE
)
==
FAIL
)
{
PyErr_SetVim
(
_
(
"cannot insert line"
));
/* Free the rest of the lines */
while
(
i
<
size
)
vim_free
(
array
[
i
++
]);
break
;
}
vim_free
(
array
[
i
]);
}
if
(
i
>
0
)
appended_lines_mark
((
linenr_T
)
n
,
(
long
)
i
);
}
/* Free the array of lines. All of its contents have now
* been freed.
*/
vim_free
(
array
);
curbuf
=
savebuf
;
update_screen
(
VALID
);
if
(
PyErr_Occurred
()
||
VimErrorCheck
())
return
FAIL
;
if
(
len_change
)
*
len_change
=
size
;
return
OK
;
}
else
{
PyErr_BadArgument
();
return
FAIL
;
}
}
/* Convert a Vim line into a Python string.
* All internal newlines are replaced by null characters.
*
...
...
@@ -2473,73 +1397,6 @@ LineToString(const char *str)
return
result
;
}
/* Convert a Python string into a Vim line.
*
* The result is in allocated memory. All internal nulls are replaced by
* newline characters. It is an error for the string to contain newline
* characters.
*
* On errors, the Python exception data is set, and NULL is returned.
*/
static
char
*
StringToLine
(
PyObject
*
obj
)
{
const
char
*
str
;
char
*
save
;
Py_ssize_t
len
;
Py_ssize_t
i
;
char
*
p
;
if
(
obj
==
NULL
||
!
PyUnicode_Check
(
obj
))
{
PyErr_BadArgument
();
return
NULL
;
}
str
=
_PyUnicode_AsString
(
obj
);
len
=
PyUnicode_GET_SIZE
(
obj
);
/*
* Error checking: String must not contain newlines, as we
* are replacing a single line, and we must replace it with
* a single line.
* A trailing newline is removed, so that append(f.readlines()) works.
*/
p
=
memchr
(
str
,
'\n'
,
len
);
if
(
p
!=
NULL
)
{
if
(
p
==
str
+
len
-
1
)
--
len
;
else
{
PyErr_SetVim
(
_
(
"string cannot contain newlines"
));
return
NULL
;
}
}
/* Create a copy of the string, with internal nulls replaced by
* newline characters, as is the vim convention.
*/
save
=
(
char
*
)
alloc
((
unsigned
)(
len
+
1
));
if
(
save
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
for
(
i
=
0
;
i
<
len
;
++
i
)
{
if
(
str
[
i
]
==
'\0'
)
save
[
i
]
=
'\n'
;
else
save
[
i
]
=
str
[
i
];
}
save
[
i
]
=
'\0'
;
return
save
;
}
static
void
init_structs
(
void
)
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment