mcabber/mcabber/screen.c
changeset 2337 ffd0e57e9563
parent 2334 6ad3cada768c
child 2338 6424627913be
equal deleted inserted replaced
2336:0dc317b5599d 2337:ffd0e57e9563
   107   GList    *top;      // If top is NULL, we'll display the last lines
   107   GList    *top;      // If top is NULL, we'll display the last lines
   108   char      cleared;  // For ex, user has issued a /clear command...
   108   char      cleared;  // For ex, user has issued a /clear command...
   109   char      lock;
   109   char      lock;
   110   char      refcount; // refcount > 0 if there are other users of this struct
   110   char      refcount; // refcount > 0 if there are other users of this struct
   111                       // e.g. with symlinked history
   111                       // e.g. with symlinked history
   112 } buffdata;
   112 } buffdata_t;
   113 
   113 
   114 typedef struct {
   114 typedef struct {
   115   WINDOW *win;
   115   WINDOW *win;
   116   PANEL  *panel;
   116   PANEL  *panel;
   117   buffdata *bd;
   117   buffdata_t *bd;
   118 } winbuf;
   118 } winbuf_t;
   119 
   119 
   120 struct dimensions {
   120 struct dimensions {
   121   int l;
   121   int l;
   122   int c;
   122   int c;
   123 };
   123 };
   127 static PANEL *rosterPanel, *chatPanel, *activechatPanel, *inputPanel;
   127 static PANEL *rosterPanel, *chatPanel, *activechatPanel, *inputPanel;
   128 static PANEL *mainstatusPanel, *chatstatusPanel;
   128 static PANEL *mainstatusPanel, *chatstatusPanel;
   129 static PANEL *logPanel;
   129 static PANEL *logPanel;
   130 static int maxY, maxX;
   130 static int maxY, maxX;
   131 static int prev_chatwidth;
   131 static int prev_chatwidth;
   132 static winbuf *statusWindow;
   132 static winbuf_t *statusWindow;
   133 static winbuf *currentWindow;
   133 static winbuf_t *currentWindow;
   134 static GList  *statushbuf;
   134 static GList  *statushbuf;
   135 
   135 
   136 static int roster_hidden;
   136 static int roster_hidden;
   137 static int chatmode;
   137 static int chatmode;
   138 static int multimode;
   138 static int multimode;
   172 
   172 
   173 typedef struct {
   173 typedef struct {
   174   char *seqstr;
   174   char *seqstr;
   175   guint mkeycode;
   175   guint mkeycode;
   176   gint  value;
   176   gint  value;
   177 } keyseq;
   177 } keyseq_t;
   178 
   178 
   179 GSList *keyseqlist;
   179 GSList *keyseqlist;
   180 static void add_keyseq(char *seqstr, guint mkeycode, gint value);
   180 static void add_keyseq(char *seqstr, guint mkeycode, gint value);
   181 
   181 
   182 static void scr_write_in_window(const char *winId, const char *text,
   182 static void scr_write_in_window(const char *winId, const char *text,
   201 #endif
   201 #endif
   202 #ifdef WITH_ASPELL
   202 #ifdef WITH_ASPELL
   203   AspellConfig *config;
   203   AspellConfig *config;
   204   AspellSpeller *checker;
   204   AspellSpeller *checker;
   205 #endif
   205 #endif
   206 } spell_checker;
   206 } spell_checker_t;
   207 
   207 
   208 GSList* spell_checkers = NULL;
   208 GSList* spell_checkers = NULL;
   209 #endif
   209 #endif
   210 
   210 
   211 typedef struct {
   211 typedef struct {
   212   int color_pair;
   212   int color_pair;
   213   int color_attrib;
   213   int color_attrib;
   214 } ccolor;
   214 } ccolor_t;
   215 
   215 
   216 typedef struct {
   216 typedef struct {
   217   char *status, *wildcard;
   217   char *status, *wildcard;
   218   ccolor *color;
   218   ccolor_t *color;
   219   GPatternSpec *compiled;
   219   GPatternSpec *compiled;
   220 } rostercolor;
   220 } rostercolor_t;
   221 
   221 
   222 static GSList *rostercolrules = NULL;
   222 static GSList *rostercolrules = NULL;
   223 
   223 
   224 static GHashTable *muccolors = NULL, *nickcolors = NULL;
   224 static GHashTable *muccolors = NULL, *nickcolors = NULL;
   225 
   225 
   226 typedef struct {
   226 typedef struct {
   227   bool manual; // Manually set?
   227   bool manual; // Manually set?
   228   ccolor *color;
   228   ccolor_t *color;
   229 } nickcolor;
   229 } nickcolor_t;
   230 
   230 
   231 static int nickcolcount = 0;
   231 static int nickcolcount = 0;
   232 static ccolor ** nickcols = NULL;
   232 static ccolor_t ** nickcols = NULL;
   233 static muccoltype glob_muccol = MC_OFF;
   233 static muccol_t glob_muccol = MC_OFF;
   234 
   234 
   235 /* Functions */
   235 /* Functions */
   236 
   236 
   237 static int find_color(const char *name)
   237 static int find_color(const char *name)
   238 {
   238 {
   264 
   264 
   265   scr_LogPrint(LPRINT_LOGNORM, "ERROR: Wrong color: %s", name);
   265   scr_LogPrint(LPRINT_LOGNORM, "ERROR: Wrong color: %s", name);
   266   return -1;
   266   return -1;
   267 }
   267 }
   268 
   268 
   269 static ccolor *get_user_color(const char *color)
   269 static ccolor_t *get_user_color(const char *color)
   270 {
   270 {
   271   bool isbright = FALSE;
   271   bool isbright = FALSE;
   272   int cl;
   272   int cl;
   273   ccolor *ccol;
   273   ccolor_t *ccol;
   274   if (!strncmp(color, "bright", 6)) {
   274   if (!strncmp(color, "bright", 6)) {
   275     isbright = TRUE;
   275     isbright = TRUE;
   276     color += 6;
   276     color += 6;
   277   }
   277   }
   278   cl = find_color(color);
   278   cl = find_color(color);
   279   if (cl < 0)
   279   if (cl < 0)
   280     return NULL;
   280     return NULL;
   281   ccol = g_new0(ccolor, 1);
   281   ccol = g_new0(ccolor_t, 1);
   282   ccol->color_attrib = isbright ? A_BOLD : A_NORMAL;
   282   ccol->color_attrib = isbright ? A_BOLD : A_NORMAL;
   283   ccol->color_pair = cl + COLOR_max; // User colors come after the internal ones
   283   ccol->color_pair = cl + COLOR_max; // User colors come after the internal ones
   284   return ccol;
   284   return ccol;
   285 }
   285 }
   286 
   286 
   295 
   295 
   296 // Sets the coloring mode for given MUC
   296 // Sets the coloring mode for given MUC
   297 // The MUC room does not need to be in the roster at that time
   297 // The MUC room does not need to be in the roster at that time
   298 // muc - the JID of room
   298 // muc - the JID of room
   299 // type - the new type
   299 // type - the new type
   300 void scr_muc_color(const char *muc, muccoltype type)
   300 void scr_muc_color(const char *muc, muccol_t type)
   301 {
   301 {
   302   gchar *muclow = g_utf8_strdown(muc, -1);
   302   gchar *muclow = g_utf8_strdown(muc, -1);
   303   if (type == MC_REMOVE) { // Remove it
   303   if (type == MC_REMOVE) { // Remove it
   304     if (strcmp(muc, "*")) {
   304     if (strcmp(muc, "*")) {
   305       if (muccolors && g_hash_table_lookup(muccolors, muclow))
   305       if (muccolors && g_hash_table_lookup(muccolors, muclow))
   308       scr_LogPrint(LPRINT_NORMAL, "Can not remove global coloring mode");
   308       scr_LogPrint(LPRINT_NORMAL, "Can not remove global coloring mode");
   309     }
   309     }
   310     g_free(muclow);
   310     g_free(muclow);
   311   } else { // Add or overwrite
   311   } else { // Add or overwrite
   312     if (strcmp(muc, "*")) {
   312     if (strcmp(muc, "*")) {
   313       muccoltype *value = g_new(muccoltype, 1);
   313       muccol_t *value = g_new(muccol_t, 1);
   314       *value = type;
   314       *value = type;
   315       ensure_string_htable(&muccolors, g_free);
   315       ensure_string_htable(&muccolors, g_free);
   316       g_hash_table_replace(muccolors, muclow, value);
   316       g_hash_table_replace(muccolors, muclow, value);
   317     } else {
   317     } else {
   318       glob_muccol = type;
   318       glob_muccol = type;
   334   bool need_update = FALSE;
   334   bool need_update = FALSE;
   335   snick = g_strdup_printf("<%s>", nick);
   335   snick = g_strdup_printf("<%s>", nick);
   336   mnick = g_strdup_printf("*%s ", nick);
   336   mnick = g_strdup_printf("*%s ", nick);
   337   if (!strcmp(color, "-")) { // Remove the color
   337   if (!strcmp(color, "-")) { // Remove the color
   338     if (nickcolors) {
   338     if (nickcolors) {
   339       nickcolor *nc = g_hash_table_lookup(nickcolors, snick);
   339       nickcolor_t *nc = g_hash_table_lookup(nickcolors, snick);
   340       if (nc) { // Have this nick already
   340       if (nc) { // Have this nick already
   341         nc->manual = FALSE;
   341         nc->manual = FALSE;
   342         nc = g_hash_table_lookup(nickcolors, mnick);
   342         nc = g_hash_table_lookup(nickcolors, mnick);
   343         assert(nc); // Must have both at the same time
   343         assert(nc); // Must have both at the same time
   344         nc->manual = FALSE;
   344         nc->manual = FALSE;
   346     }
   346     }
   347     g_free(snick); // They are not saved in the hash
   347     g_free(snick); // They are not saved in the hash
   348     g_free(mnick);
   348     g_free(mnick);
   349     need_update = TRUE;
   349     need_update = TRUE;
   350   } else {
   350   } else {
   351     ccolor *cl = get_user_color(color);
   351     ccolor_t *cl = get_user_color(color);
   352     if (!cl) {
   352     if (!cl) {
   353       scr_LogPrint(LPRINT_NORMAL, "No such color name");
   353       scr_LogPrint(LPRINT_NORMAL, "No such color name");
   354       g_free(snick);
   354       g_free(snick);
   355       g_free(mnick);
   355       g_free(mnick);
   356     } else {
   356     } else {
   357       nickcolor *nc = g_new(nickcolor, 1);
   357       nickcolor_t *nc = g_new(nickcolor_t, 1);
   358       ensure_string_htable(&nickcolors, NULL);
   358       ensure_string_htable(&nickcolors, NULL);
   359       nc->manual = TRUE;
   359       nc->manual = TRUE;
   360       nc->color = cl;
   360       nc->color = cl;
   361       // Free the struct, if any there already
   361       // Free the struct, if any there already
   362       g_free(g_hash_table_lookup(nickcolors, mnick));
   362       g_free(g_hash_table_lookup(nickcolors, mnick));
   369   if (need_update && chatmode &&
   369   if (need_update && chatmode &&
   370       (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_ROOM))
   370       (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_ROOM))
   371     scr_update_buddy_window();
   371     scr_update_buddy_window();
   372 }
   372 }
   373 
   373 
   374 static void free_rostercolrule(rostercolor *col)
   374 static void free_rostercolrule(rostercolor_t *col)
   375 {
   375 {
   376   g_free(col->status);
   376   g_free(col->status);
   377   g_free(col->wildcard);
   377   g_free(col->wildcard);
   378   g_free(col->color);
   378   g_free(col->color);
   379   g_pattern_spec_free(col->compiled);
   379   g_pattern_spec_free(col->compiled);
   403                       const char *color)
   403                       const char *color)
   404 {
   404 {
   405   GSList *head;
   405   GSList *head;
   406   GSList *found = NULL;
   406   GSList *found = NULL;
   407   for (head = rostercolrules; head; head = g_slist_next(head)) {
   407   for (head = rostercolrules; head; head = g_slist_next(head)) {
   408     rostercolor *rc = head->data;
   408     rostercolor_t *rc = head->data;
   409     if ((!strcmp(status, rc->status)) && (!strcmp(wildcard, rc->wildcard))) {
   409     if ((!strcmp(status, rc->status)) && (!strcmp(wildcard, rc->wildcard))) {
   410       found = head;
   410       found = head;
   411       break;
   411       break;
   412     }
   412     }
   413   }
   413   }
   420     } else {
   420     } else {
   421       scr_LogPrint(LPRINT_NORMAL, "No such color rule, nothing removed");
   421       scr_LogPrint(LPRINT_NORMAL, "No such color rule, nothing removed");
   422       return FALSE;
   422       return FALSE;
   423     }
   423     }
   424   } else {
   424   } else {
   425     ccolor *cl = get_user_color(color);
   425     ccolor_t *cl = get_user_color(color);
   426     if (!cl) {
   426     if (!cl) {
   427       scr_LogPrint(LPRINT_NORMAL, "No such color name");
   427       scr_LogPrint(LPRINT_NORMAL, "No such color name");
   428       return FALSE;
   428       return FALSE;
   429     }
   429     }
   430     if (found) {
   430     if (found) {
   431       rostercolor *rc = found->data;
   431       rostercolor_t *rc = found->data;
   432       g_free(rc->color);
   432       g_free(rc->color);
   433       rc->color = cl;
   433       rc->color = cl;
   434     } else {
   434     } else {
   435       rostercolor *rc = g_new(rostercolor, 1);
   435       rostercolor_t *rc = g_new(rostercolor_t, 1);
   436       rc->status = g_strdup(status);
   436       rc->status = g_strdup(status);
   437       rc->wildcard = g_strdup(wildcard);
   437       rc->wildcard = g_strdup(wildcard);
   438       rc->compiled = g_pattern_spec_new(wildcard);
   438       rc->compiled = g_pattern_spec_new(wildcard);
   439       rc->color = cl;
   439       rc->color = cl;
   440       rostercolrules = g_slist_prepend(rostercolrules, rc);
   440       rostercolrules = g_slist_prepend(rostercolrules, rc);
   567       while (ncolors < ncolor_end && *ncolors) {
   567       while (ncolors < ncolor_end && *ncolors) {
   568         if ((*ncolors == ' ') || (*ncolors == '\t')) {
   568         if ((*ncolors == ' ') || (*ncolors == '\t')) {
   569           ncolors++;
   569           ncolors++;
   570         } else {
   570         } else {
   571           char *end = ncolors;
   571           char *end = ncolors;
   572           ccolor *cl;
   572           ccolor_t *cl;
   573           while (*end && (*end != ' ') && (*end != '\t'))
   573           while (*end && (*end != ' ') && (*end != '\t'))
   574             end++;
   574             end++;
   575           *end = '\0';
   575           *end = '\0';
   576           cl = get_user_color(ncolors);
   576           cl = get_user_color(ncolors);
   577           if (!cl) {
   577           if (!cl) {
   585       }
   585       }
   586       g_free(ncolor_start);
   586       g_free(ncolor_start);
   587     }
   587     }
   588     if (!nickcols) { // Fallback to have something
   588     if (!nickcols) { // Fallback to have something
   589       nickcolcount = 1;
   589       nickcolcount = 1;
   590       nickcols = g_new(ccolor*, 1);
   590       nickcols = g_new(ccolor_t*, 1);
   591       *nickcols = g_new(ccolor, 1);
   591       *nickcols = g_new(ccolor_t, 1);
   592       (*nickcols)->color_pair = COLOR_GENERAL;
   592       (*nickcols)->color_pair = COLOR_GENERAL;
   593       (*nickcols)->color_attrib = A_NORMAL;
   593       (*nickcols)->color_attrib = A_NORMAL;
   594     }
   594     }
   595   }
   595   }
   596 
   596 
  1034                            const gchar *message, gpointer user_data)
  1034                            const gchar *message, gpointer user_data)
  1035 {
  1035 {
  1036   scr_log_print(LPRINT_NORMAL, "[%s] %s", log_domain, message);
  1036   scr_log_print(LPRINT_NORMAL, "[%s] %s", log_domain, message);
  1037 }
  1037 }
  1038 
  1038 
  1039 static winbuf *scr_search_window(const char *winId, int special)
  1039 static winbuf_t *scr_search_window(const char *winId, int special)
  1040 {
  1040 {
  1041   char *id;
  1041   char *id;
  1042   winbuf *wbp;
  1042   winbuf_t *wbp;
  1043 
  1043 
  1044   if (special)
  1044   if (special)
  1045     return statusWindow; // Only one special window atm.
  1045     return statusWindow; // Only one special window atm.
  1046 
  1046 
  1047   if (!winId)
  1047   if (!winId)
  1059   return (scr_search_window(bjid, FALSE) != NULL);
  1059   return (scr_search_window(bjid, FALSE) != NULL);
  1060 }
  1060 }
  1061 
  1061 
  1062 //  scr_new_buddy(title, dontshow)
  1062 //  scr_new_buddy(title, dontshow)
  1063 // Note: title (aka winId/jid) can be NULL for special buffers
  1063 // Note: title (aka winId/jid) can be NULL for special buffers
  1064 static winbuf *scr_new_buddy(const char *title, int dont_show)
  1064 static winbuf_t *scr_new_buddy(const char *title, int dont_show)
  1065 {
  1065 {
  1066   winbuf *tmp;
  1066   winbuf_t *tmp;
  1067   char *id;
  1067   char *id;
  1068 
  1068 
  1069   tmp = g_new0(winbuf, 1);
  1069   tmp = g_new0(winbuf_t, 1);
  1070 
  1070 
  1071   tmp->win = activechatWnd;
  1071   tmp->win = activechatWnd;
  1072   tmp->panel = activechatPanel;
  1072   tmp->panel = activechatPanel;
  1073 
  1073 
  1074   if (!dont_show) {
  1074   if (!dont_show) {
  1081   }
  1081   }
  1082   update_panels();
  1082   update_panels();
  1083 
  1083 
  1084   // If title is NULL, this is a special buffer
  1084   // If title is NULL, this is a special buffer
  1085   if (!title) {
  1085   if (!title) {
  1086     tmp->bd = g_new0(buffdata, 1);
  1086     tmp->bd = g_new0(buffdata_t, 1);
  1087     return tmp;
  1087     return tmp;
  1088   }
  1088   }
  1089 
  1089 
  1090   id = hlog_get_log_jid(title);
  1090   id = hlog_get_log_jid(title);
  1091   if (id) {
  1091   if (id) {
  1092     // This is a symlinked history log file.
  1092     // This is a symlinked history log file.
  1093     // Let's check if the target JID buffer has already been created.
  1093     // Let's check if the target JID buffer has already been created.
  1094     winbuf *wb = scr_search_window(id, FALSE);
  1094     winbuf_t *wb = scr_search_window(id, FALSE);
  1095     if (!wb)
  1095     if (!wb)
  1096       wb = scr_new_buddy(id, TRUE);
  1096       wb = scr_new_buddy(id, TRUE);
  1097     tmp->bd = wb->bd;
  1097     tmp->bd = wb->bd;
  1098     tmp->bd->refcount++;
  1098     tmp->bd->refcount++;
  1099     g_free(id);
  1099     g_free(id);
  1100   } else {  // Load buddy history from file (if enabled)
  1100   } else {  // Load buddy history from file (if enabled)
  1101     tmp->bd = g_new0(buffdata, 1);
  1101     tmp->bd = g_new0(buffdata_t, 1);
  1102     hlog_read_history(title, &tmp->bd->hbuf, scr_gettextwidth());
  1102     hlog_read_history(title, &tmp->bd->hbuf, scr_gettextwidth());
  1103 
  1103 
  1104     // Set a readmark to separate new content
  1104     // Set a readmark to separate new content
  1105     hbuf_set_readmark(tmp->bd->hbuf, TRUE);
  1105     hbuf_set_readmark(tmp->bd->hbuf, TRUE);
  1106   }
  1106   }
  1175   return timepreflen;
  1175   return timepreflen;
  1176 }
  1176 }
  1177 
  1177 
  1178 //  scr_update_window()
  1178 //  scr_update_window()
  1179 // (Re-)Display the given chat window.
  1179 // (Re-)Display the given chat window.
  1180 static void scr_update_window(winbuf *win_entry)
  1180 static void scr_update_window(winbuf_t *win_entry)
  1181 {
  1181 {
  1182   int n, mark_offset = 0;
  1182   int n, mark_offset = 0;
  1183   guint prefixwidth;
  1183   guint prefixwidth;
  1184   char pref[96];
  1184   char pref[96];
  1185   hbb_line **lines, *line;
  1185   hbb_line **lines, *line;
  1293 
  1293 
  1294       // The MUC nick - overwrite with proper color
  1294       // The MUC nick - overwrite with proper color
  1295       if (line->mucnicklen) {
  1295       if (line->mucnicklen) {
  1296         char *mucjid;
  1296         char *mucjid;
  1297         char tmp;
  1297         char tmp;
  1298         nickcolor *actual = NULL;
  1298         nickcolor_t *actual = NULL;
  1299         muccoltype type, *typetmp;
  1299         muccol_t type, *typetmp;
  1300 
  1300 
  1301         // Store the char after the nick
  1301         // Store the char after the nick
  1302         tmp = line->text[line->mucnicklen];
  1302         tmp = line->text[line->mucnicklen];
  1303         type = glob_muccol;
  1303         type = glob_muccol;
  1304         // Terminate the string after the nick
  1304         // Terminate the string after the nick
  1312         g_free(mucjid);
  1312         g_free(mucjid);
  1313         // Need to generate a color for the specified nick?
  1313         // Need to generate a color for the specified nick?
  1314         if ((type == MC_ALL) && (!nickcolors ||
  1314         if ((type == MC_ALL) && (!nickcolors ||
  1315             !g_hash_table_lookup(nickcolors, line->text))) {
  1315             !g_hash_table_lookup(nickcolors, line->text))) {
  1316           char *snick, *mnick;
  1316           char *snick, *mnick;
  1317           nickcolor *nc;
  1317           nickcolor_t *nc;
  1318           const char *p = line->text;
  1318           const char *p = line->text;
  1319           unsigned int nicksum = 0;
  1319           unsigned int nicksum = 0;
  1320           snick = g_strdup(line->text);
  1320           snick = g_strdup(line->text);
  1321           mnick = g_strdup(line->text);
  1321           mnick = g_strdup(line->text);
  1322           nc = g_new(nickcolor, 1);
  1322           nc = g_new(nickcolor_t, 1);
  1323           ensure_string_htable(&nickcolors, NULL);
  1323           ensure_string_htable(&nickcolors, NULL);
  1324           while (*p)
  1324           while (*p)
  1325             nicksum += *p++;
  1325             nicksum += *p++;
  1326           nc->color = nickcols[nicksum % nickcolcount];
  1326           nc->color = nickcols[nicksum % nickcolcount];
  1327           nc->manual = FALSE;
  1327           nc->manual = FALSE;
  1393   }
  1393   }
  1394 
  1394 
  1395   g_free(lines);
  1395   g_free(lines);
  1396 }
  1396 }
  1397 
  1397 
  1398 static winbuf *scr_create_window(const char *winId, int special, int dont_show)
  1398 static winbuf_t *scr_create_window(const char *winId, int special, int dont_show)
  1399 {
  1399 {
  1400   if (special) {
  1400   if (special) {
  1401     if (!statusWindow) {
  1401     if (!statusWindow) {
  1402       statusWindow = scr_new_buddy(NULL, dont_show);
  1402       statusWindow = scr_new_buddy(NULL, dont_show);
  1403       statusWindow->bd->hbuf = statushbuf;
  1403       statusWindow->bd->hbuf = statushbuf;
  1411 //  scr_show_window()
  1411 //  scr_show_window()
  1412 // Display the chat window with the given identifier.
  1412 // Display the chat window with the given identifier.
  1413 // "special" must be true if this is a special buffer window.
  1413 // "special" must be true if this is a special buffer window.
  1414 static void scr_show_window(const char *winId, int special)
  1414 static void scr_show_window(const char *winId, int special)
  1415 {
  1415 {
  1416   winbuf *win_entry;
  1416   winbuf_t *win_entry;
  1417 
  1417 
  1418   win_entry = scr_search_window(winId, special);
  1418   win_entry = scr_search_window(winId, special);
  1419 
  1419 
  1420   if (!win_entry) {
  1420   if (!win_entry) {
  1421     win_entry = scr_create_window(winId, special, FALSE);
  1421     win_entry = scr_create_window(winId, special, FALSE);
  1490 static void scr_write_in_window(const char *winId, const char *text,
  1490 static void scr_write_in_window(const char *winId, const char *text,
  1491                                 time_t timestamp, unsigned int prefix_flags,
  1491                                 time_t timestamp, unsigned int prefix_flags,
  1492                                 int force_show, unsigned mucnicklen,
  1492                                 int force_show, unsigned mucnicklen,
  1493                                 gpointer xep184)
  1493                                 gpointer xep184)
  1494 {
  1494 {
  1495   winbuf *win_entry;
  1495   winbuf_t *win_entry;
  1496   char *text_locale;
  1496   char *text_locale;
  1497   int dont_show = FALSE;
  1497   int dont_show = FALSE;
  1498   int special;
  1498   int special;
  1499   guint num_history_blocks;
  1499   guint num_history_blocks;
  1500   bool setmsgflg = FALSE;
  1500   bool setmsgflg = FALSE;
  1847   return;
  1847   return;
  1848 }
  1848 }
  1849 
  1849 
  1850 static void resize_win_buffer(gpointer key, gpointer value, gpointer data)
  1850 static void resize_win_buffer(gpointer key, gpointer value, gpointer data)
  1851 {
  1851 {
  1852   winbuf *wbp = value;
  1852   winbuf_t *wbp = value;
  1853   struct dimensions *dim = data;
  1853   struct dimensions *dim = data;
  1854   int chat_x_pos, chat_y_pos;
  1854   int chat_x_pos, chat_y_pos;
  1855   int new_chatwidth;
  1855   int new_chatwidth;
  1856 
  1856 
  1857   if (!(wbp && wbp->win))
  1857   if (!(wbp && wbp->win))
  1987       wprintw(chatstatusWnd, "#");
  1987       wprintw(chatstatusWnd, "#");
  1988     }
  1988     }
  1989   }
  1989   }
  1990 
  1990 
  1991   if (chatmode && !isgrp) {
  1991   if (chatmode && !isgrp) {
  1992     winbuf *win_entry;
  1992     winbuf_t *win_entry;
  1993     win_entry = scr_search_window(buddy_getjid(BUDDATA(current_buddy)), isspe);
  1993     win_entry = scr_search_window(buddy_getjid(BUDDATA(current_buddy)), isspe);
  1994     if (win_entry && win_entry->bd->lock)
  1994     if (win_entry && win_entry->bd->lock)
  1995       mvwprintw(chatstatusWnd, 0, 0, "*");
  1995       mvwprintw(chatstatusWnd, 0, 0, "*");
  1996   }
  1996   }
  1997 
  1997 
  2256         int color = get_color(COLOR_ROSTER);
  2256         int color = get_color(COLOR_ROSTER);
  2257         if ((!isspe) && (!isgrp)) { // Look for color rules
  2257         if ((!isspe) && (!isgrp)) { // Look for color rules
  2258           GSList *head;
  2258           GSList *head;
  2259           const char *bjid = buddy_getjid(BUDDATA(buddy));
  2259           const char *bjid = buddy_getjid(BUDDATA(buddy));
  2260           for (head = rostercolrules; head; head = g_slist_next(head)) {
  2260           for (head = rostercolrules; head; head = g_slist_next(head)) {
  2261             rostercolor *rc = head->data;
  2261             rostercolor_t *rc = head->data;
  2262             if (g_pattern_match_string(rc->compiled, bjid) &&
  2262             if (g_pattern_match_string(rc->compiled, bjid) &&
  2263                 (!strcmp("*", rc->status) || strchr(rc->status, status))) {
  2263                 (!strcmp("*", rc->status) || strchr(rc->status, status))) {
  2264               color = compose_color(rc->color);
  2264               color = compose_color(rc->color);
  2265               break;
  2265               break;
  2266             }
  2266             }
  2412     scr_show_window(jidto, FALSE);
  2412     scr_show_window(jidto, FALSE);
  2413 }
  2413 }
  2414 
  2414 
  2415 void scr_remove_receipt_flag(const char *bjid, gconstpointer xep184)
  2415 void scr_remove_receipt_flag(const char *bjid, gconstpointer xep184)
  2416 {
  2416 {
  2417   winbuf *win_entry = scr_search_window(bjid, FALSE);
  2417   winbuf_t *win_entry = scr_search_window(bjid, FALSE);
  2418   if (win_entry && xep184) {
  2418   if (win_entry && xep184) {
  2419     hbuf_remove_receipt(win_entry->bd->hbuf, xep184);
  2419     hbuf_remove_receipt(win_entry->bd->hbuf, xep184);
  2420     if (chatmode && (buddy_search_jid(bjid) == current_buddy))
  2420     if (chatmode && (buddy_search_jid(bjid) == current_buddy))
  2421       scr_update_buddy_window();
  2421       scr_update_buddy_window();
  2422   }
  2422   }
  2841 // Scroll up/down the current buddy window,
  2841 // Scroll up/down the current buddy window,
  2842 // - half a screen if nblines is 0,
  2842 // - half a screen if nblines is 0,
  2843 // - up if updown == -1, down if updown == 1
  2843 // - up if updown == -1, down if updown == 1
  2844 void scr_buffer_scroll_up_down(int updown, unsigned int nblines)
  2844 void scr_buffer_scroll_up_down(int updown, unsigned int nblines)
  2845 {
  2845 {
  2846   winbuf *win_entry;
  2846   winbuf_t *win_entry;
  2847   int n, nbl;
  2847   int n, nbl;
  2848   GList *hbuf_top;
  2848   GList *hbuf_top;
  2849   guint isspe;
  2849   guint isspe;
  2850 
  2850 
  2851   // Get win_entry
  2851   // Get win_entry
  2898 
  2898 
  2899 //  scr_buffer_clear()
  2899 //  scr_buffer_clear()
  2900 // Clear the current buddy window (used for the /clear command)
  2900 // Clear the current buddy window (used for the /clear command)
  2901 void scr_buffer_clear(void)
  2901 void scr_buffer_clear(void)
  2902 {
  2902 {
  2903   winbuf *win_entry;
  2903   winbuf_t *win_entry;
  2904   guint isspe;
  2904   guint isspe;
  2905 
  2905 
  2906   // Get win_entry
  2906   // Get win_entry
  2907   if (!current_buddy) return;
  2907   if (!current_buddy) return;
  2908   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  2908   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  2919   update_panels();
  2919   update_panels();
  2920 }
  2920 }
  2921 
  2921 
  2922 //  buffer_purge()
  2922 //  buffer_purge()
  2923 // key: winId/jid
  2923 // key: winId/jid
  2924 // value: winbuf structure
  2924 // value: winbuf_t structure
  2925 // data: int, set to 1 if the buffer should be closed.
  2925 // data: int, set to 1 if the buffer should be closed.
  2926 // NOTE: does not work for special buffers.
  2926 // NOTE: does not work for special buffers.
  2927 // Returns TRUE IFF the win_entry can be closed and freed.
  2927 // Returns TRUE IFF the win_entry can be closed and freed.
  2928 static gboolean buffer_purge(gpointer key, gpointer value, gpointer data)
  2928 static gboolean buffer_purge(gpointer key, gpointer value, gpointer data)
  2929 {
  2929 {
  2930   int *p_closebuf = data;
  2930   int *p_closebuf = data;
  2931   winbuf *win_entry = value;
  2931   winbuf_t *win_entry = value;
  2932   gboolean retval = FALSE;
  2932   gboolean retval = FALSE;
  2933 
  2933 
  2934   // Delete the current hbuf
  2934   // Delete the current hbuf
  2935   // unless we close the buffer *and* this is a shared bd structure
  2935   // unless we close the buffer *and* this is a shared bd structure
  2936   if (!(*p_closebuf && win_entry->bd->refcount))
  2936   if (!(*p_closebuf && win_entry->bd->refcount))
  2959 //  scr_buffer_purge(closebuf, jid)
  2959 //  scr_buffer_purge(closebuf, jid)
  2960 // Purge/Drop the current buddy buffer or jid's buffer if jid != NULL.
  2960 // Purge/Drop the current buddy buffer or jid's buffer if jid != NULL.
  2961 // If closebuf is 1, close the buffer.
  2961 // If closebuf is 1, close the buffer.
  2962 void scr_buffer_purge(int closebuf, const char *jid)
  2962 void scr_buffer_purge(int closebuf, const char *jid)
  2963 {
  2963 {
  2964   winbuf *win_entry;
  2964   winbuf_t *win_entry;
  2965   guint isspe;
  2965   guint isspe;
  2966   const char *cjid;
  2966   const char *cjid;
  2967   char *ljid = NULL;
  2967   char *ljid = NULL;
  2968   guint hold_chatmode = FALSE;
  2968   guint hold_chatmode = FALSE;
  2969 
  2969 
  3046 // lock = 1 : lock
  3046 // lock = 1 : lock
  3047 // lock = 0 : unlock
  3047 // lock = 0 : unlock
  3048 // lock = -1: toggle lock status
  3048 // lock = -1: toggle lock status
  3049 void scr_buffer_scroll_lock(int lock)
  3049 void scr_buffer_scroll_lock(int lock)
  3050 {
  3050 {
  3051   winbuf *win_entry;
  3051   winbuf_t *win_entry;
  3052   guint isspe;
  3052   guint isspe;
  3053 
  3053 
  3054   // Get win_entry
  3054   // Get win_entry
  3055   if (!current_buddy) return;
  3055   if (!current_buddy) return;
  3056   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  3056   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  3089 // If action = 1, set the readmark flag on the last message
  3089 // If action = 1, set the readmark flag on the last message
  3090 // If action = 0, reset the readmark flag
  3090 // If action = 0, reset the readmark flag
  3091 // If action = -1, remove the readmark flag iff it is on the last line
  3091 // If action = -1, remove the readmark flag iff it is on the last line
  3092 void scr_buffer_readmark(gchar action)
  3092 void scr_buffer_readmark(gchar action)
  3093 {
  3093 {
  3094   winbuf *win_entry;
  3094   winbuf_t *win_entry;
  3095   guint isspe;
  3095   guint isspe;
  3096   int autolock;
  3096   int autolock;
  3097 
  3097 
  3098   // Get win_entry
  3098   // Get win_entry
  3099   if (!current_buddy) return;
  3099   if (!current_buddy) return;
  3115 //  scr_buffer_top_bottom()
  3115 //  scr_buffer_top_bottom()
  3116 // Jump to the head/tail of the current buddy window
  3116 // Jump to the head/tail of the current buddy window
  3117 // (top if topbottom == -1, bottom topbottom == 1)
  3117 // (top if topbottom == -1, bottom topbottom == 1)
  3118 void scr_buffer_top_bottom(int topbottom)
  3118 void scr_buffer_top_bottom(int topbottom)
  3119 {
  3119 {
  3120   winbuf *win_entry;
  3120   winbuf_t *win_entry;
  3121   guint isspe;
  3121   guint isspe;
  3122 
  3122 
  3123   // Get win_entry
  3123   // Get win_entry
  3124   if (!current_buddy) return;
  3124   if (!current_buddy) return;
  3125   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  3125   isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
  3142 //  scr_buffer_search(direction, text)
  3142 //  scr_buffer_search(direction, text)
  3143 // Jump to the next line containing text
  3143 // Jump to the next line containing text
  3144 // (backward search if direction == -1, forward if topbottom == 1)
  3144 // (backward search if direction == -1, forward if topbottom == 1)
  3145 void scr_buffer_search(int direction, const char *text)
  3145 void scr_buffer_search(int direction, const char *text)
  3146 {
  3146 {
  3147   winbuf *win_entry;
  3147   winbuf_t *win_entry;
  3148   GList *current_line, *search_res;
  3148   GList *current_line, *search_res;
  3149   guint isspe;
  3149   guint isspe;
  3150 
  3150 
  3151   // Get win_entry
  3151   // Get win_entry
  3152   if (!current_buddy) return;
  3152   if (!current_buddy) return;
  3176 
  3176 
  3177 //  scr_buffer_percent(n)
  3177 //  scr_buffer_percent(n)
  3178 // Jump to the specified position in the buffer, in %
  3178 // Jump to the specified position in the buffer, in %
  3179 void scr_buffer_percent(int pc)
  3179 void scr_buffer_percent(int pc)
  3180 {
  3180 {
  3181   winbuf *win_entry;
  3181   winbuf_t *win_entry;
  3182   GList *search_res;
  3182   GList *search_res;
  3183   guint isspe;
  3183   guint isspe;
  3184 
  3184 
  3185   // Get win_entry
  3185   // Get win_entry
  3186   if (!current_buddy) return;
  3186   if (!current_buddy) return;
  3208 //  scr_buffer_date(t)
  3208 //  scr_buffer_date(t)
  3209 // Jump to the first line after date t in the buffer
  3209 // Jump to the first line after date t in the buffer
  3210 // t is a date in seconds since `00:00:00 1970-01-01 UTC'
  3210 // t is a date in seconds since `00:00:00 1970-01-01 UTC'
  3211 void scr_buffer_date(time_t t)
  3211 void scr_buffer_date(time_t t)
  3212 {
  3212 {
  3213   winbuf *win_entry;
  3213   winbuf_t *win_entry;
  3214   GList *search_res;
  3214   GList *search_res;
  3215   guint isspe;
  3215   guint isspe;
  3216 
  3216 
  3217   // Get win_entry
  3217   // Get win_entry
  3218   if (!current_buddy) return;
  3218   if (!current_buddy) return;
  3237 
  3237 
  3238 //  scr_buffer_jump_readmark()
  3238 //  scr_buffer_jump_readmark()
  3239 // Jump to the buffer readmark, if there's one
  3239 // Jump to the buffer readmark, if there's one
  3240 void scr_buffer_jump_readmark(void)
  3240 void scr_buffer_jump_readmark(void)
  3241 {
  3241 {
  3242   winbuf *win_entry;
  3242   winbuf_t *win_entry;
  3243   GList *search_res;
  3243   GList *search_res;
  3244   guint isspe;
  3244   guint isspe;
  3245 
  3245 
  3246   // Get win_entry
  3246   // Get win_entry
  3247   if (!current_buddy) return;
  3247   if (!current_buddy) return;
  3288   g_free(extfname);
  3288   g_free(extfname);
  3289 }
  3289 }
  3290 
  3290 
  3291 //  buffer_list()
  3291 //  buffer_list()
  3292 // key: winId/jid
  3292 // key: winId/jid
  3293 // value: winbuf structure
  3293 // value: winbuf_t structure
  3294 // data: none.
  3294 // data: none.
  3295 static void buffer_list(gpointer key, gpointer value, gpointer data)
  3295 static void buffer_list(gpointer key, gpointer value, gpointer data)
  3296 {
  3296 {
  3297   GList *head;
  3297   GList *head;
  3298   winbuf *win_entry = value;
  3298   winbuf_t *win_entry = value;
  3299 
  3299 
  3300   head = g_list_first(win_entry->bd->hbuf);
  3300   head = g_list_first(win_entry->bd->hbuf);
  3301 
  3301 
  3302   scr_LogPrint(LPRINT_NORMAL, " %s  (%u/%u)", (const char *) key,
  3302   scr_LogPrint(LPRINT_NORMAL, " %s  (%u/%u)", (const char *) key,
  3303                g_list_length(head), hbuf_get_blocks_number(head));
  3303                g_list_length(head), hbuf_get_blocks_number(head));
  3353     if (special)
  3353     if (special)
  3354       current_id = buddy_getname(BUDDATA(current_buddy));
  3354       current_id = buddy_getname(BUDDATA(current_buddy));
  3355     else
  3355     else
  3356       current_id = buddy_getjid(BUDDATA(current_buddy));
  3356       current_id = buddy_getjid(BUDDATA(current_buddy));
  3357     if (current_id) {
  3357     if (current_id) {
  3358       winbuf *win_entry = scr_search_window(current_id, special);
  3358       winbuf_t *win_entry = scr_search_window(current_id, special);
  3359       if (!win_entry) return;
  3359       if (!win_entry) return;
  3360       iscurrentlocked = win_entry->bd->lock;
  3360       iscurrentlocked = win_entry->bd->lock;
  3361     }
  3361     }
  3362   } else {
  3362   } else {
  3363     current_id = NULL;
  3363     current_id = NULL;
  3373 // TODO: avoid code duplication with scr_setmsgflag_if_needed()
  3373 // TODO: avoid code duplication with scr_setmsgflag_if_needed()
  3374 void scr_setattentionflag_if_needed(const char *bjid, int special,
  3374 void scr_setattentionflag_if_needed(const char *bjid, int special,
  3375                                     guint value, enum setuiprio_ops action)
  3375                                     guint value, enum setuiprio_ops action)
  3376 {
  3376 {
  3377   const char *current_id;
  3377   const char *current_id;
  3378   winbuf *wb;
  3378   winbuf_t *wb;
  3379   bool iscurrentlocked = FALSE;
  3379   bool iscurrentlocked = FALSE;
  3380 
  3380 
  3381   if (!bjid)
  3381   if (!bjid)
  3382     return;
  3382     return;
  3383 
  3383 
  3389     if (special)
  3389     if (special)
  3390       current_id = buddy_getname(BUDDATA(current_buddy));
  3390       current_id = buddy_getname(BUDDATA(current_buddy));
  3391     else
  3391     else
  3392       current_id = buddy_getjid(BUDDATA(current_buddy));
  3392       current_id = buddy_getjid(BUDDATA(current_buddy));
  3393     if (current_id) {
  3393     if (current_id) {
  3394       winbuf *win_entry = scr_search_window(current_id, special);
  3394       winbuf_t *win_entry = scr_search_window(current_id, special);
  3395       if (!win_entry) return;
  3395       if (!win_entry) return;
  3396       iscurrentlocked = win_entry->bd->lock;
  3396       iscurrentlocked = win_entry->bd->lock;
  3397     }
  3397     }
  3398   } else {
  3398   } else {
  3399     current_id = NULL;
  3399     current_id = NULL;
  4250   refresh_inputline();
  4250   refresh_inputline();
  4251 }
  4251 }
  4252 
  4252 
  4253 static void add_keyseq(char *seqstr, guint mkeycode, gint value)
  4253 static void add_keyseq(char *seqstr, guint mkeycode, gint value)
  4254 {
  4254 {
  4255   keyseq *ks;
  4255   keyseq_t *ks;
  4256 
  4256 
  4257   // Let's make sure the length is correct
  4257   // Let's make sure the length is correct
  4258   if (strlen(seqstr) > MAX_KEYSEQ_LENGTH) {
  4258   if (strlen(seqstr) > MAX_KEYSEQ_LENGTH) {
  4259     scr_LogPrint(LPRINT_LOGNORM, "add_keyseq(): key sequence is too long!");
  4259     scr_LogPrint(LPRINT_LOGNORM, "add_keyseq(): key sequence is too long!");
  4260     return;
  4260     return;
  4261   }
  4261   }
  4262 
  4262 
  4263   ks = g_new0(keyseq, 1);
  4263   ks = g_new0(keyseq_t, 1);
  4264   ks->seqstr = g_strdup(seqstr);
  4264   ks->seqstr = g_strdup(seqstr);
  4265   ks->mkeycode = mkeycode;
  4265   ks->mkeycode = mkeycode;
  4266   ks->value = value;
  4266   ks->value = value;
  4267   keyseqlist = g_slist_append(keyseqlist, ks);
  4267   keyseqlist = g_slist_append(keyseqlist, ks);
  4268 }
  4268 }
  4272 // Return value:
  4272 // Return value:
  4273 // -1  if "seq" matches no known sequence
  4273 // -1  if "seq" matches no known sequence
  4274 //  0  if "seq" could match 1 or more known sequences
  4274 //  0  if "seq" could match 1 or more known sequences
  4275 // >0  if "seq" matches a key sequence; the mkey code is returned
  4275 // >0  if "seq" matches a key sequence; the mkey code is returned
  4276 //     and *ret is set to the matching keyseq structure.
  4276 //     and *ret is set to the matching keyseq structure.
  4277 static inline gint match_keyseq(int *iseq, keyseq **ret)
  4277 static inline gint match_keyseq(int *iseq, keyseq_t **ret)
  4278 {
  4278 {
  4279   GSList *ksl;
  4279   GSList *ksl;
  4280   keyseq *ksp;
  4280   keyseq_t *ksp;
  4281   char *p, c;
  4281   char *p, c;
  4282   int *i;
  4282   int *i;
  4283   int needmore = FALSE;
  4283   int needmore = FALSE;
  4284 
  4284 
  4285   for (ksl = keyseqlist; ksl; ksl = g_slist_next(ksl)) {
  4285   for (ksl = keyseqlist; ksl; ksl = g_slist_next(ksl)) {
  4330   if (len)
  4330   if (len)
  4331     return 0;
  4331     return 0;
  4332   return c;
  4332   return c;
  4333 }
  4333 }
  4334 
  4334 
  4335 void scr_getch(keycode *kcode)
  4335 void scr_getch(keycode_t *kcode)
  4336 {
  4336 {
  4337   keyseq *mks = NULL;
  4337   keyseq_t *mks = NULL;
  4338   int  ks[MAX_KEYSEQ_LENGTH+1];
  4338   int  ks[MAX_KEYSEQ_LENGTH+1];
  4339   int i;
  4339   int i;
  4340 
  4340 
  4341   memset(kcode, 0, sizeof(keycode));
  4341   memset(kcode, 0, sizeof(keycode_t));
  4342   memset(ks,  0, sizeof(ks));
  4342   memset(ks,  0, sizeof(ks));
  4343 
  4343 
  4344   kcode->value = wgetch(inputWnd);
  4344   kcode->value = wgetch(inputWnd);
  4345   if (utf8_mode) {
  4345   if (utf8_mode) {
  4346     bool ismeta = (kcode->value == 27);
  4346     bool ismeta = (kcode->value == 27);
  4422   if (colors_stalled)
  4422   if (colors_stalled)
  4423     parse_colors();
  4423     parse_colors();
  4424   doupdate();
  4424   doupdate();
  4425 }
  4425 }
  4426 
  4426 
  4427 static void bindcommand(keycode kcode)
  4427 static void bindcommand(keycode_t kcode)
  4428 {
  4428 {
  4429   gchar asciikey[16], asciicode[16];
  4429   gchar asciikey[16], asciicode[16];
  4430   const gchar *boundcmd;
  4430   const gchar *boundcmd;
  4431 
  4431 
  4432   if (kcode.utf8)
  4432   if (kcode.utf8)
  4507     process_command(mkcmdstr("roster down"), TRUE);
  4507     process_command(mkcmdstr("roster down"), TRUE);
  4508 }
  4508 }
  4509 
  4509 
  4510 //  scr_process_key(key)
  4510 //  scr_process_key(key)
  4511 // Handle the pressed key, in the command line (bottom).
  4511 // Handle the pressed key, in the command line (bottom).
  4512 void scr_process_key(keycode kcode)
  4512 void scr_process_key(keycode_t kcode)
  4513 {
  4513 {
  4514   int key = kcode.value;
  4514   int key = kcode.value;
  4515   int display_char = FALSE;
  4515   int display_char = FALSE;
  4516   int vi_search = FALSE;
  4516   int vi_search = FALSE;
  4517   static int ex_or_search_mode = FALSE;
  4517   static int ex_or_search_mode = FALSE;
  4877 }
  4877 }
  4878 
  4878 
  4879 #if defined(WITH_ENCHANT) || defined(WITH_ASPELL)
  4879 #if defined(WITH_ENCHANT) || defined(WITH_ASPELL)
  4880 static void spell_checker_free(gpointer data)
  4880 static void spell_checker_free(gpointer data)
  4881 {
  4881 {
  4882   spell_checker* sc = data;
  4882   spell_checker_t *sc = data;
  4883 #ifdef WITH_ENCHANT
  4883 #ifdef WITH_ENCHANT
  4884   enchant_broker_free_dict(sc->broker, sc->checker);
  4884   enchant_broker_free_dict(sc->broker, sc->checker);
  4885   enchant_broker_free(sc->broker);
  4885   enchant_broker_free(sc->broker);
  4886 #endif
  4886 #endif
  4887 #ifdef WITH_ASPELL
  4887 #ifdef WITH_ASPELL
  4889   delete_aspell_config(sc->config);
  4889   delete_aspell_config(sc->config);
  4890 #endif
  4890 #endif
  4891   g_free(sc);
  4891   g_free(sc);
  4892 }
  4892 }
  4893 
  4893 
  4894 static spell_checker* new_spell_checker(const char* spell_lang)
  4894 static spell_checker_t* new_spell_checker(const char* spell_lang)
  4895 {
  4895 {
  4896   spell_checker* sc = g_new(spell_checker, 1);
  4896   spell_checker_t *sc = g_new(spell_checker_t, 1);
  4897 #ifdef WITH_ASPELL
  4897 #ifdef WITH_ASPELL
  4898   const char *spell_encoding = settings_opt_get("spell_encoding");
  4898   const char *spell_encoding = settings_opt_get("spell_encoding");
  4899   AspellCanHaveError *possible_err;
  4899   AspellCanHaveError *possible_err;
  4900   sc->config = new_aspell_config();
  4900   sc->config = new_aspell_config();
  4901   if (spell_encoding)
  4901   if (spell_encoding)
  4926 // initialization
  4926 // initialization
  4927 void spellcheck_init(void)
  4927 void spellcheck_init(void)
  4928 {
  4928 {
  4929   int spell_enable            = settings_opt_get_int("spell_enable");
  4929   int spell_enable            = settings_opt_get_int("spell_enable");
  4930   const char *spell_lang     = settings_opt_get("spell_lang");
  4930   const char *spell_lang     = settings_opt_get("spell_lang");
  4931   gchar** langs;
  4931   gchar **langs;
  4932   gchar** lang_iter;
  4932   gchar **lang_iter;
  4933   spell_checker* sc;
  4933   spell_checker_t *sc;
  4934 
  4934 
  4935   if (!spell_enable)
  4935   if (!spell_enable)
  4936     return;
  4936     return;
  4937 
  4937 
  4938   spellcheck_deinit();
  4938   spellcheck_deinit();
  4968 }
  4968 }
  4969 
  4969 
  4970 typedef struct {
  4970 typedef struct {
  4971   const char* str;
  4971   const char* str;
  4972   int len;
  4972   int len;
  4973 } spell_substring;
  4973 } spell_substring_t;
  4974 
  4974 
  4975 static int spellcheckword(gconstpointer sc_ptr, gconstpointer substr_ptr)
  4975 static int spellcheckword(gconstpointer sc_ptr, gconstpointer substr_ptr)
  4976 {
  4976 {
  4977   spell_checker* sc = (spell_checker*) sc_ptr;
  4977   spell_checker_t *sc = (spell_checker_t*) sc_ptr;
  4978   spell_substring* substr = (spell_substring*) substr_ptr;
  4978   spell_substring_t *substr = (spell_substring_t*) substr_ptr;
  4979 #ifdef WITH_ENCHANT
  4979 #ifdef WITH_ENCHANT
  4980   // enchant_dict_check will return 0 on good word
  4980   // enchant_dict_check will return 0 on good word
  4981   return enchant_dict_check(sc->checker, substr->str, substr->len);
  4981   return enchant_dict_check(sc->checker, substr->str, substr->len);
  4982 #endif
  4982 #endif
  4983 #ifdef WITH_ASPELL
  4983 #ifdef WITH_ASPELL
  4991 
  4991 
  4992 // Spell checking function
  4992 // Spell checking function
  4993 static void spellcheck(char *line, char *checked)
  4993 static void spellcheck(char *line, char *checked)
  4994 {
  4994 {
  4995   const char *start, *line_start;
  4995   const char *start, *line_start;
  4996   spell_substring substr;
  4996   spell_substring_t substr;
  4997 
  4997 
  4998   if (inputLine[0] == 0 || inputLine[0] == COMMAND_CHAR)
  4998   if (inputLine[0] == 0 || inputLine[0] == COMMAND_CHAR)
  4999     return;
  4999     return;
  5000 
  5000 
  5001   // Give up early if not languages are loaded
  5001   // Give up early if not languages are loaded