163 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
						|
 | 
						|
/** \file
 | 
						|
 * \ingroup pythonintern
 | 
						|
 *
 | 
						|
 * This file extends the text editor with C/Python API methods and attributes.
 | 
						|
 */
 | 
						|
 | 
						|
#define PY_SSIZE_T_CLEAN
 | 
						|
 | 
						|
#include <Python.h>
 | 
						|
 | 
						|
#include "DNA_text_types.h"
 | 
						|
 | 
						|
#include "MEM_guardedalloc.h"
 | 
						|
 | 
						|
#include "WM_api.h"
 | 
						|
 | 
						|
#include "BKE_text.h"
 | 
						|
 | 
						|
#include "bpy_capi_utils.h"
 | 
						|
#include "bpy_rna.h"
 | 
						|
#include "bpy_rna_text.h"
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Data structures.
 | 
						|
 * \{ */
 | 
						|
 | 
						|
/**
 | 
						|
 * Struct representing a selection which is extracted from Python arguments.
 | 
						|
 */
 | 
						|
typedef struct TextRegion {
 | 
						|
  int curl;
 | 
						|
  int curc;
 | 
						|
  int sell;
 | 
						|
  int selc;
 | 
						|
} TextRegion;
 | 
						|
 | 
						|
/** \} */
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Text Editor Get / Set region text API
 | 
						|
 * \{ */
 | 
						|
 | 
						|
PyDoc_STRVAR(bpy_rna_region_as_string_doc,
 | 
						|
             ".. method:: region_as_string(range=None)\n"
 | 
						|
             "\n"
 | 
						|
             "   :arg range: The region of text to be returned, "
 | 
						|
             "defaulting to the selection when no range is passed.\n"
 | 
						|
             "      Each int pair represents a line and column: "
 | 
						|
             "((start_line, start_column), (end_line, end_column))\n"
 | 
						|
             "      The values match Python's slicing logic "
 | 
						|
             "(negative values count backwards from the end, the end value is not inclusive).\n"
 | 
						|
             "   :type range: Two pairs of ints\n"
 | 
						|
             "   :return: The specified region as a string.\n"
 | 
						|
             "   :rtype: str.\n");
 | 
						|
/* Receive a Python Tuple as parameter to represent the region range. */
 | 
						|
static PyObject *bpy_rna_region_as_string(PyObject *self, PyObject *args, PyObject *kwds)
 | 
						|
{
 | 
						|
  BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
 | 
						|
  Text *text = pyrna->ptr.data;
 | 
						|
  /* Parse the region range. */
 | 
						|
  TextRegion region;
 | 
						|
 | 
						|
  static const char *_keywords[] = {"range", NULL};
 | 
						|
  static _PyArg_Parser _parser = {
 | 
						|
      "|$"         /* Optional keyword only arguments. */
 | 
						|
      "((ii)(ii))" /* `range` */
 | 
						|
      ":region_as_string",
 | 
						|
      _keywords,
 | 
						|
      0,
 | 
						|
  };
 | 
						|
  if (!_PyArg_ParseTupleAndKeywordsFast(
 | 
						|
          args, kwds, &_parser, ®ion.curl, ®ion.curc, ®ion.sell, ®ion.selc)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (PyDict_GET_SIZE(kwds) > 0) {
 | 
						|
    txt_sel_set(text, region.curl, region.curc, region.sell, region.selc);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Return an empty string if there is no selection. */
 | 
						|
  if (!txt_has_sel(text)) {
 | 
						|
    return PyUnicode_FromString("");
 | 
						|
  }
 | 
						|
  char *buf = txt_sel_to_buf(text, NULL);
 | 
						|
  PyObject *sel_text = PyUnicode_FromString(buf);
 | 
						|
  MEM_freeN(buf);
 | 
						|
  /* Return the selected text. */
 | 
						|
  return sel_text;
 | 
						|
}
 | 
						|
 | 
						|
PyMethodDef BPY_rna_region_as_string_method_def = {
 | 
						|
    "region_as_string",
 | 
						|
    (PyCFunction)bpy_rna_region_as_string,
 | 
						|
    METH_VARARGS | METH_KEYWORDS,
 | 
						|
    bpy_rna_region_as_string_doc,
 | 
						|
};
 | 
						|
 | 
						|
PyDoc_STRVAR(bpy_rna_region_from_string_doc,
 | 
						|
             ".. method:: region_from_string(body, range=None)\n"
 | 
						|
             "\n"
 | 
						|
             "   :arg body: The text to be inserted.\n"
 | 
						|
             "   :type body: str\n"
 | 
						|
             "   :arg range: The region of text to be returned, "
 | 
						|
             "defaulting to the selection when no range is passed.\n"
 | 
						|
             "      Each int pair represents a line and column: "
 | 
						|
             "((start_line, start_column), (end_line, end_column))\n"
 | 
						|
             "      The values match Python's slicing logic "
 | 
						|
             "(negative values count backwards from the end, the end value is not inclusive).\n"
 | 
						|
             "   :type range: Two pairs of ints\n");
 | 
						|
static PyObject *bpy_rna_region_from_string(PyObject *self, PyObject *args, PyObject *kwds)
 | 
						|
{
 | 
						|
  BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
 | 
						|
  Text *text = pyrna->ptr.data;
 | 
						|
 | 
						|
  /* Parse the region range. */
 | 
						|
  const char *buf;
 | 
						|
  Py_ssize_t buf_len;
 | 
						|
  TextRegion region;
 | 
						|
 | 
						|
  static const char *_keywords[] = {"", "range", NULL};
 | 
						|
  static _PyArg_Parser _parser = {
 | 
						|
      "s#"         /* `buf` (positional). */
 | 
						|
      "|$"         /* Optional keyword only arguments. */
 | 
						|
      "((ii)(ii))" /* `range` */
 | 
						|
      ":region_from_string",
 | 
						|
      _keywords,
 | 
						|
      0,
 | 
						|
  };
 | 
						|
  if (!_PyArg_ParseTupleAndKeywordsFast(args,
 | 
						|
                                        kwds,
 | 
						|
                                        &_parser,
 | 
						|
                                        &buf,
 | 
						|
                                        &buf_len,
 | 
						|
                                        ®ion.curl,
 | 
						|
                                        ®ion.curc,
 | 
						|
                                        ®ion.sell,
 | 
						|
                                        ®ion.selc)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (PyDict_GET_SIZE(kwds) > 0) {
 | 
						|
    txt_sel_set(text, region.curl, region.curc, region.sell, region.selc);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Set the selected text. */
 | 
						|
  txt_insert_buf(text, buf, buf_len);
 | 
						|
  /* Update the text editor. */
 | 
						|
  WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
 | 
						|
 | 
						|
  Py_RETURN_NONE;
 | 
						|
}
 | 
						|
 | 
						|
PyMethodDef BPY_rna_region_from_string_method_def = {
 | 
						|
    "region_from_string",
 | 
						|
    (PyCFunction)bpy_rna_region_from_string,
 | 
						|
    METH_VARARGS | METH_KEYWORDS,
 | 
						|
    bpy_rna_region_from_string_doc,
 | 
						|
};
 | 
						|
 | 
						|
/** \} */
 |