Fiddling with time formatting
authorMyhailo Danylenko <isbear@ukrpost.net>
Thu, 18 Oct 2012 02:18:10 +0300
changeset 51 5e5992999357
parent 50 1c5d368913c9
child 52 887f44e99aa1
Fiddling with time formatting
completion-sorting.diff
fix-date-fill.diff
series
timeformat.diff
--- 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)