--- a/completion-sorting.diff Wed Oct 17 03:07:22 2012 +0300
+++ b/completion-sorting.diff Thu Oct 18 02:18:10 2012 +0300
@@ -1,5 +1,5 @@
# HG changeset patch
-# Parent 3c7cebacae165329047f6859c26224e9c8a67807
+# Parent f8958ab545ac1af3e3fbc3b3b025de66fd1ffa51
Make completion sorting order configurable
* Use allocated plain array for categories
@@ -10,9 +10,9 @@
* [todo] Reallocate array, when need more completions
* [todo] Design and publish interface to dynamic completion cbs
-diff -r 3c7cebacae16 mcabber/mcabber/compl.c
---- a/mcabber/mcabber/compl.c Wed Oct 17 02:33:43 2012 +0300
-+++ b/mcabber/mcabber/compl.c Wed Oct 17 03:00:30 2012 +0300
+diff -r f8958ab545ac mcabber/mcabber/compl.c
+--- a/mcabber/mcabber/compl.c Mon Oct 15 19:53:02 2012 +0200
++++ b/mcabber/mcabber/compl.c Thu Oct 18 00:00:39 2012 +0300
@@ -2,7 +2,7 @@
* compl.c -- Completion system
*
@@ -22,7 +22,7 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
-@@ -47,49 +47,96 @@
+@@ -47,49 +47,97 @@
GSList *next; // pointer to next completion to try
} compl;
@@ -80,10 +80,11 @@
+}
+
+static inline void register_builtin_cat(guint c, compl_handler_t dynamic) {
-+ Categories[c-1].flags = COMPL_CAT_BUILTIN | COMPL_CAT_ACTIVE;
++ Categories[c-1].flags = COMPL_CAT_BUILTIN | COMPL_CAT_ACTIVE;
++ Categories[c-1].words = NULL;
++ Categories[c-1].dynamic = dynamic;
+ if (dynamic != NULL) {
+ Categories[c-1].flags |= COMPL_CAT_DYNAMIC;
-+ Categories[c-1].dynamic = dynamic;
+ }
}
@@ -94,7 +95,7 @@
+#else
+ num_categories = COMPL_MODULE;
+#endif
-+ Categories = g_new0(category, num_categories);
++ Categories = g_new(category, num_categories);
+
// Builtin completion categories:
- register_builtin_cat(COMPL_CMD);
@@ -147,7 +148,7 @@
// compl_new_category()
// Reserves id for new completion category.
// Returns 0, if no more categories can be allocated.
-@@ -97,32 +144,68 @@
+@@ -97,32 +145,87 @@
// as it is likely to change in future.
guint compl_new_category(void)
{
@@ -168,8 +169,19 @@
+ return i+1;
+ }
}
-+ // XXX realloc
-+ scr_log_print(LPRINT_LOGNORM, "Warning: run out of completion categories!");
++ {
++ guint new_num = num_categories + 16; // *2?
++ category *new_categories = g_try_renew(category, Categories, new_num);
++ if (new_categories) {
++ Categories = new_categories;
++ num_categories = new_num;
++ Categories[i].flags = COMPL_CAT_ACTIVE;
++ Categories[i].words = NULL;
++ return i+1;
++ } else
++ scr_log_print(LPRINT_LOGNORM, "Warning: Unable to reallocate "
++ "more memory for completion categories!");
++ }
+ return 0;
}
@@ -181,15 +193,20 @@
+void compl_del_category(guint compl)
{
- if (!id) {
+- scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category() - "
+- "Invalid category.");
++ GSList *wel;
++
+ if (!compl) {
- scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category() - "
-- "Invalid category.");
-+ "Invalid category.");
++ scr_log_print(LPRINT_DEBUG, "Error: compl_del_category() - "
++ "Invalid category.");
return;
}
- id--;
- registered_cats &= ~(1<<id);
++
+ compl--;
++
+ if ((compl >= num_categories) ||
+ (Categories[compl].flags & COMPL_CAT_BUILTIN)) {
+ scr_log_print(LPRINT_DEBUG, "Error: compl_del_category() "
@@ -198,39 +215,80 @@
+ }
+
+ Categories[compl].flags = 0;
-+ // XXX free words
++ for (wel = Categories[compl].words; wel; wel = g_slist_next (wel))
++ g_free (wel -> data);
++ g_slist_free (Categories[compl].words);
+}
+
-+// compl_set_sorting_order(category,order)
++// compl_set_flags (category, flags)
+// Sets sorting order for given category.
+// In future can be merged with new_category, set more flags,
+// maybe even set dynamic callback.
+void compl_set_flags(guint compl, guint new_flags)
+{
+ if (!compl) {
-+ scr_log_print(LPRINT_LOGNORM, "Error: compl_set_flags() - "
-+ "Invalid category.");
++ scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - "
++ "Invalid category.");
+ return;
+ }
++
+ compl--;
++
+ if (compl < num_categories) {
+ guint flags = Categories[compl].flags;
+ if (flags & COMPL_CAT_BUILTIN)
+ scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - "
-+ "Invalid category.");
++ "Rejecting builtin category.");
+ else if (!(flags & COMPL_CAT_ACTIVE))
+ scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - "
-+ "Invalid category.");
++ "Not existing category.");
+ else
+ Categories[compl].flags = (flags & ~COMPL_CAT_USERFLAGS)
+ | ((new_flags << 2) & COMPL_CAT_USERFLAGS);
+ } else
+ scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - "
-+ "Invalid category.");
++ "Not existing category.");
}
#endif
-@@ -222,13 +305,30 @@
+@@ -136,12 +239,15 @@
+ guint new_completion(const char *prefix, GSList *compl_cat, const gchar *suffix)
+ {
+ compl *c;
++ guint ret_len = 0;
+ GSList *sl_cat;
+ gint (*cmp)(const char *s1, const char *s2, size_t n);
+ size_t len = strlen(prefix);
+
+ if (InputCompl) { // This should not happen, but hey...
+- cancel_completion();
++ scr_log_print(LPRINT_DEBUG, "Warinng: new_completion() - "
++ "Previous completion exists!");
++ done_completion();
+ }
+
+ if (settings_opt_get_int("completion_ignore_case"))
+@@ -160,14 +266,15 @@
+ compval = g_strdup_printf("%s%s", word+len, suffix);
+ else
+ compval = g_strdup(word+len);
+- c->list = g_slist_insert_sorted(c->list, compval,
+- (GCompareFunc)g_ascii_strcasecmp);
++ // for a bit of efficiency, will reverse order afterwards
++ c->list = g_slist_prepend(c->list, compval);
++ ret_len ++;
+ }
+ }
+ }
+- c->next = c->list;
++ c->next = c->list = g_slist_reverse (c->list);
+ InputCompl = c;
+- return g_slist_length(c->list);
++ return ret_len;
+ }
+
+ // done_completion();
+@@ -222,35 +329,46 @@
/* Categories functions */
@@ -264,7 +322,8 @@
char *nword;
if (!categ) {
-@@ -236,21 +336,15 @@
+- scr_log_print(LPRINT_LOGNORM, "Error: compl_add_category_word() - "
++ scr_log_print(LPRINT_DEBUG, "Error: compl_add_category_word() - "
"Invalid category.");
return;
}
@@ -278,10 +337,10 @@
- if (catv == ((category*)sl_cat->data)->flag)
- break;
+
-+ if ((categ > num_categories) ||
++ if ((categ >= num_categories) ||
+ !(Categories[categ].flags & COMPL_CAT_ACTIVE)) {
-+ scr_log_print(LPRINT_LOGNORM, "Error: compl_add_category_word() - "
-+ "Invalid category.");
++ scr_log_print(LPRINT_DEBUG, "Error: compl_add_category_word() - "
++ "Not existing category.");
+ return;
}
- if (!sl_cat) { // Category not found, let's create it
@@ -293,7 +352,7 @@
// If word is not space-terminated, we add one trailing space
for (nword = (char*)word; *nword; nword++)
-@@ -262,20 +356,28 @@
+@@ -262,59 +380,64 @@
nword = g_strdup(word);
}
@@ -325,11 +384,14 @@
- guint64 catv;
- GSList *sl_cat, *sl_elt;
- category *cat;
-+ GSList *sl_elt;
++ GSList *wel;
char *nword;
if (!categ) {
-@@ -285,16 +387,13 @@
+- scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category_word() - "
++ scr_log_print(LPRINT_DEBUG, "Error: compl_del_category_word() - "
+ "Invalid category.");
+ return;
}
categ--;
@@ -339,10 +401,10 @@
- for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
- if (catv == ((category*)sl_cat->data)->flag)
- break;
-+ if ((categ > num_categories) ||
++ if ((categ >= num_categories) ||
+ !(Categories[categ].flags & COMPL_CAT_ACTIVE)) {
-+ scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category_word() - "
-+ "Invalid category.");
++ scr_log_print(LPRINT_DEBUG, "Error: compl_del_category_word() - "
++ "Not existing category.");
+ return;
}
- if (!sl_cat) return; // Category not found, finished!
@@ -351,22 +413,40 @@
// If word is not space-terminated, we add one trailing space
for (nword = (char*)word; *nword; nword++)
-@@ -306,11 +405,12 @@
- nword = g_strdup(word);
+ ;
+ if (nword > word) nword--;
+- if (*nword != ' ') { // Add a space
+- nword = g_strdup_printf("%s ", word);
+- } else { // word is fine
+- nword = g_strdup(word);
++ if (*nword != ' ') // Add a space
++ word = nword = g_strdup_printf("%s ", word);
++ else
++ nword = NULL;
++
++ for (wel = Categories[categ].words; wel; wel = g_slist_next (wel)) {
++ if (!strcasecmp((char*)wel->data, word)) {
++ g_free(wel->data);
++ Categories[categ].words = g_slist_delete_link
++ (Categories[categ].words, wel);
++ break; // Only remove first occurence
++ }
}
- sl_elt = cat->words;
-+ sl_elt = Categories[categ].words;
- while (sl_elt) {
- if (!strcasecmp((char*)sl_elt->data, nword)) {
- g_free(sl_elt->data);
+- while (sl_elt) {
+- if (!strcasecmp((char*)sl_elt->data, nword)) {
+- g_free(sl_elt->data);
- cat->words = g_slist_delete_link(cat->words, sl_elt);
-+ Categories[categ].words = g_slist_delete_link
-+ (Categories[categ].words, sl_elt);
- break; // Only remove first occurence
- }
- sl_elt = g_slist_next(sl_elt);
-@@ -323,48 +423,28 @@
+- break; // Only remove first occurence
+- }
+- sl_elt = g_slist_next(sl_elt);
+- }
++ g_free (nword);
+ }
+
+ // compl_get_category_list()
+@@ -323,48 +446,28 @@
// whole list after use.
GSList *compl_get_category_list(guint categ, guint *dynlist)
{
@@ -374,7 +454,8 @@
- GSList *sl_cat;
-
if (!categ) {
- scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - "
+- scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - "
++ scr_log_print(LPRINT_DEBUG, "Error: compl_get_category_list() - "
"Invalid category.");
return NULL;
}
@@ -411,8 +492,8 @@
- return compl;
+ if ((categ > num_categories) ||
+ !(Categories[categ].flags & COMPL_CAT_ACTIVE)) {
-+ scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - "
-+ "Invalid category.");
++ scr_log_print(LPRINT_DEBUG, "Error: compl_get_category_list() - "
++ "Not existing category.");
+ return NULL;
}
@@ -428,9 +509,9 @@
}
/* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */
-diff -r 3c7cebacae16 mcabber/mcabber/compl.h
---- a/mcabber/mcabber/compl.h Wed Oct 17 02:33:43 2012 +0300
-+++ b/mcabber/mcabber/compl.h Wed Oct 17 03:00:30 2012 +0300
+diff -r f8958ab545ac mcabber/mcabber/compl.h
+--- a/mcabber/mcabber/compl.h Mon Oct 15 19:53:02 2012 +0200
++++ b/mcabber/mcabber/compl.h Thu Oct 18 00:00:39 2012 +0300
@@ -28,10 +28,17 @@
#define COMPL_OTRPOLICY 21
#define COMPL_MODULE 22
@@ -450,10 +531,10 @@
#endif
void compl_add_category_word(guint categ, const gchar *command);
-diff -r 3c7cebacae16 mcabber/mcabber/main.c
---- a/mcabber/mcabber/main.c Wed Oct 17 02:33:43 2012 +0300
-+++ b/mcabber/mcabber/main.c Wed Oct 17 03:00:30 2012 +0300
-@@ -368,13 +368,13 @@
+diff -r f8958ab545ac mcabber/mcabber/main.c
+--- a/mcabber/mcabber/main.c Mon Oct 15 19:53:02 2012 +0200
++++ b/mcabber/mcabber/main.c Thu Oct 18 00:00:39 2012 +0300
+@@ -364,13 +364,13 @@
}
/* Initialize command system, roster and default key bindings */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fix-date-fill.diff Thu Oct 18 02:18:10 2012 +0300
@@ -0,0 +1,39 @@
+# HG changeset patch
+# Parent 450e74018eb436aef07e67ef7ae49cd05f48b3c9
+Fix empty prefix filling
+Not useful in vanilla, as there's no prefixes
+longer than that static string. Also not add spaces
+to prefixes - they are already in format string.
+
+diff -r 450e74018eb4 mcabber/mcabber/screen.c
+--- a/mcabber/mcabber/screen.c Thu Oct 18 01:49:44 2012 +0300
++++ b/mcabber/mcabber/screen.c Thu Oct 18 02:08:24 2012 +0300
+@@ -1139,9 +1139,9 @@
+
+ if (line->timestamp &&
+ !(line->flags & (HBB_PREFIX_SPECIAL|HBB_PREFIX_CONT))) {
+- strftime(date, 30, gettprefix(), localtime(&line->timestamp));
++ strftime(date, 63, gettprefix(), localtime(&line->timestamp));
+ } else
+- strcpy(date, " ");
++ memset(date, ' ', (preflen>64) ? 64 : preflen);
+
+ if (!(line->flags & HBB_PREFIX_CONT)) {
+ if (line->flags & HBB_PREFIX_INFO) {
+@@ -1181,13 +1181,12 @@
+ receiptflag = '-';
+ g_snprintf(pref, preflen, "%s%c%c> ", date, receiptflag, cryptflag);
+ } else if (line->flags & HBB_PREFIX_SPECIAL) {
+- strftime(date, 30, getspectprefix(), localtime(&line->timestamp));
+- g_snprintf(pref, preflen, "%s ", date);
++ strftime(pref, preflen, getspectprefix(), localtime(&line->timestamp));
+ } else {
+- g_snprintf(pref, preflen, "%s ", date);
++ strncpy(pref, date, preflen);
+ }
+ } else {
+- g_snprintf(pref, preflen, " ");
++ strncpy(pref, date, preflen);
+ }
+ }
+
--- a/series Wed Oct 17 03:07:22 2012 +0300
+++ b/series Thu Oct 18 02:18:10 2012 +0300
@@ -1,4 +1,5 @@
completion-sorting.diff
+fix-date-fill.diff
switch-to-experimental.diff
separate-extcmd.diff
modularize-extcmd.diff
@@ -7,5 +8,6 @@
roster-state-colors.diff
add-cmake.diff
use-gslice.diff
+timeformat.diff
templates.diff
dynamic-layout.diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/timeformat.diff Thu Oct 18 02:18:10 2012 +0300
@@ -0,0 +1,124 @@
+# HG changeset patch
+# Parent f6642109fbfb5029d85f3f7c4dc9d93e100d607a
+[experimental] Allow user to modify time formatting
+
+ * give user full control and full responsibility
+ * add time_prefix = 3, that uses
+ * time_format (normal prefix format string)
+ * time_format_special (special prefix format string)
+ * time_prefix_len (normal prefix width + 5)
+ * fall back to 0, if any of these unset
+
+diff -r f6642109fbfb mcabber/mcabber/screen.c
+--- a/mcabber/mcabber/screen.c Thu Oct 18 00:00:46 2012 +0300
++++ b/mcabber/mcabber/screen.c Thu Oct 18 01:49:44 2012 +0300
+@@ -853,38 +853,100 @@
+ static const char *timeprefixes[] = {
+ "%m-%d %H:%M ",
+ "%H:%M ",
+- " "
++ " ",
++ NULL,
+ };
+
+ static const char *spectimeprefixes[] = {
+ "%m-%d %H:%M:%S ",
+ "%H:%M:%S ",
+- " "
++ " ",
++ NULL,
+ };
+
+ static int timepreflengths[] = {
+ // (length of the corresponding timeprefix + 5)
+ 17,
+ 11,
+- 6
++ 6,
++ 0,
+ };
+
++/*
++static struct {
++ char format;
++ unsigned short len;
++} timeprefix_characters[] = {
++ { 'C', 2 },
++ { 'd', 2 },
++ { 'D', 10 },
++ { 'e', 2 },
++ { 'F', 10 },
++ { 'G', 4 },
++ { 'g', 2 },
++ { 'H', 2 },
++ { 'I', 2 },
++ { 'j', 3 },
++ { 'k', 2 },
++ { 'l', 2 },
++ { 'm', 2 },
++ { 'M', 2 },
++ { 'p', 2 }, // ? locale-dependent, can set LC_CTIME=C?
++ { 'P', 2 }, // ?
++ { 'R', 5 },
++ { 'S', 2 },
++ { 'T', 8 },
++ { 'u', 1 },
++ { 'U', 2 },
++ { 'V', 2 },
++ { 'w', 1 },
++ { 'W', 2 },
++ { 'y', 2 },
++ { 'Y', 4 },
++ { 'z', 5 },
++ { '%', 1 },
++ { '\0', 0 }, // end marker
++};
++*/
++
++static guint gettprefixnum (void)
++{
++ guint n = settings_opt_get_int ("time_prefix");
++ static gboolean initialized = FALSE;
++ if (n < 3)
++ return n;
++ if (n > 3)
++ return 0;
++ if (!initialized) {
++ const char *tp = settings_opt_get ("time_format");
++ const char *stp = settings_opt_get ("time_format_special");
++ guint tpl = settings_opt_get_int ("time_prefix_len");
++ if (!tp || !*tp || !stp || !*stp || tpl < 6) {
++ tp = timeprefixes[0];
++ stp = spectimeprefixes[0];
++ tpl = timepreflengths[0];
++ }
++ timeprefixes[3] = g_strdup (tp);
++ spectimeprefixes[3] = g_strdup (stp);
++ timepreflengths[3] = tpl;
++ initialized = TRUE;
++ }
++ return 3;
++}
++
+ static const char *gettprefix(void)
+ {
+- guint n = settings_opt_get_int("time_prefix");
+- return timeprefixes[(n < 3 ? n : 0)];
++ return timeprefixes[gettprefixnum()];
+ }
+
+ static const char *getspectprefix(void)
+ {
+- guint n = settings_opt_get_int("time_prefix");
+- return spectimeprefixes[(n < 3 ? n : 0)];
++ return spectimeprefixes[gettprefixnum()];
+ }
+
+ guint scr_getprefixwidth(void)
+ {
+- guint n = settings_opt_get_int("time_prefix");
+- return timepreflengths[(n < 3 ? n : 0)];
++ return timepreflengths[gettprefixnum()];
+ }
+
+ guint scr_gettextwidth(void)