1
0
mirror of https://github.com/moparisthebest/hexchat synced 2024-11-29 20:52:16 -05:00

Parse attributes in the input box

This commit is contained in:
TingPing 2013-10-01 07:03:53 -04:00
parent 3cb4439121
commit af2458f556
3 changed files with 226 additions and 30 deletions

View File

@ -86,7 +86,6 @@ GdkColor colors[] = {
{0, 0x8888, 0x8a8a, 0x8585}, /* 40 away user (grey) */ {0, 0x8888, 0x8a8a, 0x8585}, /* 40 away user (grey) */
{0, 0xa4a4, 0x0000, 0x0000}, /* 41 spell checker color (red) */ {0, 0xa4a4, 0x0000, 0x0000}, /* 41 spell checker color (red) */
}; };
#define MAX_COL 41
void void

View File

@ -32,6 +32,7 @@ extern GdkColor colors[];
#define COL_NEW_MSG 39 #define COL_NEW_MSG 39
#define COL_AWAY 40 #define COL_AWAY 40
#define COL_SPELL 41 #define COL_SPELL 41
#define MAX_COL 41
void palette_alloc (GtkWidget * widget); void palette_alloc (GtkWidget * widget);
void palette_load (void); void palette_load (void);

View File

@ -42,6 +42,7 @@
#include "../common/cfgfiles.h" #include "../common/cfgfiles.h"
#include "../common/hexchatc.h" #include "../common/hexchatc.h"
#include "xtext.h"
/* /*
* Bunch of poop to make enchant into a runtime dependency rather than a * Bunch of poop to make enchant into a runtime dependency rather than a
@ -275,7 +276,26 @@ gtk_entry_find_position (GtkEntry *entry, gint x)
} }
static void static void
insert_underline(SexySpellEntry *entry, guint start, guint end) insert_hiddenchar (SexySpellEntry *entry, guint start, guint end)
{
PangoAttribute *hattr;
PangoRectangle *rect = g_malloc (sizeof (PangoRectangle));
rect->x = 0;
rect->y = 0;
rect->width = 0;
rect->height = 0;
hattr = pango_attr_shape_new (rect, rect);
hattr->start_index = start;
hattr->end_index = end;
pango_attr_list_insert (entry->priv->attr_list, hattr);
g_free (rect);
}
static void
insert_underline_error (SexySpellEntry *entry, guint start, guint end)
{ {
int fh, l; int fh, l;
int red, green, blue; int red, green, blue;
@ -324,6 +344,72 @@ insert_underline(SexySpellEntry *entry, guint start, guint end)
pango_attr_list_insert (entry->priv->attr_list, unline); pango_attr_list_insert (entry->priv->attr_list, unline);
} }
static void
insert_underline (SexySpellEntry *entry, guint start, gboolean toggle)
{
PangoAttribute *uattr;
uattr = pango_attr_underline_new (toggle ? PANGO_UNDERLINE_NONE : PANGO_UNDERLINE_SINGLE);
uattr->start_index = start;
uattr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
pango_attr_list_change (entry->priv->attr_list, uattr);
}
static void
insert_bold (SexySpellEntry *entry, guint start, gboolean toggle)
{
PangoAttribute *battr;
battr = pango_attr_weight_new (toggle ? PANGO_WEIGHT_NORMAL : PANGO_WEIGHT_BOLD);
battr->start_index = start;
battr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
pango_attr_list_change (entry->priv->attr_list, battr);
}
static void
insert_italic (SexySpellEntry *entry, guint start, gboolean toggle)
{
PangoAttribute *iattr;
iattr = pango_attr_style_new (toggle ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC);
iattr->start_index = start;
iattr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
pango_attr_list_change (entry->priv->attr_list, iattr);
}
static void
insert_color (SexySpellEntry *entry, guint start, int fgcolor, int bgcolor)
{
PangoAttribute *fgattr;
PangoAttribute *bgattr;
if (fgcolor < 0 || fgcolor > MAX_COL)
fgattr = pango_attr_foreground_new (colors[COL_FG].red, colors[COL_FG].green, colors[COL_FG].blue);
else
fgattr = pango_attr_foreground_new (colors[fgcolor].red, colors[fgcolor].green, colors[fgcolor].blue);
if (bgcolor < 0 || bgcolor > MAX_COL)
bgattr = pango_attr_background_new (colors[COL_BG].red, colors[COL_BG].green, colors[COL_BG].blue);
else
bgattr = pango_attr_background_new (colors[bgcolor].red, colors[bgcolor].green, colors[bgcolor].blue);
fgattr->start_index = start;
fgattr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
pango_attr_list_change (entry->priv->attr_list, fgattr);
bgattr->start_index = start;
bgattr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
pango_attr_list_change (entry->priv->attr_list, bgattr);
}
static void
insert_reset (SexySpellEntry *entry, guint start)
{
insert_bold (entry, start, TRUE);
insert_underline (entry, start, TRUE);
insert_italic (entry, start, TRUE);
insert_color (entry, start, -1, -1);
}
static void static void
get_word_extents_from_position(SexySpellEntry *entry, gint *start, gint *end, guint position) get_word_extents_from_position(SexySpellEntry *entry, gint *start, gint *end, guint position)
{ {
@ -785,7 +871,119 @@ check_word(SexySpellEntry *entry, int start, int end)
pango_attr_iterator_destroy(it); pango_attr_iterator_destroy(it);
if (word_misspelled(entry, start, end)) if (word_misspelled(entry, start, end))
insert_underline(entry, start, end); insert_underline_error(entry, start, end);
}
static void
check_attributes (SexySpellEntry *entry, char *text, int len)
{
PangoAttribute *attr;
PangoAttrList *attr_list = entry->priv->attr_list;
gboolean bold = FALSE;
gboolean italic = FALSE;
gboolean underline = FALSE;
int parsing_color = 0;
char fg_color[3];
char bg_color[3];
int i, bg_offset, fg_offset = 0;
memset (bg_color, 0, sizeof(bg_color));
memset (fg_color, 0, sizeof(fg_color));
for (i = 0; i < len; i++)
{
switch (text[i])
{
case ATTR_BOLD:
insert_hiddenchar (entry, i, i + 1);
insert_bold (entry, i, bold);
bold = !bold;
break;
case ATTR_ITALICS:
insert_italic (entry, i, italic);
italic = !italic;
break;
case ATTR_UNDERLINE:
insert_underline (entry, i, underline);
underline = !underline;
break;
case ATTR_RESET:
insert_hiddenchar (entry, i, i + 1);
insert_reset (entry, i);
break;
case ATTR_COLOR:
parsing_color = 1;
break;
default:
if (!parsing_color)
continue;
if (!g_unichar_isdigit (text[i]))
{
if (text[i] == ',' && parsing_color <= 3)
{
parsing_color = 3;
continue;
}
else
parsing_color = 5;
}
switch (parsing_color)
{
case 1:
fg_color[0] = text[i];
parsing_color++;
fg_offset = 2;
continue;
case 2:
fg_color[1] = text[i];
parsing_color++;
fg_offset++;
continue;
case 3:
bg_color[0] = text[i];
parsing_color++;
bg_offset = 3 + fg_offset; /* 1 extra for , */
continue;
case 4:
bg_color[1] = text[i];
parsing_color++;
bg_offset++;
continue;
case 5:
if (bg_color[0] != 0)
{
insert_hiddenchar (entry, i - bg_offset, i);
insert_color (entry, i, atoi (fg_color), atoi (bg_color));
}
else if (fg_color[0] != 0)
{
insert_hiddenchar (entry, i - fg_offset, i);
insert_color (entry, i, atoi (fg_color), -1);
}
else
{
insert_hiddenchar (entry, i - 1, i);
insert_color (entry, i, -1, -1);
}
memset (bg_color, 0, sizeof(bg_color));
memset (fg_color, 0, sizeof(fg_color));
parsing_color = 0;
fg_offset = 0;
continue;
default:
insert_hiddenchar (entry, i - 1, i);
insert_color (entry, i, -1, -1);
}
}
}
} }
static void static void
@ -794,25 +992,30 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
GdkRectangle rect; GdkRectangle rect;
GtkWidget *widget = GTK_WIDGET(entry); GtkWidget *widget = GTK_WIDGET(entry);
PangoLayout *layout; PangoLayout *layout;
int length, i; int length, i, text_len;
char *text;
if ((have_enchant == FALSE) || (entry->priv->checked == FALSE))
return;
if (g_slist_length(entry->priv->dict_list) == 0)
return;
/* Remove all existing pango attributes. These will get readded as we check */ /* Remove all existing pango attributes. These will get readded as we check */
pango_attr_list_unref(entry->priv->attr_list); pango_attr_list_unref(entry->priv->attr_list);
entry->priv->attr_list = pango_attr_list_new(); entry->priv->attr_list = pango_attr_list_new();
if (have_enchant && entry->priv->checked
&& g_slist_length (entry->priv->dict_list) != 0)
{
/* Loop through words */ /* Loop through words */
for (i = 0; entry->priv->words[i]; i++) { for (i = 0; entry->priv->words[i]; i++)
{
length = strlen (entry->priv->words[i]); length = strlen (entry->priv->words[i]);
if (length == 0) if (length == 0)
continue; continue;
check_word (entry, entry->priv->word_starts[i], entry->priv->word_ends[i]); check_word (entry, entry->priv->word_starts[i], entry->priv->word_ends[i]);
} }
}
/* Check for attributes */
text = gtk_entry_get_text (GTK_ENTRY (entry));
text_len = gtk_entry_get_text_length (GTK_ENTRY (entry));
check_attributes (entry, text, text_len);
layout = gtk_entry_get_layout(GTK_ENTRY(entry)); layout = gtk_entry_get_layout(GTK_ENTRY(entry));
pango_layout_set_attributes(layout, entry->priv->attr_list); pango_layout_set_attributes(layout, entry->priv->attr_list);
@ -832,10 +1035,9 @@ sexy_spell_entry_expose(GtkWidget *widget, GdkEventExpose *event)
GtkEntry *gtk_entry = GTK_ENTRY(widget); GtkEntry *gtk_entry = GTK_ENTRY(widget);
PangoLayout *layout; PangoLayout *layout;
if (entry->priv->checked) {
layout = gtk_entry_get_layout(gtk_entry); layout = gtk_entry_get_layout(gtk_entry);
pango_layout_set_attributes(layout, entry->priv->attr_list); pango_layout_set_attributes(layout, entry->priv->attr_list);
}
return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event); return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event);
} }
@ -915,12 +1117,9 @@ static void
sexy_spell_entry_changed(GtkEditable *editable, gpointer data) sexy_spell_entry_changed(GtkEditable *editable, gpointer data)
{ {
SexySpellEntry *entry = SEXY_SPELL_ENTRY(editable); SexySpellEntry *entry = SEXY_SPELL_ENTRY(editable);
if (entry->priv->checked == FALSE)
return;
if (g_slist_length(entry->priv->dict_list) == 0)
return;
if (entry->priv->words) { if (entry->priv->words)
{
g_strfreev(entry->priv->words); g_strfreev(entry->priv->words);
g_free(entry->priv->word_starts); g_free(entry->priv->word_starts);
g_free(entry->priv->word_ends); g_free(entry->priv->word_ends);
@ -1329,11 +1528,8 @@ sexy_spell_entry_set_checked(SexySpellEntry *entry, gboolean checked)
PangoLayout *layout; PangoLayout *layout;
GdkRectangle rect; GdkRectangle rect;
pango_attr_list_unref(entry->priv->attr_list); /* This will unmark any existing */
entry->priv->attr_list = pango_attr_list_new(); sexy_spell_entry_recheck_all (entry);
layout = gtk_entry_get_layout(GTK_ENTRY(entry));
pango_layout_set_attributes(layout, entry->priv->attr_list);
rect.x = 0; rect.y = 0; rect.x = 0; rect.y = 0;
rect.width = widget->allocation.width; rect.width = widget->allocation.width;