diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c index f01cb479..663b6051 100644 --- a/src/common/cfgfiles.c +++ b/src/common/cfgfiles.c @@ -590,6 +590,7 @@ const struct prefs vars[] = {"gui_gtk3_theme", P_OFFSET (hex_gui_gtk3_theme), TYPE_STR}, {"text_indent", P_OFFINT (hex_text_indent), TYPE_BOOL}, {"text_max_indent", P_OFFINT (hex_text_max_indent), TYPE_INT}, + {"text_wrap_align", P_OFFINT (hex_text_wrap_align), TYPE_INT}, {"text_max_lines", P_OFFINT (hex_text_max_lines), TYPE_INT}, {"text_replay", P_OFFINT (hex_text_replay), TYPE_BOOL}, {"text_search_case_match", P_OFFINT (hex_text_search_case_match), TYPE_BOOL}, @@ -881,6 +882,7 @@ load_default_config(void) prefs.hex_net_reconnect_delay = 10; prefs.hex_notify_timeout = 15; prefs.hex_text_max_indent = 256; + prefs.hex_text_wrap_align = 0; prefs.hex_text_max_lines = 5000; prefs.hex_url_grabber_limit = 100; /* 0 means unlimited */ diff --git a/src/common/zoitechat.h b/src/common/zoitechat.h index b93005b5..ee60e6df 100644 --- a/src/common/zoitechat.h +++ b/src/common/zoitechat.h @@ -306,6 +306,7 @@ struct zoitechatprefs int hex_net_reconnect_delay; int hex_notify_timeout; int hex_text_max_indent; + int hex_text_wrap_align; int hex_text_max_lines; int hex_url_grabber_limit; diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 4fa488b9..e00c845c 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -59,6 +59,8 @@ static struct zoitechatprefs setup_prefs; static GtkWidget *cancel_button; static GtkWidget *font_dialog = NULL; static GtkWidget *setup_topicbar_multiline_toggle = NULL; +static GtkWidget *setup_wrap_align_label = NULL; +static GtkWidget *setup_wrap_align_combo = NULL; enum { @@ -157,6 +159,14 @@ static const char *const langsmenu[] = }; #endif +static const char *const wrapalignmenu[] = +{ + N_("Start of line (default)"), + N_("Prefix (nick name)"), + N_("Message"), + NULL +}; + static const setting appearance_settings[] = { {ST_HEADER, N_("General"),0,0,0}, @@ -172,6 +182,7 @@ static const setting appearance_settings[] = {ST_TOGGLR, N_("Indent nick names"), P_OFFINTNL(hex_text_indent), N_("Make nick names right-justified"),0,0}, {ST_TOGGLE, N_ ("Show marker line"), P_OFFINTNL (hex_text_show_marker), N_ ("Insert a red line after the last read text."), 0, 0}, {ST_TOGGLE, N_("Keep search position when closing"), P_OFFINTNL(hex_text_search_keep_position), 0, 0, 0}, + {ST_MENU, N_("Align wrapped lines under:"), P_OFFINTNL(hex_text_wrap_align), N_("Where wrapped lines start when nick names are not indented"), wrapalignmenu, 0}, {ST_HEADER, N_("Timestamps"),0,0,0}, {ST_TOGGLE, N_("Enable timestamps"), P_OFFINTNL(hex_stamp_text),0,0,1}, @@ -857,6 +868,20 @@ setup_topicbar_inline_toggled_cb (GtkToggleButton *but, gpointer userdata) !gtk_toggle_button_get_active (but)); } +static void +setup_text_indent_toggled_cb (GtkToggleButton *but, gpointer userdata) +{ + gboolean sens = !gtk_toggle_button_get_active (but); + + (void) userdata; + + /* wrapped line alignment only applies without nick indentation */ + if (setup_wrap_align_label) + gtk_widget_set_sensitive (setup_wrap_align_label, sens); + if (setup_wrap_align_combo) + gtk_widget_set_sensitive (setup_wrap_align_combo, sens); +} + static void setup_create_toggleR (GtkWidget *tab, int row, const setting *set) { @@ -867,6 +892,9 @@ setup_create_toggleR (GtkWidget *tab, int row, const setting *set) setup_get_int (&setup_prefs, set)); g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (setup_toggle_cb), (gpointer)set); + if (set->offset == STRUCT_OFFSET_INT (struct zoitechatprefs, hex_text_indent)) + g_signal_connect (G_OBJECT (wid), "toggled", + G_CALLBACK (setup_text_indent_toggled_cb), NULL); if (set->tooltip) gtk_widget_set_tooltip_text (wid, _(set->tooltip)); setup_table_attach (tab, wid, 4, 5, row, row + 1, TRUE, FALSE, @@ -1279,6 +1307,16 @@ setup_create_menu (GtkWidget *table, int row, const setting *set) setup_table_attach (table, cbox, 3, 6, row, row + 1, TRUE, FALSE, SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0); + + if (set->offset == STRUCT_OFFSET_INT (struct zoitechatprefs, hex_text_wrap_align)) + { + setup_wrap_align_label = wid; + setup_wrap_align_combo = cbox; + g_object_add_weak_pointer (G_OBJECT (wid), (gpointer *)&setup_wrap_align_label); + g_object_add_weak_pointer (G_OBJECT (cbox), (gpointer *)&setup_wrap_align_combo); + gtk_widget_set_sensitive (wid, !setup_prefs.hex_text_indent); + gtk_widget_set_sensitive (cbox, !setup_prefs.hex_text_indent); + } } static void diff --git a/src/fe-gtk/textgui.c b/src/fe-gtk/textgui.c index 3268a7c5..9b6baf3f 100644 --- a/src/fe-gtk/textgui.c +++ b/src/fe-gtk/textgui.c @@ -92,7 +92,7 @@ PrintTextLine (xtext_buffer *xtbuf, unsigned char *text, int len, int indent, ti memcpy (new_text, stamp, stamp_size); g_free (stamp); memcpy (new_text + stamp_size, text, len); - gtk_xtext_append (xtbuf, new_text, len + stamp_size, timet); + gtk_xtext_append_wrap (xtbuf, new_text, len + stamp_size, timet, stamp_size); g_free (new_text); } else gtk_xtext_append (xtbuf, text, len, timet); diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c index c9235567..4baff180 100644 --- a/src/fe-gtk/xtext.c +++ b/src/fe-gtk/xtext.c @@ -81,6 +81,7 @@ struct textentry gint16 mark_end; int indent; gint16 left_len; + gint16 stamp_len; /* bytes of str taken by the timestamp (no-indent mode) */ GSList *slp; GArray *sublines; /* byte offsets at the end of each screen row */ int subline_count; @@ -296,6 +297,7 @@ static void gtk_xtext_get_property (GObject *object, guint prop_id, static void gtk_xtext_render_ents (GtkXText * xtext, textentry *, textentry *); static void gtk_xtext_recalc_widths (xtext_buffer *buf, int); static void gtk_xtext_fix_indent (xtext_buffer *buf); +static int gtk_xtext_text_width (GtkXText *xtext, unsigned char *text, int len); static int gtk_xtext_find_subline (GtkXText *xtext, textentry *ent, int line); /* For use by gtk_xtext_strip_color() and its callers -- */ struct offlen_s { @@ -1322,6 +1324,36 @@ gtk_xtext_selection_clear (xtext_buffer *buf) return ret; } +/* x position that the lines after the first of 'ent' start at */ + +static int +gtk_xtext_cont_indent (xtext_buffer *buf, textentry *ent) +{ + int w, off; + + if (ent->left_len != -1 || prefs.hex_text_wrap_align < 1) + return buf->indent; + + /* 1 = under the prefix (nick), 2 = under the message */ + off = ent->stamp_len; + if (prefs.hex_text_wrap_align >= 2) + { + /* the nick (or "*") is the first word after the timestamp */ + while (off < ent->str_len && ent->str[off] != ' ') + off++; + while (off < ent->str_len && ent->str[off] == ' ') + off++; + } + if (off <= 0 || off >= ent->str_len) + return buf->indent; + + w = ent->indent + gtk_xtext_text_width (buf->xtext, ent->str, off); + /* leave room for the text, or just wrap normally */ + if (w > (buf->window_width - MARGIN) / 2) + return buf->indent; + return w; +} + static int find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent) { @@ -1414,7 +1446,7 @@ gtk_xtext_find_x (GtkXText * xtext, int x, textentry * ent, int subline, if (subline < 1) indent = ent->indent; else - indent = xtext->buffer->indent; + indent = gtk_xtext_cont_indent (xtext->buffer, ent); if (line > gtk_adjustment_get_page_size (xtext->adj) || line < 0) { @@ -4035,7 +4067,7 @@ gtk_xtext_render_line (GtkXText * xtext, textentry * ent, int line, taken--; } - indent = xtext->buffer->indent; + indent = gtk_xtext_cont_indent (xtext->buffer, ent); line++; taken++; str += len; @@ -4296,7 +4328,7 @@ gtk_xtext_lines_taken (xtext_buffer *buf, textentry *ent) str += len; end = str - ent->str; g_array_append_val (ent->sublines, end); - indent = buf->indent; + indent = gtk_xtext_cont_indent (buf, ent); } while (str < ent->str + ent->str_len); } @@ -5376,6 +5408,7 @@ gtk_xtext_append_indent (xtext_buffer *buf, prefix_width = gtk_xtext_text_width (buf->xtext, str, left_len + 1); ent->left_len = left_len; + ent->stamp_len = 0; ent->str = str; ent->str_len = left_len + 1 + right_len; ent->indent = buf->indent - prefix_width; @@ -5421,6 +5454,14 @@ gtk_xtext_append_indent (xtext_buffer *buf, void gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp) +{ + gtk_xtext_append_wrap (buf, text, len, stamp, 0); +} + +/* stamp_len: how many bytes at the start of text are the timestamp */ + +void +gtk_xtext_append_wrap (xtext_buffer *buf, unsigned char *text, int len, time_t stamp, int stamp_len) { textentry *ent; @@ -5438,6 +5479,7 @@ gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp) memcpy (ent->str, text, len); ent->indent = 0; ent->left_len = -1; + ent->stamp_len = (stamp_len > 0 && stamp_len < ent->str_len) ? stamp_len : 0; gtk_xtext_append_entry (buf, ent, stamp); } @@ -5474,7 +5516,7 @@ gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area) } else { - gtk_xtext_append (out, ent->str, ent->str_len, 0); + gtk_xtext_append_wrap (out, ent->str, ent->str_len, 0, ent->stamp_len); } if (out->text_last) diff --git a/src/fe-gtk/xtext.h b/src/fe-gtk/xtext.h index fdd442a9..eec6178f 100644 --- a/src/fe-gtk/xtext.h +++ b/src/fe-gtk/xtext.h @@ -281,6 +281,7 @@ struct _GtkXTextClass GtkWidget *gtk_xtext_new (const XTextColor *palette, int separator); void gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp); +void gtk_xtext_append_wrap (xtext_buffer *buf, unsigned char *text, int len, time_t stamp, int stamp_len); void gtk_xtext_append_indent (xtext_buffer *buf, unsigned char *left_text, int left_len, unsigned char *right_text, int right_len,