Merge pull request #4077 from LiquidCake/saveactions_persistent_temp_files_doc
[geany-mirror.git] / src / sciwrappers.c
bloba25307302b60a6993f3beb6aac4628c451fe04ed
1 /*
2 * sciwrappers.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2005 The Geany contributors
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 /** @file sciwrappers.h
22 * Wrapper functions for the Scintilla editor widget @c SCI_* messages.
23 * You should also check the https://scintilla.org documentation, as it is more detailed.
25 * To get Scintilla notifications, use the
26 * @link pluginsignals.c @c "editor-notify" signal @endlink.
28 * @note These functions were originally from the cssed project
29 * (https://sourceforge.net/projects/cssed/, thanks).
30 * @see scintilla_send_message().
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
37 #include "sciwrappers.h"
38 #include <Lexilla.h> /* ILexer5 */
40 #include "editor.h"
41 #include "utils.h"
43 #include <string.h>
46 #ifndef NDEBUG
48 sptr_t sci_send_message_internal (const gchar *file, guint line, ScintillaObject *sci,
49 guint msg, uptr_t wparam, sptr_t lparam)
51 sptr_t result;
52 gint status;
54 scintilla_send_message(sci, SCI_SETSTATUS, 0, 0);
55 result = scintilla_send_message(sci, msg, wparam, lparam);
56 status = scintilla_send_message(sci, SCI_GETSTATUS, 0, 0);
58 if (status != 0)
60 const gchar *sub_msg = "unknown";
61 switch (status)
63 case SC_STATUS_FAILURE:
64 sub_msg = "generic failure";
65 break;
66 case SC_STATUS_BADALLOC:
67 sub_msg = "memory is exhausted";
68 break;
69 case SC_STATUS_WARN_REGEX:
70 sub_msg = "regular expression is invalid";
71 break;
72 default:
73 if (status >= SC_STATUS_WARN_START)
74 sub_msg = "unknown warning";
75 else
76 sub_msg = "unknown failure";
77 break;
79 #define SCI_STATUS_FORMAT_STRING "%s:%u: scintilla has non-zero status " \
80 "code '%d' after sending message '%u' to instance '%p' with " \
81 "wParam='%lu' and lParam='%ld': %s"
82 if (status >= SC_STATUS_WARN_START)
84 g_warning(SCI_STATUS_FORMAT_STRING, file, line, status, msg,
85 (gpointer)sci, wparam, lparam, sub_msg);
87 else
89 g_critical(SCI_STATUS_FORMAT_STRING, file, line, status, msg,
90 (gpointer)sci, wparam, lparam, sub_msg);
94 return result;
96 #endif
99 /* line numbers visibility */
100 void sci_set_line_numbers(ScintillaObject *sci, gboolean set)
102 if (set)
104 gchar tmp_str[15];
105 gint len = (gint) SSM(sci, SCI_GETLINECOUNT, 0, 0);
106 gint width;
108 g_snprintf(tmp_str, 15, "_%d", len);
109 width = sci_text_width(sci, STYLE_LINENUMBER, tmp_str);
110 SSM(sci, SCI_SETMARGINWIDTHN, 0, width);
111 SSM(sci, SCI_SETMARGINSENSITIVEN, 0, FALSE); /* use default behaviour */
113 else
115 SSM(sci, SCI_SETMARGINWIDTHN, 0, 0);
120 void sci_set_mark_long_lines(ScintillaObject *sci, gint type, gint column, const gchar *colour)
122 glong colour_val = utils_parse_color_to_bgr(colour); /* Scintilla uses a "long" value */
124 if (column == 0)
125 type = 2;
126 switch (type)
128 case 0:
130 SSM(sci, SCI_SETEDGEMODE, EDGE_LINE, 0);
131 break;
133 case 1:
135 SSM(sci, SCI_SETEDGEMODE, EDGE_BACKGROUND, 0);
136 break;
138 case 2:
140 SSM(sci, SCI_SETEDGEMODE, EDGE_NONE, 0);
141 return;
144 SSM(sci, SCI_SETEDGECOLUMN, (uptr_t) column, 0);
145 SSM(sci, SCI_SETEDGECOLOUR, (uptr_t) colour_val, 0);
149 /* Calls SCI_TEXTHEIGHT but tries very hard to cache the result as it's a very
150 * expensive operation */
151 static gint sci_text_height_cached(ScintillaObject *sci)
153 struct height_spec {
154 gchar *font;
155 gint size;
156 gint zoom;
157 gint extra;
159 static struct height_spec cache = {0};
160 static gint cache_value = 0;
161 struct height_spec current;
163 current.font = sci_get_string(sci, SCI_STYLEGETFONT, 0);
164 current.size = SSM(sci, SCI_STYLEGETSIZEFRACTIONAL, 0, 0);
165 current.zoom = SSM(sci, SCI_GETZOOM, 0, 0);
166 current.extra = SSM(sci, SCI_GETEXTRAASCENT, 0, 0) + SSM(sci, SCI_GETEXTRADESCENT, 0, 0);
168 if (g_strcmp0(current.font, cache.font) == 0 &&
169 current.size == cache.size &&
170 current.zoom == cache.zoom &&
171 current.extra == cache.extra)
173 g_free(current.font);
175 else
177 g_free(cache.font);
178 cache = current;
180 cache_value = SSM(sci, SCI_TEXTHEIGHT, 0, 0);
183 return cache_value;
186 /* compute margin width based on ratio of line height */
187 static gint margin_width_from_line_height(ScintillaObject *sci, gdouble ratio, gint threshold)
189 const gint line_height = sci_text_height_cached(sci);
190 gint width;
192 width = line_height * ratio;
193 /* round down to an even size */
194 width = width - (width % 2);
195 /* if under threshold, just use the line height */
196 if (width < threshold)
197 width = MIN(threshold, line_height);
199 return width;
203 /* symbol margin visibility */
204 void sci_set_symbol_margin(ScintillaObject *sci, gboolean set)
206 if (set)
208 const gint width = margin_width_from_line_height(sci, 0.88, 16);
210 SSM(sci, SCI_SETMARGINWIDTHN, 1, width);
211 SSM(sci, SCI_SETMARGINSENSITIVEN, 1, TRUE);
213 else
215 SSM(sci, SCI_SETMARGINWIDTHN, 1, 0);
216 SSM(sci, SCI_SETMARGINSENSITIVEN, 1, FALSE);
221 /* folding margin visibility */
222 void sci_set_folding_margin_visible(ScintillaObject *sci, gboolean set)
224 if (set)
226 const gint width = margin_width_from_line_height(sci, 0.66, 12);
228 SSM(sci, SCI_SETMARGINWIDTHN, 2, width);
229 SSM(sci, SCI_SETMARGINSENSITIVEN, 2, TRUE);
231 else
233 SSM(sci, SCI_SETMARGINSENSITIVEN, 2, FALSE);
234 SSM(sci, SCI_SETMARGINWIDTHN, 2, 0);
239 /* end of lines */
240 void sci_set_visible_eols(ScintillaObject *sci, gboolean set)
242 SSM(sci, SCI_SETVIEWEOL, set != FALSE, 0);
246 void sci_set_visible_white_spaces(ScintillaObject *sci, gboolean set)
248 if (set)
249 SSM(sci, SCI_SETVIEWWS, SCWS_VISIBLEALWAYS, 0);
250 else
251 SSM(sci, SCI_SETVIEWWS, SCWS_INVISIBLE, 0);
255 void sci_set_lines_wrapped(ScintillaObject *sci, gboolean set)
257 if (set)
258 SSM(sci, SCI_SETWRAPMODE, SC_WRAP_WORD, 0);
259 else
260 SSM(sci, SCI_SETWRAPMODE, SC_WRAP_NONE, 0);
264 gint sci_get_eol_mode(ScintillaObject *sci)
266 return (gint) SSM(sci, SCI_GETEOLMODE, 0, 0);
270 void sci_set_eol_mode(ScintillaObject *sci, gint eolmode)
272 SSM(sci, SCI_SETEOLMODE, (uptr_t) eolmode, 0);
273 sci_set_eol_representation_characters(sci, eolmode);
277 /* Show only EOL characters if they differ from the file default EOL character */
278 void sci_set_eol_representation_characters(ScintillaObject *sci, gint new_eolmode)
280 const gchar *eolchar = NULL;
281 const gchar *new_eolchar = NULL;
282 gboolean visible = FALSE;
283 gint *eolmode;
284 gint appearance;
285 gint eol_modes[3] = {SC_EOL_CRLF, SC_EOL_CR, SC_EOL_LF};
287 foreach_c_array(eolmode, eol_modes, 3)
289 visible = (*eolmode != new_eolmode) || ! editor_prefs.show_line_endings_only_when_differ;
290 new_eolchar = (visible) ? utils_get_eol_short_name(*eolmode) : "";
291 appearance = (visible) ? SC_REPRESENTATION_BLOB : SC_REPRESENTATION_PLAIN;
292 eolchar = utils_get_eol_char(*eolmode);
294 SSM(sci, SCI_SETREPRESENTATION, (sptr_t) eolchar, (sptr_t) new_eolchar);
295 SSM(sci, SCI_SETREPRESENTATIONAPPEARANCE, (sptr_t) eolchar, appearance);
300 void sci_convert_eols(ScintillaObject *sci, gint eolmode)
302 SSM(sci, SCI_CONVERTEOLS, (uptr_t) eolmode, 0);
306 void sci_add_text(ScintillaObject *sci, const gchar *text)
308 if (text != NULL)
309 { /* if null text is passed scintilla will segfault */
310 SSM(sci, SCI_ADDTEXT, strlen(text), (sptr_t) text);
315 /** Sets all text.
316 * @param sci Scintilla widget.
317 * @param text Text. */
318 GEANY_API_SYMBOL
319 void sci_set_text(ScintillaObject *sci, const gchar *text)
321 if( text != NULL ){ /* if null text is passed to scintilla will segfault */
322 SSM(sci, SCI_SETTEXT, 0, (sptr_t) text);
327 gboolean sci_can_undo(ScintillaObject *sci)
329 return SSM(sci, SCI_CANUNDO, 0, 0) != FALSE;
333 gboolean sci_can_redo(ScintillaObject *sci)
335 return SSM(sci, SCI_CANREDO, 0, 0) != FALSE;
339 void sci_undo(ScintillaObject *sci)
341 if (sci_can_undo(sci))
342 SSM(sci, SCI_UNDO, 0, 0);
346 void sci_redo(ScintillaObject *sci)
348 if (sci_can_redo(sci))
349 SSM(sci, SCI_REDO, 0, 0);
353 /** Begins grouping a set of edits together as one Undo action.
354 * You must call sci_end_undo_action() after making your edits.
355 * @param sci Scintilla @c GtkWidget. */
356 GEANY_API_SYMBOL
357 void sci_start_undo_action(ScintillaObject *sci)
359 SSM(sci, SCI_BEGINUNDOACTION, 0, 0);
363 /** Ends grouping a set of edits together as one Undo action.
364 * @param sci Scintilla @c GtkWidget.
365 * @see sci_start_undo_action(). */
366 GEANY_API_SYMBOL
367 void sci_end_undo_action(ScintillaObject *sci)
369 SSM(sci, SCI_ENDUNDOACTION, 0, 0);
373 void sci_set_undo_collection(ScintillaObject *sci, gboolean set)
375 SSM(sci, SCI_SETUNDOCOLLECTION, set != FALSE, 0);
379 void sci_empty_undo_buffer(ScintillaObject *sci)
381 SSM(sci, SCI_EMPTYUNDOBUFFER, 0, 0);
385 gboolean sci_is_modified(ScintillaObject *sci)
387 return (SSM(sci, SCI_GETMODIFY, 0, 0) != 0);
391 void sci_zoom_in(ScintillaObject *sci)
393 SSM(sci, SCI_ZOOMIN, 0, 0);
397 void sci_zoom_out(ScintillaObject *sci)
399 SSM(sci, SCI_ZOOMOUT, 0, 0);
403 void sci_zoom_off(ScintillaObject *sci)
405 SSM(sci, SCI_SETZOOM, 0, 0);
409 /** Sets a line marker.
410 * @param sci Scintilla widget.
411 * @param line_number Line number.
412 * @param marker Marker number. */
413 GEANY_API_SYMBOL
414 void sci_set_marker_at_line(ScintillaObject *sci, gint line_number, gint marker)
416 SSM(sci, SCI_MARKERADD, (uptr_t) line_number, marker);
420 /** Deletes a line marker.
421 * @param sci Scintilla widget.
422 * @param line_number Line number.
423 * @param marker Marker number. */
424 GEANY_API_SYMBOL
425 void sci_delete_marker_at_line(ScintillaObject *sci, gint line_number, gint marker)
427 SSM(sci, SCI_MARKERDELETE, (uptr_t) line_number, marker);
431 /** Checks if a line has a marker set.
432 * @param sci Scintilla widget.
433 * @param line Line number.
434 * @param marker Marker number.
435 * @return Whether it's set. */
436 GEANY_API_SYMBOL
437 gboolean sci_is_marker_set_at_line(ScintillaObject *sci, gint line, gint marker)
439 gint state;
441 state = (gint) SSM(sci, SCI_MARKERGET, (uptr_t) line, 0);
442 return (state & (1 << marker));
446 void sci_toggle_marker_at_line(ScintillaObject *sci, gint line, gint marker)
448 gboolean set = sci_is_marker_set_at_line(sci, line, marker);
450 if (!set)
451 sci_set_marker_at_line(sci, line, marker);
452 else
453 sci_delete_marker_at_line(sci, line, marker);
457 /* Returns the line number of the next marker that matches marker_mask, or -1.
458 * marker_mask is a bitor of 1 << marker_index. (See MarkerHandleSet::MarkValue()).
459 * Note: If there is a marker on the line, it returns the same line. */
460 gint sci_marker_next(ScintillaObject *sci, gint line, gint marker_mask, gboolean wrap)
462 gint marker_line;
464 marker_line = (gint) SSM(sci, SCI_MARKERNEXT, (uptr_t) line, marker_mask);
465 if (wrap && marker_line == -1)
466 marker_line = (gint) SSM(sci, SCI_MARKERNEXT, 0, marker_mask);
467 return marker_line;
471 /* Returns the line number of the previous marker that matches marker_mask, or -1.
472 * marker_mask is a bitor of 1 << marker_index. (See MarkerHandleSet::MarkValue()).
473 * Note: If there is a marker on the line, it returns the same line. */
474 gint sci_marker_previous(ScintillaObject *sci, gint line, gint marker_mask, gboolean wrap)
476 gint marker_line;
478 marker_line = (gint) SSM(sci, SCI_MARKERPREVIOUS, (uptr_t) line, marker_mask);
479 if (wrap && marker_line == -1)
481 gint len = sci_get_length(sci);
482 gint last_line = sci_get_line_from_position(sci, len - 1);
484 marker_line = (gint) SSM(sci, SCI_MARKERPREVIOUS, (uptr_t) last_line, marker_mask);
486 return marker_line;
490 /** Gets the line number from @a position.
491 * @param sci Scintilla widget.
492 * @param position Position.
493 * @return The line. */
494 GEANY_API_SYMBOL
495 gint sci_get_line_from_position(ScintillaObject *sci, gint position)
497 return (gint) SSM(sci, SCI_LINEFROMPOSITION, (uptr_t) position, 0);
501 /** Gets the column number relative to the start of the line that @a position is on.
502 * @param sci Scintilla widget.
503 * @param position Position.
504 * @return The column. */
505 GEANY_API_SYMBOL
506 gint sci_get_col_from_position(ScintillaObject *sci, gint position)
508 return (gint) SSM(sci, SCI_GETCOLUMN, (uptr_t) position, 0);
512 gint sci_get_position_from_col(ScintillaObject *sci, gint line, gint col)
514 return (gint) SSM(sci, SCI_FINDCOLUMN, line, col);
518 /** Gets the position for the start of @a line.
519 * @param sci Scintilla widget.
520 * @param line Line.
521 * @return Position. */
522 GEANY_API_SYMBOL
523 gint sci_get_position_from_line(ScintillaObject *sci, gint line)
525 return (gint) SSM(sci, SCI_POSITIONFROMLINE, (uptr_t) line, 0);
529 /** Gets the cursor position.
530 * @param sci Scintilla widget.
531 * @return Position. */
532 GEANY_API_SYMBOL
533 gint sci_get_current_position(ScintillaObject *sci)
535 return (gint) SSM(sci, SCI_GETCURRENTPOS, 0, 0);
539 gint sci_get_cursor_virtual_space(ScintillaObject *sci)
541 gint selection_mode = sci_get_selection_mode(sci);
543 return selection_mode == SC_SEL_RECTANGLE || selection_mode == SC_SEL_THIN ?
544 SSM(sci, SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE, 0, 0) :
545 SSM(sci, SCI_GETSELECTIONNCARETVIRTUALSPACE,
546 SSM(sci, SCI_GETMAINSELECTION, 0, 0), 0);
550 /** Sets the cursor position.
551 * @param sci Scintilla widget.
552 * @param position Position.
553 * @param scroll_to_caret Whether to scroll the cursor in view. */
554 GEANY_API_SYMBOL
555 void sci_set_current_position(ScintillaObject *sci, gint position, gboolean scroll_to_caret)
557 if (scroll_to_caret)
558 SSM(sci, SCI_GOTOPOS, (uptr_t) position, 0);
559 else
561 SSM(sci, SCI_SETCURRENTPOS, (uptr_t) position, 0);
562 SSM(sci, SCI_SETANCHOR, (uptr_t) position, 0); /* to avoid creation of a selection */
564 SSM(sci, SCI_CHOOSECARETX, 0, 0);
568 /* Set the cursor line without scrolling the view.
569 * Use sci_goto_line() to also scroll. */
570 void sci_set_current_line(ScintillaObject *sci, gint line)
572 gint pos = sci_get_position_from_line(sci, line);
573 sci_set_current_position(sci, pos, FALSE);
577 /** Gets the total number of lines.
578 * @param sci Scintilla widget.
579 * @return The line count. */
580 GEANY_API_SYMBOL
581 gint sci_get_line_count(ScintillaObject *sci)
583 return (gint) SSM(sci, SCI_GETLINECOUNT, 0, 0);
587 /** Sets the selection start position.
588 * @param sci Scintilla widget.
589 * @param position Position. */
590 GEANY_API_SYMBOL
591 void sci_set_selection_start(ScintillaObject *sci, gint position)
593 SSM(sci, SCI_SETSELECTIONSTART, (uptr_t) position, 0);
597 /** Sets the selection end position.
598 * @param sci Scintilla widget.
599 * @param position Position. */
600 GEANY_API_SYMBOL
601 void sci_set_selection_end(ScintillaObject *sci, gint position)
603 SSM(sci, SCI_SETSELECTIONEND, (uptr_t) position, 0);
607 void sci_set_selection(ScintillaObject *sci, gint anchorPos, gint currentPos)
609 SSM(sci, SCI_SETSEL, (uptr_t) anchorPos, currentPos);
613 /** Gets the position at the end of a line
614 * @param sci Scintilla widget.
615 * @param line Line.
616 * @return The position at the end of the line. */
617 GEANY_API_SYMBOL
618 gint sci_get_line_end_position(ScintillaObject *sci, gint line)
620 return (gint) SSM(sci, SCI_GETLINEENDPOSITION, (uptr_t) line, 0);
624 void sci_cut(ScintillaObject *sci)
626 SSM(sci, SCI_CUT, 0, 0);
630 void sci_copy(ScintillaObject *sci)
632 SSM(sci, SCI_COPY, 0, 0);
636 void sci_paste(ScintillaObject *sci)
638 SSM(sci, SCI_PASTE, 0, 0);
642 void sci_clear(ScintillaObject *sci)
644 SSM(sci, SCI_CLEAR, 0, 0);
648 /** Gets the selection start position.
649 * @param sci Scintilla widget.
650 * @return Position. */
651 GEANY_API_SYMBOL
652 gint sci_get_selection_start(ScintillaObject *sci)
654 return (gint) SSM(sci, SCI_GETSELECTIONSTART, 0, 0);
658 /** Gets the selection end position.
659 * @param sci Scintilla widget.
660 * @return Position. */
661 GEANY_API_SYMBOL
662 gint sci_get_selection_end(ScintillaObject *sci)
664 return (gint) SSM(sci, SCI_GETSELECTIONEND, 0, 0);
668 /** Replaces selection.
669 * @param sci Scintilla widget.
670 * @param text Text. */
671 GEANY_API_SYMBOL
672 void sci_replace_sel(ScintillaObject *sci, const gchar *text)
674 SSM(sci, SCI_REPLACESEL, 0, (sptr_t) text);
678 /** Gets the length of all text.
679 * @param sci Scintilla widget.
680 * @return Length. */
681 GEANY_API_SYMBOL
682 gint sci_get_length(ScintillaObject *sci)
684 return (gint) SSM(sci, SCI_GETLENGTH, 0, 0);
688 /** Gets the currently used lexer
689 * @param sci Scintilla widget.
690 * @returns The lexer ID
692 GEANY_API_SYMBOL
693 gint sci_get_lexer(ScintillaObject *sci)
695 return (gint) SSM(sci, SCI_GETLEXER, 0, 0);
699 void sci_set_lexer(ScintillaObject *sci, guint lexer_id)
701 gint old = sci_get_lexer(sci);
703 /* TODO, LexerNameFromID() is already deprecated */
704 const char *lexer_name = LexerNameFromID(lexer_id);
705 if (! lexer_name)
707 g_warning("Failed to find lexer for ID %u", lexer_id);
708 return;
711 ILexer5 *lexer = CreateLexer(lexer_name);
713 SSM(sci, SCI_SETILEXER, 0, (uintptr_t) lexer);
715 if (old != (gint)lexer_id)
716 SSM(sci, SCI_CLEARDOCUMENTSTYLE, 0, 0);
720 /** Gets line length.
721 * @param sci Scintilla widget.
722 * @param line Line number.
723 * @return Length. */
724 GEANY_API_SYMBOL
725 gint sci_get_line_length(ScintillaObject *sci, gint line)
727 return (gint) SSM(sci, SCI_LINELENGTH, (uptr_t) line, 0);
731 /* safe way to read Scintilla string into new memory.
732 * works with any string buffer messages that follow the Windows message convention. */
733 gchar *sci_get_string(ScintillaObject *sci, guint msg, gulong wParam)
735 gint size = (gint) SSM(sci, msg, wParam, 0);
736 gchar *str = g_malloc(size + 1);
738 SSM(sci, msg, wParam, (sptr_t) str);
739 str[size] = '\0'; /* ensure termination, needed for SCI_GETLINE */
740 return str;
744 /** Gets line contents.
745 * @param sci Scintilla widget.
746 * @param line_num Line number.
747 * @return A @c NULL-terminated copy of the line text. */
748 GEANY_API_SYMBOL
749 gchar *sci_get_line(ScintillaObject *sci, gint line_num)
751 return sci_get_string(sci, SCI_GETLINE, (gulong) line_num);
755 /** Gets all text.
756 * @deprecated sci_get_text is deprecated and should not be used in newly-written code.
757 * Use sci_get_contents() instead.
759 * @param sci Scintilla widget.
760 * @param len Length of @a text buffer, usually sci_get_length() + 1.
761 * @param text Text buffer; must be allocated @a len bytes for null-termination. */
762 GEANY_API_SYMBOL
763 void sci_get_text(ScintillaObject *sci, gint len, gchar *text)
765 g_return_if_fail(len > 0);
766 SSM(sci, SCI_GETTEXT, (uptr_t) len - 1, (sptr_t) text);
770 /** Allocates and fills a buffer with text from the start of the document.
771 * @param sci Scintilla widget.
772 * @param buffer_len Buffer length to allocate, including the terminating
773 * null char, e.g. sci_get_length() + 1. Alternatively use @c -1 to get all
774 * text (since Geany 1.23).
775 * @return A copy of the text. Should be freed when no longer needed.
777 * @since 1.23 (0.17)
779 GEANY_API_SYMBOL
780 gchar *sci_get_contents(ScintillaObject *sci, gint buffer_len)
782 gchar *text;
784 g_return_val_if_fail(buffer_len != 0, NULL);
786 if (buffer_len < 0)
787 buffer_len = sci_get_length(sci) + 1;
789 text = g_malloc(buffer_len);
790 SSM(sci, SCI_GETTEXT, (uptr_t) buffer_len - 1, (sptr_t) text);
791 return text;
795 /** Gets selected text.
796 * @deprecated sci_get_selected_text is deprecated and should not be used in newly-written code.
797 * Use sci_get_selection_contents() instead.
799 * @note You must ensure NUL termination yourself, this function does
800 * not NUL terminate the buffer itself.
802 * @param sci Scintilla widget.
803 * @param text Text buffer; must be allocated sci_get_selected_text_length() + 1 bytes
804 * for null-termination. */
805 GEANY_API_SYMBOL
806 void sci_get_selected_text(ScintillaObject *sci, gchar *text)
808 SSM(sci, SCI_GETSELTEXT, 0, (sptr_t) text);
812 /** Gets selected text.
813 * @param sci Scintilla widget.
815 * @return The selected text. Should be freed when no longer needed.
817 * @since 0.17
819 GEANY_API_SYMBOL
820 gchar *sci_get_selection_contents(ScintillaObject *sci)
822 return sci_get_string(sci, SCI_GETSELTEXT, 0);
826 /** Gets selected text length including the terminating NUL character.
827 * @deprecated sci_get_selected_text_length is deprecated and should not be used in newly-written code.
828 * Use sci_get_selected_text_length2() instead.
829 * @param sci Scintilla widget.
830 * @return Length. */
831 GEANY_API_SYMBOL
832 gint sci_get_selected_text_length(ScintillaObject *sci)
834 return (gint) SSM(sci, SCI_GETSELTEXT, 0, 0) + 1;
838 /** Gets selected text length without the terminating NUL character.
839 * @param sci Scintilla widget.
840 * @return Length. */
841 GEANY_API_SYMBOL
842 gint sci_get_selected_text_length2(ScintillaObject *sci)
844 return (gint) SSM(sci, SCI_GETSELTEXT, 0, 0);
848 gint sci_get_position_from_xy(ScintillaObject *sci, gint x, gint y, gboolean nearby)
850 /* for nearby return -1 if there is no character near to the x,y point. */
851 return (gint) SSM(sci, (nearby) ? SCI_POSITIONFROMPOINTCLOSE : SCI_POSITIONFROMPOINT, (uptr_t) x, y);
855 /** Checks if a line is visible (folding may have hidden it).
856 * @param sci Scintilla widget.
857 * @param line Line number.
858 * @return Whether @a line will be drawn on the screen. */
859 GEANY_API_SYMBOL
860 gboolean sci_get_line_is_visible(ScintillaObject *sci, gint line)
862 return SSM(sci, SCI_GETLINEVISIBLE, (uptr_t) line, 0) != FALSE;
866 /** Makes @a line visible (folding may have hidden it).
867 * @param sci Scintilla widget.
868 * @param line Line number. */
869 GEANY_API_SYMBOL
870 void sci_ensure_line_is_visible(ScintillaObject *sci, gint line)
872 SSM(sci, SCI_ENSUREVISIBLE, (uptr_t) line, 0);
876 gint sci_get_fold_level(ScintillaObject *sci, gint line)
878 return (gint) SSM(sci, SCI_GETFOLDLEVEL, (uptr_t) line, 0);
882 /* Get the line number of the fold point before start_line, or -1 if there isn't one */
883 gint sci_get_fold_parent(ScintillaObject *sci, gint start_line)
885 return (gint) SSM(sci, SCI_GETFOLDPARENT, (uptr_t) start_line, 0);
889 void sci_toggle_fold(ScintillaObject *sci, gint line)
891 SSM(sci, SCI_TOGGLEFOLD, (uptr_t) line, 0);
895 gboolean sci_get_fold_expanded(ScintillaObject *sci, gint line)
897 return SSM(sci, SCI_GETFOLDEXPANDED, (uptr_t) line, 0) != FALSE;
901 void sci_colourise(ScintillaObject *sci, gint start, gint end)
903 SSM(sci, SCI_COLOURISE, (uptr_t) start, end);
907 void sci_clear_all(ScintillaObject *sci)
909 SSM(sci, SCI_CLEARALL, 0, 0);
913 gint sci_get_end_styled(ScintillaObject *sci)
915 return (gint) SSM(sci, SCI_GETENDSTYLED, 0, 0);
919 void sci_set_tab_width(ScintillaObject *sci, gint width)
921 SSM(sci, SCI_SETTABWIDTH, (uptr_t) width, 0);
925 /** Gets display tab width (this is not indent width, see GeanyIndentPrefs).
926 * @param sci Scintilla widget.
927 * @return Width.
929 * @since 0.15
931 GEANY_API_SYMBOL
932 gint sci_get_tab_width(ScintillaObject *sci)
934 return (gint) SSM(sci, SCI_GETTABWIDTH, 0, 0);
938 /** Gets a character.
939 * @param sci Scintilla widget.
940 * @param pos Position.
941 * @return Char. */
942 GEANY_API_SYMBOL
943 gchar sci_get_char_at(ScintillaObject *sci, gint pos)
945 return (gchar) SSM(sci, SCI_GETCHARAT, (uptr_t) pos, 0);
949 void sci_set_savepoint(ScintillaObject *sci)
951 SSM(sci, SCI_SETSAVEPOINT, 0, 0);
955 void sci_set_indentation_guides(ScintillaObject *sci, gint mode)
957 SSM(sci, SCI_SETINDENTATIONGUIDES, (uptr_t) mode, 0);
961 void sci_use_popup(ScintillaObject *sci, gboolean enable)
963 SSM(sci, SCI_USEPOPUP, enable != FALSE, 0);
967 /** Checks if there's a selection.
968 * @param sci Scintilla widget.
969 * @return Whether a selection is present.
971 * @since 0.15
973 GEANY_API_SYMBOL
974 gboolean sci_has_selection(ScintillaObject *sci)
976 if (SSM(sci, SCI_GETSELECTIONEND, 0, 0) - SSM(sci, SCI_GETSELECTIONSTART, 0, 0))
977 return TRUE;
978 else
979 return FALSE;
983 void sci_goto_pos(ScintillaObject *sci, gint pos, gboolean unfold)
985 if (unfold) SSM(sci, SCI_ENSUREVISIBLE, (uptr_t) SSM(sci, SCI_LINEFROMPOSITION, (uptr_t) pos, 0), 0);
986 SSM(sci, SCI_GOTOPOS, (uptr_t) pos, 0);
990 void sci_set_search_anchor(ScintillaObject *sci)
992 SSM(sci, SCI_SEARCHANCHOR, 0, 0);
996 /* removes a selection if pos < 0 */
997 void sci_set_anchor(ScintillaObject *sci, gint pos)
999 if (pos < 0)
1000 pos = sci_get_current_position(sci);
1002 SSM(sci, SCI_SETANCHOR, (uptr_t) pos, 0);
1006 /** Scrolls the cursor in view.
1007 * @param sci Scintilla widget. */
1008 GEANY_API_SYMBOL
1009 void sci_scroll_caret(ScintillaObject *sci)
1011 SSM(sci, SCI_SCROLLCARET, 0, 0);
1015 void sci_scroll_columns(ScintillaObject *sci, gint columns)
1017 SSM(sci, SCI_LINESCROLL, (uptr_t) columns, 0);
1021 gint sci_search_next(ScintillaObject *sci, gint flags, const gchar *text)
1023 /* FIXME: SCI_SEACHNEXT() actually returns long */
1024 return (gint) SSM(sci, SCI_SEARCHNEXT, (uptr_t) flags, (sptr_t) text);
1028 gint sci_search_prev(ScintillaObject *sci, gint flags, const gchar *text)
1030 /* FIXME: SCI_SEACHPREV() actually returns long */
1031 return (gint) SSM(sci, SCI_SEARCHPREV, (uptr_t) flags, (sptr_t) text);
1035 /** Finds text in the document.
1036 * The @a ttf argument should be a pointer to a Sci_TextToFind structure which contains
1037 * the text to find and the range in which the text should be searched.
1039 * Please refer to the Scintilla documentation for a more detailed description.
1041 * @param sci Scintilla widget.
1042 * @param flags Bitmask of Scintilla search flags (@c SCFIND_*, see Scintilla documentation).
1043 * @param ttf Pointer to a TextToFind structure which contains the text to find and the range.
1044 * @return The position of the start of the found text if it succeeds, otherwise @c -1.
1045 * The @c chrgText.cpMin and @c chrgText.cpMax members of @c TextToFind are filled in
1046 * with the start and end positions of the found text.
1048 GEANY_API_SYMBOL
1049 gint sci_find_text(ScintillaObject *sci, gint flags, struct Sci_TextToFind *ttf)
1051 return (gint) SSM(sci, SCI_FINDTEXT, (uptr_t) flags, (sptr_t) ttf);
1054 /* * Sets the font for a particular style.
1055 * @param sci Scintilla widget.
1056 * @param style The style.
1057 * @param font The font name.
1058 * @param size The font (fractional) size. */
1059 void sci_set_font_fractional(ScintillaObject *sci, gint style, const gchar *font, gdouble size)
1061 SSM(sci, SCI_STYLESETFONT, (uptr_t) style, (sptr_t) font);
1063 /* Adding 0.5 is for rounding. */
1064 SSM(sci, SCI_STYLESETSIZEFRACTIONAL, (uptr_t) style, (sptr_t) (SC_FONT_SIZE_MULTIPLIER * size + 0.5));
1067 /** Sets the font for a particular style.
1068 * @param sci Scintilla widget.
1069 * @param style The style.
1070 * @param font The font name.
1071 * @param size The font size. */
1072 GEANY_API_SYMBOL
1073 void sci_set_font(ScintillaObject *sci, gint style, const gchar *font, gint size)
1075 sci_set_font_fractional(sci, style, font, size);
1079 /** Jumps to the specified line in the document.
1080 * If @a unfold is set and @a line is hidden by a fold, it is unfolded
1081 * first to ensure it is visible.
1082 * @param sci Scintilla widget.
1083 * @param line Line.
1084 * @param unfold Whether to unfold first.
1086 GEANY_API_SYMBOL
1087 void sci_goto_line(ScintillaObject *sci, gint line, gboolean unfold)
1089 if (unfold) SSM(sci, SCI_ENSUREVISIBLE, (uptr_t) line, 0);
1090 SSM(sci, SCI_GOTOLINE, (uptr_t) line, 0);
1094 void sci_marker_delete_all(ScintillaObject *sci, gint marker)
1096 SSM(sci, SCI_MARKERDELETEALL, (uptr_t) marker, 0);
1100 /** Gets style ID at @a position.
1101 * @param sci Scintilla widget.
1102 * @param position Position.
1103 * @return Style ID. */
1104 GEANY_API_SYMBOL
1105 gint sci_get_style_at(ScintillaObject *sci, gint position)
1107 return (gint) SSM(sci, SCI_GETSTYLEAT, (uptr_t) position, 0);
1111 void sci_set_codepage(ScintillaObject *sci, gint cp)
1113 g_return_if_fail(cp == 0 || cp == SC_CP_UTF8);
1114 SSM(sci, SCI_SETCODEPAGE, (uptr_t) cp, 0);
1118 void sci_assign_cmdkey(ScintillaObject *sci, gint key, gint command)
1120 SSM(sci, SCI_ASSIGNCMDKEY, (uptr_t) key, command);
1124 void sci_clear_cmdkey(ScintillaObject *sci, gint key)
1126 SSM(sci, SCI_CLEARCMDKEY, (uptr_t) key, 0);
1130 /** Gets text between @a start and @a end.
1131 * @deprecated sci_get_text_range is deprecated and should not be used in newly-written code.
1132 * Use sci_get_contents_range() instead.
1134 * @param sci Scintilla widget.
1135 * @param start Start.
1136 * @param end End.
1137 * @param text Text will be zero terminated and must be allocated (end - start + 1) bytes. */
1138 GEANY_API_SYMBOL
1139 void sci_get_text_range(ScintillaObject *sci, gint start, gint end, gchar *text)
1141 struct Sci_TextRange tr;
1142 tr.chrg.cpMin = start;
1143 tr.chrg.cpMax = end;
1144 tr.lpstrText = text;
1145 SSM(sci, SCI_GETTEXTRANGE, 0, (sptr_t) &tr);
1149 /** Gets text between @a start and @a end.
1150 * @param sci Scintilla widget.
1151 * @param start Start position.
1152 * @param end End position.
1153 * @return The text inside the given range. Should be freed when no longer needed.
1155 * @since 0.17
1157 GEANY_API_SYMBOL
1158 gchar *sci_get_contents_range(ScintillaObject *sci, gint start, gint end)
1160 gchar *text;
1162 g_return_val_if_fail(start < end, NULL);
1164 text = g_malloc((gsize) (end - start) + 1);
1165 sci_get_text_range(sci, start, end, text);
1166 return text;
1170 void sci_line_duplicate(ScintillaObject *sci)
1172 SSM(sci, SCI_LINEDUPLICATE, 0, 0);
1176 void sci_selection_duplicate(ScintillaObject *sci)
1178 SSM(sci, SCI_SELECTIONDUPLICATE, 0, 0);
1182 /** Inserts text.
1183 * @param sci Scintilla widget.
1184 * @param pos Position, or -1 for current.
1185 * @param text Text. */
1186 GEANY_API_SYMBOL
1187 void sci_insert_text(ScintillaObject *sci, gint pos, const gchar *text)
1189 SSM(sci, SCI_INSERTTEXT, (uptr_t) pos, (sptr_t) text);
1193 GEANY_API_SYMBOL
1194 void sci_set_target_start(ScintillaObject *sci, gint start)
1196 SSM(sci, SCI_SETTARGETSTART, (uptr_t) start, 0);
1200 GEANY_API_SYMBOL
1201 void sci_set_target_end(ScintillaObject *sci, gint end)
1203 SSM(sci, SCI_SETTARGETEND, (uptr_t) end, 0);
1207 GEANY_API_SYMBOL
1208 gint sci_replace_target(ScintillaObject *sci, const gchar *text, gboolean regex)
1210 return (gint) SSM(sci, (regex) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET, (uptr_t) -1, (sptr_t) text);
1214 void sci_set_keywords(ScintillaObject *sci, guint k, const gchar *text)
1216 SSM(sci, SCI_SETKEYWORDS, k, (sptr_t) text);
1220 void sci_set_readonly(ScintillaObject *sci, gboolean readonly)
1222 SSM(sci, SCI_SETREADONLY, readonly != FALSE, 0);
1226 /** Sends Scintilla commands without any parameters.
1227 * @param sci The Scintilla @c GtkWidget.
1228 * @param cmd @c SCI_COMMAND.
1229 * @see https://scintilla.org for the documentation.
1231 * @since 0.16
1233 GEANY_API_SYMBOL
1234 void sci_send_command(ScintillaObject *sci, gint cmd)
1236 SSM(sci, cmd, 0, 0);
1240 /** Gets current line number.
1241 * @param sci Scintilla widget.
1242 * @return Line number. */
1243 GEANY_API_SYMBOL
1244 gint sci_get_current_line(ScintillaObject *sci)
1246 return (gint) SSM(sci, SCI_LINEFROMPOSITION, (uptr_t) SSM(sci, SCI_GETCURRENTPOS, 0, 0), 0);
1250 /* Get number of lines partially or fully selected.
1251 * Returns 1 if there is a partial selection on the same line.
1252 * Returns 2 if a whole line is selected including the line break char(s). */
1253 gint sci_get_lines_selected(ScintillaObject *sci)
1255 gint start = (gint) SSM(sci, SCI_GETSELECTIONSTART, 0, 0);
1256 gint end = (gint) SSM(sci, SCI_GETSELECTIONEND, 0, 0);
1257 gint line_start;
1258 gint line_end;
1260 if (start == end)
1261 return 0; /* no selection */
1263 line_start = (gint) SSM(sci, SCI_LINEFROMPOSITION, (uptr_t) start, 0);
1264 line_end = (gint) SSM(sci, SCI_LINEFROMPOSITION, (uptr_t) end, 0);
1266 return line_end - line_start + 1;
1270 gint sci_get_first_visible_line(ScintillaObject *sci)
1272 return (gint) SSM(sci, SCI_GETFIRSTVISIBLELINE, 0, 0);
1277 * Sets the current indicator. This is necessary to define an indicator for a range of text or
1278 * clearing indicators for a range of text.
1280 * @param sci Scintilla widget.
1281 * @param indic The indicator number to set.
1283 * @see sci_indicator_clear
1285 * @since 0.16
1287 GEANY_API_SYMBOL
1288 void sci_indicator_set(ScintillaObject *sci, gint indic)
1290 SSM(sci, SCI_SETINDICATORCURRENT, (uptr_t) indic, 0);
1294 void sci_indicator_fill(ScintillaObject *sci, gint pos, gint len)
1296 SSM(sci, SCI_INDICATORFILLRANGE, (uptr_t) pos, len);
1301 * Clears the currently set indicator from a range of text.
1302 * Starting at @a pos, @a len characters long.
1303 * In order to make this function properly, you need to set the current indicator before with
1304 * @ref sci_indicator_set().
1306 * @param sci Scintilla widget.
1307 * @param pos Starting position.
1308 * @param len Length.
1310 * @since 0.16
1312 GEANY_API_SYMBOL
1313 void sci_indicator_clear(ScintillaObject *sci, gint pos, gint len)
1315 SSM(sci, SCI_INDICATORCLEARRANGE, (uptr_t) pos, len);
1319 void sci_select_all(ScintillaObject *sci)
1321 SSM(sci, SCI_SELECTALL, 0, 0);
1325 gint sci_get_line_indent_position(ScintillaObject *sci, gint line)
1327 return (gint) SSM(sci, SCI_GETLINEINDENTPOSITION, (uptr_t) line, 0);
1331 void sci_set_autoc_max_height(ScintillaObject *sci, gint val)
1333 SSM(sci, SCI_AUTOCSETMAXHEIGHT, (uptr_t) val, 0);
1337 /** Finds a matching brace at @a pos.
1338 * @param sci Scintilla widget.
1339 * @param pos Position.
1340 * @return Matching brace position.
1342 * @since 0.15
1344 GEANY_API_SYMBOL
1345 gint sci_find_matching_brace(ScintillaObject *sci, gint pos)
1347 return (gint) SSM(sci, SCI_BRACEMATCH, (uptr_t) pos, 0);
1351 gint sci_get_overtype(ScintillaObject *sci)
1353 return (gint) SSM(sci, SCI_GETOVERTYPE, 0, 0);
1357 void sci_set_tab_indents(ScintillaObject *sci, gboolean set)
1359 SSM(sci, SCI_SETTABINDENTS, set != FALSE, 0);
1363 void sci_set_use_tabs(ScintillaObject *sci, gboolean set)
1365 SSM(sci, SCI_SETUSETABS, set != FALSE, 0);
1369 gint sci_get_pos_at_line_sel_start(ScintillaObject *sci, gint line)
1371 return (gint) SSM(sci, SCI_GETLINESELSTARTPOSITION, (uptr_t) line, 0);
1375 gint sci_get_pos_at_line_sel_end(ScintillaObject *sci, gint line)
1377 return (gint) SSM(sci, SCI_GETLINESELENDPOSITION, (uptr_t) line, 0);
1381 /** Gets selection mode.
1382 * @param sci Scintilla widget.
1383 * @return Selection mode. */
1384 GEANY_API_SYMBOL
1385 gint sci_get_selection_mode(ScintillaObject *sci)
1387 return (gint) SSM(sci, SCI_GETSELECTIONMODE, 0, 0);
1391 /** Sets selection mode.
1392 * @param sci Scintilla widget.
1393 * @param mode Mode. */
1394 GEANY_API_SYMBOL
1395 void sci_set_selection_mode(ScintillaObject *sci, gint mode)
1397 SSM(sci, SCI_SETSELECTIONMODE, (uptr_t) mode, 0);
1401 void sci_set_scrollbar_mode(ScintillaObject *sci, gboolean visible)
1403 SSM(sci, SCI_SETHSCROLLBAR, visible != FALSE, 0);
1404 SSM(sci, SCI_SETVSCROLLBAR, visible != FALSE, 0);
1408 /** Sets the indentation of a line.
1409 * @param sci Scintilla widget.
1410 * @param line Line to indent.
1411 * @param indent Indentation width.
1413 * @since 0.19
1415 GEANY_API_SYMBOL
1416 void sci_set_line_indentation(ScintillaObject *sci, gint line, gint indent)
1418 SSM(sci, SCI_SETLINEINDENTATION, (uptr_t) line, indent);
1422 /** Gets the indentation width of a line.
1423 * @param sci Scintilla widget.
1424 * @param line Line to get the indentation from.
1425 * @return Indentation width.
1427 * @since 0.19
1429 GEANY_API_SYMBOL
1430 gint sci_get_line_indentation(ScintillaObject *sci, gint line)
1432 return (gint) SSM(sci, SCI_GETLINEINDENTATION, (uptr_t) line, 0);
1436 void sci_set_caret_policy_x(ScintillaObject *sci, gint policy, gint slop)
1438 SSM(sci, SCI_SETXCARETPOLICY, (uptr_t) policy, slop);
1442 void sci_set_caret_policy_y(ScintillaObject *sci, gint policy, gint slop)
1444 SSM(sci, SCI_SETYCARETPOLICY, (uptr_t) policy, slop);
1448 void sci_set_scroll_stop_at_last_line(ScintillaObject *sci, gboolean set)
1450 SSM(sci, SCI_SETENDATLASTLINE, set != FALSE, 0);
1454 void sci_cancel(ScintillaObject *sci)
1456 SSM(sci, SCI_CANCEL, 0, 0);
1460 gint sci_get_position_after(ScintillaObject *sci, gint start)
1462 return (gint) SSM(sci, SCI_POSITIONAFTER, (uptr_t) start, 0);
1466 void sci_lines_join(ScintillaObject *sci)
1468 SSM(sci, SCI_LINESJOIN, 0, 0);
1472 gint sci_text_width(ScintillaObject *sci, gint styleNumber, const gchar *text)
1474 return (gint) SSM(sci, SCI_TEXTWIDTH, (uptr_t) styleNumber, (sptr_t) text);
1478 void sci_move_selected_lines_down(ScintillaObject *sci)
1480 SSM(sci, SCI_MOVESELECTEDLINESDOWN, 0, 0);
1484 void sci_move_selected_lines_up(ScintillaObject *sci)
1486 SSM(sci, SCI_MOVESELECTEDLINESUP, 0, 0);
1490 gint sci_word_start_position(ScintillaObject *sci, gint position, gboolean onlyWordCharacters)
1492 return SSM(sci, SCI_WORDSTARTPOSITION, position, onlyWordCharacters);
1496 gint sci_word_end_position(ScintillaObject *sci, gint position, gboolean onlyWordCharacters)
1498 return SSM(sci, SCI_WORDENDPOSITION, position, onlyWordCharacters);