⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_python.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
}

/* 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 *buf, int lo, int hi)
{
    int i;
    int 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;
}

/* 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 *buf, int n, PyObject *line, int *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 *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
	{
	    mark_adjust((linenr_t)n, (linenr_t)n, (long)MAXLNUM, -1L);
	    changed();
	}

	curbuf = savebuf;
	update_screen(NOT_VALID);

	if (PyErr_Occurred() || VimErrorCheck())
	    return FAIL;

	if (len_change)
	    *len_change = -1;

	return OK;
    }
    else if (PyString_Check(line))
    {
	char *save = StringToLine(line);
	BUF *savebuf = curbuf;

	if (save == NULL)
	    return FAIL;

	/* We do not need to free save, as we pass responsibility for
	 * it to vim, via the final parameter of ml_replace().
	 */
	PyErr_Clear();
	curbuf = buf;

	if (u_savesub((linenr_t)n) == FAIL)
	    PyErr_SetVim("cannot save undo information");
	else if (ml_replace((linenr_t)n, (char_u *)save, TRUE) == FAIL)
	    PyErr_SetVim("cannot replace line");
	else
	{
	    changed();
#ifdef SYNTAX_HL
	    syn_changed((linenr_t)n); /* recompute syntax hl. for this line */
#endif
	}

	curbuf = savebuf;
	update_screen(NOT_VALID);

	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
 * list 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
SetBufferLineList(BUF *buf, int lo, int hi, PyObject *list, int *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 list	   - this is a replacement.
     *	  3. Anything else - this is an error.
     */
    if (list == Py_None || list == NULL)
    {
	int i;
	int ok = 0;
	int n = hi - lo;
	BUF *savebuf = curbuf;

	PyErr_Clear();
	curbuf = buf;

	if (u_savedel((linenr_t)lo, (long)n) == FAIL)
	    PyErr_SetVim("cannot save undo information");
	else
	{
	    ok = 1;

	    for (i = 0; i < n; ++i)
	    {
		if (ml_delete((linenr_t)lo, FALSE) == FAIL)
		{
		    PyErr_SetVim("cannot delete line");
		    ok = 0;
		    break;
		}
		changed();
	    }
	}

	if (ok)
	    mark_adjust((linenr_t)lo, (linenr_t)(hi-1), (long)MAXLNUM,
								    (long)-n);

	curbuf = savebuf;
	update_screen(NOT_VALID);

	if (PyErr_Occurred() || VimErrorCheck())
	    return FAIL;

	if (len_change)
	    *len_change = -n;

	return OK;
    }
    else if (PyList_Check(list))
    {
	int i;
	int n = PyList_Size(list);
	int lines = hi - lo;
	char **array;
	BUF *savebuf;

	array = (char **)alloc((unsigned)(n * sizeof(char *)));
	if (array == NULL)
	{
	    PyErr_NoMemory();
	    return FAIL;
	}

	for (i = 0; i < n; ++i)
	{
	    PyObject *line = PyList_GetItem(list, 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)(lo-1), (linenr_t)hi) == FAIL)
	    PyErr_SetVim("cannot save undo information");

	/* If the size of the range is reducing (ie, n < lines) we
	 * need to delete some lines. We do this at the start, by
	 * repeatedly deleting line "lo".
	 */
	if (!PyErr_Occurred())
	{
	    for (i = 0; i < lines - n; ++i)
	    {
		if (ml_delete((linenr_t)lo, FALSE) == FAIL)
		{
		    PyErr_SetVim("cannot delete line");
		    break;
		}
		changed();
	    }
	}

	/* For as long as possible, replace the existing lines with the
	 * new lines. This is a more efficient operation, as it requires
	 * less memory allocation and freeing.
	 */
	if (!PyErr_Occurred())
	{
	    for (i = 0; i < lines && i < n; ++i)
	    {
		if (ml_replace((linenr_t)(lo+i), (char_u *)array[i], TRUE)
								      == FAIL)
		{
		    PyErr_SetVim("cannot replace line");
		    break;
		}
		changed();
#ifdef SYNTAX_HL
		/* recompute syntax hl. for this line */
		syn_changed((linenr_t)(lo+i));
#endif
	    }
	}

	/* Now we may need to insert the remaining new lines. If we do, we
	 * must free the strings as we finish with them (we can't pass the
	 * responsibility to vim in this case).
	 */
	if (!PyErr_Occurred())
	{
	    while (i < n)
	    {
		if (ml_append((linenr_t)(lo+i-1), (char_u *)array[i], 0, FALSE) == FAIL)
		{
		    PyErr_SetVim("cannot insert line");
		    break;
		}
		changed();
		vim_free(array[i]);
		++i;
	    }
	}

	/* Free any left-over lines, as a result of an error */
	while (i < n)
	{
	    vim_free(array[i]);
	    ++i;
	}

	/* Adjust marks. Invalidate any which lie in the
	 * changed range, and move any in the remainder of the buffer.
	 */
	if (!PyErr_Occurred())
	    mark_adjust((linenr_t)lo, (linenr_t)(hi-1), (long)MAXLNUM, (long)(n - lines));

	/* Free the array of lines. All of its contents have now
	 * been dealt with (either freed, or the responsibility passed
	 * to vim.
	 */
	vim_free(array);

	curbuf = savebuf;
	update_screen(NOT_VALID);

	if (PyErr_Occurred() || VimErrorCheck())
	    return FAIL;

	if (len_change)
	    *len_change = n - lines;

	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 *buf, int n, PyObject *lines, int *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 *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
	{
	    mark_adjust((linenr_t)(n+1), (linenr_t)MAXLNUM, 1L, 0L);
	    changed();
	}

	vim_free(str);
	curbuf = savebuf;
	update_screen(NOT_VALID);

	if (PyErr_Occurred() || VimErrorCheck())
	    return FAIL;

	if (len_change)
	    *len_change = 1;

	return OK;
    }
    else if (PyList_Check(lines))
    {
	int i;
	int ok = 0;
	int size = PyList_Size(lines);
	char **array;
	BUF *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
	{
	    ok = 1;
	    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");
		    ok = 0;

		    /* Free the rest of the lines */
		    while (i < size)
			vim_free(array[i++]);

		    break;
		}
		changed();
		vim_free(array[i]);
	    }
	}

	if (ok)
	    mark_adjust((linenr_t)(n+1), (linenr_t)MAXLNUM, (long)size, 0L);

	/* Free the array of lines. All of its contents have now
	 * been freed.
	 */
	vim_free(array);

	curbuf = savebuf;
	update_screen(NOT_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.
 *
 * On errors, the Python exception data is set, and NULL is returned.
 */
    static PyObject *
LineToString(const char *str)
{
    PyObject *result;
    int len = strlen(str);
    char *p;

    /* Allocate an Python string object, with uninitialised contents. We
     * must do it this way, so that we can modify the string in place
     * later. See the Python source, Objects/stringobject.c for details.
     */
    result = PyString_FromStringAndSize(NULL, len);
    if (result == NULL)
	return NULL;

    p = PyString_AsString(result);

    while (*str)
    {
	if (*str == '\n')
	    *p = '\0';
	else
	    *p = *str;

	++p;
	++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;
    int len;
    int i;

    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.
     */
    if (memchr(str, '\n', len))
    {
	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;
}

/* Check to see whether a Vim error has been reported, or a keyboard
 * interrupt has been detected.
 */
    static int
VimErrorCheck(void)
{
    if (got_int)
    {
	PyErr_SetNone(PyExc_KeyboardInterrupt);
	return 1;
    }
    else if (did_emsg && !PyErr_Occurred())
    {
	PyErr_SetNone(VimError);
	return 1;
    }

    return 0;
}


#if PYTHON_API_VERSION < 1007 /* Python 1.4 */

    char *
Py_GetProgramName(void)
{
    return "vim";
}
#endif /* Python 1.4 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -