/* Copyright (C) 2000-2003 Markus Lausser (sgop@users.sf.net) This is free software distributed under the terms of the GNU Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include "lopster.h" #include "connection.h" #include "global.h" #include "scheme.h" #include "support.h" #include "chat.h" #include "utils.h" scheme_t *scheme_new(void) { scheme_t *scheme; scheme = g_malloc(sizeof(scheme_t)); scheme->name = NULL; scheme->colors = NULL; scheme->server_prefix = NULL; scheme->client_prefix = NULL; scheme->join_prefix = NULL; scheme->part_prefix = NULL; scheme->style = gtk_style_copy(gtk_widget_get_style(global.win)); return scheme; } void scheme_set_back(scheme_t* scheme) { style_t* style; GdkColor* color; style = style_get(scheme, "chat_background"); color = style->back; if (!color) return; // scheme->style->font = global.styles[STYLE_TAB1]->font; scheme->style->base[GTK_STATE_NORMAL].pixel = color->pixel; scheme->style->base[GTK_STATE_NORMAL].red = color->red; scheme->style->base[GTK_STATE_NORMAL].green = color->green; scheme->style->base[GTK_STATE_NORMAL].blue = color->blue; color = style->fore; scheme->style->text[GTK_STATE_NORMAL].pixel = color->pixel; scheme->style->text[GTK_STATE_NORMAL].red = color->red; scheme->style->text[GTK_STATE_NORMAL].green = color->green; scheme->style->text[GTK_STATE_NORMAL].blue = color->blue; } static scheme_t *verify_scheme(scheme_t* scheme) { int mods = 0; if (!scheme) { scheme = scheme_new(); scheme->name = g_strdup("default"); mods = 1; } if (!scheme) return NULL; if (!style_search(scheme, "text")) { scheme->colors = g_list_append(scheme->colors, style_new("text", "#c5b593", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "url")) { scheme->colors = g_list_append(scheme->colors, style_new("url", "#ff7777", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "user")) { scheme->colors = g_list_append(scheme->colors, style_new("user", "#007de7", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "yourself")) { scheme->colors = g_list_append(scheme->colors, style_new("yourself", "#e5cf00", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "friend")) { scheme->colors = g_list_append(scheme->colors, style_new("friend", "#de5a6a", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "whisper")) { scheme->colors = g_list_append(scheme->colors, style_new("whisper", "#ffee00", "#3f3f3f", "-adobe-courier-medium-r-normal-*-*-140-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-140-*")); mods = 1; } if (!style_search(scheme, "join")) { scheme->colors = g_list_append(scheme->colors, style_new("join", "#009f46", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "part")) { scheme->colors = g_list_append(scheme->colors, style_new("part", "#009f46", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "error")) { scheme->colors = g_list_append(scheme->colors, style_new("error", "#ffc4b2", "NULL", "-adobe-helvetica-medium-r-normal-*-*-120-*-*-p-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "message")) { scheme->colors = g_list_append(scheme->colors, style_new("message", "#b2ccff", "NULL", "-b&h-lucidatypewriter-medium-r-normal-*-*-120-*-*-m-*-iso8859-1,*-medium-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "highlight")) { scheme->colors = g_list_append(scheme->colors, style_new("highlight", "#ded305", "NULL", "-b&h-lucidatypewriter-bold-r-normal-*-*-120-*-*-m-*-iso8859-1,*-bold-r-normal-*-*-120-*")); mods = 1; } if (!style_search(scheme, "transfer_running")) { scheme->colors = g_list_append(scheme->colors, style_new("transfer_running", "#ff0011", "#ffd484", "NULL")); mods = 1; } if (!style_search(scheme, "transfer_waiting")) { scheme->colors = g_list_append(scheme->colors, style_new("transfer_waiting", "#002173", "#94bfdd", "NULL")); mods = 1; } if (!style_search(scheme, "transfer_bar1")) { scheme->colors = g_list_append(scheme->colors, style_new("transfer_bar1", "#1700ff", "#77aee5", "NULL")); mods = 1; } if (!style_search(scheme, "transfer_bar2")) { scheme->colors = g_list_append(scheme->colors, style_new("transfer_bar2", "#ff0300", "#ffa393", "NULL")); mods = 1; } if (!style_search(scheme, "library_marked")) { scheme->colors = g_list_append(scheme->colors, style_new("library_marked", "#000000", "#eeeeee", "NULL")); mods = 1; } if (!style_search(scheme, "chat_background")) { scheme->colors = g_list_append(scheme->colors, style_new("chat_background", "#ffffff", "#000000", "NULL")); mods = 1; } if (!scheme->client_prefix) { scheme->client_prefix = g_strdup("%K=%c=%C= "); mods = 1; } if (!scheme->server_prefix) { scheme->server_prefix = g_strdup("%K;%r;%R; "); mods = 1; } if (!scheme->join_prefix) { scheme->join_prefix = g_strdup("%K-%g=%G> "); mods = 1; } if (!scheme->part_prefix) { scheme->part_prefix = g_strdup("%G<%g=%K- "); mods = 1; } scheme_set_back(scheme); if (mods) scheme_save(scheme); return scheme; } void scheme_destroy(scheme_t * scheme) { GList *dlist; style_t *style; if (!scheme) return; if (scheme->name) g_free(scheme->name); for (dlist = scheme->colors; dlist; dlist = dlist->next) { style = dlist->data; style_destroy(style); } g_list_free(scheme->colors); g_free(scheme->server_prefix); g_free(scheme->client_prefix); g_free(scheme->join_prefix); g_free(scheme->part_prefix); gtk_style_unref(scheme->style); g_free(scheme); } static scheme_t* scheme_load_2(char* filename, char* name) { char temp[2048]; char *pos; char *sname; char *sfore; char *sback; char *sfont; FILE *file; scheme_t *scheme; style_t *style; file = fopen(filename, "r"); if (file == NULL) { client_message("Error", "Could not load scheme!"); return NULL; } scheme = scheme_new(); scheme->name = g_strdup(name); fgets(temp, sizeof(temp), file); while (mfgets(temp, sizeof(temp), file)) { if (temp[0] == '#') continue; if (!strncasecmp(temp, "ServerPrefix", 12)) { pos = strchr(temp, '=') + 1; scheme->server_prefix = g_strdup(pos); continue; } else if (!strncasecmp(temp, "ClientPrefix", 12)) { pos = strchr(temp, '=') + 1; scheme->client_prefix = g_strdup(pos); continue; } else if (!strncasecmp(temp, "JoinPrefix", 10)) { pos = strchr(temp, '=') + 1; scheme->join_prefix = g_strdup(pos); continue; } else if (!strncasecmp(temp, "PartPrefix", 10)) { pos = strchr(temp, '=') + 1; scheme->part_prefix = g_strdup(pos); continue; } /// pos = arg(temp, 0); if (!pos) { g_warning("Error in scheme file %s\n", filename); fclose(file); return 0; } sname = pos; /// pos = arg(NULL, 0); if (!pos) { g_warning("Error in scheme file %s\n", filename); fclose(file); return 0; } pos = strtok(pos, "[]"); if (!pos) { g_warning("Error in scheme file %s\n", filename); fclose(file); return 0; } sfore = pos; /// pos = strtok(NULL, "[]"); if (!pos) { g_warning("Error in scheme file %s\n", filename); fclose(file); return 0; } sback = pos; /// pos = strtok(NULL, "[]"); if (!pos) { g_warning("Error in scheme file %s\n", filename); fclose(file); return 0; } sfont = pos; // upgrade file if (!strcasecmp(sname, "library_unshared")) style = style_new("library_marked", sfore, sback, sfont); else style = style_new(sname, sfore, sback, sfont); if (style) scheme->colors = g_list_append(scheme->colors, style); } fclose(file); scheme = verify_scheme(scheme); return scheme; } scheme_t *scheme_load(char *name) { int version; char filename[2048]; sprintf(filename, "%s/schemes/%s", global.options.config_dir, name); /////////////////////// version = scheme_is_valid(name); if (version == 2) return scheme_load_2(filename, name); else return NULL; } void scheme_save(scheme_t * scheme) { char filename[2048]; style_t *style; FILE *file; GList *dlist; if (!scheme) return; sprintf(filename, "%s/schemes/%s", global.options.config_dir, scheme->name); if ((file = fopen(filename, "w")) == NULL) { client_message("Error", "Could not save scheme [%s]", scheme->name); return; } fprintf(file, "LSF1.2\n"); for (dlist = scheme->colors; dlist; dlist = dlist->next) { style = (style_t *) (dlist->data); fprintf(file, "%s [%s][%s][%s]\n", style->name, style->n_fore, style->n_back, style->n_font); } fprintf(file, "ServerPrefix=%s\n", scheme->server_prefix); fprintf(file, "ClientPrefix=%s\n", scheme->client_prefix); fprintf(file, "JoinPrefix=%s\n", scheme->join_prefix); fprintf(file, "PartPrefix=%s\n", scheme->part_prefix); fclose(file); scheme_update_list(scheme->name); } void scheme_delete(char *name) { char filename[2048]; sprintf(filename, "%s/schemes/%s", global.options.config_dir, name); unlink(filename); scheme_update_list(NULL); } int scheme_is_valid(char *name) { struct stat st; FILE *file; char temp[2048]; int version = 0; sprintf(temp, "%s/schemes/%s", global.options.config_dir, name); if (stat(temp, &st) < 0) return 0; if ((file = fopen(temp, "r")) == NULL) return 0; fgets(temp, sizeof(temp), file); if (!strncmp(temp, "LSF1.2", 6)) version = 2; fclose(file); return version; } void scheme_update_list(char *current) { char dirname[2048]; GtkWidget *temp; GList *list2; struct dirent *entry; struct stat buf; char filename[2048]; DIR *dir; char *cur = NULL; GList* dlist; if (!global.options_win) return; // dont know why i have to duplicate the string here // original would be messed up till end of function if (current) cur = g_strdup(current); sprintf(dirname, "%s/schemes", global.options.config_dir); list2 = NULL; if ((dir = opendir(dirname)) == NULL) { g_warning("could not open dir [%s]", dirname); } else { while ((entry = readdir(dir)) != NULL) { // if (!strncmp(entry->d_name, ".", 1)) continue; // if (!strncmp(entry->d_name, "..", 2)) continue; sprintf(filename, "%s/%s", dirname, entry->d_name); stat(filename, &buf); if (S_ISREG(buf.st_mode)) { if (scheme_is_valid(entry->d_name)) { list2 = g_list_insert_sorted(list2, g_strdup(entry->d_name), (GCompareFunc) g_strcasecmp); } } } closedir(dir); } temp = lookup_widget(global.options_win, "combo7"); if (list2) { gtk_combo_set_popdown_strings(GTK_COMBO(temp), list2); for (dlist = list2; dlist; dlist = dlist->next) g_free(dlist->data); g_list_free(list2); } temp = lookup_widget(global.options_win, "combo_entry15"); if (cur) { gtk_entry_set_text(GTK_ENTRY(temp), cur); g_free(cur); } } static void text_print_channel(GtkWidget * widget, scheme_t * scheme, char *color, char *text) { style_t *style; style = style_get(scheme, color); gtk_text_freeze(GTK_TEXT(widget)); gtk_text_insert(GTK_TEXT(widget), style->font, style->fore, style->back, text, strlen(text)); gtk_text_thaw(GTK_TEXT(widget)); return; } void scheme_draw(scheme_t * scheme) { GtkWidget *temp; GtkWidget *win; char *prefix; char stime[200] = ""; win = global.options_win; if (!win) return; temp = lookup_widget(win, "text8"); gtk_text_backward_delete(GTK_TEXT(temp), gtk_text_get_length(GTK_TEXT(temp))); scheme_set_back(scheme); gtk_widget_set_style(temp, global.styles[0]); gtk_widget_set_style(temp, scheme->style); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } prefix = cparse(scheme->join_prefix); text_print_colored(temp, scheme, "message", prefix); text_print_colored(temp, scheme, "user", "["); text_print_colored(temp, scheme, "join", "Testuser1 joined channel"); text_print_colored(temp, scheme, "user", "]\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } text_print_colored(temp, scheme, "user", "<"); text_print_colored(temp, scheme, "yourself", "Yourself"); text_print_colored(temp, scheme, "user", "> "); text_print_colored(temp, scheme, "text", "Hello!\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } text_print_colored(temp, scheme, "user", "<"); text_print_colored(temp, scheme, "user", "Testuser1"); text_print_colored(temp, scheme, "user", "> "); text_print_colored(temp, scheme, "text", "Hi.\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } prefix = cparse(scheme->part_prefix); text_print_colored(temp, scheme, "message", prefix); text_print_colored(temp, scheme, "user", "["); text_print_colored(temp, scheme, "part", "Testuser2 left channel"); text_print_colored(temp, scheme, "user", "]\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } text_print_colored(temp, scheme, "user", "<"); text_print_colored(temp, scheme, "user", "Testuser1 emote message"); text_print_colored(temp, scheme, "user", ">\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } prefix = cparse(scheme->server_prefix); text_print_colored(temp, scheme, "error", prefix); prefix = cparse("%W["); text_print_colored(temp, scheme, "error", prefix); text_print_colored(temp, scheme, "error", "Error"); prefix = cparse("%W] "); text_print_colored(temp, scheme, "error", prefix); text_print_colored(temp, scheme, "error", "A server message\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } text_print_colored(temp, scheme, "whisper", " This is a private message\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } text_print_colored(temp, scheme, "user", "<"); text_print_colored(temp, scheme, "friend", "Friend_User"); text_print_colored(temp, scheme, "user", "> "); text_print_colored(temp, scheme, "text", "This is a message with "); text_print_colored(temp, scheme, "highlight", "highlighted text\n"); if (global.options.timestamps != TIME_NONE) { text_print_channel(temp, scheme, "text", "["); text_print_channel(temp, scheme, "message", current_time(stime, global.options.timestamps)); text_print_channel(temp, scheme, "text", "] "); } prefix = cparse(scheme->client_prefix); text_print_colored(temp, scheme, "message", prefix); prefix = cparse("%W["); text_print_colored(temp, scheme, "message", prefix); text_print_colored(temp, scheme, "message", "Message"); prefix = cparse("%W] "); text_print_colored(temp, scheme, "message", prefix); text_print_colored(temp, scheme, "message", "A client message\n"); } void scheme_load_global(char *scheme) { if (scheme && *scheme) global.scheme = scheme_load(scheme); if (global.scheme) return; global.scheme = scheme_load("default"); if (global.scheme) return; global.scheme = verify_scheme(global.scheme); } style_t *style_new(char *name, char *fore, char *back, char *font) { style_t *style; GdkColor color; style = g_malloc(sizeof(style_t)); style->name = g_strdup(name); if (fore) { style->n_fore = g_strdup(fore); if (strcmp(fore, "NULL")) { gdk_color_parse(fore, &color); style->fore = gdk_color_copy(&color); } else { style->fore = NULL; } } else { style->n_fore = g_strdup("NULL"); style->fore = NULL; } if (back) { style->n_back = g_strdup(back); if (strcmp(back, "NULL")) { gdk_color_parse(back, &color); style->back = gdk_color_copy(&color); } else { style->back = NULL; } } else { style->n_back = g_strdup("NULL"); style->back = NULL; } if (font) { style->n_font = g_strdup(font); if (strcmp(font, "NULL")) { style->font = gdk_fontset_load(font); } else { style->font = NULL; } } else { style->n_font = g_strdup("NULL"); style->font = NULL; } return style; } void style_destroy(style_t * style) { if (style->name) g_free(style->name); if (style->n_fore) g_free(style->n_fore); if (style->n_back) g_free(style->n_back); if (style->n_font) g_free(style->n_font); g_free(style); } void style_update(scheme_t * scheme, char *name, char *fore, char *back, char *font) { style_t *style; GdkColor color; style = style_search(scheme, name); if (!style) { style = style_new(name, fore, back, font); scheme->colors = g_list_append(scheme->colors, style); return; } if (fore) { if (style->n_fore) g_free(style->n_fore); style->n_fore = g_strdup(fore); if (strcmp(fore, "NULL")) { gdk_color_parse(fore, &color); style->fore = gdk_color_copy(&color); } else { style->fore = NULL; } } if (back) { if (style->n_back) g_free(style->n_back); style->n_back = g_strdup(back); if (strcmp(back, "NULL")) { gdk_color_parse(back, &color); style->back = gdk_color_copy(&color); } else { style->back = NULL; } } if (font) { if (style->n_font) g_free(style->n_font); style->n_font = g_strdup(font); if (strcmp(font, "NULL")) { style->font = gdk_fontset_load(font); } else { style->font = NULL; } } } style_t *style_search(scheme_t * scheme, char *name) { GList *dlist; style_t *style; if (!scheme) return NULL; for (dlist = scheme->colors; dlist; dlist = dlist->next) { style = dlist->data; if (!g_strcasecmp(name, style->name)) return style; } return NULL; } style_t *style_get(scheme_t * scheme, char *name) { style_t *style; static style_t *d_style = NULL; style = style_search(scheme, name); if (style) return style; if (d_style == NULL) d_style = style_new("dummy style", "NULL", "NULL", "NULL"); return d_style; } void text_print_channel_color(GtkWidget * widget, scheme_t * scheme, char *color, GdkColor * fore, GdkColor * back, char *text) { style_t *style; GdkColor *f; GdkColor *b; style = style_get(scheme, color); if (fore) f = fore; else f = style->fore; if (back) b = back; else b = style->back; gtk_text_freeze(GTK_TEXT(widget)); gtk_text_insert(GTK_TEXT(widget), style->font, f, b, text, strlen(text)); gtk_text_thaw(GTK_TEXT(widget)); return; } void text_print_colored(GtkWidget * widget, scheme_t * scheme, char *base_color, char *text) { GdkColor *fgcolor = NULL; GdkColor *bgcolor = NULL; char *pos2; int len; char temp_str[2048]; int index; while (1) { pos2 = search_highlight_string(text, &len); if (!pos2) break; strncpy(temp_str, text, pos2 - text); temp_str[pos2 - text] = 0; text_print_channel_color(widget, scheme, base_color, fgcolor, bgcolor, temp_str); if ((pos2[0] == 0x03)) { if ((pos2[1] == 0) || (pos2[2] == 0) || (pos2[3] == 0)) return; if (pos2[1] == 0x0f) { fgcolor = NULL; bgcolor = NULL; len = 2; } else if (pos2[1] == ',') { index = ColorTable2(pos2[3] - '0'); if (index < 0) index = -index; bgcolor = &global.color_table[index]; len = 4; } else if (pos2[1] != '-') { index = ColorTable(pos2[1] - '0', pos2[2] - '0'); if (index < 0) index = -index; fgcolor = &global.color_table[index]; len = 3; } } else { strncpy(temp_str, pos2, len); temp_str[len] = 0; text_print_channel(widget, scheme, "highlight", temp_str); } text = pos2 + len; } text_print_channel_color(widget, scheme, base_color, fgcolor, bgcolor, text); return; }