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; |
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); |
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; |
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; |
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); |
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) |
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 |