commit e59c8e2731ec7d5341fbe02d4914b36736ddfa04
Author: Egmont Koblinger <egmont@gmail.com>
Date:   Sun Feb 8 18:06:09 2015 +0100

    730632-bring-back-word-chars

diff --git a/doc/reference/vte-sections.txt b/doc/reference/vte-sections.txt
index 745d8f1..904d00f 100644
--- a/doc/reference/vte-sections.txt
+++ b/doc/reference/vte-sections.txt
@@ -44,6 +44,7 @@ vte_terminal_set_scrollback_lines
 vte_terminal_set_font
 vte_terminal_get_font
 vte_terminal_get_has_selection
+vte_terminal_set_word_char_exceptions
 vte_terminal_set_backspace_binding
 vte_terminal_set_delete_binding
 vte_terminal_set_mouse_autohide
diff --git a/glade/vte.xml.in.in b/glade/vte.xml.in.in
index 26c823a..da2d39d 100644
--- a/glade/vte.xml.in.in
+++ b/glade/vte.xml.in.in
@@ -34,6 +34,7 @@
         <property id="vadjustment" />
         <property id="vscroll-policy" />
         <property id="window-title" />
+        <property id="word-char-exceptions" />
       </properties>
     </glade-widget-class>
   </glade-widget-classes>
diff --git a/src/vte-private.h b/src/vte-private.h
index b4fc654..4ad6838 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -286,6 +286,7 @@ struct _VteTerminalPrivate {
         VteCharacterReplacement *character_replacement;     /* pointer to the active one */
 
 	/* Selection information. */
+	gchar *word_char_exceptions;
 	gboolean has_selection;
 	gboolean selecting;
 	gboolean selecting_after_threshold;
diff --git a/src/vte.c b/src/vte.c
index e9dbe57..8f32f16 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -82,7 +82,7 @@ typedef gunichar wint_t;
 #define howmany(x, y) (((x) + ((y) - 1)) / (y))
 #endif
 
-#define WORD_CHAR_ASCII_PUNCT "-,.;/?%&#_=+@~"
+#define WORD_CHAR_EXCEPTIONS_DEFAULT "-,.;/?%&#_=+@~"
 
 static int _vte_unichar_width(gunichar c, int utf8_ambiguous_width);
 static void vte_terminal_set_visibility (VteTerminal *terminal, GdkVisibilityState state);
@@ -176,6 +176,7 @@ enum {
         PROP_SCROLL_ON_KEYSTROKE,
         PROP_SCROLL_ON_OUTPUT,
         PROP_WINDOW_TITLE,
+        PROP_WORD_CHAR_EXCEPTIONS,
 };
 
 /* these static variables are guarded by the GDK mutex */
@@ -5245,18 +5246,19 @@ vte_terminal_key_release(GtkWidget *widget, GdkEventKey *event)
  * @terminal: a #VteTerminal
  * @c: a candidate Unicode code point
  *
- * Checks if a particular character is considered to be part of a word or not.
+ * Checks if a particular character is considered to be part of a word or not,
+ * based on the values last passed to vte_terminal_set_word_char_exceptions().
  *
  * Returns: %TRUE if the character is considered to be part of a word
  */
 gboolean
 _vte_terminal_is_word_char(VteTerminal *terminal, gunichar c)
 {
+        gboolean is_exception = terminal->pvt->word_char_exceptions != NULL &&
+                                g_utf8_strchr(terminal->pvt->word_char_exceptions, -1, c) != NULL;
+
 	return g_unichar_isgraph(c) &&
-               (g_unichar_isalnum(c) ||
-                (g_unichar_ispunct(c) &&
-                 (c >= 0x80 ||
-                  strchr (WORD_CHAR_ASCII_PUNCT, (int) c) != NULL)));
+               (g_unichar_isalnum(c) ^ is_exception);
 }
 
 /* Check if the characters in the two given locations are in the same class
@@ -8111,6 +8113,9 @@ vte_terminal_init(VteTerminal *terminal)
         pvt->scrollback_lines = -1; /* force update in vte_terminal_set_scrollback_lines */
 	vte_terminal_set_scrollback_lines(terminal, VTE_SCROLLBACK_INIT);
 
+	/* Selection info. */
+	vte_terminal_set_word_char_exceptions(terminal, WORD_CHAR_EXCEPTIONS_DEFAULT);
+
 	/* Miscellaneous options. */
 	vte_terminal_set_backspace_binding(terminal, VTE_ERASE_AUTO);
 	vte_terminal_set_delete_binding(terminal, VTE_ERASE_AUTO);
@@ -8517,6 +8522,9 @@ vte_terminal_finalize(GObject *object)
 		}
 		g_free(terminal->pvt->selection);
 	}
+	if (terminal->pvt->word_char_exceptions != NULL) {
+		g_free(terminal->pvt->word_char_exceptions);
+	}
 
 	/* Clear the output histories. */
 	_vte_ring_fini(terminal->pvt->normal_screen.row_data);
@@ -10136,6 +10144,9 @@ vte_terminal_get_property (GObject *object,
                 case PROP_WINDOW_TITLE:
                         g_value_set_string (value, vte_terminal_get_window_title (terminal));
                         break;
+                case PROP_WORD_CHAR_EXCEPTIONS:
+                        g_value_set_string (value, NULL /* FIXME */);
+                        break;
 
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -10219,6 +10230,9 @@ vte_terminal_set_property (GObject *object,
                 case PROP_SCROLL_ON_OUTPUT:
                         vte_terminal_set_scroll_on_output (terminal, g_value_get_boolean (value));
                         break;
+                case PROP_WORD_CHAR_EXCEPTIONS:
+                        vte_terminal_set_word_char_exceptions (terminal, g_value_get_string (value));
+                        break;
 
                 /* Not writable */
                 case PROP_CURRENT_DIRECTORY_URI:
@@ -11093,6 +11107,24 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
 
         /**
+         * VteTerminal:word-char-exceptions:
+         *
+         * When the user double-clicks to start selection, the terminal will extend
+         * the selection on word boundaries.  It will treat characters included in
+         * word-char-exceptions as exceptions to alphanumeric characters.  Any
+         * non-alphanumeric character present here will also act as word characters.
+         * Alphanumeric characters, if present, will act as non word characters.
+         *
+         * Since: 0.40 ???
+         */
+        g_object_class_install_property
+                (gobject_class,
+                 PROP_WORD_CHAR_EXCEPTIONS,
+                 g_param_spec_string ("word-char-exceptions", NULL, NULL,
+                                      WORD_CHAR_EXCEPTIONS_DEFAULT,
+                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+        /**
          * VteTerminal:current-directory-uri:
          *
          * The current directory URI, or %NULL if unset.
@@ -11712,6 +11744,34 @@ vte_terminal_set_scrollback_lines(VteTerminal *terminal, glong lines)
 }
 
 /**
+ * vte_terminal_set_word_char_exceptions:
+ * @terminal: a #VteTerminal
+ * @spec: a specification
+ *
+ * When the user double-clicks to start selection, the terminal will extend
+ * the selection on word boundaries.  It will treat characters included in @spec
+ * as exceptions to alphanumeric characters.  Any non-alphanumeric character
+ * present here will also act as word characters.  Alphanumeric characters, if
+ * present, will act as non word characters.
+ *
+ * Since: 0.40 ???
+ */
+void
+vte_terminal_set_word_char_exceptions(VteTerminal *terminal, const char *spec)
+{
+        if (terminal->pvt->word_char_exceptions != NULL) {
+               g_free(terminal->pvt->word_char_exceptions);
+               terminal->pvt->word_char_exceptions = NULL;
+        }
+
+        if (spec != NULL) {
+                terminal->pvt->word_char_exceptions = g_strdup(spec);
+        }
+
+        g_object_notify(G_OBJECT(terminal), "word-char-exceptions");
+}
+
+/**
  * vte_terminal_set_backspace_binding:
  * @terminal: a #VteTerminal
  * @binding: a #VteEraseBinding for the backspace key
diff --git a/src/vteterminal.h b/src/vteterminal.h
index 59f8ce7..45e863c 100644
--- a/src/vteterminal.h
+++ b/src/vteterminal.h
@@ -236,6 +236,9 @@ gboolean vte_terminal_get_allow_bold(VteTerminal *terminal) _VTE_GNUC_NONNULL(1)
 /* Check if the terminal is the current selection owner. */
 gboolean vte_terminal_get_has_selection(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
 
+/* Set the list of word char exceptions. */
+void vte_terminal_set_word_char_exceptions(VteTerminal *terminal, const char *spec);
+
 /* Set what happens when the user strikes backspace or delete. */
 void vte_terminal_set_backspace_binding(VteTerminal *terminal,
 					VteEraseBinding binding) _VTE_GNUC_NONNULL(1);
