1 #if defined(HAVE_CONFIG_H) && !defined(GEANYPY_WINDOWS)
2 # include "config.h"
3 #endif
4
5 #include "geanypy.h"
6
7
8 static void
Editor_dealloc(Editor * self)9 Editor_dealloc(Editor *self)
10 {
11 self->ob_type->tp_free((PyObject *) self);
12 }
13
14
15 static int
Editor_init(Editor * self)16 Editor_init(Editor *self)
17 {
18 self->editor = NULL;
19 return 0;
20 }
21
22
23 static PyObject *
Editor_get_property(Editor * self,const gchar * prop_name)24 Editor_get_property(Editor *self, const gchar *prop_name)
25 {
26 g_return_val_if_fail(self != NULL, NULL);
27 g_return_val_if_fail(prop_name != NULL, NULL);
28
29 if (!self->editor)
30 {
31 PyErr_SetString(PyExc_RuntimeError,
32 "Editor instance not initialized properly");
33 return NULL;
34 }
35
36 if (g_str_equal(prop_name, "eol_char"))
37 return PyString_FromString(editor_get_eol_char(self->editor));
38 else if (g_str_equal(prop_name, "eol_char_name"))
39 return PyString_FromString(editor_get_eol_char_name(self->editor));
40 else if (g_str_equal(prop_name, "indent_prefs"))
41 {
42 const GeanyIndentPrefs *indent_prefs;
43 IndentPrefs *py_prefs;
44 indent_prefs = editor_get_indent_prefs(self->editor);
45 if (indent_prefs)
46 {
47 py_prefs = IndentPrefs_create_new_from_geany_indent_prefs(
48 (GeanyIndentPrefs *) indent_prefs);
49 return (PyObject *) py_prefs;
50 }
51 Py_RETURN_NONE;
52 }
53 else if (g_str_equal(prop_name, "auto_indent"))
54 {
55 if (self->editor->auto_indent)
56 Py_RETURN_TRUE;
57 else
58 Py_RETURN_FALSE;
59 }
60 else if (g_str_equal(prop_name, "document"))
61 {
62 PyObject *py_doc;
63 py_doc = (PyObject *) Document_create_new_from_geany_document(
64 self->editor->document);
65 if (!py_doc || py_doc == Py_None)
66 Py_RETURN_NONE;
67 return py_doc;
68 }
69 else if (g_str_equal(prop_name, "line_breaking"))
70 {
71 if (self->editor->line_breaking)
72 Py_RETURN_TRUE;
73 else
74 Py_RETURN_FALSE;
75 }
76 else if (g_str_equal(prop_name, "line_wrapping"))
77 {
78 if (self->editor->line_wrapping)
79 Py_RETURN_TRUE;
80 else
81 Py_RETURN_FALSE;
82 }
83 else if (g_str_equal(prop_name, "scintilla"))
84 {
85 Scintilla *sci;
86 sci = Scintilla_create_new_from_scintilla(self->editor->sci);
87 if (!sci)
88 Py_RETURN_NONE;
89 return (PyObject *) sci;
90 }
91 else if (g_str_equal(prop_name, "scroll_percent"))
92 return PyFloat_FromDouble((gdouble) self->editor->scroll_percent);
93
94 PyErr_SetString(PyExc_AttributeError, "can't get property");
95 Py_RETURN_NONE;
96 }
97
98
99 static int
Editor_set_property(Editor * self,PyObject * value,const gchar * prop_name)100 Editor_set_property(Editor *self, PyObject *value, const gchar *prop_name)
101 {
102 g_return_val_if_fail(self != NULL, -1);
103 g_return_val_if_fail(value != NULL, -1);
104 g_return_val_if_fail(prop_name != NULL, -1);
105
106 if (!self->editor)
107 {
108 PyErr_SetString(PyExc_RuntimeError,
109 "Editor instance not initialized properly");
110 return -1;
111 }
112
113 if (g_str_equal(prop_name, "indent_type"))
114 {
115 long indent_type = PyInt_AsLong(value);
116 if (indent_type == -1 && PyErr_Occurred())
117 {
118 PyErr_Print();
119 return -1;
120 }
121 editor_set_indent_type(self->editor, (GeanyIndentType) indent_type);
122 return 0;
123 }
124
125 PyErr_SetString(PyExc_AttributeError, "can't set property");
126 return -1;
127 }
128
129
130 static PyObject *
Editor_create_widget(Editor * self)131 Editor_create_widget(Editor *self)
132 {
133 ScintillaObject *sci;
134 PyObject *pysci;
135
136 if (self->editor == NULL)
137 Py_RETURN_NONE;
138
139 sci = editor_create_widget(self->editor);
140 if (!sci)
141 Py_RETURN_NONE;
142
143 pysci = pygobject_new(G_OBJECT(sci));
144 if (!pysci)
145 {
146 gtk_widget_destroy(GTK_WIDGET(sci));
147 Py_RETURN_NONE;
148 }
149
150 return pysci;
151 }
152
153
154 static PyObject *
Editor_find_snippet(Editor * self,PyObject * args,PyObject * kwargs)155 Editor_find_snippet(Editor *self, PyObject *args, PyObject *kwargs)
156 {
157 gchar *name;
158 const gchar *snippet;
159 static gchar *kwlist[] = { "snippet_name", NULL };
160
161 if (PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
162 {
163 if (name != NULL)
164 {
165 snippet = editor_find_snippet(self->editor, name);
166 if (snippet != NULL)
167 return Py_BuildValue("s", snippet);
168 }
169 }
170 Py_RETURN_NONE;
171 }
172
173
174 static PyObject *
Editor_get_word_at_position(Editor * self,PyObject * args,PyObject * kwargs)175 Editor_get_word_at_position(Editor *self, PyObject *args, PyObject *kwargs)
176 {
177 gint pos = -1;
178 gchar *wordchars = NULL, *word = NULL;
179 PyObject *py_word;
180 static gchar *kwlist[] = { "pos", "wordchars", NULL };
181
182 if (PyArg_ParseTupleAndKeywords(args, kwargs, "|iz", kwlist, &pos, &wordchars))
183 {
184 word = editor_get_word_at_pos(self->editor, pos, wordchars);
185 if (word != NULL)
186 {
187 py_word = Py_BuildValue("s", word);
188 g_free(word);
189 return py_word;
190 }
191 }
192
193 Py_RETURN_NONE;
194 }
195
196
197 static PyObject *
Editor_goto_pos(Editor * self,PyObject * args,PyObject * kwargs)198 Editor_goto_pos(Editor *self, PyObject *args, PyObject *kwargs)
199 {
200 gint pos, mark = FALSE, result;
201 static gchar *kwlist[] = { "pos", "mark", NULL };
202
203 if (PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, &pos, &mark))
204 {
205 result = editor_goto_pos(self->editor, pos, mark);
206 if (result)
207 Py_RETURN_TRUE;
208 else
209 Py_RETURN_FALSE;
210 }
211 Py_RETURN_NONE;
212 }
213
214
215 static PyObject *
Editor_indicator_clear(Editor * self,PyObject * args,PyObject * kwargs)216 Editor_indicator_clear(Editor *self, PyObject *args, PyObject *kwargs)
217 {
218 gint indic;
219 static gchar *kwlist[] = { "indic", NULL };
220 if (PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &indic))
221 editor_indicator_clear(self->editor, indic);
222 Py_RETURN_NONE;
223 }
224
225
226 static PyObject *
Editor_indicator_set_on_line(Editor * self,PyObject * args,PyObject * kwargs)227 Editor_indicator_set_on_line(Editor *self, PyObject *args, PyObject *kwargs)
228 {
229 gint indic, line_num;
230 static gchar *kwlist[] = { "indic", "line", NULL };
231 if (PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &indic, &line_num))
232 editor_indicator_set_on_line(self->editor, indic, line_num);
233 Py_RETURN_NONE;
234 }
235
236
237 static PyObject *
Editor_indicator_set_on_range(Editor * self,PyObject * args,PyObject * kwargs)238 Editor_indicator_set_on_range(Editor *self, PyObject *args, PyObject *kwargs)
239 {
240 gint indic, start, end;
241 static gchar *kwlist[] = { "indic", "start", "end", NULL };
242 if (PyArg_ParseTupleAndKeywords(args, kwargs, "iii", kwlist, &indic, &start, &end))
243 editor_indicator_set_on_range(self->editor, indic, start, end);
244 Py_RETURN_NONE;
245 }
246
247
248 static PyObject *
Editor_insert_snippet(Editor * self,PyObject * args,PyObject * kwargs)249 Editor_insert_snippet(Editor *self, PyObject *args, PyObject *kwargs)
250 {
251 gint pos = 0;
252 gchar *snippet = NULL;
253 static gchar *kwlist[] = { "pos", "snippet", NULL };
254 if (PyArg_ParseTupleAndKeywords(args, kwargs, "is", kwlist, &pos, &snippet))
255 editor_insert_snippet(self->editor, pos, snippet);
256 Py_RETURN_NONE;
257 }
258
259
260 static PyObject *
Editor_insert_text_block(Editor * self,PyObject * args,PyObject * kwargs)261 Editor_insert_text_block(Editor *self, PyObject *args, PyObject *kwargs)
262 {
263 gchar *text = NULL;
264 gint insert_pos, cursor_index = -1, newline_indent_size = -1;
265 gint replace_newlines = 0;
266 static gchar *kwlist[] = { "text", "insert_pos", "cursor_index",
267 "newline_indent_size", "replace_newlines", NULL };
268
269 if (PyArg_ParseTupleAndKeywords(args, kwargs, "si|iii", kwlist, &text,
270 &insert_pos, &cursor_index, &newline_indent_size, &replace_newlines))
271 {
272 editor_insert_text_block(self->editor, text, insert_pos, cursor_index,
273 newline_indent_size, (gboolean) replace_newlines);
274 }
275
276 Py_RETURN_NONE;
277 }
278
279
280 static PyMethodDef Editor_methods[] = {
281 { "create_widget", (PyCFunction) Editor_create_widget, METH_NOARGS,
282 "Creates a new Scintilla widget based on the settings for "
283 "editor." },
284 { "find_snippet", (PyCFunction) Editor_find_snippet, METH_KEYWORDS,
285 "Get snippet by name." },
286 { "get_word_at_position", (PyCFunction) Editor_get_word_at_position, METH_KEYWORDS,
287 "Finds the word at the position specified." },
288 { "goto_pos", (PyCFunction) Editor_goto_pos, METH_KEYWORDS,
289 "Moves to position, switching to the current document if "
290 "necessary, setting a marker if mark is set." },
291 { "indicator_clear", (PyCFunction) Editor_indicator_clear, METH_KEYWORDS,
292 "Deletes all currently set indicators matching the specified "
293 "indicator in the editor." },
294 { "indicator_set_on_line", (PyCFunction) Editor_indicator_set_on_line, METH_KEYWORDS,
295 "Sets an indicator on the specified line." },
296 { "indicator_set_on_range", (PyCFunction) Editor_indicator_set_on_range, METH_KEYWORDS,
297 "Sets an indicator on the range specified." },
298 { "insert_snippet", (PyCFunction) Editor_insert_snippet, METH_KEYWORDS,
299 "Replaces all special sequences in snippet and inserts it at "
300 "the specified position." },
301 { "insert_text_block", (PyCFunction) Editor_insert_text_block, METH_KEYWORDS,
302 "Inserts text, replacing tab chars and newline chars accordingly "
303 "for the document." },
304 { NULL }
305 };
306
307
308 static PyGetSetDef Editor_getseters[] = {
309 GEANYPY_GETSETDEF(Editor, "eol_char",
310 "The endo of line character(s)."),
311 GEANYPY_GETSETDEF(Editor, "eol_char_name",
312 "The localized name (for displaying) of the used end of line "
313 "characters in the editor."),
314 GEANYPY_GETSETDEF(Editor, "indent_prefs",
315 "Editor's indentation preferences."),
316 GEANYPY_GETSETDEF(Editor, "indent_type",
317 "Sets the indent type for the editor."),
318 GEANYPY_GETSETDEF(Editor, "auto_indent",
319 "True if auto-indentation is enabled."),
320 GEANYPY_GETSETDEF(Editor, "document",
321 "The document associated with the editor."),
322 GEANYPY_GETSETDEF(Editor, "line_breaking",
323 "Whether to split long lines as you type."),
324 GEANYPY_GETSETDEF(Editor, "line_wrapping",
325 "True if line wrapping is enabled."),
326 GEANYPY_GETSETDEF(Editor, "scintilla",
327 "The Scintilla widget used by the editor."),
328 GEANYPY_GETSETDEF(Editor, "scroll_percent",
329 "Percentage to scroll view by on paint, if positive."),
330 { NULL },
331 };
332
333
334 static PyTypeObject EditorType = {
335 PyObject_HEAD_INIT(NULL)
336 0, /* ob_size */
337 "geany.editor.Editor", /* tp_name */
338 sizeof(Editor), /* tp_basicsize */
339 0, /* tp_itemsize */
340 (destructor)Editor_dealloc, /* tp_dealloc */
341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* tp_print - tp_as_buffer */
342 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
343 "Wrapper around a GeanyEditor structure.", /* tp_doc */
344 0, 0, 0, 0, 0, 0, /* tp_traverse - tp_iternext */
345 Editor_methods, /* tp_methods */
346 0, /* tp_members */
347 Editor_getseters, /* tp_getset */
348 0, 0, 0, 0, 0, /* tp_base - tp_dictoffset */
349 (initproc)Editor_init, /* tp_init */
350 0, 0, /* tp_alloc - tp_new */
351
352 };
353
354
355 static PyObject *
Editor__find_snippet(PyObject * module,PyObject * args,PyObject * kwargs)356 Editor__find_snippet(PyObject *module, PyObject *args, PyObject *kwargs)
357 {
358 gchar *name;
359 const gchar *snippet;
360 static gchar *kwlist[] = { "snippet_name", NULL };
361
362 if (PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
363 {
364 if (name != NULL)
365 {
366 snippet = editor_find_snippet(NULL, name);
367 if (snippet != NULL)
368 return Py_BuildValue("s", snippet);
369 }
370 }
371 Py_RETURN_NONE;
372 }
373
374
375 static PyObject *
Editor_get_default_eol_char(PyObject * module)376 Editor_get_default_eol_char(PyObject *module)
377 {
378 const gchar *eol_char = editor_get_eol_char(NULL);
379 if (eol_char != NULL)
380 return Py_BuildValue("s", eol_char);
381 Py_RETURN_NONE;
382 }
383
384
385 static PyObject *
Editor_get_default_eol_char_name(PyObject * module)386 Editor_get_default_eol_char_name(PyObject *module)
387 {
388 const gchar *eol_char_name = editor_get_eol_char_name(NULL);
389 if (eol_char_name != NULL)
390 return Py_BuildValue("s", eol_char_name);
391 Py_RETURN_NONE;
392 }
393
394
395 static PyObject *
Editor_get_default_indent_prefs(PyObject * module)396 Editor_get_default_indent_prefs(PyObject *module)
397 {
398 const GeanyIndentPrefs *indent_prefs;
399 IndentPrefs *py_prefs;
400 indent_prefs = editor_get_indent_prefs(NULL);
401 if (indent_prefs != NULL)
402 {
403 py_prefs = IndentPrefs_create_new_from_geany_indent_prefs((GeanyIndentPrefs *)indent_prefs);
404 return (PyObject *) py_prefs;
405 }
406 Py_RETURN_NONE;
407 }
408
409
410 static
411 PyMethodDef EditorModule_methods[] = {
412 { "find_snippet", (PyCFunction) Editor__find_snippet, METH_VARARGS,
413 "Gets a snippet by name from the default set." },
414 { "get_default_eol_char", (PyCFunction) Editor_get_default_eol_char, METH_NOARGS,
415 "The default eol char." },
416 { "get_default_eol_char_name", (PyCFunction) Editor_get_default_eol_char_name, METH_NOARGS,
417 "Retrieves the localized name (for displaying) of the default end "
418 "of line characters." },
419 { "get_default_indent_prefs", (PyCFunction) Editor_get_default_indent_prefs, METH_NOARGS,
420 "Gets the default indentation preferences." },
421 { NULL }
422 };
423
424
initeditor(void)425 PyMODINIT_FUNC initeditor(void)
426 {
427 PyObject *m;
428
429 EditorType.tp_new = PyType_GenericNew;
430 if (PyType_Ready(&EditorType) < 0)
431 return;
432
433 IndentPrefsType.tp_new = PyType_GenericNew;
434 if (PyType_Ready(&IndentPrefsType) < 0)
435 return;
436
437 m = Py_InitModule3("editor", EditorModule_methods,
438 "Editor information and management.");
439
440 Py_INCREF(&EditorType);
441 PyModule_AddObject(m, "Editor", (PyObject *)&EditorType);
442
443 Py_INCREF(&IndentPrefsType);
444 PyModule_AddObject(m, "IndentPrefs", (PyObject *)&IndentPrefsType);
445
446 PyModule_AddIntConstant(m, "INDENT_TYPE_SPACES",
447 (glong) GEANY_INDENT_TYPE_SPACES);
448 PyModule_AddIntConstant(m, "INDENT_TYPE_TABS",
449 (glong) GEANY_INDENT_TYPE_TABS);
450 PyModule_AddIntConstant(m, "INDENT_TYPE_BOTH",
451 (glong) GEANY_INDENT_TYPE_BOTH);
452 PyModule_AddIntConstant(m, "INDICATOR_ERROR",
453 (glong) GEANY_INDICATOR_ERROR);
454 PyModule_AddIntConstant(m, "INDICATOR_SEARCH",
455 (glong) GEANY_INDICATOR_SEARCH);
456 PyModule_AddStringConstant(m, "WORDCHARS", GEANY_WORDCHARS);
457
458 PyModule_AddIntConstant(m, "INDENT_TYPE_SPACES", (glong) GEANY_INDENT_TYPE_SPACES);
459 PyModule_AddIntConstant(m, "INDENT_TYPE_TABS", (glong) GEANY_INDENT_TYPE_TABS);
460 PyModule_AddIntConstant(m, "INDENT_TYPE_BOTH", (glong) GEANY_INDENT_TYPE_BOTH);
461 }
462
463
Editor_create_new_from_geany_editor(GeanyEditor * editor)464 Editor *Editor_create_new_from_geany_editor(GeanyEditor *editor)
465 {
466 Editor *self;
467 self = (Editor *) PyObject_CallObject((PyObject *) &EditorType, NULL);
468 self->editor = editor;
469 return self;
470 }
471