Hi all.

This is actually reply to http://lists.uvena.de/geany-devel/2009-July/000834.html . I did not find any way to reply to my own message.

I had some time to think about a better implementation for split_lines(). Now it does not change user's selection and can be undone with one undo action.

Here is the new patch, use it instead of the previous one. It is still for rev. 3951. Alternative link: http://pastie.org/544316 .

Best regards,
Eugene.
diff --git a/src/editor.c b/src/editor.c
index 2efdaec..75aaf50 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -101,7 +101,6 @@ static void auto_table(GeanyEditor *editor, gint pos);
 static void close_block(GeanyEditor *editor, gint pos);
 static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos);
 static void editor_auto_latex(GeanyEditor *editor, gint pos);
-static void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line);
 
 
 void editor_snippets_free(void)
@@ -4271,7 +4270,7 @@ void editor_replace_spaces(GeanyEditor *editor)
 }
 
 
-static void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line)
+void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line)
 {
 	gint line_start = sci_get_position_from_line(editor->sci, line);
 	gint line_end = sci_get_line_end_position(editor->sci, line);
diff --git a/src/editor.h b/src/editor.h
index 50eafb6..2d21738 100644
--- a/src/editor.h
+++ b/src/editor.h
@@ -100,7 +100,7 @@ typedef struct GeanyEditorPrefs
 	gboolean	show_white_space;
 	gboolean	show_indent_guide;
 	gboolean	show_line_endings;
-	gint		long_line_type;
+	gint		long_line_type; /* 0 - line, 1 - background, 2 - none */
 	gint		long_line_column;
 	gchar		*long_line_color;
 	gboolean	show_markers_margin;		/* view menu */
@@ -251,6 +251,8 @@ void editor_replace_tabs(GeanyEditor *editor);
 
 void editor_replace_spaces(GeanyEditor *editor);
 
+void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line);
+
 void editor_strip_trailing_spaces(GeanyEditor *editor);
 
 void editor_ensure_final_newline(GeanyEditor *editor);
diff --git a/src/keybindings.c b/src/keybindings.c
index 6c25932..12c39de 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -263,6 +263,10 @@ static void init_default_kb(void)
 		GDK_space, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "edit_calltip", _("Show calltip"), NULL);
 	keybindings_set_item(group, GEANY_KEYS_EDITOR_MACROLIST, cb_func_editor_action,
 		GDK_Return, GDK_CONTROL_MASK, "edit_macrolist", _("Show macro list"), NULL);
+	keybindings_set_item(group, GEANY_KEYS_EDITOR_SPLITLINES, cb_func_editor_action,
+		0, 0, "edit_splitlines", _("Split lines"), NULL);
+	keybindings_set_item(group, GEANY_KEYS_EDITOR_JOINLINES, cb_func_editor_action,
+		0, 0, "edit_joinlines", _("Join lines"), NULL);
 
 	group = ADD_KB_GROUP(CLIPBOARD, _("Clipboard"));
 
@@ -1830,6 +1834,120 @@ static void delete_lines(GeanyEditor *editor)
 }
 
 
+static void join_lines(GeanyEditor *editor)
+{
+	gint start, end, i;
+
+	start = sci_get_line_from_position(editor->sci,
+		sci_get_selection_start(editor->sci));
+	end = sci_get_line_from_position(editor->sci,
+		sci_get_selection_end(editor->sci));
+
+	/* if there is only one line in selection, join it with the following one */
+	if (end == start)
+		end = start + 1;
+
+	/*
+	 * remove trailing spaces for every line except the last one
+	 * so that these spaces won't appear within text after joining
+	 */
+	for (i = start; i < end; i++)
+		editor_strip_line_trailing_spaces(editor, i);
+
+	/* remove starting spaces from second and following lines due to the same reason */
+	for (i = start+1; i <= end; i++)
+		sci_set_line_indentation(editor->sci, i, 0);
+
+	/*
+	 * SCI_LINESJOIN automatically adds spaces between joined lines, including
+	 * empty ones. We should drop empty lines if we want only one space to be
+	 * inserted (see also example below). I don't think we should care of that.
+	 */
+
+	sci_set_target_start(editor->sci,
+		sci_get_position_from_line(editor->sci, start));
+	sci_set_target_end(editor->sci,
+		sci_get_position_from_line(editor->sci, end));
+	sci_lines_join(editor->sci);
+
+	/*
+	 * Example: joining
+	 *
+	 * [TAB]if (something_wrong)
+	 * [TAB]{
+	 * [TAB][TAB]
+	 * [TAB][TAB]exit(1);[SPACE][SPACE]
+	 * [TAB]}[SPACE]
+	 *
+	 * gives
+	 *
+	 * [TAB]if (something_wrong) {  exit(1); }[SPACE]
+	 */
+}
+
+
+static void split_lines(GeanyEditor *editor)
+{
+	gint start, indent, linescount, i;
+
+	/* do nothing if long line marker is disabled */
+	if (editor_prefs.long_line_type == 2)
+		return;
+
+	start = sci_get_line_from_position(editor->sci,
+		sci_get_selection_start(editor->sci));
+
+	/*
+	 * If several lines are selected, first join them.
+	 * This allows to reformat text paragraphs easily.
+	 */
+	if (sci_get_lines_selected(editor->sci) > 1)
+		join_lines(editor);
+
+	/*
+	 * If this line is short enough, just return
+	 */
+	if (editor_prefs.long_line_column >
+		sci_get_line_end_position(editor->sci, start) -
+		sci_get_position_from_line(editor->sci, start))
+	{
+		return;
+	}
+
+	/*
+	 * We have to manipulate line indentation so that indentation
+	 * of the resulting lines would be consistent. For example,
+	 * the result of splitting "[TAB]very long content":
+	 *
+	 * +-------------+-------------+
+	 * |   proper    |    wrong    |
+	 * +-------------+-------------+
+	 * | [TAB]very   | [TAB]very   |
+	 * | [TAB]long   | long        |
+	 * | [TAB]content| content     |
+	 * +-------------+-------------+
+	 */
+	indent = sci_get_line_indentation(editor->sci, start);
+	sci_set_line_indentation(editor->sci, start, 0);
+
+	/*
+	 * Use sci_get_line_count() to determine how many new lines
+	 * appeared during splitting. SCI_LINESSPLIT should better return
+	 * this value itself...
+	 */
+	sci_target_from_selection(editor->sci);
+	linescount = sci_get_line_count(editor->sci);
+	sci_lines_split(editor->sci,
+		(editor_prefs.long_line_column - indent) *
+		sci_text_width(editor->sci, STYLE_DEFAULT, " "));
+	linescount = sci_get_line_count(editor->sci) - linescount;
+
+	/* Fix indentation. */
+	for (i = start; i <= start + linescount; i++)
+		sci_set_line_indentation(editor->sci, i, indent);
+}
+
+
 /* common function for editor keybindings, only valid when scintilla has focus. */
 static void cb_func_editor_action(guint key_id)
 {
@@ -1905,6 +2023,16 @@ static void cb_func_editor_action(guint key_id)
 			}
 			break;
 		}
+		case GEANY_KEYS_EDITOR_SPLITLINES:
+			sci_start_undo_action(doc->editor->sci);
+			split_lines(doc->editor);
+			sci_end_undo_action(doc->editor->sci);
+			break;
+		case GEANY_KEYS_EDITOR_JOINLINES:
+			sci_start_undo_action(doc->editor->sci);
+			join_lines(doc->editor);
+			sci_end_undo_action(doc->editor->sci);
+			break;
 	}
 }
 
diff --git a/src/keybindings.h b/src/keybindings.h
index 8dd8a29..5e0f9bd 100644
--- a/src/keybindings.h
+++ b/src/keybindings.h
@@ -133,6 +133,8 @@ enum
 	GEANY_KEYS_EDITOR_CALLTIP,
 	GEANY_KEYS_EDITOR_MACROLIST,
 	GEANY_KEYS_EDITOR_DELETELINETOEND,
+	GEANY_KEYS_EDITOR_SPLITLINES,
+	GEANY_KEYS_EDITOR_JOINLINES,
 	GEANY_KEYS_EDITOR_COUNT
 };
 
diff --git a/src/sciwrappers.c b/src/sciwrappers.c
index 6f916bf..e17a61f 100644
--- a/src/sciwrappers.c
+++ b/src/sciwrappers.c
@@ -1084,4 +1084,27 @@ gint sci_get_position_after(ScintillaObject *sci, gint start)
 	return SSM(sci, SCI_POSITIONAFTER, start, 0);
 }
 
+void sci_lines_split(ScintillaObject *sci, gint pixelWidth)
+{
+	SSM(sci, SCI_LINESSPLIT, pixelWidth, 0);
+}
 
+void sci_lines_join(ScintillaObject *sci)
+{
+	SSM(sci, SCI_LINESJOIN, 0, 0);
+}
+
+void sci_set_target_start(ScintillaObject *sci, gint pos)
+{
+	SSM(sci, SCI_SETTARGETSTART, pos, 0);
+}
+
+void sci_set_target_end(ScintillaObject *sci, gint pos)
+{
+	SSM(sci, SCI_SETTARGETEND, pos, 0);
+}
+
+gint sci_text_width(ScintillaObject *sci, gint styleNumber, const gchar *text)
+{
+	return SSM(sci, SCI_TEXTWIDTH, styleNumber, (sptr_t) text);
+}
diff --git a/src/sciwrappers.h b/src/sciwrappers.h
index 624c77d..261d87e 100644
--- a/src/sciwrappers.h
+++ b/src/sciwrappers.h
@@ -59,7 +59,7 @@ gint				sci_marker_previous			(ScintillaObject* sci, gint line, gint marker_mask
 
 gint 				sci_get_col_from_position	(ScintillaObject* sci, gint position);
 gint 				sci_get_line_from_position	(ScintillaObject* sci, gint position);
-gint 				sci_get_position_from_line	(ScintillaObject* sci, gint line );
+gint 				sci_get_position_from_line	(ScintillaObject* sci, gint line);
 gint 				sci_get_current_position	(ScintillaObject* sci);
 void 				sci_set_current_position	(ScintillaObject* sci, gint position, gboolean scroll_to_caret);
 void 				sci_set_current_line		(ScintillaObject* sci, gint line);
@@ -176,4 +176,10 @@ void				sci_cancel					(ScintillaObject *sci);
 gint				sci_get_target_end			(ScintillaObject *sci);
 gint				sci_get_position_after		(ScintillaObject *sci, gint start);
 
+void				sci_lines_split				(ScintillaObject *sci, gint pixelWidth);
+void				sci_lines_join				(ScintillaObject *sci);
+void				sci_set_target_start		(ScintillaObject *sci, gint pos);
+void				sci_set_target_end			(ScintillaObject *sci, gint pos);
+gint				sci_text_width				(ScintillaObject *sci, int styleNumber, const char * text);
+
 #endif
_______________________________________________
Geany-devel mailing list
[email protected]
http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to