6 Commits

Author SHA1 Message Date
bdee1481ed version bump for minor fix (auto replace) 2026-01-13 14:38:07 -07:00
3ffa020c2c Fixed auto replace. Now will handle auto replace no matter where or how the text is put in. 2026-01-13 14:16:40 -07:00
deepend-tildeclub
24ac7c8167 Update homepage and help URLs in appdata file 2026-01-13 01:44:35 -07:00
deepend-tildeclub
1b0487faa8 Update screenshot URL in appdata XML 2026-01-13 01:31:40 -07:00
deepend-tildeclub
fed2525c7a Update APPCAST_URL to new GitHub location 2026-01-13 00:58:14 -07:00
deepend-tildeclub
0662c39c19 Update version from 2.12.4 to 2.17.1 2026-01-13 00:54:39 -07:00
7 changed files with 95 additions and 59 deletions

View File

@@ -12,12 +12,12 @@
<p>ZoiteChat is an easy to use yet extensible IRC Client based on Hexchat. It allows you to securely join multiple networks and talk to users privately or in channels using a customizable interface. You can even transfer files.</p> <p>ZoiteChat is an easy to use yet extensible IRC Client based on Hexchat. It allows you to securely join multiple networks and talk to users privately or in channels using a customizable interface. You can even transfer files.</p>
<p>ZoiteChat supports features such as: DCC, SASL, proxies, spellcheck, alerts, logging, custom themes, and Python/Perl scripts.</p> <p>ZoiteChat supports features such as: DCC, SASL, proxies, spellcheck, alerts, logging, custom themes, and Python/Perl scripts.</p>
</description> </description>
<url type="homepage">http://zoitechat.zoite.net</url> <url type="homepage">http://zoitechat.github.io</url>
<url type="bugtracker">https://github.com/zoitechat/zoitechat</url> <url type="bugtracker">https://github.com/zoitechat/zoitechat</url>
<url type="help">https://zoitechat.zoite.net/docs/en/latest/</url> <url type="help">https://hexchat.readthedocs.io/en/latest/</url>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot type="default">
<image>http://i.imgur.com/tLMguQz.png</image> <image>https://zoitechat.github.io/assets/ZoiteChat.png</image>
<caption>Main Chat Window</caption> <caption>Main Chat Window</caption>
</screenshot> </screenshot>
</screenshots> </screenshots>
@@ -25,9 +25,17 @@
<id>zoitechat.desktop</id> <id>zoitechat.desktop</id>
</provides> </provides>
<releases> <releases>
<release date="2026-01-13" version="2.17.2">
<description>
<p>This is a release with small fixes:</p>
<ul>
<li>Changes to Auto Replace. Will make matches in almost any scenario, Pasted, typed, beginning, end or middle of words/scentences etc.</li>
</ul>
</description>
</release>
<release date="2026-01-12" version="2.17.1"> <release date="2026-01-12" version="2.17.1">
<description> <description>
<p>This is a pre-release with small improvements and fixes:</p> <p>This is a release with small improvements and fixes:</p>
<ul> <ul>
<li>First implementation of dark mode.</li> <li>First implementation of dark mode.</li>
</ul> </ul>

View File

@@ -1,5 +1,5 @@
project('zoitechat', 'c', project('zoitechat', 'c',
version: '2.17.1', version: '2.17.2',
meson_version: '>= 0.47.0', meson_version: '>= 0.47.0',
default_options: [ default_options: [
'c_std=gnu89', 'c_std=gnu89',

View File

@@ -24,7 +24,7 @@
#include "zoitechat-plugin.h" #include "zoitechat-plugin.h"
#define APPCAST_URL "https://zoitechat.zoite.net/appcast.xml" #define APPCAST_URL "https://zoitechat.github.io/appcast.xml"
static zoitechat_plugin *ph; /* plugin handle */ static zoitechat_plugin *ph; /* plugin handle */
static char name[] = "Update Checker"; static char name[] = "Update Checker";

View File

@@ -23,6 +23,7 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h> #include <ctype.h>
#include <stddef.h>
#ifdef WIN32 #ifdef WIN32
#include <io.h> #include <io.h>
@@ -53,6 +54,7 @@
#include "fkeys.h" #include "fkeys.h"
static void replace_handle (GtkWidget * wid); static void replace_handle (GtkWidget * wid);
void key_check_replace_on_change (GtkEditable *editable, gpointer data);
void key_action_tab_clean (void); void key_action_tab_clean (void);
/***************** Key Binding Code ******************/ /***************** Key Binding Code ******************/
@@ -1773,71 +1775,94 @@ key_action_put_history (GtkWidget * wid, GdkEventKey * ent, char *d1,
static void static void
replace_handle (GtkWidget *t) replace_handle (GtkWidget *t)
{ {
const char *text, *postfix_pnt; const char *text;
struct popup *pop; struct popup *pop;
GSList *list = replace_list; GSList *list = replace_list;
char word[256]; glong cursor_pos;
char postfix[256]; const char *cursor_ptr;
char outbuf[4096]; const char *match_start;
int c, len, xlen; GString *buf;
gboolean matched;
size_t replacement_len;
size_t match_len;
ptrdiff_t cursor_byte_offset;
ptrdiff_t match_start_offset;
ptrdiff_t match_end_offset;
ptrdiff_t new_cursor_offset;
const char *best_match;
size_t best_len;
struct popup *best_pop;
text = SPELL_ENTRY_GET_TEXT (t); text = SPELL_ENTRY_GET_TEXT (t);
len = strlen (text); if (!text || text[0] == '\0')
if (len < 1)
return; return;
for (c = len - 1; c > 0; c--) cursor_pos = SPELL_ENTRY_GET_POS (t);
{ cursor_ptr = g_utf8_offset_to_pointer (text, cursor_pos);
if (text[c] == ' ') matched = FALSE;
break; match_start = NULL;
} match_len = 0;
if (text[c] == ' ') best_match = NULL;
c++; best_len = 0;
xlen = c; best_pop = NULL;
if (len - c >= (sizeof (word) - 12))
return;
if (len - c < 1)
return;
memcpy (word, &text[c], len - c);
word[len - c] = 0;
len = strlen (word);
if (word[0] == '\'' && word[len] == '\'')
return;
postfix_pnt = NULL;
for (c = 0; c < len; c++)
{
if (word[c] == '\'')
{
postfix_pnt = &word[c + 1];
word[c] = 0;
break;
}
}
if (postfix_pnt != NULL)
{
if (strlen (postfix_pnt) > sizeof (postfix) - 12)
return;
strcpy (postfix, postfix_pnt);
}
while (list) while (list)
{ {
pop = (struct popup *) list->data; pop = (struct popup *) list->data;
if (strcmp (pop->name, word) == 0) if (pop->name[0] != '\0')
{ {
memcpy (outbuf, text, xlen); size_t pop_len = strlen (pop->name);
outbuf[xlen] = 0; const char *found = strstr (text, pop->name);
if (postfix_pnt == NULL)
g_snprintf (word, sizeof (word), "%s", pop->cmd); if (found && (!best_match || found < best_match))
else {
g_snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix); best_match = found;
g_strlcat (outbuf, word, sizeof(outbuf)); best_len = pop_len;
SPELL_ENTRY_SET_TEXT (t, outbuf); best_pop = pop;
SPELL_ENTRY_SET_POS (t, -1); }
return;
} }
list = list->next; list = list->next;
} }
if (best_match)
{
match_start = best_match;
match_len = best_len;
pop = best_pop;
matched = TRUE;
}
if (!matched)
return;
replacement_len = strlen (pop->cmd);
cursor_byte_offset = cursor_ptr - text;
match_start_offset = match_start - text;
match_end_offset = match_start_offset + (ptrdiff_t) match_len;
if (cursor_byte_offset <= match_start_offset)
new_cursor_offset = cursor_byte_offset;
else if (cursor_byte_offset >= match_end_offset)
new_cursor_offset = cursor_byte_offset + ((ptrdiff_t) replacement_len - (ptrdiff_t) match_len);
else
new_cursor_offset = match_start_offset + (ptrdiff_t) replacement_len;
buf = g_string_sized_new (strlen (text) + 32);
g_string_append_len (buf, text, match_start - text);
g_string_append (buf, pop->cmd);
g_string_append (buf, match_start + match_len);
SPELL_ENTRY_SET_TEXT (t, buf->str);
SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, new_cursor_offset));
g_string_free (buf, TRUE);
} }
void
key_check_replace_on_change (GtkEditable *editable, gpointer data)
{
static gboolean replace_in_progress = FALSE;
if (replace_in_progress)
return;
replace_in_progress = TRUE;
replace_handle (GTK_WIDGET (editable));
replace_in_progress = FALSE;
}

View File

@@ -34,5 +34,6 @@ void key_dialog_show (void);
int key_handle_key_press (GtkWidget * wid, GdkEventKey * evt, session *sess); int key_handle_key_press (GtkWidget * wid, GdkEventKey * evt, session *sess);
int key_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, int key_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2,
session *sess); session *sess);
void key_check_replace_on_change (GtkEditable *editable, gpointer data);
#endif #endif

View File

@@ -3002,6 +3002,8 @@ mg_create_entry (session *sess, GtkWidget *box)
gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 0); gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 0);
g_signal_connect (G_OBJECT (entry), "activate", g_signal_connect (G_OBJECT (entry), "activate",
G_CALLBACK (mg_inputbox_cb), gui); G_CALLBACK (mg_inputbox_cb), gui);
g_signal_connect (G_OBJECT (entry), "changed",
G_CALLBACK (key_check_replace_on_change), NULL);
gtk_container_add (GTK_CONTAINER (hbox), entry); gtk_container_add (GTK_CONTAINER (hbox), entry);
gtk_widget_set_name (entry, "zoitechat-inputbox"); gtk_widget_set_name (entry, "zoitechat-inputbox");

View File

@@ -1 +1 @@
2.12.4 2.17.2