From 22908f34cb7927e73fc03de3909ed45f3860f5c3 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Mon, 2 Jan 2006 17:56:45 +0000 Subject: [PATCH] Added matching --- gnoemoe/gm-triggers.c | 163 ++++++++++++++++++++++++++++++++++++++++++ gnoemoe/gm-triggers.h | 87 ++++++++++++---------- 2 files changed, 212 insertions(+), 38 deletions(-) diff --git a/gnoemoe/gm-triggers.c b/gnoemoe/gm-triggers.c index eae6b1c..a1e94c8 100644 --- a/gnoemoe/gm-triggers.c +++ b/gnoemoe/gm-triggers.c @@ -199,6 +199,169 @@ gm_trigger_set_actions(GmTrigger *trigger, GList *actions) { trigger->actions = actions; } +gboolean +gm_trigger_match_user(GmTrigger *trigger, gchar const *username, + GmTriggerConditionType condition, regmatch_t *matches, gint nmatch) { + GmTriggerData *data; + GList *item; + gint cmatch = 0, offset, ret; + + if (!trigger->conditions) { + return FALSE; + } + + for (item = trigger->conditions; item; item = item->next) { + data = (GmTriggerData *)(item->data); + + if (cmatch >= nmatch) { + return FALSE; + } + + if (data->type == condition) { + offset = 0; + ret = regexec(&(data->expr), (char *)(username), + (nmatch - cmatch) - 1, matches + cmatch, 0); + + if (ret == 0) { + while (matches[cmatch].rm_so != -1) { + matches[cmatch].rm_eo = matches[cmatch].rm_eo - + matches[cmatch].rm_so; + matches[cmatch].rm_so = matches[cmatch].rm_so + offset; + cmatch++; + } + } else { + return FALSE; + } + } else { + return FALSE; + } + } + + return TRUE; +} + +gboolean +gm_trigger_match(GmTrigger *trigger, gchar *text, regmatch_t *matches, + gint nmatch) { + GmTriggerData *data; + GList *item; + gchar *tmp; + gboolean istrue; + gint cmatch = 0, ret, offset, len; + + if (!trigger->conditions) { + return FALSE; + } + + for (item = trigger->conditions; item; item = item->next) { + data = (GmTriggerData *)(item->data); + len = g_utf8_strlen(data->data, -1); + + if (cmatch >= nmatch) { + return FALSE; + } + + switch (data->type) { + case TCT_CONTAINS: case TCT_NOT_CONTAINS: case TCT_BEGINS: + case TCT_NOT_BEGINS: case TCT_ENDS: case TCT_NOT_ENDS: + tmp = strstr(text, data->data); + + switch (data->type) { + case TCT_CONTAINS: + if (tmp != NULL) { + while (tmp != NULL && cmatch < nmatch) { + matches[cmatch].rm_so = + g_utf8_pointer_to_offset(text, tmp); + matches[cmatch].rm_eo = len; + tmp = strstr(tmp + len, data->data); + + if (tmp != NULL) { + ++cmatch; + } + } + } else { + return FALSE; + } + break; + case TCT_NOT_CONTAINS: + if (tmp == NULL) { + matches[cmatch].rm_so = 0; + matches[cmatch].rm_eo = len; + } else { + return FALSE; + } + break; + case TCT_NOT_BEGINS: + if (tmp != text) { + matches[cmatch].rm_so = 0; + matches[cmatch].rm_eo = g_utf8_strlen(text, -1); + } else { + return FALSE; + } + break; + default: + istrue = (tmp != NULL && + (g_utf8_pointer_to_offset(text, tmp) + len) == + g_utf8_strlen(text, -1)); + if (istrue && data->type == TCT_ENDS) { + matches[cmatch].rm_so = + g_utf8_pointer_to_offset(text, tmp); + matches[cmatch].rm_eo = len; + } else if (!istrue && data->type == TCT_NOT_ENDS) { + matches[cmatch].rm_so = 0; + matches[cmatch].rm_eo = g_utf8_strlen(text, -1); + } else { + return FALSE; + } + } + + cmatch++; + matches[cmatch].rm_so = -1; + break; + case TCT_MATCHES: case TCT_NOT_MATCHES: + offset = 0; + ret = regexec(&(data->expr), (char *)text, + (nmatch - cmatch) - 1, matches + cmatch, 0); + + if (ret == 0 && data->type == TCT_MATCHES) { + while (ret == 0) { + while (matches[cmatch].rm_so != -1) { + matches[cmatch].rm_eo = matches[cmatch].rm_eo - + matches[cmatch].rm_so; + matches[cmatch].rm_so = matches[cmatch].rm_so + + offset; + ++cmatch; + } + + offset = matches[cmatch - 1].rm_so + + matches[cmatch - 1].rm_eo; + + if (cmatch < nmatch) { + ret = regexec(&(data->expr), + (char *)(text + offset), + (nmatch - cmatch) - 1, + matches + cmatch, + 0); + } else { + ret = 1; + } + } + } else if (ret != 0 && data->type == TCT_NOT_MATCHES) { + matches[cmatch].rm_so = 0; + matches[cmatch].rm_eo = g_utf8_strlen(text, -1); + } else { + return FALSE; + } + break; + default: + return FALSE; + break; + } + } + + return TRUE; +} + gint gm_trigger_type_from_name(const gchar *name, const trigger_trans *trans_table) { diff --git a/gnoemoe/gm-triggers.h b/gnoemoe/gm-triggers.h index c2f9196..ef961e4 100644 --- a/gnoemoe/gm-triggers.h +++ b/gnoemoe/gm-triggers.h @@ -10,13 +10,19 @@ G_BEGIN_DECLS /* * Type checking and casting macros */ -#define GM_TYPE_TRIGGERS (gm_triggers_get_type()) -#define GM_TRIGGERS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GM_TYPE_TRIGGERS, GmTriggers)) -#define GM_TRIGGERS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GM_TYPE_TRIGGERS, GmTriggers const)) -#define GM_TRIGGERS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GM_TYPE_TRIGGERS, GmTriggersClass)) -#define GM_IS_TRIGGERS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GM_TYPE_TRIGGERS)) -#define GM_IS_TRIGGERS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GM_TYPE_TRIGGERS)) -#define GM_TRIGGERS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GM_TYPE_TRIGGERS, GmTriggersClass)) +#define GM_TYPE_TRIGGERS (gm_triggers_get_type()) +#define GM_TRIGGERS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_TRIGGERS, GmTriggers)) +#define GM_TRIGGERS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_TRIGGERS, GmTriggers const)) +#define GM_TRIGGERS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_TRIGGERS, GmTriggersClass)) +#define GM_IS_TRIGGERS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_TRIGGERS)) +#define GM_IS_TRIGGERS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_TRIGGERS)) +#define GM_TRIGGERS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_TRIGGERS, GmTriggersClass)) /* Private structure type */ typedef struct _GmTriggersPrivate GmTriggersPrivate; @@ -45,49 +51,49 @@ struct _GmTriggersClass { }; typedef enum _GmTriggerType { - TT_OUTPUT = 0, - TT_USERS + TT_OUTPUT = 0, + TT_USERS } GmTriggerType; typedef enum _GmTriggerConditionType { - TCT_CONTAINS = 0, - TCT_NOT_CONTAINS, - TCT_BEGINS, - TCT_NOT_BEGINS, - TCT_ENDS, - TCT_NOT_ENDS, - TCT_MATCHES, - TCT_NOT_MATCHES, - TCT_USER_ONLINE, - TCT_USER_OFFLINE, - TCT_USER_IDLE, - TCT_USER_IDLE_OFF, - TCT_USER_AWAY, - TCT_USER_AWAY_OFF + TCT_CONTAINS = 0, + TCT_NOT_CONTAINS, + TCT_BEGINS, + TCT_NOT_BEGINS, + TCT_ENDS, + TCT_NOT_ENDS, + TCT_MATCHES, + TCT_NOT_MATCHES, + TCT_USER_ONLINE, + TCT_USER_OFFLINE, + TCT_USER_IDLE, + TCT_USER_IDLE_OFF, + TCT_USER_AWAY, + TCT_USER_AWAY_OFF } GmTriggerConditionType; typedef enum _GmTriggerActionType { - TAT_HIGHLIGHT_LINE = 0, - TAT_HIGHLIGHT_MATCH, - TAT_BEEP, - TAT_PLAY_SOUND, - TAT_NOTIFY, - TAT_RUN_SCRIPT, - TAT_RUN + TAT_HIGHLIGHT_LINE = 0, + TAT_HIGHLIGHT_MATCH, + TAT_BEEP, + TAT_PLAY_SOUND, + TAT_NOTIFY, + TAT_RUN_SCRIPT, + TAT_RUN } GmTriggerActionType; typedef struct _GmTriggerData { - gint type; - gchar *data; - regex_t expr; + guint type; + gchar *data; + regex_t expr; } GmTriggerData; typedef struct _GmTrigger { - gchar *name; - GmTriggerType event; - - GList *conditions; - GList *actions; + gchar *name; + GmTriggerType event; + + GList *conditions; + GList *actions; } GmTrigger; GType gm_triggers_get_type(void) G_GNUC_CONST; @@ -111,6 +117,11 @@ void gm_trigger_add_action(GmTrigger *trigger, GmTriggerData *action); void gm_trigger_set_conditions(GmTrigger *trigger, GList *conditions); void gm_trigger_set_actions(GmTrigger *trigger, GList *actions); +gboolean gm_trigger_match_user(GmTrigger *trigger, gchar const *username, + GmTriggerConditionType condition, regmatch_t *matches, gint nmatch); +gboolean gm_trigger_match(GmTrigger *trigger, gchar *text, regmatch_t *matches, + gint nmatch); + GmTriggerData *gm_trigger_data_new(gint type, gchar *data); void gm_trigger_data_free(GmTriggerData *tdata);