From: <ro...@us...> - 2006-06-07 01:51:34
|
Revision: 16227 Author: roast Date: 2006-06-06 18:51:23 -0700 (Tue, 06 Jun 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16227&view=rev Log Message: ----------- xmllogformat v0.3.1-0x support. 1<x<3 somewhere. Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/util.c Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-06-06 17:42:02 UTC (rev 16226) +++ branches/soc-2006-file-loggers/src/log.c 2006-06-07 01:51:23 UTC (rev 16227) @@ -34,6 +34,7 @@ static GSList *loggers = NULL; +static GaimLogLogger *xml_logger; static GaimLogLogger *html_logger; static GaimLogLogger *txt_logger; static GaimLogLogger *old_logger; @@ -46,6 +47,14 @@ static void log_get_log_sets_common(GHashTable *sets); +static gsize xml_logger_write(GaimLog *log, GaimMessageFlags type, + const char *from, time_t time, const char *message); +static void xml_logger_finalize(GaimLog *log); +static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account); +static GList *xml_logger_list_syslog(GaimAccount *account); +//static char *xml_logger_read(GaimLog *log, GaimLogReadFlags *flags); +static int xml_logger_total_size(GaimLogType type, const char *name, GaimAccount *account); + static gsize html_logger_write(GaimLog *log, GaimMessageFlags type, const char *from, time_t time, const char *message); static void html_logger_finalize(GaimLog *log); @@ -558,6 +567,17 @@ gaim_prefs_add_string("/core/logging/format", "txt"); + xml_logger = gaim_log_logger_new("xml", _("Unified Log Format (XML)"), 8, + NULL, + xml_logger_write, + xml_logger_finalize, + xml_logger_list, + txt_logger_read, + gaim_log_common_sizer, + xml_logger_total_size, + xml_logger_list_syslog); + gaim_log_logger_add(xml_logger); + html_logger = gaim_log_logger_new("html", _("HTML"), 8, NULL, html_logger_write, @@ -645,7 +665,7 @@ /* This log is new */ char *dir; struct tm *tm; - const char *tz; + char *tz; const char *date; char *filename; char *path; @@ -656,13 +676,18 @@ gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); + // roast: tz must be strdup'd. gaim_escape_filename returns a pointer to static data, + // and I need it for escaping remote_user's name for the filename below tm = localtime(&log->time); - tz = gaim_escape_filename(gaim_utf8_strftime("%Z", tm)); - date = gaim_utf8_strftime("%Y-%m-%d.%H%M%S%z", tm); + tz = g_strdup(gaim_escape_filename(gaim_utf8_strftime("%Z", tm))); + date = gaim_utf8_strftime("%Y-%m-%dT%H%M%S%z", tm); - filename = g_strdup_printf("%s%s%s", date, tz, ext ? ext : ""); + filename = g_strdup_printf("%s_%s%s%s", + gaim_escape_filename(gaim_normalize(log->account, log->name)), + date, tz, ext ? ext : ""); path = g_build_filename(dir, filename, NULL); + g_free(tz); g_free(dir); g_free(filename); @@ -926,116 +951,125 @@ g_dir_close(log_dir); } -#if 0 /* Maybe some other time. */ /**************** ** XML LOGGER ** ****************/ +/* static const char *str_from_msg_type (GaimMessageFlags type) { + return ""; - return ""; - } +*/ -static void xml_logger_write(GaimLog *log, +static gsize xml_logger_write(GaimLog *log, GaimMessageFlags type, const char *from, time_t time, const char *message) { - char *xhtml = NULL; + char *msg_fixed; + const char *date = gaim_utf8_strftime("%F %T%z", localtime(&log->time)); + GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); + GaimLogCommonLoggerData *data = log->logger_data; + gsize written = 0; + GaimLogType original_type = log->type; + + /* This log is new. We could use the loggers 'new' function, but + * creating a new file there would result in empty files in the case + * that you open a convo with someone, but don't say anything. + */ if (!log->logger_data) { - /* This log is new. We could use the loggers 'new' function, but - * creating a new file there would result in empty files in the case - * that you open a convo with someone, but don't say anything. - */ - struct tm *tm; - const char *tz; - const char *date; - char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); - char *name; - char *filename; + const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); + gaim_log_common_writer(log, ".chatlog"); - if (dir == NULL) - return; + data = log->logger_data; - tm = localtime(&log->time); - tz = gaim_escape_filename(gaim_utf8_strftime("%Z", tm); - date = gaim_utf8_strftime("%Y-%m-%d.%H%M%S%z", tm); + // if file doesn't exist, die + if (!data->file) return 0; + + fprintf(data->file, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + + if (log->type == GAIM_LOG_SYSTEM) + written += fprintf(data->file, "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\" gaim:logtype=\"system\">\n", + prpl, gaim_account_get_username(log->account)); + else + written += fprintf(data->file, "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\">\n", + prpl, gaim_account_get_username(log->account)); + written += fprintf(data->file, "\t<event time=\"%s\" type=\"logStart\" \/>\n", date); + } - name = g_strdup_printf("%s%s%s", date, tz, ext ? ext : ""); + /* if we can't write to the file, give up before we hurt ourselves */ + if(!data->file) + return 0; - gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); + gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); - filename = g_build_filename(dir, name, NULL); - g_free(dir); - g_free(name); - - log->logger_data = g_fopen(filename, "a"); - if (!log->logger_data) { - gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); - g_free(filename); - return; - } - g_free(filename); - fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" - "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); - - date = gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", localtime(&log->time)); - fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", - date, log->name, prpl); + if (log->type == GAIM_LOG_SYSTEM) { + written += fprintf(data->file, "\t<event time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</event>\n", date, from, msg_fixed); } + else if (type & GAIM_MESSAGE_SYSTEM) { + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</message>\n", date, from, msg_fixed); + } + else if (type & GAIM_MESSAGE_ERROR) { + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"error\">%s</message>\n", date, from, msg_fixed); + } + else if (type & GAIM_MESSAGE_WHISPER) { + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"whisper\">%s</message>\n", date, from, msg_fixed); + } + else if (type & GAIM_MESSAGE_AUTO_RESP && (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV)) { + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" auto=\"true\">%s</message>\n", date, from, msg_fixed); + } + else if (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV) { + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\">%s</message>\n", date, from, msg_fixed); + } + else { + gaim_debug_error("log", "Unhandled message type."); + written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\">%s</message>\n", date, from, msg_fixed); + } - /* if we can't write to the file, give up before we hurt ourselves */ - if(!data->file) - return; + // TODO: haven't written end of file and seeked back - date = log_get_timestamp(log, time); + g_free(msg_fixed); + fflush(data->file); - gaim_markup_html_to_xhtml(message, &xhtml, NULL); - if (from) - fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", - str_from_msg_type(type), - type & GAIM_MESSAGE_SEND ? "direction='sent'" : - type & GAIM_MESSAGE_RECV ? "direction='received'" : "", - from, date, xhtml); - else - fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", - str_from_msg_type(type), - type & GAIM_MESSAGE_SEND ? "direction='sent'" : - type & GAIM_MESSAGE_RECV ? "direction='received'" : "", - date, xhtml): - fflush(log->logger_data); - g_free(date); - g_free(xhtml); + return written; } - static void xml_logger_finalize(GaimLog *log) +static void xml_logger_finalize(GaimLog *log) { - if (log->logger_data) { - fprintf(log->logger_data, "</conversation>\n"); - fclose(log->logger_data); - log->logger_data = NULL; + GaimLogCommonLoggerData *data = log->logger_data; + if (data) { + if (data->file) { + const char *date = gaim_utf8_strftime("%F %T%z", localtime(&log->time)); + fprintf(data->file, "\t<event time=\"%s\" type=\"logEnd\" \/>\n", date); + fprintf(data->file, "</conversation>\n"); + + fclose(data->file); + } + g_free(data->path); + + g_slice_free(GaimLogCommonLoggerData, data); } } static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account) { - return gaim_log_common_lister(type, sn, account, ".xml", &xml_logger); + return gaim_log_common_lister(type, sn, account, ".chatlog", xml_logger); } -static GaimLogLogger xml_logger = { - N_("XML"), "xml", - NULL, - xml_logger_write, - xml_logger_finalize, - xml_logger_list, - NULL, - NULL, - NULL -}; -#endif +// xml_logger_Read +static int xml_logger_total_size(GaimLogType type, const char *name, GaimAccount *account) +{ + return gaim_log_common_total_sizer(type, name, account, ".chatlog"); +} + +static GList *xml_logger_list_syslog(GaimAccount *account) +{ + return gaim_log_common_lister(GAIM_LOG_SYSTEM, ".system", account, ".chatlog", html_logger); +} + /**************************** ** HTML LOGGER ************* ****************************/ Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-06-06 17:42:02 UTC (rev 16226) +++ branches/soc-2006-file-loggers/src/util.c 2006-06-07 01:51:23 UTC (rev 16227) @@ -1342,7 +1342,7 @@ face = g_string_append_c(face, *q); q++; } - g_string_append_printf(style, "font-family: %s; ", face->str); + g_string_append_printf(style, "font-family: %s; ", g_strstrip(face->str)); g_string_free(face, TRUE); p = q; } else if(!g_ascii_strncasecmp(p, "size=", strlen("size="))) { @@ -1392,7 +1392,7 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); if(style->len) - g_string_append_printf(xhtml, "<span style='%s'>", style->str); + g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); else pt->ignore = TRUE; g_string_free(style, TRUE); @@ -1412,7 +1412,7 @@ color = g_string_append_c(color, *q); q++; } - g_string_append_printf(xhtml, "<span style='background: %s;'>", color->str); + g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str)); g_string_free(color, TRUE); if ((c = strchr(c, '>')) != NULL) c++; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-06-16 03:24:29
|
Revision: 16266 Author: roast Date: 2006-06-15 20:24:25 -0700 (Thu, 15 Jun 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16266&view=rev Log Message: ----------- added a unified xml logging format to gtk imhtml parser Modified Paths: -------------- branches/soc-2006-file-loggers/src/util.c branches/soc-2006-file-loggers/src/util.h Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-06-16 03:06:31 UTC (rev 16265) +++ branches/soc-2006-file-loggers/src/util.c 2006-06-16 03:24:25 UTC (rev 16266) @@ -1512,6 +1512,310 @@ g_string_free(plain, TRUE); } +gboolean +gaim_ufl_to_xhtml(const char *ufl, char **xhtml_out) +{ + GString *xhtml = g_string_new(""); + GList *tags = NULL, *tag; + const char *c = ufl; + + GString *loggedby = NULL; + gboolean bad_formatting = FALSE; + + while(!bad_formatting && c && *c) { + if(*c == '<') { + if (*(c+1) == '/') { /* list all expected closing tags */ + if(!g_ascii_strncasecmp(c, "</chat", 6)) { + const char *p = c; + while(*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } + } else { /* opening tag */ + if(!g_ascii_strncasecmp(c, "<?xml", 5)) { + const char *p = c; + while(*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<event", 6)) { + /* TODO: the event tag parsing. will do after message is done */ + const char *p = c; + while (*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<chat", 5)) { + const char *p = c; + bad_formatting = TRUE; + + while(*p && *p != '>') { + bad_formatting = FALSE; + if(!g_ascii_strncasecmp(p, "account=", strlen("account="))) { + const char *q = p + strlen("account="); + char delim = 0; + if (loggedby == NULL) + loggedby = g_string_new(""); + else { + bad_formatting = TRUE; + continue; + } + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } + while(*q && ((delim != 0 && *q != delim) || + (delim == 0 && *q != ' '))) { + loggedby = g_string_append_c(loggedby, *q); + q++; + } + p = q; + } + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<message", 8)) { + const char *p = c; + GString *msgdata = g_string_new(""); + gboolean self_closing = FALSE; + char *msgfixed = NULL; + GString *timestamp = g_string_new(""); + GString *sender = g_string_new(""); + gboolean selfsent = FALSE, autoresp = FALSE, meify = FALSE; + struct tm tm; + + /* assume bad formatting. attributes must exist */ + bad_formatting = TRUE; + + while(*p && *p != '>') { + bad_formatting = FALSE; + if (!g_ascii_strncasecmp(p, "time=", strlen("time="))) { + const char *q = p + strlen("time="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + timestamp = g_string_append_c(timestamp, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "sender=", strlen("sender="))) { + const char *q = p + strlen("sender="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + sender = g_string_append_c(sender, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "data=", strlen("data="))) { + /* TODO: this may NOT be ratified. removed if deemed illegal! */ + const char *q = p + strlen("data="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + msgdata = g_string_append_c(msgdata, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "self=\"true\"", strlen("self=\"true\"")) || + !g_ascii_strncasecmp(p, "self='true'", strlen("self='true'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("self='true"); + selfsent = TRUE; + } else if(!g_ascii_strncasecmp(p, "auto=\"true\"", strlen("auto=\"true\"")) || + !g_ascii_strncasecmp(p, "auto='true'", strlen("auto='true'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("auto='true"); + autoresp = TRUE; + } else if(!g_ascii_strncasecmp(p, "type=\"action\"", strlen("type=\"action\"")) || + !g_ascii_strncasecmp(p, "type='action'", strlen("type='action'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("type='action'"); + meify = TRUE; + } else if(!g_ascii_strncasecmp(p, "/>", strlen("/>"))) { + /* we want *p == '>' at the end of this while loop */ + self_closing = TRUE; + } + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + + /* check that all required attributes were set + or if the msgdata was not set and it self-closed */ + if (timestamp->len == 0 || sender->len == 0 || + (self_closing && msgdata->len == 0)) { + bad_formatting = TRUE; + continue; + } + + if (!self_closing) { + while(*p) { + if (!g_ascii_strncasecmp(p, "</message>", strlen("</message>"))) { + p += strlen("</message>"); + break; + } + msgdata = g_string_append_c(msgdata, *p); + + p++; + } + /* get rid of new lines */ + if (*p == '\n') + p++; + + c = p; + } + + /* now create the gaim markup for this */ + /* we have access to: message.timestamp, message.sender, selfsent, message.auto msgdata/msgfixed, chat's loggedby */ + gaim_str_to_time(timestamp->str, FALSE, &tm, NULL, NULL); + + if (meify) { + g_string_append_printf(xhtml, "<font color=\"062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br />\n", gaim_time_format(&tm), sender->str, msgdata->str); + } else if (!strncmp(sender->str, loggedby->str, strlen(sender->str)) && !selfsent) { + g_string_append_printf(xhtml, "<font color=\"16569E\"><font size=\"2\">(%s)</font> <b>%s%s: </b></font> %s<br />\n", gaim_time_format(&tm), (autoresp)?"Auto-response from ":"", sender->str, msgdata->str); + } else { + g_string_append_printf(xhtml, "<font color=\"A82F2F\"><font size=\"2\">(%s)</font> <b>%s%s: </b></font> %s<br />\n", gaim_time_format(&tm), (autoresp)?"Auto-response from ":"", sender->str, msgdata->str); + } + + g_string_free(msgdata, TRUE); + g_free(msgfixed); + } else if(!g_ascii_strncasecmp(c, "<!--", strlen("<!--"))) { + char *p = strstr(c + strlen("<!--"), "-->"); + if(p) { + xhtml = g_string_append(xhtml, "<!--"); + c += strlen("<!--"); + continue; + } + } + } + } else if(*c == '&') { + char buf[7]; + char *pln; + int len = 1; + guint pound; + if(!g_ascii_strncasecmp(c, "&", 5)) { + pln = "&"; + len = 5; + } else if(!g_ascii_strncasecmp(c, "<", 4)) { + pln = "<"; + len = 4; + } else if(!g_ascii_strncasecmp(c, ">", 4)) { + pln = ">"; + len = 4; + } else if(!g_ascii_strncasecmp(c, " ", 6)) { + pln = " "; + len = 6; + } else if(!g_ascii_strncasecmp(c, "©", 6)) { + pln = "©"; + len = 6; + } else if(!g_ascii_strncasecmp(c, """, 6)) { + pln = "\""; + len = 6; + } else if(!g_ascii_strncasecmp(c, "®", 5)) { + pln = "®"; + len = 5; + } else if(!g_ascii_strncasecmp(c, "'", 6)) { + pln = "\'"; + len = 6; + } else if(*(c+1) == '#' && (sscanf(c, "&#%u;", £) == 1) && + pound != 0 && *(c+3+(gint)log10(pound)) == ';') { + int buflen = g_unichar_to_utf8((gunichar)pound, buf); + buf[buflen] = '\0'; + pln = buf; + + + len = 2; + while(isdigit((gint) c [len])) len++; + if(c [len] == ';') len++; + } else { + len = 1; + g_snprintf(buf, sizeof(buf), "%c", *c); + pln = buf; + } + xhtml = g_string_append_len(xhtml, c, len); + c += len; + } else { + if (*c != ' ' && *c != '\t' && *c != '\n') { + /* don't copy over the whitespace in the XML file */ + xhtml = g_string_append_c(xhtml, *c); + } + c++; + } + } + tag = tags; + while(tag) { + struct gaim_parse_tag *pt = tag->data; + if(!pt->ignore) + g_string_append_printf(xhtml, "</%s>", pt->dest_tag); + tag = tag->next; + } + g_list_free(tags); + if(xhtml_out) + *xhtml_out = g_strdup(xhtml->str); + g_string_free(xhtml, TRUE); + + /* notify caller if bad formatting was encountered */ + return bad_formatting == TRUE; +} + + /* The following are probably reasonable changes: * - \n should be converted to a normal space * - in addition to <br>, <p> and <div> etc. should also be converted into \n Modified: branches/soc-2006-file-loggers/src/util.h =================================================================== --- branches/soc-2006-file-loggers/src/util.h 2006-06-16 03:06:31 UTC (rev 16265) +++ branches/soc-2006-file-loggers/src/util.h 2006-06-16 03:24:25 UTC (rev 16266) @@ -396,6 +396,15 @@ char **dest_plain); /** + * Converts Unified Logging Format XML to GTK IMHTML. + * + * @param ufl The ULF XML. + * @param xhtml_out The destination GTK IMHTML output. + * @return TRUE if input was well formatted, FALSE if input was not well formatted (and expect faulty output). + */ +gboolean gaim_ufl_to_xhtml(const char *ulf, char **xhtml_out); + +/** * Strips HTML tags from a string. * * @param str The string to strip HTML from. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-06-26 00:12:47
|
Revision: 16339 Author: roast Date: 2006-06-25 17:12:31 -0700 (Sun, 25 Jun 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16339&view=rev Log Message: ----------- merged with svn trunk. 16329:16338. Modified Paths: -------------- branches/soc-2006-file-loggers/console/Makefile branches/soc-2006-file-loggers/console/gntblist.c branches/soc-2006-file-loggers/console/gntgaim.c branches/soc-2006-file-loggers/console/libgnt/Makefile branches/soc-2006-file-loggers/console/libgnt/gnt.h branches/soc-2006-file-loggers/console/libgnt/gntbox.c branches/soc-2006-file-loggers/console/libgnt/gntmain.c branches/soc-2006-file-loggers/console/libgnt/gnttree.c branches/soc-2006-file-loggers/console/libgnt/gntwidget.c branches/soc-2006-file-loggers/plugins/ChangeLog.API branches/soc-2006-file-loggers/src/blist.c branches/soc-2006-file-loggers/src/blist.h branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/status.c Modified: branches/soc-2006-file-loggers/console/Makefile =================================================================== --- branches/soc-2006-file-loggers/console/Makefile 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/Makefile 2006-06-26 00:12:31 UTC (rev 16339) @@ -1,5 +1,5 @@ CFLAGS=`pkg-config --cflags gaim gobject-2.0` -g -I./libgnt/ -LDFLAGS=`pkg-config --libs gaim gobject-2.0 libxml-2.0` -lncursesw -L./libgnt/ -lgnt +LDFLAGS=`pkg-config --libs gaim gobject-2.0 libxml-2.0` -lncursesw -L./libgnt/ -lgnt -pg GG_SOURCES = \ gntblist.c \ @@ -13,7 +13,9 @@ gntblist.o \ gntui.o -all: gntgaim +all: + cd libgnt && make + make gntgaim gntgaim: gntgaim.o $(GG_OBJECTS) $(CC) -o gntgaim gntgaim.o $(GG_OBJECTS) $(LDFLAGS) @@ -22,6 +24,7 @@ gntui.o: gntui.c $(GG_HEADERS) clean: + cd libgnt && make clean rm *.o rm gntgaim Modified: branches/soc-2006-file-loggers/console/gntblist.c =================================================================== --- branches/soc-2006-file-loggers/console/gntblist.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/gntblist.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -24,6 +24,7 @@ static void add_buddy(GaimBuddy *buddy, GGBlist *ggblist); static void add_group(GaimGroup *group, GGBlist *ggblist); +static void add_node(GaimBlistNode *node, GGBlist *ggblist); static void draw_tooltip(GGBlist *ggblist); static void @@ -31,6 +32,15 @@ { } +static void add_node(GaimBlistNode *node, GGBlist *ggblist) +{ + if (GAIM_BLIST_NODE_IS_BUDDY(node)) + add_buddy((GaimBuddy*)node, ggblist); + else if (GAIM_BLIST_NODE_IS_GROUP(node)) + add_group((GaimGroup*)node, ggblist); + draw_tooltip(ggblist); +} + static void remove_tooltip(GGBlist *ggblist) { @@ -56,14 +66,8 @@ GaimGroup *group = gaim_buddy_get_group((GaimBuddy*)node); if (gaim_blist_get_group_online_count(group) == 0) node_remove(list, (GaimBlistNode*)group); - else if (ggblist->tnode == (GaimBlistNode *)group) /* Need to update the counts */ - draw_tooltip(ggblist); } - - if (ggblist->tnode == node) - { - remove_tooltip(ggblist); - } + draw_tooltip(ggblist); } static void @@ -73,7 +77,7 @@ { GaimBuddy *buddy = (GaimBuddy*)node; if (gaim_presence_is_online(gaim_buddy_get_presence(buddy))) - add_buddy(buddy, list->ui_data); + add_node((GaimBlistNode*)buddy, list->ui_data); else node_remove(gaim_get_blist(), node); } @@ -171,19 +175,16 @@ return; group = gaim_buddy_get_group(buddy); - add_group(group, ggblist); + add_node((GaimBlistNode*)group, ggblist); node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, get_buddy_display_name(buddy), group, NULL); - - if (ggblist->tnode == (GaimBlistNode*)group) - draw_tooltip(ggblist); } static void buddy_signed_on(GaimBuddy *buddy, GGBlist *ggblist) { - add_buddy(buddy, ggblist); + add_node((GaimBlistNode*)buddy, ggblist); } static void @@ -221,6 +222,8 @@ if (ggblist->tooltip) { + /* XXX: Once we can properly redraw on expose events, this can be removed at the end + * to avoid the blinking*/ remove_tooltip(ggblist); } @@ -292,6 +295,8 @@ g_string_free(str, TRUE); ggblist->tooltip = box; ggblist->tnode = node; + + gnt_widget_set_name(ggblist->tooltip, "tooltip"); } static void @@ -332,6 +337,7 @@ gaim_get_blist()->ui_data = ggblist; ggblist->window = gnt_box_new(FALSE, FALSE); + gnt_widget_set_name(ggblist->window, "buddylist"); gnt_box_set_toplevel(GNT_BOX(ggblist->window), TRUE); gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List")); gnt_box_set_pad(GNT_BOX(ggblist->window), 0); Modified: branches/soc-2006-file-loggers/console/gntgaim.c =================================================================== --- branches/soc-2006-file-loggers/console/gntgaim.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/gntgaim.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -169,7 +169,7 @@ int main(int argc, char **argv) { /* XXX: Don't puke */ - freopen("/dev/null", "w", stderr); + freopen(".error", "w", stderr); /* Initialize the libgaim stuff */ init_libgaim(); Modified: branches/soc-2006-file-loggers/console/libgnt/Makefile =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/Makefile 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/Makefile 2006-06-26 00:12:31 UTC (rev 16339) @@ -1,5 +1,5 @@ CFLAGS=`pkg-config --cflags gobject-2.0` -g -LDFLAGS=`pkg-config --libs gobject-2.0` -lncursesw +LDFLAGS=`pkg-config --libs gobject-2.0` -lncursesw -pg HEADERS = \ gntwidget.h \ Modified: branches/soc-2006-file-loggers/console/libgnt/gnt.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnt.h 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/gnt.h 2006-06-26 00:12:31 UTC (rev 16339) @@ -3,15 +3,11 @@ #include "gntcolors.h" #include "gntkeys.h" -/* XXX: Find a better place for this */ -#define SCROLL_HEIGHT 4096 -#define SCROLL_WIDTH 512 - void gnt_init(); void gnt_main(); -void gnt_screen_take_focus(GntWidget *widget); +void gnt_screen_occupy(GntWidget *widget); -void gnt_screen_remove_widget(GntWidget *widget); +void gnt_screen_release(GntWidget *widget); Modified: branches/soc-2006-file-loggers/console/libgnt/gntbox.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -16,7 +16,9 @@ for (iter = box->list; iter; iter = iter->next) { - gnt_widget_draw(GNT_WIDGET(iter->data)); + GntWidget *w = GNT_WIDGET(iter->data); + gnt_widget_draw(w); + overwrite(w->window, widget->window); } if (box->title) @@ -39,6 +41,8 @@ g_free(title); } wrefresh(widget->window); + + gnt_screen_occupy(widget); DEBUG; } @@ -202,7 +206,7 @@ now = box->list; } - if (now) + if (now && now != box->active) { gnt_widget_set_focus(box->active->data, FALSE); box->active = now; @@ -263,10 +267,21 @@ gnt_widget_destroy(iter->data); } + gnt_screen_release(w); + g_list_free(box->list); } static void +gnt_box_expose(GntWidget *widget, int x, int y, int width, int height) +{ + WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x); + copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE); + wrefresh(win); + delwin(win); +} + +static void gnt_box_class_init(GntBoxClass *klass) { GObjectClass *obj_class = G_OBJECT_CLASS(klass); @@ -274,6 +289,7 @@ parent_class = GNT_WIDGET_CLASS(klass); parent_class->destroy = gnt_box_destroy; parent_class->draw = gnt_box_draw; + parent_class->expose = gnt_box_expose; parent_class->map = gnt_box_map; parent_class->size_request = gnt_box_size_request; parent_class->set_position = gnt_box_set_position; Modified: branches/soc-2006-file-loggers/console/libgnt/gntmain.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -9,6 +9,10 @@ static int max_x; static int max_y; +static GHashTable *nodes; + +static void free_node(gpointer data); + void gnt_screen_take_focus(GntWidget *widget) { focus_list = g_list_prepend(focus_list, widget); @@ -95,6 +99,8 @@ max_x = getmaxx(stdscr); max_y = getmaxy(stdscr); + nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node); + wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); noecho(); refresh(); @@ -108,3 +114,83 @@ g_main_run(loop); } +/********************************* + * Stuff for 'window management' * + *********************************/ + +typedef struct +{ + GntWidget *me; + GList *below; /* List of widgets below me */ + GList *above; /* List of widgets above me */ +} GntNode; + +static void +free_node(gpointer data) +{ + GntNode *node = data; + g_list_free(node->below); + g_list_free(node->above); + g_free(node); +} + +static void +check_intersection(gpointer key, gpointer value, gpointer data) +{ + GntNode *n = value; + GntNode *nu = data; + + if (value == NULL) + return; + + if (n->me->priv.x + n->me->priv.width < nu->me->priv.x) + return; + if (nu->me->priv.x + nu->me->priv.width < n->me->priv.x) + return; + + if (n->me->priv.y + n->me->priv.height < nu->me->priv.y) + return; + if (nu->me->priv.y + nu->me->priv.height < n->me->priv.y) + return; + + n->above = g_list_prepend(n->above, nu->me); + nu->below = g_list_prepend(nu->below, n->me); +} + +void gnt_screen_occupy(GntWidget *widget) +{ + /* XXX: what happens if this is called more than once for the same widget? + * perhaps _release first? */ + GntNode *node = g_new0(GntNode, 1); + node->me = widget; + + g_hash_table_foreach(nodes, check_intersection, node); + g_hash_table_replace(nodes, widget, node); +} + +void gnt_screen_release(GntWidget *widget) +{ + GList *iter; + GntNode *node = g_hash_table_lookup(nodes, widget); + if (node == NULL || node->below == NULL) /* Yay! Nothing to do. */ + return; + + /* XXX: This is not going to work. + * It will be necessary to build a topology and go from there. */ + for (iter = node->below; iter; iter = iter->next) + { + GntWidget *w = iter->data; + int left, right, top, bottom; + + left = MAX(widget->priv.x, w->priv.x) - w->priv.x; + right = MIN(widget->priv.x + widget->priv.width, w->priv.x + w->priv.width) - w->priv.x; + + top = MAX(widget->priv.y, w->priv.y) - w->priv.y; + bottom = MIN(widget->priv.y + widget->priv.height, w->priv.y + w->priv.height) - w->priv.y; + + gnt_widget_expose(w, left, top, right - left, bottom - top); + } + + g_hash_table_remove(nodes, widget); +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gnttree.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -6,6 +6,7 @@ enum { SIG_SELECTION_CHANGED, + SIG_SCROLLED, SIGS, }; @@ -345,6 +346,14 @@ NULL, NULL, gnt_closure_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); + signals[SIG_SCROLLED] = + g_signal_new("scrolled", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); DEBUG; } @@ -445,6 +454,7 @@ } redraw_tree(tree); + g_signal_emit(tree, signals[SIG_SCROLLED], 0, count); } static int Modified: branches/soc-2006-file-loggers/console/libgnt/gntwidget.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntwidget.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/console/libgnt/gntwidget.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -225,8 +225,6 @@ delwin(obj->window); if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING)) g_object_run_dispose(G_OBJECT(obj)); - /* XXX: This may be the wrong place */ - /*gnt_screen_remove_widget(obj);*/ DEBUG; } @@ -264,11 +262,10 @@ else werase(widget->window); +#if 0 + /* XXX: No shadow for now :( */ if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_SHADOW)) { - /* XXX: Find out the actual windows beneath this window, and - * draw the shadow on them */ - /* XXX: Or perhaps do all these from a psedo-WM! */ widget->back = newwin(widget->priv.height, widget->priv.width, widget->priv.y + 1, widget->priv.x + 1); wbkgd(widget->back, COLOR_PAIR(GNT_COLOR_SHADOW)); @@ -279,6 +276,7 @@ touchline(widget->back, 0, widget->priv.height); wrefresh(widget->back); } +#endif wrefresh(widget->window); g_signal_emit(widget, signals[SIG_DRAW], 0); Modified: branches/soc-2006-file-loggers/plugins/ChangeLog.API =================================================================== --- branches/soc-2006-file-loggers/plugins/ChangeLog.API 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/plugins/ChangeLog.API 2006-06-26 00:12:31 UTC (rev 16339) @@ -176,6 +176,7 @@ notify_searchresults in GaimNotifyUiOps. * gaim_conversation_get_send_history(), and send_history from GaimConversation + * Removed ui_ops from GaimBuddyList. Use gaim_blist_get_ui_ops() instead Added: * gaim_prefs_disconnect_by_handle() Modified: branches/soc-2006-file-loggers/src/blist.c =================================================================== --- branches/soc-2006-file-loggers/src/blist.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/src/blist.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -655,17 +655,18 @@ GaimBuddyList *gaim_blist_new() { + GaimBlistUiOps *ui_ops; GaimBuddyList *gbl = g_new0(GaimBuddyList, 1); GAIM_DBUS_REGISTER_POINTER(gbl, GaimBuddyList); - gbl->ui_ops = gaim_blist_get_ui_ops(); + ui_ops = gaim_blist_get_ui_ops(); gbl->buddies = g_hash_table_new_full((GHashFunc)_gaim_blist_hbuddy_hash, (GEqualFunc)_gaim_blist_hbuddy_equal, (GDestroyNotify)_gaim_blist_hbuddy_free_key, NULL); - if (gbl->ui_ops != NULL && gbl->ui_ops->new_list != NULL) - gbl->ui_ops->new_list(gbl); + if (ui_ops != NULL && ui_ops->new_list != NULL) + ui_ops->new_list(gbl); return gbl; } @@ -690,7 +691,7 @@ void gaim_blist_show() { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); if (ops && ops->show) ops->show(gaimbuddylist); @@ -698,7 +699,7 @@ void gaim_blist_destroy() { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); gaim_debug(GAIM_DEBUG_INFO, "blist", "Destroying\n"); @@ -708,7 +709,7 @@ void gaim_blist_set_visible(gboolean show) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); if (ops && ops->set_visible) ops->set_visible(gaimbuddylist, show); @@ -744,7 +745,7 @@ void gaim_blist_update_buddy_status(GaimBuddy *buddy, GaimStatus *old_status) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimPresence *presence; GaimStatus *status; @@ -794,7 +795,7 @@ void gaim_blist_update_buddy_icon(GaimBuddy *buddy) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); g_return_if_fail(buddy != NULL); @@ -808,7 +809,7 @@ */ void gaim_blist_rename_buddy(GaimBuddy *buddy, const char *name) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); struct _gaim_hbuddy *hb; g_return_if_fail(buddy != NULL); @@ -834,7 +835,7 @@ void gaim_blist_alias_contact(GaimContact *contact, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimConversation *conv; char *old_alias = contact->alias; GaimBlistNode *bnode; @@ -868,7 +869,7 @@ void gaim_blist_alias_chat(GaimChat *chat, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); char *old_alias = chat->alias; g_return_if_fail(chat != NULL); @@ -890,7 +891,7 @@ void gaim_blist_alias_buddy(GaimBuddy *buddy, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimConversation *conv; char *old_alias = buddy->alias; @@ -918,7 +919,7 @@ void gaim_blist_server_alias_buddy(GaimBuddy *buddy, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimConversation *conv; char *old_alias = buddy->server_alias; @@ -949,7 +950,7 @@ */ void gaim_blist_rename_group(GaimGroup *source, const char *new_name) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimGroup *dest; gchar *old_name; GList *moved_buddies = NULL; @@ -1071,7 +1072,7 @@ GaimChat *gaim_chat_new(GaimAccount *account, const char *alias, GHashTable *components) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimChat *chat; g_return_val_if_fail(account != NULL, FALSE); @@ -1094,7 +1095,7 @@ GaimBuddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBuddy *buddy; g_return_val_if_fail(account != NULL, FALSE); @@ -1169,7 +1170,7 @@ void gaim_blist_add_chat(GaimChat *chat, GaimGroup *group, GaimBlistNode *node) { GaimBlistNode *cnode = (GaimBlistNode*)chat; - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); g_return_if_fail(chat != NULL); g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT((GaimBlistNode *)chat)); @@ -1251,7 +1252,7 @@ GaimBlistNode *cnode, *bnode; GaimGroup *g; GaimContact *c; - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); struct _gaim_hbuddy *hb; g_return_if_fail(buddy != NULL); @@ -1400,7 +1401,7 @@ void gaim_contact_set_alias(GaimContact *contact, const char *alias) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); char *old_alias = contact->alias; g_return_if_fail(contact != NULL); @@ -1486,7 +1487,7 @@ void gaim_blist_add_contact(GaimContact *contact, GaimGroup *group, GaimBlistNode *node) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimGroup *g; GaimBlistNode *gnode, *cnode, *bnode; @@ -1652,7 +1653,7 @@ g_return_if_fail(group != NULL); g_return_if_fail(GAIM_BLIST_NODE_IS_GROUP((GaimBlistNode *)group)); - ops = gaimbuddylist->ui_ops; + ops = gaim_blist_get_ui_ops(); if (!gaimbuddylist->root) { gaimbuddylist->root = gnode; @@ -1702,7 +1703,7 @@ void gaim_blist_remove_contact(GaimContact *contact) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *node, *gnode; g_return_if_fail(contact != NULL); @@ -1749,7 +1750,7 @@ void gaim_blist_remove_buddy(GaimBuddy *buddy) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *node, *cnode, *gnode; GaimContact *contact; GaimGroup *group; @@ -1837,7 +1838,7 @@ void gaim_blist_remove_chat(GaimChat *chat) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *node, *gnode; GaimGroup *group; @@ -1881,7 +1882,7 @@ void gaim_blist_remove_group(GaimGroup *group) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *node; GList *l; @@ -2244,7 +2245,7 @@ void gaim_blist_add_account(GaimAccount *account) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *gnode, *cnode, *bnode; g_return_if_fail(gaimbuddylist != NULL); @@ -2286,7 +2287,7 @@ void gaim_blist_remove_account(GaimAccount *account) { - GaimBlistUiOps *ops = gaimbuddylist->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); GaimBlistNode *gnode, *cnode, *bnode; GaimBuddy *buddy; GaimChat *chat; Modified: branches/soc-2006-file-loggers/src/blist.h =================================================================== --- branches/soc-2006-file-loggers/src/blist.h 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/src/blist.h 2006-06-26 00:12:31 UTC (rev 16339) @@ -152,8 +152,6 @@ struct _GaimBuddyList { GaimBlistNode *root; /**< The first node in the buddy list */ GHashTable *buddies; /**< Every buddy in this list */ - GaimBlistUiOps *ui_ops; /**< The UI operations for the buddy list */ - void *ui_data; /**< UI-specific data. */ }; Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/src/log.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -23,6 +23,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "internal.h" #include "account.h" #include "dbus-maybe.h" #include "debug.h" Modified: branches/soc-2006-file-loggers/src/status.c =================================================================== --- branches/soc-2006-file-loggers/src/status.c 2006-06-25 23:15:25 UTC (rev 16338) +++ branches/soc-2006-file-loggers/src/status.c 2006-06-26 00:12:31 UTC (rev 16339) @@ -1298,7 +1298,7 @@ update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence, time_t current_time, gboolean old_idle, gboolean idle) { - GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; + GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); if (!old_idle && idle) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-02 15:50:02
|
Revision: 16395 Author: roast Date: 2006-07-02 08:49:54 -0700 (Sun, 02 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16395&view=rev Log Message: ----------- fixing botched 16338 commit. Modified Paths: -------------- branches/soc-2006-file-loggers/console/gntblist.c branches/soc-2006-file-loggers/console/libgnt/test.c branches/soc-2006-file-loggers/src/util.c Modified: branches/soc-2006-file-loggers/console/gntblist.c =================================================================== --- branches/soc-2006-file-loggers/console/gntblist.c 2006-07-02 09:37:25 UTC (rev 16394) +++ branches/soc-2006-file-loggers/console/gntblist.c 2006-07-02 15:49:54 UTC (rev 16395) @@ -149,14 +149,14 @@ #else /* XXX: Let's use these some time */ case GAIM_STATUS_OFFLINE: - strncpy(status, "M-bM-^JM-^W", sizeof(status) - 1); + strncpy(status, "⊗", sizeof(status) - 1); break; case GAIM_STATUS_AVAILABLE: /* XXX: Detect idleness */ - strncpy(status, "M-bM-^WM-/", sizeof(status) - 1); + strncpy(status, "◯", sizeof(status) - 1); break; default: - strncpy(status, "M-bM-^JM-^V", sizeof(status) - 1); + strncpy(status, "⊖", sizeof(status) - 1); break; #endif } Modified: branches/soc-2006-file-loggers/console/libgnt/test.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/test.c 2006-07-02 09:37:25 UTC (rev 16394) +++ branches/soc-2006-file-loggers/console/libgnt/test.c 2006-07-02 15:49:54 UTC (rev 16395) @@ -70,7 +70,7 @@ gnt_init(); GntWidget *widget = gnt_button_new("Button 1"); - GntWidget *widget2 = gnt_button_new("Button 2 has a longish text with a UTF-8 thing M-bM-^@M-&"); + GntWidget *widget2 = gnt_button_new("Button 2 has a longish text with a UTF-8 thing …"); GntWidget *label = gnt_label_new("So wassup dudes and dudettes!!\nSo this is, like,\nthe third line!! \\o/"); GntWidget *vbox, *hbox, *tree; WINDOW *test; @@ -104,7 +104,7 @@ gnt_tree_add_row_after(GNT_TREE(tree), "b", "b", "d", NULL); GNT_WIDGET_UNSET_FLAGS(hbox, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); - gnt_box_set_title(GNT_BOX(hbox), "111111111111111111111111111111111111111111111111111111111111111This is the title M-bM-^@M-&"); + gnt_box_set_title(GNT_BOX(hbox), "111111111111111111111111111111111111111111111111111111111111111This is the title …"); /*gnt_widget_set_take_focus(vbox, TRUE);*/ /*gnt_widget_set_take_focus(hbox, TRUE);*/ Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-07-02 09:37:25 UTC (rev 16394) +++ branches/soc-2006-file-loggers/src/util.c 2006-07-02 15:49:54 UTC (rev 16395) @@ -3659,6 +3659,7 @@ "GET %s%s HTTP/%s\r\n" "Connection: close\r\n" "User-Agent: %s\r\n" + "Accept: */*\r\n" "Host: %s\r\n\r\n", (gfud->full ? "" : "/"), (gfud->full ? gfud->url : gfud->website.page), @@ -3668,6 +3669,7 @@ gfud->request = g_strdup_printf( "GET %s%s HTTP/%s\r\n" "Connection: close\r\n" + "Accept: */*\r\n" "Host: %s\r\n\r\n", (gfud->full ? "" : "/"), (gfud->full ? gfud->url : gfud->website.page), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-04 05:17:12
|
Revision: 16420 Author: roast Date: 2006-07-03 22:17:07 -0700 (Mon, 03 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16420&view=rev Log Message: ----------- preliminary (but completely functional) GIOChannel use for xmllogger without error checking Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/log.h Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-07-04 03:50:59 UTC (rev 16419) +++ branches/soc-2006-file-loggers/src/log.c 2006-07-04 05:17:07 UTC (rev 16420) @@ -720,15 +720,21 @@ log->logger_data = data = g_slice_new0(GaimLogCommonLoggerData); - data->file = g_fopen(path, "w+"); - if (data->file == NULL) - { + if (current_logger == xml_logger) { + data->channel = g_io_channel_new_file(path, "w+", NULL); + } + else { + data->file = g_fopen(path, "w+"); + } + + // they can't be /both/ null + if (data->channel == NULL && data->file == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "log", - "Could not create log file %s\n", path); - + "Could not create log file %s\n", path); + if (log->conv != NULL) gaim_conversation_write(log->conv, NULL, _("Logging of this conversation failed."), - GAIM_MESSAGE_ERROR, time(NULL)); + GAIM_MESSAGE_ERROR, time(NULL)); g_free(dir); g_free(path); g_free(extname); @@ -1013,7 +1019,10 @@ GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); GaimLogCommonLoggerData *data = log->logger_data; - gsize written = 0; + gsize written = 0, written_buf = 0; + char writebuf[4096]; + GIOStatus iostat; + GError *gerror = NULL; /* This log is new. We could use the loggers 'new' function, but * creating a new file there would result in empty files in the case @@ -1027,36 +1036,36 @@ data = log->logger_data; // if file doesn't exist, die - if (!data->file) return 0; + if (!data->channel) return 0; + + g_snprintf(writebuf, sizeof(writebuf), + "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\"%s>\n" + "\t<event time=\"%s\" type=\"logStart\" />\n", + prpl, gaim_account_get_username(log->account), + log->type == GAIM_LOG_SYSTEM ? "gaim:logtype=\"system\"" : "", date); - fprintf(data->file, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); - - if (log->type == GAIM_LOG_SYSTEM) - written += fprintf(data->file, "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\" gaim:logtype=\"system\">\n", - prpl, gaim_account_get_username(log->account)); - else - written += fprintf(data->file, "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\">\n", - prpl, gaim_account_get_username(log->account)); - written += fprintf(data->file, "\t<event time=\"%s\" type=\"logStart\" />\n", date); + iostat = g_io_channel_write_chars(data->channel, writebuf, -1, &written_buf, &gerror); + written += written_buf; } /* if we can't write to the file, give up before we hurt ourselves */ - if(!data->file) + if(!data->channel) return 0; gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); if (log->type == GAIM_LOG_SYSTEM) { - written += fprintf(data->file, "\t<event time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</event>\n", date, from, msg_fixed); + g_snprintf(writebuf, sizeof(writebuf), "\t<event time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</event>\n", date, from, msg_fixed); } else if (type & GAIM_MESSAGE_SYSTEM) { - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</message>\n", date, from, msg_fixed); + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"system\">%s</message>\n", date, from, msg_fixed); } else if (type & GAIM_MESSAGE_ERROR) { - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"error\">%s</message>\n", date, from, msg_fixed); + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"error\">%s</message>\n", date, from, msg_fixed); } else if (type & GAIM_MESSAGE_WHISPER) { - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"whisper\">%s</message>\n", date, from, msg_fixed); + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"whisper\">%s</message>\n", date, from, msg_fixed); } else if (type & GAIM_MESSAGE_AUTO_RESP && (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV)) { gboolean recv_from_self = FALSE; @@ -1070,7 +1079,7 @@ } } - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\"%s auto=\"true\">%s</message>\n", + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\"%s auto=\"true\">%s</message>\n", date, from, recv_from_self ? " gaim:self=\"true\"" : "", msg_fixed); } else if (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV) { @@ -1085,36 +1094,33 @@ } } - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\"%s>%s</message>\n", + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\"%s>%s</message>\n", date, from, recv_from_self ? " gaim:self=\"true\"" : "", msg_fixed); } else { gaim_debug_error("log", "Unhandled message type."); - written += fprintf(data->file, "\t<message time=\"%s\" sender=\"%s\">%s</message>\n", date, from, msg_fixed); + g_snprintf(writebuf, sizeof(writebuf), "\t<message time=\"%s\" sender=\"%s\">%s</message>\n", date, from, msg_fixed); } + iostat = g_io_channel_write_chars(data->channel, writebuf, -1, &written_buf, &gerror); + written += written_buf; + + g_free(date); g_free(msg_fixed); // append suffix to file and seek back to keep a valid XML document out of the user space buffer - { - fpos_t tail; - const char *date = gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", NULL); + g_snprintf(writebuf, sizeof(writebuf), + "\t<event time=\"%s\" type=\"logEnd\" />\n" + "</chat>\n", + gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", NULL)); - if (fgetpos(data->file, &tail) != 0) { - gaim_debug_error("log", "Could not save logfile stream position. Not writing tail."); - } - else { - fprintf(data->file, "\t<event time=\"%s\" type=\"logEnd\" />\n", date); - fprintf(data->file, "</chat>\n"); + iostat = g_io_channel_write_chars(data->channel, writebuf, -1, &written_buf, &gerror); + iostat = g_io_channel_seek_position(data->channel, -1*(gint64)(written_buf), G_SEEK_CUR, &gerror); - if (fsetpos(data->file, &tail) != 0) { - gaim_debug_error("log", "Could not return logfile strem position after tail write."); - } - } - } + //gaim_debug_error("log", "Could not return logfile stream position after tail write."); - g_free(date); - fflush(data->file); + iostat = g_io_channel_flush(data->channel, &gerror); + return written; } @@ -1122,16 +1128,23 @@ { GaimLogCommonLoggerData *data = log->logger_data; if (data) { - if (data->file) { - const char *date = gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", NULL); - fprintf(data->file, "\t<event time=\"%s\" type=\"logEnd\" />\n", date); - fprintf(data->file, "</chat>\n"); + if (data->channel) { + char writebuf[256]; + GIOStatus iostat; + GError *gerror = NULL; - fclose(data->file); - } - g_free(data->path); + g_snprintf(writebuf, sizeof(writebuf), + "\t<event time=\"%s\" type=\"logEnd\" />\n" + "</chat>\n", + gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", NULL)); - g_slice_free(GaimLogCommonLoggerData, data); + iostat = g_io_channel_write_chars(data->channel, writebuf, -1, NULL, &gerror); + + iostat = g_io_channel_shutdown(data->channel, TRUE, &gerror); // this may cause hanging + } + g_free(data->path); + + g_slice_free(GaimLogCommonLoggerData, data); } } Modified: branches/soc-2006-file-loggers/src/log.h =================================================================== --- branches/soc-2006-file-loggers/src/log.h 2006-07-04 03:50:59 UTC (rev 16419) +++ branches/soc-2006-file-loggers/src/log.h 2006-07-04 05:17:07 UTC (rev 16420) @@ -138,6 +138,7 @@ struct _GaimLogCommonLoggerData { char *path; FILE *file; + GIOChannel *channel; void *extra_data; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-17 02:58:56
|
Revision: 16498 Author: roast Date: 2006-07-16 19:58:46 -0700 (Sun, 16 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16498&view=rev Log Message: ----------- added buzz message-type logging support into Yahoo and MSN Modified Paths: -------------- branches/soc-2006-file-loggers/plugins/ChangeLog.API branches/soc-2006-file-loggers/src/conversation.h branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/protocols/msn/msn.c branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.c Modified: branches/soc-2006-file-loggers/plugins/ChangeLog.API =================================================================== --- branches/soc-2006-file-loggers/plugins/ChangeLog.API 2006-07-16 19:09:06 UTC (rev 16497) +++ branches/soc-2006-file-loggers/plugins/ChangeLog.API 2006-07-17 02:58:46 UTC (rev 16498) @@ -291,6 +291,7 @@ * gaim_proxy_get_setup() * GaimNotifySearchResultsCallback: Added user_data. * gaim_notify_searchresults: Added user_data. + * GAIM_MESSAGE_BELL, for pokes, nudges, and buzzes (and bells) Signals - Changed: (See the Doxygen docs for details on all signals.) * Signal propagation now stops after a handler returns a non-NULL value. Modified: branches/soc-2006-file-loggers/src/conversation.h =================================================================== --- branches/soc-2006-file-loggers/src/conversation.h 2006-07-16 19:09:06 UTC (rev 16497) +++ branches/soc-2006-file-loggers/src/conversation.h 2006-07-17 02:58:46 UTC (rev 16498) @@ -115,7 +115,8 @@ GAIM_MESSAGE_DELAYED = 0x0400, /**< Delayed message. */ GAIM_MESSAGE_RAW = 0x0800, /**< "Raw" message - don't apply formatting */ - GAIM_MESSAGE_IMAGES = 0x1000 /**< Message contains images */ + GAIM_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ + GAIM_MESSAGE_BELL = 0x2000 /**< Bell/Poke/Nudge message */ } GaimMessageFlags; Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-07-16 19:09:06 UTC (rev 16497) +++ branches/soc-2006-file-loggers/src/log.c 2006-07-17 02:58:46 UTC (rev 16498) @@ -1068,6 +1068,9 @@ else if (type & GAIM_MESSAGE_WHISPER) { g_string_printf(writebuf, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"whisper\">%s</message>\n", date, from, msg_fixed); } + else if (type & GAIM_MESSAGE_BELL) { + g_string_printf(writebuf, "\t<message time=\"%s\" sender=\"%s\" gaim:type=\"bell\">%s</message>\n", date, from, msg_fixed); + } else if (type & GAIM_MESSAGE_AUTO_RESP && (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV)) { gboolean recv_from_self = FALSE; if (type & GAIM_MESSAGE_RECV) { Modified: branches/soc-2006-file-loggers/src/protocols/msn/msn.c =================================================================== --- branches/soc-2006-file-loggers/src/protocols/msn/msn.c 2006-07-16 19:09:06 UTC (rev 16497) +++ branches/soc-2006-file-loggers/src/protocols/msn/msn.c 2006-07-17 02:58:46 UTC (rev 16498) @@ -110,7 +110,7 @@ msn_switchboard_send_msg(swboard, msg, TRUE); - gaim_conversation_write(conv, NULL, _("You have just sent a Nudge!"), GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(conv, NULL, _("You have just sent a Nudge!"), GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_BELL, time(NULL)); return GAIM_CMD_RET_OK; } Modified: branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.c =================================================================== --- branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.c 2006-07-16 19:09:06 UTC (rev 16497) +++ branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.c 2006-07-17 02:58:46 UTC (rev 16498) @@ -767,7 +767,7 @@ if (!strcmp(m, "<ding>")) { GaimConversation *c = gaim_conversation_new(GAIM_CONV_TYPE_IM, gaim_connection_get_account(gc), im->from); - gaim_conv_im_write(GAIM_CONV_IM(c), "", _("Buzz!!"), GAIM_MESSAGE_NICK|GAIM_MESSAGE_RECV, + gaim_conv_im_write(GAIM_CONV_IM(c), "", _("Buzz!!"), GAIM_MESSAGE_NICK|GAIM_MESSAGE_RECV|GAIM_MESSAGE_BELL, im->time); g_free(m); g_free(im); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-17 03:13:19
|
Revision: 16499 Author: roast Date: 2006-07-16 20:12:41 -0700 (Sun, 16 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16499&view=rev Log Message: ----------- merged with svn trunk. 16464:16498. Modified Paths: -------------- branches/soc-2006-file-loggers/console/gntaccount.c branches/soc-2006-file-loggers/console/gntblist.c branches/soc-2006-file-loggers/console/gntconv.c branches/soc-2006-file-loggers/console/libgnt/Makefile.am branches/soc-2006-file-loggers/console/libgnt/gnt.h branches/soc-2006-file-loggers/console/libgnt/gntbox.c branches/soc-2006-file-loggers/console/libgnt/gntbox.h branches/soc-2006-file-loggers/console/libgnt/gntbutton.c branches/soc-2006-file-loggers/console/libgnt/gntentry.c branches/soc-2006-file-loggers/console/libgnt/gntlabel.c branches/soc-2006-file-loggers/console/libgnt/gntmain.c branches/soc-2006-file-loggers/console/libgnt/gnttextview.c branches/soc-2006-file-loggers/console/libgnt/gnttree.c branches/soc-2006-file-loggers/console/libgnt/gnttree.h branches/soc-2006-file-loggers/console/libgnt/gntwidget.c branches/soc-2006-file-loggers/console/libgnt/gntwidget.h branches/soc-2006-file-loggers/console/libgnt/test/Makefile branches/soc-2006-file-loggers/console/libgnt/test/focus.c branches/soc-2006-file-loggers/console/libgnt/test/multiwin.c branches/soc-2006-file-loggers/pixmaps/status/default/Makefile.am branches/soc-2006-file-loggers/plugins/spellchk.c branches/soc-2006-file-loggers/plugins/tcl/tcl.c branches/soc-2006-file-loggers/plugins/tcl/tcl_gaim.h branches/soc-2006-file-loggers/plugins/tcl/tcl_glib.c branches/soc-2006-file-loggers/plugins/tcl/tcl_signals.c branches/soc-2006-file-loggers/src/Makefile.am branches/soc-2006-file-loggers/src/Makefile.mingw branches/soc-2006-file-loggers/src/gtkimhtml.c branches/soc-2006-file-loggers/src/log.h branches/soc-2006-file-loggers/src/protocols/irc/irc.h branches/soc-2006-file-loggers/src/protocols/jabber/jabber.c branches/soc-2006-file-loggers/src/protocols/jabber/jabber.h branches/soc-2006-file-loggers/src/protocols/msn/httpconn.h branches/soc-2006-file-loggers/src/protocols/msn/msn.c branches/soc-2006-file-loggers/src/protocols/oscar/oscar.c branches/soc-2006-file-loggers/src/protocols/oscar/oscar.h branches/soc-2006-file-loggers/src/protocols/sametime/sametime.c branches/soc-2006-file-loggers/src/protocols/simple/simple.h branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.h branches/soc-2006-file-loggers/src/util.c Added Paths: ----------- branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c branches/soc-2006-file-loggers/console/libgnt/gntcombobox.h branches/soc-2006-file-loggers/console/libgnt/gntline.c branches/soc-2006-file-loggers/console/libgnt/gntline.h branches/soc-2006-file-loggers/console/libgnt/gntmarshal.c branches/soc-2006-file-loggers/console/libgnt/gntmarshal.h branches/soc-2006-file-loggers/console/libgnt/test/combo.c branches/soc-2006-file-loggers/src/circbuffer.c branches/soc-2006-file-loggers/src/circbuffer.h Removed Paths: ------------- branches/soc-2006-file-loggers/console/libgnt/gntutils.c branches/soc-2006-file-loggers/console/libgnt/gntutils.h branches/soc-2006-file-loggers/pixmaps/status/default/nr.png branches/soc-2006-file-loggers/src/gaim_buffer.c branches/soc-2006-file-loggers/src/gaim_buffer.h Modified: branches/soc-2006-file-loggers/console/gntaccount.c =================================================================== --- branches/soc-2006-file-loggers/console/gntaccount.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/gntaccount.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -1,11 +1,17 @@ #include <gnt.h> #include <gntbox.h> #include <gntbutton.h> +#include <gntcombobox.h> +#include <gntentry.h> #include <gntlabel.h> +#include <gntline.h> #include <gnttree.h> +#include <account.h> +#include <accountopt.h> #include <connection.h> #include <notify.h> +#include <plugin.h> #include <request.h> #include "gntaccount.h" @@ -19,7 +25,167 @@ static GGAccountList accounts; +typedef struct +{ + GaimAccount *account; /* NULL for a new account */ + + GntWidget *window; + + GntWidget *protocol; + GntWidget *screenname; + GntWidget *password; + GntWidget *alias; + + GntWidget *splits; + GList *split_entries; +} AccountEditDialog; + static void +edit_dialog_destroy(AccountEditDialog *dialog) +{ + g_free(dialog); +} + +static void +save_account_cb(AccountEditDialog *dialog) +{ +} + +static void +update_user_splits(AccountEditDialog *dialog) +{ + GntWidget *hbox; + GaimPlugin *plugin; + GaimPluginProtocolInfo *prplinfo; + GList *iter; + char *username = NULL; + + if (dialog->splits) + { + gnt_box_remove_all(GNT_BOX(dialog->splits)); + g_list_free(dialog->split_entries); + } + else + { + dialog->splits = gnt_box_new(FALSE, TRUE); + gnt_box_set_pad(GNT_BOX(dialog->splits), 0); + } + + dialog->split_entries = NULL; + + plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); + if (!plugin) + return; + prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin); + + username = g_strdup(gaim_account_get_username(dialog->account)); + + for (iter = prplinfo->user_splits; iter; iter = iter->next) + { + GaimAccountUserSplit *split = iter->data; + GntWidget *entry; + char *buf; + + hbox = gnt_box_new(TRUE, FALSE); + gnt_box_add_widget(GNT_BOX(dialog->splits), hbox); + + buf = g_strdup_printf("%s:", gaim_account_user_split_get_text(split)); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf)); + + entry = gnt_entry_new(NULL); + gnt_box_add_widget(GNT_BOX(hbox), entry); + + dialog->split_entries = g_list_append(dialog->split_entries, entry); + g_free(buf); + } + + /* XXX: Add default/custom values to the splits */ + g_free(username); +} + +static void +prpl_changed_cb(GntWidget *combo, GaimPlugin *old, GaimPlugin *new, AccountEditDialog *dialog) +{ + update_user_splits(dialog); + gnt_box_readjust(GNT_BOX(dialog->window)); + gnt_widget_draw(dialog->window); +} + +static void +add_account(GntWidget *b, gpointer null) +{ + GntWidget *window, *hbox; + GntWidget *combo, *button, *entry; + GList *list, *iter; + AccountEditDialog *dialog; + + dialog = g_new0(AccountEditDialog, 1); + + dialog->window = window = gnt_box_new(FALSE, TRUE); + gnt_box_set_toplevel(GNT_BOX(window), TRUE); + gnt_box_set_title(GNT_BOX(window), _("New Account")); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); + gnt_box_set_pad(GNT_BOX(window), 0); + + hbox = gnt_box_new(TRUE, FALSE); + gnt_box_add_widget(GNT_BOX(window), hbox); + gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); + + dialog->protocol = combo = gnt_combo_box_new(); + list = gaim_plugins_get_protocols(); + for (iter = list; iter; iter = iter->next) + { + gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data, + ((GaimPlugin*)iter->data)->info->name); + } + g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:"))); + gnt_box_add_widget(GNT_BOX(hbox), combo); + + hbox = gnt_box_new(TRUE, FALSE); + gnt_box_add_widget(GNT_BOX(window), hbox); + + dialog->screenname = entry = gnt_entry_new(NULL); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Screen name:"))); + gnt_box_add_widget(GNT_BOX(hbox), entry); + + /* User splits */ + update_user_splits(dialog); + gnt_box_add_widget(GNT_BOX(window), dialog->splits); + + hbox = gnt_box_new(TRUE, FALSE); + gnt_box_add_widget(GNT_BOX(window), hbox); + + dialog->password = entry = gnt_entry_new(NULL); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:"))); + gnt_box_add_widget(GNT_BOX(hbox), entry); + + hbox = gnt_box_new(TRUE, FALSE); + gnt_box_add_widget(GNT_BOX(window), hbox); + + dialog->alias = entry = gnt_entry_new(NULL); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:"))); + gnt_box_add_widget(GNT_BOX(hbox), entry); + + gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE)); + + hbox = gnt_box_new(FALSE, FALSE); + gnt_box_add_widget(GNT_BOX(window), hbox); + + button = gnt_button_new(_("Cancel")); + gnt_box_add_widget(GNT_BOX(hbox), button); + g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window); + + button = gnt_button_new(_("Save")); + gnt_box_add_widget(GNT_BOX(hbox), button); + g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog); + + g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog); + + gnt_widget_show(window); +} + +static void account_toggled(GntWidget *widget, void *key, gpointer null) { GaimAccount *account = key; @@ -32,15 +198,18 @@ GList *iter; GntWidget *box, *button; - accounts.window = gnt_box_new(TRUE, TRUE); + accounts.window = gnt_box_new(FALSE, TRUE); gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE); gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts")); gnt_box_set_pad(GNT_BOX(accounts.window), 0); + gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID); gnt_widget_set_name(accounts.window, "accounts"); gnt_box_add_widget(GNT_BOX(accounts.window), gnt_label_new(_("You can enable/disable accounts from the following list."))); + gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE)); + accounts.tree = gnt_tree_new(); GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER); @@ -62,10 +231,13 @@ gnt_widget_set_size(accounts.tree, 40, 10); gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree); + gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE)); + box = gnt_box_new(FALSE, FALSE); button = gnt_button_new(_("Add")); gnt_box_add_widget(GNT_BOX(box), button); + g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account), NULL); button = gnt_button_new(_("Modify")); gnt_box_add_widget(GNT_BOX(box), button); Modified: branches/soc-2006-file-loggers/console/gntblist.c =================================================================== --- branches/soc-2006-file-loggers/console/gntblist.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/gntblist.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -234,6 +234,9 @@ GntTree *tree = GNT_TREE(ggblist->tree); GaimBlistNode *node = gnt_tree_get_selection_data(tree); + if (!node) + return; + if (GAIM_BLIST_NODE_IS_BUDDY(node)) { GaimBuddy *buddy = (GaimBuddy *)node; Modified: branches/soc-2006-file-loggers/console/gntconv.c =================================================================== --- branches/soc-2006-file-loggers/console/gntconv.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/gntconv.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -47,17 +47,29 @@ if (key[0] == '\r' && key[1] == 0) { const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry)); - switch (gaim_conversation_get_type(ggconv->conv)) + if (*text == '/') { - case GAIM_CONV_TYPE_IM: - gaim_conv_im_send_with_flags(GAIM_CONV_IM(ggconv->conv), text, GAIM_MESSAGE_SEND); - break; - case GAIM_CONV_TYPE_CHAT: - gaim_conv_chat_send(GAIM_CONV_CHAT(ggconv->conv), text); - break; - default: - g_return_val_if_reached(FALSE); + /* XXX: Need to check for /-commands here */ + gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), + _("Commands are not supported yet. Message was NOT sent."), + GNT_TEXT_FLAG_DIM | GNT_TEXT_FLAG_UNDERLINE); + gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv)); + gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0); } + else + { + switch (gaim_conversation_get_type(ggconv->conv)) + { + case GAIM_CONV_TYPE_IM: + gaim_conv_im_send_with_flags(GAIM_CONV_IM(ggconv->conv), text, GAIM_MESSAGE_SEND); + break; + case GAIM_CONV_TYPE_CHAT: + gaim_conv_chat_send(GAIM_CONV_CHAT(ggconv->conv), text); + break; + default: + g_return_val_if_reached(FALSE); + } + } gnt_entry_clear(GNT_ENTRY(ggconv->entry)); return TRUE; } @@ -107,7 +119,7 @@ type = gaim_conversation_get_type(conv); title = g_strdup_printf(_("%s"), gaim_conversation_get_name(conv)); - ggc->window = gnt_box_new(TRUE, TRUE); + ggc->window = gnt_box_new(FALSE, TRUE); gnt_box_set_title(GNT_BOX(ggc->window), title); gnt_box_set_toplevel(GNT_BOX(ggc->window), TRUE); gnt_box_set_pad(GNT_BOX(ggc->window), 0); Modified: branches/soc-2006-file-loggers/console/libgnt/Makefile.am =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/Makefile.am 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/Makefile.am 2006-07-17 03:12:41 UTC (rev 16499) @@ -8,11 +8,13 @@ gntbox.c \ gntbutton.c \ gntcolors.c \ + gntcombobox.c \ gntentry.c \ gntlabel.c \ + gntline.c \ + gntmarshal.c \ gnttextview.c \ gnttree.c \ - gntutils.c \ gntmain.c libgnt_la_headers = \ @@ -20,12 +22,14 @@ gntbox.h \ gntbutton.h \ gntcolors.h \ + gntcombobox.h \ gntentry.h \ gntkeys.h \ gntlabel.h \ + gntline.h \ + gntmarshal.h \ gnttextview.h \ gnttree.h \ - gntutils.h \ gnt.h libgnt_laincludedir=$(includedir)/gnt Modified: branches/soc-2006-file-loggers/console/libgnt/gnt.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnt.h 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gnt.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -17,6 +17,8 @@ void gnt_screen_take_focus(GntWidget *widget); +void gnt_screen_resize_widget(GntWidget *widget, int width, int height); + gboolean gnt_widget_has_focus(GntWidget *widget); void gnt_widget_set_urgent(GntWidget *widget); Modified: branches/soc-2006-file-loggers/console/libgnt/gntbox.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -77,7 +77,7 @@ gboolean has_border = FALSE; w = h = 0; - max = -1; + max = 0; curx = widget->priv.x; cury = widget->priv.y; if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) @@ -93,15 +93,21 @@ gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); if (box->vertical) { - cury += h + box->pad; - if (max < w) - max = w; + if (h) + { + cury += h + box->pad; + if (max < w) + max = w; + } } else { - curx += w + box->pad; - if (max < h) - max = h; + if (w) + { + curx += w + box->pad; + if (max < h) + max = h; + } } } @@ -112,6 +118,14 @@ max += 2; } + if (box->list) + { + if (box->vertical) + cury -= box->pad; + else + curx -= box->pad; + } + if (box->vertical) { widget->priv.width = max; @@ -127,8 +141,18 @@ static void gnt_box_set_position(GntWidget *widget, int x, int y) { - gnt_widget_size_request(widget); - reposition_children(widget); + GList *iter; + int changex, changey; + + changex = widget->priv.x - x; + changey = widget->priv.y - y; + + for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) + { + GntWidget *w = GNT_WIDGET(iter->data); + gnt_widget_set_position(w, w->priv.x - changex, + w->priv.y - changey); + } } static void @@ -136,25 +160,43 @@ { GntBox *box = GNT_BOX(widget); GList *iter; + int maxw = 0, maxh = 0; g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL); + for (iter = box->list; iter; iter = iter->next) + { + int w, h; + gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); + if (maxh < h) + maxh = h; + if (maxw < w) + maxw = w; + } + if (box->homogeneous) { - int max = -1, w, h; - - /* XXX: should probably be changed based on vertical-ness */ for (iter = box->list; iter; iter = iter->next) { - gnt_widget_get_size(GNT_WIDGET(iter->data), &w, NULL); - if (max < w) - max = w; + gnt_widget_set_size(GNT_WIDGET(iter->data), maxw, maxh); } - + } + else + { for (iter = box->list; iter; iter = iter->next) { - gnt_widget_get_size(GNT_WIDGET(iter->data), NULL, &h); - gnt_widget_set_size(GNT_WIDGET(iter->data), max, h); + if (box->vertical) + { + int h; + gnt_widget_get_size(GNT_WIDGET(iter->data), NULL, &h); + gnt_widget_set_size(GNT_WIDGET(iter->data), maxw, h); + } + else + { + int w; + gnt_widget_get_size(GNT_WIDGET(iter->data), &w, NULL); + gnt_widget_set_size(GNT_WIDGET(iter->data), w, maxh); + } } } @@ -185,10 +227,21 @@ return box->active; } +static void +find_next_focus(GntBox *box) +{ + GList *iter = g_list_find(box->focus, box->active); + if (iter && iter->next) + box->active = iter->next->data; + else if (box->focus) + box->active = box->focus->data; +} + static gboolean gnt_box_key_pressed(GntWidget *widget, const char *text) { GntBox *box = GNT_BOX(widget); + GntWidget *now; if (box->active == NULL && !find_focusable_widget(box)) return FALSE; @@ -196,9 +249,10 @@ if (gnt_widget_key_pressed(box->active, text)) return TRUE; + now = box->active; + if (text[0] == 27) { - GntWidget *now = box->active; if (strcmp(text+1, GNT_KEY_LEFT) == 0) { GList *iter = g_list_find(box->focus, box->active); @@ -213,23 +267,19 @@ } else if (strcmp(text+1, GNT_KEY_RIGHT) == 0) { - GList *iter = g_list_find(box->focus, box->active); - if (iter && iter->next) - { - box->active = iter->next->data; - } - else if (box->focus) - { - box->active = box->focus->data; - } + find_next_focus(box); } + } + else if (text[0] == '\t') + { + find_next_focus(box); + } - if (now && now != box->active) - { - gnt_widget_set_focus(now, FALSE); - gnt_widget_set_focus(box->active, TRUE); - return TRUE; - } + if (now && now != box->active) + { + gnt_widget_set_focus(now, FALSE); + gnt_widget_set_focus(box->active, TRUE); + return TRUE; } return FALSE; @@ -257,16 +307,9 @@ gnt_box_destroy(GntWidget *w) { GntBox *box = GNT_BOX(w); - GList *iter; - for (iter = box->list; iter; iter = iter->next) - { - gnt_widget_destroy(iter->data); - } - + gnt_box_remove_all(box); gnt_screen_release(w); - - g_list_free(box->list); } static void @@ -285,9 +328,20 @@ GntBox *box = GNT_BOX(widget); int wchange, hchange; + if (widget->priv.width != width && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X)) + return FALSE; + if (widget->priv.height != height && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y)) + return FALSE; + + if (!box->list) + return TRUE; + wchange = widget->priv.width - width; hchange = widget->priv.height - height; + if (wchange == 0 && hchange == 0) + return TRUE; /* Quit playing games */ + /* XXX: Right now, I am trying to just apply all the changes to * just one widget. It should be possible to distribute the * changes to all the widgets in the box. */ @@ -298,14 +352,84 @@ gnt_widget_get_size(wid, &w, &h); - if (gnt_widget_set_size(wid, w - wchange, h - hchange)) + if (gnt_widget_confirm_size(wid, w - wchange, h - hchange)) + { + GList *i; + + for (i = box->list; i; i = i->next) + { + int tw, th; + if (i == iter) continue; + gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); + if (box->vertical) + { + if (!gnt_widget_confirm_size(i->data, tw - wchange, th)) + return FALSE; + } + else + { + if (!gnt_widget_confirm_size(i->data, tw, th - hchange)) + return FALSE; + } + } +#if 0 + gnt_widget_set_size(wid, w - wchange, h - hchange); + if (box->vertical) + hchange = 0; + else + wchange = 0; + + for (i = box->list; i; i = i->next) + { + int tw, th; + if (i == iter) continue; + gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); + gnt_widget_set_size(i->data, tw - wchange, th - hchange); + } +#endif + g_object_set_data(G_OBJECT(box), "size-queued", wid); return TRUE; + } } return FALSE; } static void +gnt_box_size_changed(GntWidget *widget, int oldw, int oldh) +{ + int wchange, hchange; + GList *i; + GntBox *box = GNT_BOX(widget); + GntWidget *wid; + int tw, th; + + wchange = widget->priv.width - oldw; + hchange = widget->priv.height - oldh; + + wid = g_object_get_data(G_OBJECT(box), "size-queued"); + if (wid) + { + gnt_widget_get_size(wid, &tw, &th); + gnt_widget_set_size(wid, tw + wchange, th + hchange); + g_object_set_data(G_OBJECT(box), "size-queued", NULL); + } + + if (box->vertical) + hchange = 0; + else + wchange = 0; + + for (i = box->list; i; i = i->next) + { + gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); + gnt_widget_set_size(i->data, tw + wchange, th + hchange); + } + + reposition_children(widget); +} + +static void gnt_box_class_init(GntBoxClass *klass) { parent_class = GNT_WIDGET_CLASS(klass); @@ -319,6 +443,7 @@ parent_class->lost_focus = gnt_box_lost_focus; parent_class->gained_focus = gnt_box_gained_focus; parent_class->confirm_size = gnt_box_confirm_size; + parent_class->size_changed = gnt_box_size_changed; DEBUG; } @@ -372,6 +497,10 @@ box->pad = 1; gnt_widget_set_take_focus(widget, TRUE); GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); + if (vert) + box->alignment = GNT_ALIGN_LEFT; + else + box->alignment = GNT_ALIGN_MID; return widget; } @@ -424,25 +553,119 @@ { GList *iter; GntWidget *widget = GNT_WIDGET(box); + int pos = 1; - /* XXX: werase first? */ + if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) + pos = 0; for (iter = box->list; iter; iter = iter->next) { GntWidget *w = GNT_WIDGET(iter->data); int height, width; + int x, y; if (GNT_IS_BOX(w)) gnt_box_sync_children(GNT_BOX(w)); gnt_widget_get_size(w, &width, &height); + x = w->priv.x - widget->priv.x; + y = w->priv.y - widget->priv.y; + + if (box->vertical) + { + if (box->alignment == GNT_ALIGN_RIGHT) + x += widget->priv.width - width; + else if (box->alignment == GNT_ALIGN_MID) + x += (widget->priv.width - width)/2; + if (x + width > widget->priv.width - pos) + x -= x + width - (widget->priv.width - pos); + } + else + { + if (box->alignment == GNT_ALIGN_BOTTOM) + y += widget->priv.height - height; + else if (box->alignment == GNT_ALIGN_MID) + y += (widget->priv.height - height)/2; + if (y + height >= widget->priv.height - pos) + y = widget->priv.height - height - pos; + } + copywin(w->window, widget->window, 0, 0, - w->priv.y - widget->priv.y, - w->priv.x - widget->priv.x, - w->priv.y - widget->priv.y + height - 1, - w->priv.x - widget->priv.x + width - 1, - FALSE); + y, x, y + height - 1, x + width - 1, FALSE); } } +void gnt_box_set_alignment(GntBox *box, GntAlignment alignment) +{ + box->alignment = alignment; +} + +void gnt_box_remove(GntBox *box, GntWidget *widget) +{ + box->list = g_list_remove(box->list, widget); + if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS) + && GNT_WIDGET(box)->parent == NULL && box->focus) + { + if (widget == box->active) + { + find_next_focus(box); + if (box->active == widget) /* There's only one widget */ + box->active = NULL; + } + box->focus = g_list_remove(box->focus, widget); + } + + if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(box), GNT_WIDGET_MAPPED)) + gnt_widget_draw(GNT_WIDGET(box)); +} + +void gnt_box_remove_all(GntBox *box) +{ + g_list_foreach(box->list, (GFunc)gnt_widget_destroy, NULL); + g_list_free(box->list); + g_list_free(box->focus); + box->list = NULL; + box->focus = NULL; + GNT_WIDGET(box)->priv.width = 0; + GNT_WIDGET(box)->priv.height = 0; +} + +void gnt_box_readjust(GntBox *box) +{ + GList *iter; + GntWidget *wid; + int width, height; + + g_return_if_fail(GNT_WIDGET(box)->parent == NULL); + + for (iter = box->list; iter; iter = iter->next) + { + GntWidget *w = iter->data; + if (GNT_IS_BOX(w)) + gnt_box_readjust(GNT_BOX(w)); + else + { + GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_MAPPED); + w->priv.width = 0; + w->priv.height = 0; + } + } + + wid = GNT_WIDGET(box); + GNT_WIDGET_UNSET_FLAGS(wid, GNT_WIDGET_MAPPED); + wid->priv.width = 0; + wid->priv.height = 0; + + if (wid->parent == NULL) + { + g_list_free(box->focus); + box->focus = NULL; + box->active = NULL; + gnt_widget_size_request(wid); + gnt_widget_get_size(wid, &width, &height); + gnt_screen_resize_widget(wid, width, height); + find_focusable_widget(box); + } +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gntbox.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbox.h 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntbox.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -14,6 +14,19 @@ typedef struct _GnBox GntBox; typedef struct _GnBoxClass GntBoxClass; +typedef enum +{ + /* These for vertical boxes */ + GNT_ALIGN_LEFT, + GNT_ALIGN_RIGHT, + + GNT_ALIGN_MID, + + /* These for horizontal boxes */ + GNT_ALIGN_TOP, + GNT_ALIGN_BOTTOM +} GntAlignment; + struct _GnBox { GntWidget parent; @@ -24,6 +37,7 @@ GntWidget *active; int pad; /* Number of spaces to use between widgets */ + GntAlignment alignment; /* How are the widgets going to be aligned? */ char *title; GList *focus; /* List of widgets to cycle focus (only valid for parent boxes) */ @@ -48,6 +62,9 @@ GType gnt_box_get_gtype(void); +#define gnt_vbox_new(homo) gnt_box_new(homo, TRUE) +#define gnt_hbox_new(homo) gnt_box_new(homo, FALSE) + GntWidget *gnt_box_new(gboolean homo, gboolean vert); void gnt_box_add_widget(GntBox *box, GntWidget *widget); @@ -60,6 +77,14 @@ void gnt_box_sync_children(GntBox *box); +void gnt_box_set_alignment(GntBox *box, GntAlignment alignment); + +void gnt_box_remove(GntBox *box, GntWidget *widget); /* XXX: does NOT destroy widget */ + +void gnt_box_remove_all(GntBox *box); /* Removes AND destroys all the widgets in it */ + +void gnt_box_readjust(GntBox *box); + G_END_DECLS #endif /* GNT_BOX_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gntbutton.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbutton.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntbutton.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -69,10 +69,14 @@ static void gnt_button_init(GTypeInstance *instance, gpointer class) { + GntWidget *widget = GNT_WIDGET(instance); GntButton *button = GNT_BUTTON(instance); button->priv = g_new0(GntButtonPriv, 1); - GNT_WIDGET_SET_FLAGS(GNT_WIDGET(button), GNT_WIDGET_GROW_X); /* Can be resized sideways */ + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X); + + widget->priv.minw = 4; + widget->priv.minh = 3; DEBUG; } Copied: branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c (from rev 16498, trunk/console/libgnt/gntcombobox.c) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,247 @@ +#include "gntbox.h" +#include "gntcombobox.h" +#include "gnttree.h" +#include "gntmarshal.h" + +#include <string.h> + +enum +{ + SIG_SELECTION_CHANGED, + SIGS, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; +static void (*widget_lost_focus)(GntWidget *widget); + +static void +set_selection(GntComboBox *box, gpointer key) +{ + if (box->selected != key) + { + gpointer old = box->selected; + box->selected = key; + g_signal_emit(box, signals[SIG_SELECTION_CHANGED], 0, old, key); + gnt_widget_draw(GNT_WIDGET(box)); + } +} + +static void +gnt_combo_box_draw(GntWidget *widget) +{ + GntComboBox *box = GNT_COMBO_BOX(widget); + char *text = NULL; + GntColorType type; + int len; + + if (box->dropdown) + { + text = (char *)gnt_tree_get_selection_text(GNT_TREE(box->dropdown)); + box->selected = gnt_tree_get_selection_data(GNT_TREE(box->dropdown)); + } + + if (text == NULL) + text = ""; + + text = g_strdup(text); + + if (gnt_widget_has_focus(widget)) + type = GNT_COLOR_HIGHLIGHT; + else + type = GNT_COLOR_NORMAL; + + wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); + + if ((len = g_utf8_strlen(text, -1)) > widget->priv.width - 4) + { + char *s = g_utf8_offset_to_pointer(text, widget->priv.width - 4); + *s = '\0'; + len = widget->priv.width - 4; + } + + mvwprintw(widget->window, 1, 1, text); + whline(widget->window, '\0' | COLOR_PAIR(type), widget->priv.width - 4 - len); + mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL)); + mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | COLOR_PAIR(GNT_COLOR_NORMAL)); + + g_free(text); + DEBUG; +} + +static void +gnt_combo_box_size_request(GntWidget *widget) +{ + widget->priv.height = 3; /* For now, a combobox will have border */ + widget->priv.width = 15; +} + +static void +gnt_combo_box_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static gboolean +gnt_combo_box_key_pressed(GntWidget *widget, const char *text) +{ + GntComboBox *box = GNT_COMBO_BOX(widget); + if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED)) + { + if (text[1] == 0) + { + switch (text[0]) + { + case '\r': + case '\t': + set_selection(box, gnt_tree_get_selection_data(GNT_TREE(box->dropdown))); + case 27: + gnt_widget_hide(box->dropdown->parent); + return TRUE; + break; + } + } + if (gnt_widget_key_pressed(box->dropdown, text)) + return TRUE; + } + else + { + if (text[0] == 27) + { + if (strcmp(text + 1, GNT_KEY_UP) == 0 || + strcmp(text + 1, GNT_KEY_DOWN) == 0) + { + GntWidget *parent = box->dropdown->parent; + gnt_widget_set_size(box->dropdown, widget->priv.width, 9); + gnt_widget_set_position(parent, + widget->priv.x, widget->priv.y + widget->priv.height - 1); + if (parent->window) + { + if (mvwin(parent->window, widget->priv.y + widget->priv.height - 1, + widget->priv.x) == ERR) + mvwin(parent->window, + widget->priv.y - 9 + 1, widget->priv.x); + } + + gnt_widget_draw(parent); + return TRUE; + } + } + } + + return FALSE; +} + +static void +gnt_combo_box_destroy(GntWidget *widget) +{ + gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent); +} + +static void +gnt_combo_box_lost_focus(GntWidget *widget) +{ + GntComboBox *combo = GNT_COMBO_BOX(widget); + if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED)) + gnt_widget_hide(GNT_COMBO_BOX(widget)->dropdown->parent); + widget_lost_focus(widget); +} + +static void +gnt_combo_box_class_init(GntComboBoxClass *klass) +{ + parent_class = GNT_WIDGET_CLASS(klass); + + parent_class->destroy = gnt_combo_box_destroy; + parent_class->draw = gnt_combo_box_draw; + parent_class->map = gnt_combo_box_map; + parent_class->size_request = gnt_combo_box_size_request; + parent_class->key_pressed = gnt_combo_box_key_pressed; + + widget_lost_focus = parent_class->lost_focus; + parent_class->lost_focus = gnt_combo_box_lost_focus; + + signals[SIG_SELECTION_CHANGED] = + g_signal_new("selection-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + gnt_closure_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); + + DEBUG; +} + +static void +gnt_combo_box_init(GTypeInstance *instance, gpointer class) +{ + GntWidget *box; + GntWidget *widget = GNT_WIDGET(instance); + GntComboBox *combo = GNT_COMBO_BOX(instance); + + GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), + GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW); + combo->dropdown = gnt_tree_new(); + + box = gnt_box_new(FALSE, FALSE); + GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER); + gnt_box_set_pad(GNT_BOX(box), 0); + gnt_box_add_widget(GNT_BOX(box), combo->dropdown); + + widget->priv.minw = 4; + widget->priv.minh = 3; + DEBUG; +} + +/****************************************************************************** + * GntComboBox API + *****************************************************************************/ +GType +gnt_combo_box_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntComboBoxClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_combo_box_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntComboBox), + 0, /* n_preallocs */ + gnt_combo_box_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntComboBox", + &info, 0); + } + + return type; +} + +GntWidget *gnt_combo_box_new() +{ + GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL); + + return widget; +} + +void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) +{ + gnt_tree_add_row_after(GNT_TREE(box->dropdown), key, text, NULL, NULL); + if (box->selected == NULL) + set_selection(box, key); +} + +gpointer gnt_combo_box_get_selected_data(GntComboBox *box) +{ + return box->selected; +} + Copied: branches/soc-2006-file-loggers/console/libgnt/gntcombobox.h (from rev 16498, trunk/console/libgnt/gntcombobox.h) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntcombobox.h (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntcombobox.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,55 @@ +#ifndef GNT_COMBO_BOX_H +#define GNT_COMBO_BOX_H + +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" +#include "gntwidget.h" + +#define GNT_TYPE_COMBO_BOX (gnt_combo_box_get_gtype()) +#define GNT_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_COMBO_BOX, GntComboBox)) +#define GNT_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_COMBO_BOX, GntComboBoxClass)) +#define GNT_IS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_COMBO_BOX)) +#define GNT_IS_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_COMBO_BOX)) +#define GNT_COMBO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_COMBO_BOX, GntComboBoxClass)) + +#define GNT_COMBO_BOX_FLAGS(obj) (GNT_COMBO_BOX(obj)->priv.flags) +#define GNT_COMBO_BOX_SET_FLAGS(obj, flags) (GNT_COMBO_BOX_FLAGS(obj) |= flags) +#define GNT_COMBO_BOX_UNSET_FLAGS(obj, flags) (GNT_COMBO_BOX_FLAGS(obj) &= ~(flags)) + +typedef struct _GnComboBox GntComboBox; +typedef struct _GnComboBoxPriv GntComboBoxPriv; +typedef struct _GnComboBoxClass GntComboBoxClass; + +struct _GnComboBox +{ + GntWidget parent; + + GntWidget *dropdown; /* This is a GntTree */ + + void *selected; /* Currently selected key */ +}; + +struct _GnComboBoxClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_combo_box_get_gtype(void); + +GntWidget *gnt_combo_box_new(); + +void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text); + +gpointer gnt_combo_box_get_selected_data(GntComboBox *box); + +G_END_DECLS + +#endif /* GNT_COMBO_BOX_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gntentry.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntentry.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntentry.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -83,6 +83,10 @@ entry_redraw(widget); } /* XXX: handle other keys, like home/end, and ctrl+ goodness */ + else + return FALSE; + + return TRUE; } else { @@ -136,6 +140,7 @@ entry->scroll--; entry_redraw(widget); + return TRUE; } } } @@ -166,6 +171,7 @@ static void gnt_entry_init(GTypeInstance *instance, gpointer class) { + GntWidget *widget = GNT_WIDGET(instance); GntEntry *entry = GNT_ENTRY(instance); entry->flag = GNT_ENTRY_FLAG_ALL; @@ -174,6 +180,9 @@ GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS); GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_GROW_X); + + widget->priv.minw = 3; + widget->priv.minh = 1; DEBUG; } Modified: branches/soc-2006-file-loggers/console/libgnt/gntlabel.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntlabel.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntlabel.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -70,7 +70,10 @@ static void gnt_label_init(GTypeInstance *instance, gpointer class) { - GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); + GntWidget *widget = GNT_WIDGET(instance); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X); + widget->priv.minw = 3; + widget->priv.minh = 1; DEBUG; } Copied: branches/soc-2006-file-loggers/console/libgnt/gntline.c (from rev 16498, trunk/console/libgnt/gntline.c) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntline.c (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntline.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,115 @@ +#include "gntline.h" + +enum +{ + SIGS = 1, +}; + +static GntWidgetClass *parent_class = NULL; +static guint signals[SIGS] = { 0 }; + +static void +gnt_line_draw(GntWidget *widget) +{ + GntLine *line = GNT_LINE(widget); + if (line->vertical) + mvwvline(widget->window, 1, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + widget->priv.height - 3); + else + mvwhline(widget->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + widget->priv.width - 3); +} + +static void +gnt_line_size_request(GntWidget *widget) +{ + if (GNT_LINE(widget)->vertical) + { + widget->priv.width = 1; + widget->priv.height = 5; + } + else + { + widget->priv.width = 5; + widget->priv.height = 1; + } +} + +static void +gnt_line_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + DEBUG; +} + +static void +gnt_line_class_init(GntLineClass *klass) +{ + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->draw = gnt_line_draw; + parent_class->map = gnt_line_map; + parent_class->size_request = gnt_line_size_request; + + DEBUG; +} + +static void +gnt_line_init(GTypeInstance *instance, gpointer class) +{ + GntWidget *widget = GNT_WIDGET(instance); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER); + widget->priv.minw = 1; + widget->priv.minh = 1; + DEBUG; +} + +/****************************************************************************** + * GntLine API + *****************************************************************************/ +GType +gnt_line_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntLineClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_line_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntLine), + 0, /* n_preallocs */ + gnt_line_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntLine", + &info, 0); + } + + return type; +} + +GntWidget *gnt_line_new(gboolean vertical) +{ + GntWidget *widget = g_object_new(GNT_TYPE_LINE, NULL); + GntLine *line = GNT_LINE(widget); + + line->vertical = vertical; + + if (vertical) + { + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y); + } + else + { + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X); + } + + return widget; +} + Copied: branches/soc-2006-file-loggers/console/libgnt/gntline.h (from rev 16498, trunk/console/libgnt/gntline.h) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntline.h (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntline.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,49 @@ +#ifndef GNT_LINE_H +#define GNT_LINE_H + +#include "gntwidget.h" +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" + +#define GNT_TYPE_LINE (gnt_line_get_gtype()) +#define GNT_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LINE, GntLine)) +#define GNT_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_LINE, GntLineClass)) +#define GNT_IS_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_LINE)) +#define GNT_IS_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_LINE)) +#define GNT_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_LINE, GntLineClass)) + +#define GNT_LINE_FLAGS(obj) (GNT_LINE(obj)->priv.flags) +#define GNT_LINE_SET_FLAGS(obj, flags) (GNT_LINE_FLAGS(obj) |= flags) +#define GNT_LINE_UNSET_FLAGS(obj, flags) (GNT_LINE_FLAGS(obj) &= ~(flags)) + +typedef struct _GnLine GntLine; +typedef struct _GnLinePriv GntLinePriv; +typedef struct _GnLineClass GntLineClass; + +struct _GnLine +{ + GntWidget parent; + + gboolean vertical; +}; + +struct _GnLineClass +{ + GntWidgetClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_line_get_gtype(void); + +GntWidget *gnt_line_new(gboolean vertical); + +G_END_DECLS + +#endif /* GNT_LINE_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gntmain.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -400,6 +400,7 @@ { mode = GNT_KP_MODE_NORMAL; changed = TRUE; + gnt_widget_draw(widget); } if (changed) @@ -471,19 +472,7 @@ if (changed) { - GntNode *node = g_hash_table_lookup(nodes, widget); - int x, y; - - gnt_widget_get_position(widget, &x, &y); - - hide_panel(node->panel); - gnt_widget_set_size(widget, width, height); - gnt_widget_set_position(widget, x, y); - gnt_widget_draw(widget); - replace_panel(node->panel, widget->window); - show_panel(node->panel); - update_panels(); - doupdate(); + gnt_screen_resize_widget(widget, width, height); } } } @@ -673,3 +662,21 @@ return ascii_only; } +void gnt_screen_resize_widget(GntWidget *widget, int width, int height) +{ + if (widget->parent == NULL) + { + GntNode *node = g_hash_table_lookup(nodes, widget); + if (!node) + return; + + hide_panel(node->panel); + gnt_widget_set_size(widget, width, height); + gnt_widget_draw(widget); + replace_panel(node->panel, widget->window); + show_panel(node->panel); + update_panels(); + doupdate(); + } +} + Copied: branches/soc-2006-file-loggers/console/libgnt/gntmarshal.c (from rev 16498, trunk/console/libgnt/gntmarshal.c) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntmarshal.c (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntmarshal.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,168 @@ +#include "gntmarshal.h" + +void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*func) (gpointer data1, const char *arg1, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + gboolean ret; + + g_return_if_fail(ret_value != NULL); + g_return_if_fail(n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + ret = callback(data1, g_value_get_string(param_values + 1) , data2); + g_value_set_boolean(ret_value, ret); +} + +void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*func) (gpointer data1, int, int, int, int, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 5); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + callback(data1, + g_value_get_int(param_values + 1) , + g_value_get_int(param_values + 2) , + g_value_get_int(param_values + 3) , + g_value_get_int(param_values + 4) , + data2); +} + +void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*func) (gpointer data1, int, int, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + callback(data1, + g_value_get_int(param_values + 1) , + g_value_get_int(param_values + 2) , + data2); +} + +void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*func) (gpointer data1, gpointer, gpointer, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + callback(data1, + g_value_get_pointer(param_values + 1) , + g_value_get_pointer(param_values + 2) , + data2); +} + +void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*func) (gpointer data1, int, int, gpointer data2); + register func callback; + register GCClosure *cc = (GCClosure*)closure; + register gpointer data1, data2; + gboolean ret; + + g_return_if_fail(ret_value != NULL); + g_return_if_fail(n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA(closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } + else + { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (func) (marshal_data ? marshal_data : cc->callback); + ret = callback(data1, + g_value_get_int(param_values + 1) , + g_value_get_int(param_values + 2) , + data2); + g_value_set_boolean(ret_value, ret); +} + + Copied: branches/soc-2006-file-loggers/console/libgnt/gntmarshal.h (from rev 16498, trunk/console/libgnt/gntmarshal.h) =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntmarshal.h (rev 0) +++ branches/soc-2006-file-loggers/console/libgnt/gntmarshal.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -0,0 +1,37 @@ +#include "gntwidget.h" + +void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure, + GValue *ret_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + Modified: branches/soc-2006-file-loggers/console/libgnt/gnttextview.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttextview.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gnttextview.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -113,9 +113,14 @@ static void gnt_text_view_init(GTypeInstance *instance, gpointer class) { + GntWidget *widget = GNT_WIDGET(instance); + /* XXX: For now, resizing the width is not permitted. This is because * of the way I am handling wrapped lines. */ GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_Y); + + widget->priv.minw = 5; + widget->priv.minh = 1; DEBUG; } Modified: branches/soc-2006-file-loggers/console/libgnt/gnttree.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -1,5 +1,5 @@ #include "gnttree.h" -#include "gntutils.h" +#include "gntmarshal.h" #include <string.h> @@ -201,18 +201,14 @@ g_snprintf(format, sizeof(format) - 1, "[%c] ", row->isselected ? 'X' : ' '); } - /* XXX: Need a utf8 version of snprintf */ - if ((wr = g_snprintf(str, widget->priv.width, "%s%s", format, row->text)) >= widget->priv.width) + g_snprintf(str, sizeof(str) - 1, "%s%s", format, row->text); + + if ((wr = g_utf8_strlen(str, -1)) >= widget->priv.width - 1 - pos) { /* XXX: ellipsize */ - str[widget->priv.width - 1 - pos] = 0; + char *s = g_utf8_offset_to_pointer(str, widget->priv.width - 1 - pos); + *s = '\0'; } - else - { - while (wr < widget->priv.width - 1 - pos) - str[wr++] = ' '; - str[wr] = 0; - } if (flags & GNT_TEXT_FLAG_BOLD) attr |= A_BOLD; @@ -403,7 +399,10 @@ static void gnt_tree_init(GTypeInstance *instance, gpointer class) { - GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); + GntWidget *widget = GNT_WIDGET(instance); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); + widget->priv.minw = 4; + widget->priv.minh = 3; DEBUG; } @@ -592,6 +591,13 @@ return NULL; } +const char *gnt_tree_get_selection_text(GntTree *tree) +{ + if (tree->current) + return tree->current->text; + return NULL; +} + /* XXX: Should this also remove all the children of the row being removed? */ void gnt_tree_remove(GntTree *tree, gpointer key) { @@ -707,6 +713,6 @@ return; row->flags = flags; - redraw_tree(tree); /* XXX: Is shouldn't be necessary to redraw the whole darned tree */ + redraw_tree(tree); /* XXX: It shouldn't be necessary to redraw the whole darned tree */ } Modified: branches/soc-2006-file-loggers/console/libgnt/gnttree.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttree.h 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gnttree.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -67,6 +67,8 @@ gpointer gnt_tree_get_selection_data(GntTree *tree); +const char *gnt_tree_get_selection_text(GntTree *tree); + void gnt_tree_remove(GntTree *tree, gpointer key); /* Returns the visible line number of the selected row */ Deleted: branches/soc-2006-file-loggers/console/libgnt/gntutils.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntutils.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntutils.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -1,168 +0,0 @@ -#include "gntutils.h" - -void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*func) (gpointer data1, const char *arg1, gpointer data2); - register func callback; - register GCClosure *cc = (GCClosure*)closure; - register gpointer data1, data2; - gboolean ret; - - g_return_if_fail(ret_value != NULL); - g_return_if_fail(n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA(closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } - else - { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = (func) (marshal_data ? marshal_data : cc->callback); - ret = callback(data1, g_value_get_string(param_values + 1) , data2); - g_value_set_boolean(ret_value, ret); -} - -void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*func) (gpointer data1, int, int, int, int, gpointer data2); - register func callback; - register GCClosure *cc = (GCClosure*)closure; - register gpointer data1, data2; - - g_return_if_fail(n_param_values == 5); - - if (G_CCLOSURE_SWAP_DATA(closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } - else - { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = (func) (marshal_data ? marshal_data : cc->callback); - callback(data1, - g_value_get_int(param_values + 1) , - g_value_get_int(param_values + 2) , - g_value_get_int(param_values + 3) , - g_value_get_int(param_values + 4) , - data2); -} - -void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*func) (gpointer data1, int, int, gpointer data2); - register func callback; - register GCClosure *cc = (GCClosure*)closure; - register gpointer data1, data2; - - g_return_if_fail(n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA(closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } - else - { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = (func) (marshal_data ? marshal_data : cc->callback); - callback(data1, - g_value_get_int(param_values + 1) , - g_value_get_int(param_values + 2) , - data2); -} - -void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*func) (gpointer data1, gpointer, gpointer, gpointer data2); - register func callback; - register GCClosure *cc = (GCClosure*)closure; - register gpointer data1, data2; - - g_return_if_fail(n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA(closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } - else - { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = (func) (marshal_data ? marshal_data : cc->callback); - callback(data1, - g_value_get_pointer(param_values + 1) , - g_value_get_pointer(param_values + 2) , - data2); -} - -void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*func) (gpointer data1, int, int, gpointer data2); - register func callback; - register GCClosure *cc = (GCClosure*)closure; - register gpointer data1, data2; - gboolean ret; - - g_return_if_fail(ret_value != NULL); - g_return_if_fail(n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA(closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } - else - { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = (func) (marshal_data ? marshal_data : cc->callback); - ret = callback(data1, - g_value_get_int(param_values + 1) , - g_value_get_int(param_values + 2) , - data2); - g_value_set_boolean(ret_value, ret); -} - - Deleted: branches/soc-2006-file-loggers/console/libgnt/gntutils.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntutils.h 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntutils.h 2006-07-17 03:12:41 UTC (rev 16499) @@ -1,37 +0,0 @@ -#include "gntwidget.h" - -void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -void gnt_closure_marshal_VOID__INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure, - GValue *ret_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - Modified: branches/soc-2006-file-loggers/console/libgnt/gntwidget.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntwidget.c 2006-07-17 02:58:46 UTC (rev 16498) +++ branches/soc-2006-file-loggers/console/libgnt/gntwidget.c 2006-07-17 03:12:41 UTC (rev 16499) @@ -1,11 +1,9 @@ /* Stuff brutally ripped from Gflib */ #include "gntwidget.h" -#include "gntutils.h" +#include "gntmarshal.h" #include "gnt.h" -#define MIN_SIZE 5 - enum { SIG_DESTROY, @@ -18,6 +16,7 @@ SIG_EXPOSE, SIG_SIZE_REQUEST, SIG_CONFIRM_SIZE, + SIG_SIZE_CHANGED, SIG_POSITION, SIGS }; @@ -71,7 +70,7 @@ static gboolean gnt_widget_dummy_confirm_size(GntWidget *widget, int width, int height) { - if (width < MIN_SIZE || he... [truncated message content] |
From: <ro...@us...> - 2006-07-21 03:35:18
|
Revision: 16535 Author: roast Date: 2006-07-20 20:34:03 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16535&view=rev Log Message: ----------- merged with svn trunk. 16498:16534. Modified Paths: -------------- branches/soc-2006-file-loggers/console/Makefile branches/soc-2006-file-loggers/console/gntaccount.c branches/soc-2006-file-loggers/console/gntblist.c branches/soc-2006-file-loggers/console/gntconv.c branches/soc-2006-file-loggers/console/gntgaim.c branches/soc-2006-file-loggers/console/gntgaim.h branches/soc-2006-file-loggers/console/gntui.c branches/soc-2006-file-loggers/console/libgnt/gntbox.c branches/soc-2006-file-loggers/console/libgnt/gntbox.h branches/soc-2006-file-loggers/console/libgnt/gntcolors.c branches/soc-2006-file-loggers/console/libgnt/gntcolors.h branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c branches/soc-2006-file-loggers/console/libgnt/gntlabel.c branches/soc-2006-file-loggers/console/libgnt/gntlabel.h branches/soc-2006-file-loggers/console/libgnt/gntline.h branches/soc-2006-file-loggers/console/libgnt/gntmain.c branches/soc-2006-file-loggers/console/libgnt/gnttextview.c branches/soc-2006-file-loggers/console/libgnt/gnttextview.h branches/soc-2006-file-loggers/console/libgnt/gnttree.c branches/soc-2006-file-loggers/console/libgnt/gnttree.h branches/soc-2006-file-loggers/console/libgnt/test/Makefile branches/soc-2006-file-loggers/console/libgnt/test/combo.c branches/soc-2006-file-loggers/console/libgnt/test/focus.c branches/soc-2006-file-loggers/console/libgnt/test/multiwin.c branches/soc-2006-file-loggers/console/libgnt/test/tv.c branches/soc-2006-file-loggers/plugins/dbus-example.c branches/soc-2006-file-loggers/plugins/musicmessaging/musicmessaging.c branches/soc-2006-file-loggers/plugins/tcl/tcl.c branches/soc-2006-file-loggers/src/buddyicon.h branches/soc-2006-file-loggers/src/connection.c branches/soc-2006-file-loggers/src/connection.h branches/soc-2006-file-loggers/src/conversation.c branches/soc-2006-file-loggers/src/conversation.h branches/soc-2006-file-loggers/src/core.c branches/soc-2006-file-loggers/src/dbus-server.c branches/soc-2006-file-loggers/src/dbus-server.h branches/soc-2006-file-loggers/src/gtkblist.c branches/soc-2006-file-loggers/src/gtkconv.c branches/soc-2006-file-loggers/src/gtkconv.h branches/soc-2006-file-loggers/src/gtknotify.c branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/notify.c branches/soc-2006-file-loggers/src/plugin.c branches/soc-2006-file-loggers/src/protocols/jabber/jabber.c branches/soc-2006-file-loggers/src/protocols/jabber/presence.c branches/soc-2006-file-loggers/src/protocols/jabber/roster.c branches/soc-2006-file-loggers/src/protocols/msn/dialog.c branches/soc-2006-file-loggers/src/protocols/msn/slp.c branches/soc-2006-file-loggers/src/protocols/msn/slplink.c branches/soc-2006-file-loggers/src/protocols/msn/switchboard.c branches/soc-2006-file-loggers/src/protocols/msn/switchboard.h branches/soc-2006-file-loggers/src/protocols/msn/user.c branches/soc-2006-file-loggers/src/protocols/msn/userlist.c branches/soc-2006-file-loggers/src/protocols/oscar/family_icbm.c branches/soc-2006-file-loggers/src/protocols/oscar/oscar.c branches/soc-2006-file-loggers/src/protocols/oscar/peer.c branches/soc-2006-file-loggers/src/protocols/oscar/peer_proxy.c branches/soc-2006-file-loggers/src/protocols/sametime/sametime.c branches/soc-2006-file-loggers/src/protocols/silc/silc.c branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo.c branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo_picture.c branches/soc-2006-file-loggers/src/protocols/yahoo/yahoo_picture.h branches/soc-2006-file-loggers/src/protocols/yahoo/yahoochat.c branches/soc-2006-file-loggers/src/proxy.c branches/soc-2006-file-loggers/src/signals.c branches/soc-2006-file-loggers/src/util.h Added Paths: ----------- branches/soc-2006-file-loggers/console/gntconn.c branches/soc-2006-file-loggers/console/gntconn.h branches/soc-2006-file-loggers/console/gntnotify.c branches/soc-2006-file-loggers/console/gntnotify.h branches/soc-2006-file-loggers/console/libgnt/test/wm.c Modified: branches/soc-2006-file-loggers/console/Makefile =================================================================== --- branches/soc-2006-file-loggers/console/Makefile 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/Makefile 2006-07-21 03:34:03 UTC (rev 16535) @@ -1,24 +1,30 @@ VERSION=gntgaim-0.0.0dev CC=gcc -CFLAGS=`pkg-config --cflags gaim gobject-2.0 gnt` -g -Wall -DVERSION=\"$(VERSION)\" +CFLAGS=`pkg-config --cflags gaim gobject-2.0 gnt` -g -Wall -DVERSION=\"$(VERSION)\" -DSTANDALONE LDFLAGS=`pkg-config --libs gaim gobject-2.0 libxml-2.0 gnt` -pg GG_SOURCES = \ gntaccount.c \ gntblist.c \ + gntconn.c \ gntconv.c \ + gntnotify.c \ gntui.c GG_HEADERS = \ gntaccount.h \ gntblist.h \ + gntconn.h \ gntconv.h \ + gntnotify.h \ gntui.h GG_OBJECTS = \ gntaccount.o \ gntblist.o \ + gntconn.o \ gntconv.o \ + gntnotify.o \ gntui.o all: gntgaim @@ -29,6 +35,7 @@ gntblist.o: gntblist.c $(GG_HEADERS) gntconv.o: gntconv.c $(GG_HEADERS) gntgaim.o: gntgaim.c gntgaim.h $(GG_HEADERS) +gntnotify.o: gntnotify.c $(GG_HEADERS) gntui.o: gntui.c $(GG_HEADERS) clean: Modified: branches/soc-2006-file-loggers/console/gntaccount.c =================================================================== --- branches/soc-2006-file-loggers/console/gntaccount.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntaccount.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -210,25 +210,26 @@ gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE)); - accounts.tree = gnt_tree_new(); + accounts.tree = gnt_tree_new_with_columns(2); GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER); for (iter = gaim_accounts_get_all(); iter; iter = iter->next) { GaimAccount *account = iter->data; - char *str = g_strdup_printf("%s (%s)", - gaim_account_get_username(account), gaim_account_get_protocol_id(account)); gnt_tree_add_choice(GNT_TREE(accounts.tree), account, - str, NULL, NULL); + gnt_tree_create_row(GNT_TREE(accounts.tree), + gaim_account_get_username(account), + gaim_account_get_protocol_name(account)), + NULL, NULL); gnt_tree_set_choice(GNT_TREE(accounts.tree), account, gaim_account_get_enabled(account, GAIM_GNT_UI)); - g_free(str); } g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL); - gnt_widget_set_size(accounts.tree, 40, 10); + gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40); + gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10); gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree); gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE)); Modified: branches/soc-2006-file-loggers/console/gntblist.c =================================================================== --- branches/soc-2006-file-loggers/console/gntblist.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntblist.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -1,5 +1,6 @@ #include <account.h> #include <blist.h> +#include <request.h> #include <server.h> #include <signal.h> #include <util.h> @@ -19,6 +20,9 @@ GntWidget *tooltip; GaimBlistNode *tnode; /* Who is the tooltip being displayed for? */ + + GntWidget *context; + GaimBlistNode *cnode; } GGBlist; GGBlist *ggblist; @@ -28,6 +32,7 @@ static void add_chat(GaimChat *chat, GGBlist *ggblist); static void add_node(GaimBlistNode *node, GGBlist *ggblist); static void draw_tooltip(GGBlist *ggblist); +static void remove_peripherals(GGBlist *ggblist); static void new_node(GaimBlistNode *node) @@ -124,8 +129,9 @@ GaimBlistNode *node = (GaimBlistNode *)group; if (node->ui_data) return; + gnt_tree_remove(GNT_TREE(ggblist->tree), group); node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group, - group->name, NULL, NULL); + gnt_tree_create_row(GNT_TREE(ggblist->tree), group->name), NULL, NULL); } static const char * @@ -186,8 +192,10 @@ group = gaim_chat_get_group(chat); add_node((GaimBlistNode*)group, ggblist); + gnt_tree_remove(GNT_TREE(ggblist->tree), chat); node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat, - get_display_name(node), group, NULL); + gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), + group, NULL); } static void @@ -201,8 +209,10 @@ group = gaim_buddy_get_group(buddy); add_node((GaimBlistNode*)group, ggblist); + gnt_tree_remove(GNT_TREE(ggblist->tree), buddy); node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, - get_display_name(node), group, NULL); + gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), + group, NULL); if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, GNT_TEXT_FLAG_DIM); else @@ -252,6 +262,233 @@ } static void +remove_context_menu(GGBlist *ggblist) +{ + if (ggblist->context) + gnt_widget_destroy(ggblist->context->parent); + ggblist->context = NULL; + ggblist->cnode = NULL; +} + +static void +gnt_append_menu_action(GntTree *tree, GaimMenuAction *action, gpointer parent) +{ + GList *list; + + gnt_tree_add_row_after(tree, action, + gnt_tree_create_row(tree, action->label), parent, NULL); + for (list = action->children; list; list = list->next) + gnt_append_menu_action(tree, list->data, action); +} + +static void +append_proto_menu(GntTree *tree, GaimConnection *gc, GaimBlistNode *node) +{ + GList *list; + GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if(!prpl_info || !prpl_info->blist_node_menu) + return; + + for(list = prpl_info->blist_node_menu(node); list; + list = g_list_delete_link(list, list)) + { + GaimMenuAction *act = (GaimMenuAction *) list->data; + gnt_append_menu_action(tree, act, NULL); + } +} + +static void +add_custom_action(GntTree *tree, const char *label, GaimCallback callback, + gpointer data) +{ + GaimMenuAction *action = gaim_menu_action_new(label, callback, data, NULL); + gnt_append_menu_action(tree, action, NULL); + g_signal_connect_swapped(G_OBJECT(tree), "destroy", + G_CALLBACK(gaim_menu_action_free), action); +} + +static void +create_chat_menu(GntTree *tree, GaimChat *chat) +{ +} + +static void +create_group_menu(GntTree *tree, GaimGroup *group) +{ +} + +static void +gg_blist_get_buddy_info_cb(GaimBuddy *buddy, GaimBlistNode *null) +{ + serv_get_info(buddy->account->gc, gaim_buddy_get_name(buddy)); +} + +static void +create_buddy_menu(GntTree *tree, GaimBuddy *buddy) +{ + GaimPluginProtocolInfo *prpl_info; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl); + if (prpl_info && prpl_info->get_info) + { + add_custom_action(tree, _("Get Info"), + GAIM_CALLBACK(gg_blist_get_buddy_info_cb), buddy); + } + +#if 0 + add_custom_action(tree, _("Add Buddy Pounce"), + GAIM_CALLBACK(gg_blist_add_buddy_pounce_cb)), buddy); + + if (prpl_info && prpl_info->send_file) + { + if (!prpl_info->can_receive_file || + prpl_info->can_receive_file(buddy->account->gc, buddy->name)) + add_custom_action(tree, _("Send File"), + GAIM_CALLBACK(gg_blist_show_file_cb)), buddy); + } + + add_custom_action(tree, _("View Log"), + GAIM_CALLBACK(gg_blist_view_log_cb)), buddy); +#endif + + /* Protocol actions */ + append_proto_menu(tree, + gaim_account_get_connection(gaim_buddy_get_account(buddy)), + (GaimBlistNode*)buddy); +} + +static void +append_extended_menu(GntTree *tree, GaimBlistNode *node) +{ + GList *iter; + + for (iter = gaim_blist_node_get_extended_menu(node); + iter; iter = g_list_delete_link(iter, iter)) + { + gnt_append_menu_action(tree, iter->data, NULL); + } +} + +static void +context_menu_callback(GntTree *tree, GGBlist *ggblist) +{ + GaimMenuAction *action = gnt_tree_get_selection_data(tree); + GaimBlistNode *node = ggblist->cnode; + + if (action) + { + void (*callback)(GaimBlistNode *, gpointer); + callback = (void (*)(GaimBlistNode *, gpointer))action->callback; + callback(node, action->data); + } + + remove_context_menu(ggblist); +} + +static void +gg_blist_rename_node_cb(GaimBlistNode *node, GaimBlistNode *null) +{ +} + +/* XXX: This still doesn't do anything, because request doesn't have a ui yet */ +static void +gg_blist_remove_node_cb(GaimBlistNode *node, GaimBlistNode *null) +{ + void (*callback)(gpointer); + + if (GAIM_BLIST_NODE_IS_BUDDY(node)) + callback = (void(*)(gpointer))gaim_blist_remove_buddy; + else if (GAIM_BLIST_NODE_IS_CHAT(node)) + callback = (void(*)(gpointer))gaim_blist_remove_chat; + else if (GAIM_BLIST_NODE_IS_GROUP(node)) + callback = (void(*)(gpointer))gaim_blist_remove_group; + + /* XXX: anything to do with the returned ui-handle? */ + gaim_request_action(node, _("Confirm Remove"), + _("Are you sure you want to remove ..."), NULL, /* XXX: tidy up */ + 1, node, 2, + _("Remove"), callback, + _("No"), NULL); + +} + +static void +draw_context_menu(GGBlist *ggblist) +{ + GaimBlistNode *node = NULL; + GntWidget *context = NULL, *window = NULL; + GntTree *tree = NULL; + int x, y, top, width; + char *title = NULL; + + tree = GNT_TREE(ggblist->tree); + + if (ggblist->context) + { + remove_context_menu(ggblist); + } + + node = gnt_tree_get_selection_data(tree); + + if (node == NULL) + return; + if (ggblist->tooltip) + remove_tooltip(ggblist); + + ggblist->cnode = node; + ggblist->context = context = gnt_tree_new(); + GNT_WIDGET_SET_FLAGS(context, GNT_WIDGET_NO_BORDER); + gnt_widget_set_name(context, "context menu"); + g_signal_connect(G_OBJECT(context), "activate", G_CALLBACK(context_menu_callback), ggblist); + + if (GAIM_BLIST_NODE_IS_BUDDY(node)) + { + GaimBuddy *buddy = (GaimBuddy *)node; + create_buddy_menu(GNT_TREE(context), buddy); + title = g_strdup(gaim_buddy_get_name(buddy)); + } + else if (GAIM_BLIST_NODE_IS_CHAT(node)) + { + GaimChat *chat = (GaimChat*)node; + create_chat_menu(GNT_TREE(context), chat); + title = g_strdup(gaim_chat_get_name(chat)); + } + else if (GAIM_BLIST_NODE_IS_GROUP(node)) + { + GaimGroup *group = (GaimGroup *)node; + create_group_menu(GNT_TREE(context), group); + title = g_strdup(group->name); + } + + append_extended_menu(GNT_TREE(context), node); + + /* These are common for everything */ + add_custom_action(GNT_TREE(context), _("Rename"), + GAIM_CALLBACK(gg_blist_rename_node_cb), node); + add_custom_action(GNT_TREE(context), _("Remove"), + GAIM_CALLBACK(gg_blist_remove_node_cb), node); + + window = gnt_vbox_new(FALSE); + gnt_box_set_toplevel(GNT_BOX(window), TRUE); + gnt_box_set_title(GNT_BOX(window), title); + + gnt_box_add_widget(GNT_BOX(window), context); + + /* Set the position for the popup */ + gnt_widget_get_position(GNT_WIDGET(tree), &x, &y); + gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL); + top = gnt_tree_get_selection_visible_line(tree); + + x += width; + y += top - 1; + + gnt_widget_set_position(window, x, y); + gnt_widget_draw(window); + g_free(title); +} + +static void draw_tooltip(GGBlist *ggblist) { GaimBlistNode *node; @@ -270,6 +507,9 @@ if (!gnt_widget_has_focus(ggblist->tree)) return; + if (ggblist->context) + return; + if (ggblist->tooltip) { /* XXX: Once we can properly redraw on expose events, this can be removed at the end @@ -288,7 +528,9 @@ GaimBuddy *buddy = (GaimBuddy *)node; account = gaim_buddy_get_account(buddy); - g_string_append_printf(str, _("Account: %s"), gaim_account_get_username(account)); + g_string_append_printf(str, _("Account: %s (%s)"), + gaim_account_get_username(account), + gaim_account_get_protocol_name(account)); prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); @@ -323,7 +565,9 @@ GaimChat *chat = (GaimChat *)node; GaimAccount *account = chat->account; - g_string_append_printf(str, _("Account: %s"), gaim_account_get_username(account)); + g_string_append_printf(str, _("Account: %s (%s)"), + gaim_account_get_username(account), + gaim_account_get_protocol_name(account)); title = g_strdup(gaim_chat_get_name(chat)); } @@ -368,24 +612,41 @@ static gboolean key_pressed(GntWidget *widget, const char *text, GGBlist *ggblist) { + gboolean stop = FALSE, ret = FALSE; if (text[0] == 27 && text[1] == 0) { /* Escape was pressed */ - if (ggblist->tooltip) + remove_peripherals(ggblist); + stop = TRUE; + ret = TRUE; + } + + if (ggblist->context) + { + ret = gnt_widget_key_pressed(ggblist->context, text); + stop = TRUE; + } + + if (text[0] == 27) + { + if (strcmp(text + 1, GNT_KEY_POPUP) == 0) { - gnt_widget_destroy(ggblist->tooltip); - ggblist->tooltip = NULL; - return TRUE; + draw_context_menu(ggblist); + stop = TRUE; + ret = TRUE; } } - return FALSE; + if (stop) + g_signal_stop_emission_by_name(G_OBJECT(widget), "key_pressed"); + + return ret; } static void update_buddy_display(GaimBuddy *buddy, GGBlist *ggblist) { - gnt_tree_change_text(GNT_TREE(ggblist->tree), buddy, get_display_name((GaimBlistNode*)buddy)); + gnt_tree_change_text(GNT_TREE(ggblist->tree), buddy, 0, get_display_name((GaimBlistNode*)buddy)); if (ggblist->tnode == (GaimBlistNode*)buddy) draw_tooltip(ggblist); @@ -407,6 +668,15 @@ update_buddy_display(buddy, ggblist); } +static void +remove_peripherals(GGBlist *ggblist) +{ + if (ggblist->tooltip) + remove_tooltip(ggblist); + else if (ggblist->context) + remove_context_menu(ggblist); +} + void gg_blist_init() { ggblist = g_new0(GGBlist, 1); @@ -421,7 +691,8 @@ ggblist->tree = gnt_tree_new(); GNT_WIDGET_SET_FLAGS(ggblist->tree, GNT_WIDGET_NO_BORDER); - gnt_widget_set_size(ggblist->tree, 25, getmaxy(stdscr) - 4); + gnt_tree_set_col_width(GNT_TREE(ggblist->tree), 0, 25); + gnt_widget_set_size(ggblist->tree, 0, getmaxy(stdscr) - 4); gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree); gnt_widget_show(ggblist->window); @@ -452,7 +723,7 @@ g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist); g_signal_connect_data(G_OBJECT(ggblist->tree), "gained-focus", G_CALLBACK(draw_tooltip), ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); - g_signal_connect_data(G_OBJECT(ggblist->tree), "lost-focus", G_CALLBACK(remove_tooltip), + g_signal_connect_data(G_OBJECT(ggblist->tree), "lost-focus", G_CALLBACK(remove_peripherals), ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); } Copied: branches/soc-2006-file-loggers/console/gntconn.c (from rev 16534, trunk/console/gntconn.c) =================================================================== --- branches/soc-2006-file-loggers/console/gntconn.c (rev 0) +++ branches/soc-2006-file-loggers/console/gntconn.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -0,0 +1,45 @@ +#include "notify.h" + +#include "gntconn.h" +#include "gntgaim.h" + +static void +gg_connection_report_disconnect(GaimConnection *gc, const char *text) +{ + char *act, *primary, *secondary; + GaimAccount *account = gaim_connection_get_account(gc); + + act = g_strdup_printf(_("%s (%s)"), gaim_account_get_username(account), + gaim_account_get_protocol_name(account)); + + primary = g_strdup_printf(_("%s disconnected."), act); + secondary = g_strdup_printf(_("%s was disconnected due to the following error:\n%s"), + act, text); + + gaim_notify_error(account, _("Connection Error"), primary, secondary); + + g_free(act); + g_free(primary); + g_free(secondary); +} + +static GaimConnectionUiOps ops = +{ + .connect_progress = NULL, + .connected = NULL, + .disconnected = NULL, + .notice = NULL, + .report_disconnect = gg_connection_report_disconnect +}; + +GaimConnectionUiOps *gg_connections_get_ui_ops() +{ + return &ops; +} + +void gg_connections_init() +{} + +void gg_connections_uninit() +{} + Copied: branches/soc-2006-file-loggers/console/gntconn.h (from rev 16534, trunk/console/gntconn.h) =================================================================== --- branches/soc-2006-file-loggers/console/gntconn.h (rev 0) +++ branches/soc-2006-file-loggers/console/gntconn.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -0,0 +1,8 @@ +#include "connection.h" + +GaimConnectionUiOps *gg_connections_get_ui_ops(); + +void gg_connections_init(); + +void gg_connections_uninit(); + Modified: branches/soc-2006-file-loggers/console/gntconv.c =================================================================== --- branches/soc-2006-file-loggers/console/gntconv.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntconv.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -1,4 +1,6 @@ #include <string.h> + +#include <cmds.h> #include <util.h> #include "gntgaim.h" @@ -49,12 +51,53 @@ const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry)); if (*text == '/') { - /* XXX: Need to check for /-commands here */ + GaimConversation *conv = ggconv->conv; + GaimCmdStatus status; + const char *cmdline = text + 1; + char *error = NULL, *escape; + + escape = g_markup_escape_text(cmdline, -1); + status = gaim_cmd_do_command(conv, cmdline, escape, &error); + g_free(escape); + + switch (status) + { + case GAIM_CMD_STATUS_OK: + break; + case GAIM_CMD_STATUS_NOT_FOUND: + gaim_conversation_write(conv, "", _("No such command."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + break; + case GAIM_CMD_STATUS_WRONG_ARGS: + gaim_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " + "to that command."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + break; + case GAIM_CMD_STATUS_FAILED: + gaim_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + break; + case GAIM_CMD_STATUS_WRONG_TYPE: + if(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) + gaim_conversation_write(conv, "", _("That command only works in chats, not IMs."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + else + gaim_conversation_write(conv, "", _("That command only works in IMs, not chats."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + break; + case GAIM_CMD_STATUS_WRONG_PRPL: + gaim_conversation_write(conv, "", _("That command doesn't work on this protocol."), + GAIM_MESSAGE_NO_LOG, time(NULL)); + break; + } + g_free(error); +#if 0 gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), _("Commands are not supported yet. Message was NOT sent."), GNT_TEXT_FLAG_DIM | GNT_TEXT_FLAG_UNDERLINE); gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv)); gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0); +#endif } else { @@ -202,11 +245,12 @@ { if (flags & GAIM_MESSAGE_SEND) { - who = gaim_connection_get_display_name(conv->account->gc); + GaimAccount *account = gaim_conversation_get_account(conv); + who = gaim_connection_get_display_name(gaim_account_get_connection(account)); if (!who) - who = gaim_account_get_alias(conv->account); + who = gaim_account_get_alias(account); if (!who) - who = gaim_account_get_username(conv->account); + who = gaim_account_get_username(account); } else if (flags & GAIM_MESSAGE_RECV) who = gaim_conversation_get_name(conv); @@ -230,20 +274,48 @@ } static void -gg_chat_add_users(GaimConversation *conv, GList *users, GList *flags, GList *aliases, gboolean new_arrivals) -{} +gg_chat_add_users(GaimConversation *conv, GList *users, gboolean new_arrivals) +{ + if (!new_arrivals) + { + /* Print the list of users in the room */ + GString *string = g_string_new(_("List of users:\n")); + GList *iter; + for (iter = users; iter; iter = iter->next) + { + GaimConvChatBuddy *cbuddy = iter->data; + char *str; + + if ((str = cbuddy->alias) == NULL) + str = cbuddy->name; + g_string_append_printf(string, "[ %s ]", str); + } + + gaim_conversation_write(conv, NULL, string->str, + GAIM_MESSAGE_SYSTEM, time(NULL)); + g_string_free(string, TRUE); + } + /* XXX: Add the names for string completion */ +} + static void gg_chat_rename_user(GaimConversation *conv, const char *old, const char *new_n, const char *new_a) -{} +{ + /* XXX: Update the name for string completion */ +} static void gg_chat_remove_user(GaimConversation *conv, GList *list) -{} +{ + /* XXX: Remove the name from string completion */ +} static void gg_chat_update_user(GaimConversation *conv, const char *user) -{} +{ + /* XXX: This probably will not require updating the string completion */ +} static GaimConversationUiOps conv_ui_ops = { @@ -266,9 +338,9 @@ static void destroy_ggconv(gpointer data) { - GGConv *conv = data; - gnt_widget_destroy(conv->window); - g_free(conv); + GGConv *ggconv = data; + gnt_widget_destroy(ggconv->window); + g_free(ggconv); } GaimConversationUiOps *gg_conv_get_ui_ops() @@ -276,10 +348,132 @@ return &conv_ui_ops; } +/* Xerox */ +static GaimCmdRet +say_command_cb(GaimConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) + gaim_conv_im_send(GAIM_CONV_IM(conv), args[0]); + else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) + gaim_conv_chat_send(GAIM_CONV_CHAT(conv), args[0]); + return GAIM_CMD_RET_OK; +} + +/* Xerox */ +static GaimCmdRet +me_command_cb(GaimConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + char *tmp; + + tmp = g_strdup_printf("/me %s", args[0]); + + if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) + gaim_conv_im_send(GAIM_CONV_IM(conv), tmp); + else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) + gaim_conv_chat_send(GAIM_CONV_CHAT(conv), tmp); + + g_free(tmp); + return GAIM_CMD_RET_OK; +} + +/* Xerox */ +static GaimCmdRet +debug_command_cb(GaimConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + char *tmp, *markup; + GaimCmdStatus status; + + if (!g_ascii_strcasecmp(args[0], "version")) { + tmp = g_strdup_printf("me is using %s.", VERSION); + markup = g_markup_escape_text(tmp, -1); + + status = gaim_cmd_do_command(conv, tmp, markup, error); + + g_free(tmp); + g_free(markup); + return status; + } else { + gaim_conversation_write(conv, NULL, _("Supported debug options are: version"), + GAIM_MESSAGE_NO_LOG|GAIM_MESSAGE_ERROR, time(NULL)); + return GAIM_CMD_STATUS_OK; + } +} + +/* Xerox */ +static GaimCmdRet +clear_command_cb(GaimConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + GGConv *ggconv = conv->ui_data; + gnt_text_view_clear(GNT_TEXT_VIEW(ggconv->tv)); + return GAIM_CMD_STATUS_OK; +} + +/* Xerox */ +static GaimCmdRet +help_command_cb(GaimConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + GList *l, *text; + GString *s; + + if (args[0] != NULL) { + s = g_string_new(""); + text = gaim_cmd_help(conv, args[0]); + + if (text) { + for (l = text; l; l = l->next) + if (l->next) + g_string_append_printf(s, "%s\n", (char *)l->data); + else + g_string_append_printf(s, "%s", (char *)l->data); + } else { + g_string_append(s, _("No such command (in this context).")); + } + } else { + s = g_string_new(_("Use \"/help <command>\" for help on a specific command.\n" + "The following commands are available in this context:\n")); + + text = gaim_cmd_list(conv); + for (l = text; l; l = l->next) + if (l->next) + g_string_append_printf(s, "%s, ", (char *)l->data); + else + g_string_append_printf(s, "%s.", (char *)l->data); + g_list_free(text); + } + + gaim_conversation_write(conv, NULL, s->str, GAIM_MESSAGE_NO_LOG, time(NULL)); + g_string_free(s, TRUE); + + return GAIM_CMD_STATUS_OK; +} + + void gg_conversation_init() { ggconvs = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_ggconv); + + /* Xerox */ + gaim_cmd_register("say", "S", GAIM_CMD_P_DEFAULT, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, + say_command_cb, _("say <message>: Send a message normally as if you weren't using a command."), NULL); + gaim_cmd_register("me", "S", GAIM_CMD_P_DEFAULT, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, + me_command_cb, _("me <action>: Send an IRC style action to a buddy or chat."), NULL); + gaim_cmd_register("debug", "w", GAIM_CMD_P_DEFAULT, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, + debug_command_cb, _("debug <option>: Send various debug information to the current conversation."), NULL); + gaim_cmd_register("clear", "", GAIM_CMD_P_DEFAULT, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL, + clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); + gaim_cmd_register("help", "w", GAIM_CMD_P_DEFAULT, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, + help_command_cb, _("help <command>: Help on a specific command."), NULL); } void gg_conversation_uninit() Modified: branches/soc-2006-file-loggers/console/gntgaim.c =================================================================== --- branches/soc-2006-file-loggers/console/gntgaim.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntgaim.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -299,8 +299,9 @@ /* Initialize and run the UI */ init_gnt_ui(); - +#ifdef STANDALONE gaim_core_quit(); +#endif return 0; } Modified: branches/soc-2006-file-loggers/console/gntgaim.h =================================================================== --- branches/soc-2006-file-loggers/console/gntgaim.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntgaim.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -1,4 +1,5 @@ #include <glib.h> +#include <libintl.h> #define GAIM_GNT_UI "gnt-gaim" Copied: branches/soc-2006-file-loggers/console/gntnotify.c (from rev 16534, trunk/console/gntnotify.c) =================================================================== --- branches/soc-2006-file-loggers/console/gntnotify.c (rev 0) +++ branches/soc-2006-file-loggers/console/gntnotify.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -0,0 +1,211 @@ +#include <gnt.h> +#include <gntbox.h> +#include <gntbutton.h> +#include <gntlabel.h> +#include <gnttree.h> + +#include <util.h> + +#include "gntnotify.h" +#include "gntgaim.h" + +static struct +{ + GntWidget *window; + GntWidget *tree; +} emaildialog; + +static void * +gg_notify_message(GaimNotifyMsgType type, const char *title, + const char *primary, const char *secondary) +{ + GntWidget *window, *button; + GntTextFormatFlags pf = 0, sf = 0; + + switch (type) + { + case GAIM_NOTIFY_MSG_ERROR: + sf |= GNT_TEXT_FLAG_BOLD; + case GAIM_NOTIFY_MSG_WARNING: + pf |= GNT_TEXT_FLAG_UNDERLINE; + case GAIM_NOTIFY_MSG_INFO: + pf |= GNT_TEXT_FLAG_BOLD; + break; + } + + window = gnt_box_new(FALSE, TRUE); + gnt_box_set_toplevel(GNT_BOX(window), TRUE); + gnt_box_set_title(GNT_BOX(window), title); + gnt_box_set_fill(GNT_BOX(window), FALSE); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); + + if (primary) + gnt_box_add_widget(GNT_BOX(window), + gnt_label_new_with_format(primary, pf)); + if (secondary) + gnt_box_add_widget(GNT_BOX(window), + gnt_label_new_with_format(secondary, sf)); + + button = gnt_button_new(_("OK")); + gnt_box_add_widget(GNT_BOX(window), button); + g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window); + + gnt_widget_show(window); + return window; +} + +/* handle is, in all/most occasions, a GntWidget * */ +static void gg_close_notify(GaimNotifyType type, void *handle) +{ + gnt_widget_destroy(GNT_WIDGET(handle)); +} + +static void *gg_notify_formatted(const char *title, const char *primary, + const char *secondary, const char *text) +{ + /* XXX: For now, simply strip the html and use _notify_message. For future use, + * there should be some way of parsing the makrups from GntTextView */ + char *unformat = gaim_markup_strip_html(text); + char *t = g_strdup_printf("%s%s%s", + secondary ? secondary : "", + secondary ? "\n" : "", + unformat ? unformat : ""); + + void *ret = gg_notify_message(GAIM_NOTIFY_MSG_INFO, title, primary, t); + + g_free(t); + g_free(unformat); + + return ret; +} + +static void +reset_email_dialog() +{ + emaildialog.window = NULL; + emaildialog.tree = NULL; +} + +static void +setup_email_dialog() +{ + GntWidget *box, *tree, *button; + if (emaildialog.window) + return; + + emaildialog.window = box = gnt_vbox_new(FALSE); + gnt_box_set_toplevel(GNT_BOX(box), TRUE); + gnt_box_set_title(GNT_BOX(box), _("Emails")); + gnt_box_set_fill(GNT_BOX(box), FALSE); + gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID); + gnt_box_set_pad(GNT_BOX(box), 0); + + gnt_box_add_widget(GNT_BOX(box), + gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD)); + + emaildialog.tree = tree = gnt_tree_new_with_columns(3); + gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("From"), _("Subject")); + gnt_tree_set_show_title(GNT_TREE(tree), TRUE); + gnt_tree_set_col_width(GNT_TREE(tree), 0, 15); + gnt_tree_set_col_width(GNT_TREE(tree), 1, 25); + gnt_tree_set_col_width(GNT_TREE(tree), 2, 25); + + gnt_box_add_widget(GNT_BOX(box), tree); + + button = gnt_button_new(_("Close")); + gnt_box_add_widget(GNT_BOX(box), button); + + g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), box); + g_signal_connect(G_OBJECT(box), "destroy", G_CALLBACK(reset_email_dialog), NULL); +} + +static void * +gg_notify_emails(GaimConnection *gc, size_t count, gboolean detailed, + const char **subjects, const char **froms, const char **tos, + const char **urls) +{ + GaimAccount *account = gaim_connection_get_account(gc); + GString *message = g_string_new(NULL); + void *ret; + + if (!detailed) + { + g_string_append_printf(message, + ngettext("%s (%s) has %d new message.", + "%s (%s) has %d new messages.", + (int)count), + tos ? *tos : gaim_account_get_username(account), + gaim_account_get_protocol_name(account), (int)count); + } + else + { + setup_email_dialog(); + + gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)), + gnt_tree_create_row(GNT_TREE(emaildialog.tree), + tos ? *tos : gaim_account_get_username(account), /* XXX: Perhaps add the prpl-name */ + froms ? *froms : "[Unknown sender]", + *subjects), + NULL, NULL); + gnt_widget_show(emaildialog.window); + return NULL; + } + + ret = gg_notify_message(GAIM_NOTIFY_MSG_INFO, _("New Mail"), _("You have mail!"), message->str); + g_string_free(message, TRUE); + return ret; +} + +static void * +gg_notify_email(GaimConnection *gc, const char *subject, const char *from, + const char *to, const char *url) +{ + return gg_notify_emails(gc, 1, subject != NULL, + subject ? &subject : NULL, + from ? &from : NULL, + to ? &to : NULL, + url ? &url : NULL); +} + +static void * +gg_notify_userinfo(GaimConnection *gc, const char *who, const char *text) +{ + /* Xeroxed from gtknotify.c */ + char *primary; + void *ui_handle; + + primary = g_strdup_printf(_("Info for %s"), who); + ui_handle = gg_notify_formatted(_("Buddy Information"), primary, NULL, text); + g_free(primary); + return ui_handle; +} + +static GaimNotifyUiOps ops = +{ + .notify_message = gg_notify_message, + .close_notify = gg_close_notify, /* The rest of the notify-uiops return a GntWidget. + These widgets should be destroyed from here. */ + .notify_formatted = gg_notify_formatted, + .notify_email = gg_notify_email, + .notify_emails = gg_notify_emails, + .notify_userinfo = gg_notify_userinfo, + + .notify_searchresults = NULL, /* We are going to need multi-column GntTree's for this */ + .notify_searchresults_new_rows = NULL, + .notify_uri = NULL /* This is of low-priority to me */ +}; + +GaimNotifyUiOps *gg_notify_get_ui_ops() +{ + return &ops; +} + +void gg_notify_init() +{ +} + +void gg_notify_uninit() +{ +} + + Copied: branches/soc-2006-file-loggers/console/gntnotify.h (from rev 16534, trunk/console/gntnotify.h) =================================================================== --- branches/soc-2006-file-loggers/console/gntnotify.h (rev 0) +++ branches/soc-2006-file-loggers/console/gntnotify.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -0,0 +1,8 @@ +#include "notify.h" + +GaimNotifyUiOps *gg_notify_get_ui_ops(); + +void gg_notify_init(); + +void gg_notify_uninit(); + Modified: branches/soc-2006-file-loggers/console/gntui.c =================================================================== --- branches/soc-2006-file-loggers/console/gntui.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/gntui.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -2,16 +2,23 @@ #include "gntaccount.h" #include "gntblist.h" +#include "gntconn.h" #include "gntconv.h" +#include "gntnotify.h" void init_gnt_ui() { +#ifdef STANDALONE gnt_init(); - +#endif /* Accounts */ gg_accounts_init(); gaim_accounts_set_ui_ops(gg_accounts_get_ui_ops()); + /* Connections */ + gg_connections_init(); + gaim_connections_set_ui_ops(gg_connections_get_ui_ops()); + /* Initialize the buddy list */ gg_blist_init(); gaim_blist_set_ui_ops(gg_blist_get_ui_ops()); @@ -20,17 +27,29 @@ gg_conversation_init(); gaim_conversations_set_ui_ops(gg_conv_get_ui_ops()); + /* Notify */ + gg_notify_init(); + gaim_notify_set_ui_ops(gg_notify_get_ui_ops()); + +#ifdef STANDALONE gnt_main(); gaim_accounts_set_ui_ops(NULL); gg_accounts_uninit(); + gaim_connections_set_ui_ops(NULL); + gg_connections_uninit(); + gaim_blist_set_ui_ops(NULL); gg_blist_uninit(); gaim_conversations_set_ui_ops(NULL); gg_conversation_uninit(); + gaim_notify_set_ui_ops(NULL); + gg_notify_uninit(); + gnt_quit(); +#endif } Modified: branches/soc-2006-file-loggers/console/libgnt/gntbox.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntbox.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -173,31 +173,30 @@ if (maxw < w) maxw = w; } - - if (box->homogeneous) + + for (iter = box->list; iter; iter = iter->next) { - for (iter = box->list; iter; iter = iter->next) + int w, h; + GntWidget *wid = GNT_WIDGET(iter->data); + + gnt_widget_get_size(wid, &w, &h); + + if (box->homogeneous) { - gnt_widget_set_size(GNT_WIDGET(iter->data), maxw, maxh); + if (box->vertical) + h = maxh; + else + w = maxw; } - } - else - { - for (iter = box->list; iter; iter = iter->next) + if (box->fill) { if (box->vertical) - { - int h; - gnt_widget_get_size(GNT_WIDGET(iter->data), NULL, &h); - gnt_widget_set_size(GNT_WIDGET(iter->data), maxw, h); - } + w = maxw; else - { - int w; - gnt_widget_get_size(GNT_WIDGET(iter->data), &w, NULL); - gnt_widget_set_size(GNT_WIDGET(iter->data), w, maxh); - } + h = maxh; } + + gnt_widget_set_size(wid, w, h); } reposition_children(widget); @@ -495,6 +494,7 @@ box->homogeneous = homo; box->vertical = vert; box->pad = 1; + box->fill = TRUE; gnt_widget_set_take_focus(widget, TRUE); GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); if (vert) @@ -669,3 +669,8 @@ } } +void gnt_box_set_fill(GntBox *box, gboolean fill) +{ + box->fill = fill; +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gntbox.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntbox.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntbox.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -33,6 +33,7 @@ gboolean vertical; gboolean homogeneous; + gboolean fill; GList *list; /* List of widgets */ GntWidget *active; @@ -85,6 +86,8 @@ void gnt_box_readjust(GntBox *box); +void gnt_box_set_fill(GntBox *box, gboolean fill); + G_END_DECLS #endif /* GNT_BOX_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gntcolors.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntcolors.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntcolors.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -1,10 +1,40 @@ #include <ncursesw/ncurses.h> #include "gntcolors.h" +static struct +{ + short r, g, b; +} colors[GNT_TOTAL_COLORS]; + +static void +backup_colors() +{ + short i; + for (i = 0; i < GNT_TOTAL_COLORS; i++) + { + color_content(i, &colors[i].r, + &colors[i].g, &colors[i].b); + } +} + +static void +restore_colors() +{ + short i; + for (i = 0; i < GNT_TOTAL_COLORS; i++) + { + init_color(i, colors[i].r, + colors[i].g, colors[i].b); + } +} + void gnt_init_colors() { + start_color(); if (can_change_color()) { + backup_colors(); + /* XXX: Do some init_color()s */ init_color(GNT_COLOR_BLACK, 0, 0, 0); init_color(GNT_COLOR_RED, 1000, 0, 0); @@ -39,3 +69,9 @@ } } +void +gnt_uninit_colors() +{ + restore_colors(); +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gntcolors.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntcolors.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntcolors.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -32,4 +32,6 @@ /* populate some default colors */ void gnt_init_colors(); +void gnt_uninit_colors(); + #endif Modified: branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntcombobox.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -235,7 +235,8 @@ void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) { - gnt_tree_add_row_after(GNT_TREE(box->dropdown), key, text, NULL, NULL); + gnt_tree_add_row_after(GNT_TREE(box->dropdown), key, + gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL, NULL); if (box->selected == NULL) set_selection(box, key); } Modified: branches/soc-2006-file-loggers/console/libgnt/gntlabel.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntlabel.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntlabel.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -21,8 +21,9 @@ gnt_label_draw(GntWidget *widget) { GntLabel *label = GNT_LABEL(widget); + chtype flag = gnt_text_format_flag_to_chtype(label->flags); - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(widget->window, '\0' | flag); mvwprintw(widget->window, 0, 0, label->text); DEBUG; @@ -109,13 +110,32 @@ GntWidget *gnt_label_new(const char *text) { + return gnt_label_new_with_format(text, 0); +} + +GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags) +{ GntWidget *widget = g_object_new(GNT_TYPE_LABEL, NULL); GntLabel *label = GNT_LABEL(widget); label->text = g_strdup(text); + label->flags = flags; gnt_widget_set_take_focus(widget, FALSE); GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); return widget; } +void gnt_label_set_text(GntLabel *label, const char *text) +{ + g_free(label->text); + label->text = g_strdup(text); + + if (GNT_WIDGET(label)->window) + { + gnt_widget_hide(GNT_WIDGET(label)); + gnt_label_size_request(GNT_WIDGET(label)); + gnt_widget_draw(GNT_WIDGET(label)); + } +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gntlabel.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntlabel.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntlabel.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -3,6 +3,7 @@ #include "gnt.h" #include "gntwidget.h" +#include "gnttextview.h" #define GNT_TYPE_LABEL (gnt_label_get_gtype()) #define GNT_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LABEL, GntLabel)) @@ -19,6 +20,7 @@ GntWidget parent; char *text; + GntTextFormatFlags flags; void (*gnt_reserved1)(void); void (*gnt_reserved2)(void); @@ -42,6 +44,10 @@ GntWidget *gnt_label_new(const char *text); +GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags); + +void gnt_label_set_text(GntLabel *label, const char *text); + G_END_DECLS #endif /* GNT_LABEL_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gntline.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntline.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntline.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -42,6 +42,9 @@ GType gnt_line_get_gtype(void); +#define gnt_hline_new() gnt_line_new(FALSE) +#define gnt_vline_new() gnt_line_new(TRUE) + GntWidget *gnt_line_new(gboolean vertical); G_END_DECLS Modified: branches/soc-2006-file-loggers/console/libgnt/gntmain.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gntmain.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -258,13 +258,16 @@ { GntBox *box = GNT_BOX(iter->data); - gnt_tree_add_row_after(GNT_TREE(tree), box, box->title, NULL, NULL); + gnt_tree_add_row_after(GNT_TREE(tree), box, + gnt_tree_create_row(GNT_TREE(tree), box->title), NULL, NULL); update_window_in_list(GNT_WIDGET(box)); } + gnt_tree_set_selected(GNT_TREE(tree), focus_list->data); gnt_box_add_widget(GNT_BOX(win), tree); - gnt_widget_set_size(tree, getmaxx(stdscr) / 3, getmaxy(stdscr) / 2); + gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3); + gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2); gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4); lock_focus_list = 1; @@ -274,6 +277,34 @@ g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), NULL); } +static void +shift_window(GntWidget *widget, int dir) +{ + GList *all = g_list_first(focus_list); + GList *list = g_list_find(all, widget); + int length, pos; + if (!list) + return; + + length = g_list_length(all); + pos = g_list_position(all, list); + + pos += dir; + if (dir > 0) + pos++; + + if (pos < 0) + pos = length; + else if (pos > length) + pos = 0; + + all = g_list_insert(all, widget, pos); + all = g_list_delete_link(all, list); + if (focus_list == list) + focus_list = g_list_find(all, widget); + draw_taskbar(); +} + static gboolean io_invoke(GIOChannel *source, GIOCondition cond, gpointer null) { @@ -350,6 +381,15 @@ /* Resize window */ mode = GNT_KP_MODE_RESIZE; } + else if (strcmp(buffer + 1, ",") == 0 && focus_list) + { + /* Re-order the list of windows */ + shift_window(focus_list->data, -1); + } + else if (strcmp(buffer + 1, ".") == 0 && focus_list) + { + shift_window(focus_list->data, 1); + } } } } @@ -501,7 +541,6 @@ ascii_only = TRUE; initscr(); - start_color(); gnt_init_colors(); X_MIN = 0; @@ -564,7 +603,8 @@ && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) { gnt_tree_add_row_after(GNT_TREE(window_list.tree), widget, - GNT_BOX(widget)->title, NULL, NULL); + gnt_tree_create_row(GNT_TREE(window_list.tree), GNT_BOX(widget)->title), + NULL, NULL); update_window_in_list(widget); } } @@ -654,6 +694,7 @@ void gnt_quit() { + gnt_uninit_colors(); endwin(); } Modified: branches/soc-2006-file-loggers/console/libgnt/gnttextview.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttextview.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gnttextview.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -178,20 +178,8 @@ if (text == NULL || *text == '\0') return; - if (flags & GNT_TEXT_FLAG_BOLD) - fl |= A_BOLD; - if (flags & GNT_TEXT_FLAG_UNDERLINE) - fl |= A_UNDERLINE; - if (flags & GNT_TEXT_FLAG_BLINK) - fl |= A_BLINK; + fl = gnt_text_format_flag_to_chtype(flags); - if (flags & GNT_TEXT_FLAG_DIM) - fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); - else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) - fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); - else - fl |= COLOR_PAIR(GNT_COLOR_NORMAL); - view->list = g_list_first(view->list); split = g_strsplit(text, "\n", 0); @@ -262,3 +250,39 @@ gnt_widget_draw(GNT_WIDGET(view)); } +chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags) +{ + chtype fl = 0; + + if (flags & GNT_TEXT_FLAG_BOLD) + fl |= A_BOLD; + if (flags & GNT_TEXT_FLAG_UNDERLINE) + fl |= A_UNDERLINE; + if (flags & GNT_TEXT_FLAG_BLINK) + fl |= A_BLINK; + + if (flags & GNT_TEXT_FLAG_DIM) + fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); + else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) + fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + else + fl |= COLOR_PAIR(GNT_COLOR_NORMAL); + + return fl; +} + +void gnt_text_view_clear(GntTextView *view) +{ + GntTextLine *line; + + g_list_foreach(view->list, free_text_line, NULL); + g_list_free(view->list); + view->list = NULL; + + line = g_new0(GntTextLine, 1); + view->list = g_list_append(view->list, line); + + if (GNT_WIDGET(view)->window) + gnt_widget_draw(GNT_WIDGET(view)); +} + Modified: branches/soc-2006-file-loggers/console/libgnt/gnttextview.h =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttextview.h 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gnttextview.h 2006-07-21 03:34:03 UTC (rev 16535) @@ -30,6 +30,7 @@ typedef enum { + GNT_TEXT_FLAG_NORMAL = 0, GNT_TEXT_FLAG_BOLD = 1 << 0, GNT_TEXT_FLAG_UNDERLINE = 1 << 1, GNT_TEXT_FLAG_BLINK = 1 << 2, @@ -64,6 +65,10 @@ * It first completes the current line with the current text-attributes. */ void gnt_text_view_next_line(GntTextView *view); +chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags); + +void gnt_text_view_clear(GntTextView *view); + G_END_DECLS #endif /* GNT_TEXT_VIEW_H */ Modified: branches/soc-2006-file-loggers/console/libgnt/gnttree.c =================================================================== --- branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-07-20 21:43:15 UTC (rev 16534) +++ branches/soc-2006-file-loggers/console/libgnt/gnttree.c 2006-07-21 03:34:03 UTC (rev 16535) @@ -18,7 +18,6 @@ struct _GnTreeRow { void *key; - char *text; void *data; /* XXX: unused */ gboolean collapsed; @@ -31,8 +30,16 @@ GntTreeRow *child; GntTreeRow *next; GntTreeRow *prev; + + GList *columns; }; +struct _GnTreeCol +{ + char *text; + int span; /* How many columns does it span? */ +}; + static GntWidgetClass *parent_class = NULL; static guint signals[SIGS] = { 0 }; @@ -151,14 +158,98 @@ return (hb - ha); } +static int +find_depth(GntTreeRow *row) +{ + int dep = -1; + + while (row) + { + dep++; + row = row->parent; + } + + return dep; +} + +static char * +update_row_text(GntTree *tree, GntTreeRow *row) +{ + GString *string = g_string_new(NULL); + GList *iter; + int i; + + for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) + { + GntTreeCol *col = iter->data; + char *text; + int len = g_utf8_strlen(col->text, -1); + int fl = 0; + + if (i == 0) + { + if (row->choice) + { + g_string_append_printf(string, "[%c] ", + row->isselected ? 'X' : ' '); + fl = 4; + } + else if (row->parent == NULL && row->child) + { + if (row->collapsed) + { + string = g_string_append(string, "+ "); + } + else + { + string = g_string_append(string, "- "); + } + fl = 2; + } + else + { + fl = TAB_SIZE * find_depth(row); + g_string_append_printf(string, "%*s", fl, ""); + } + len += fl; + } + else + g_string_append_c(string, '|'); + + if (len > tree->columns[i].width) + { + len = tree->columns[i].width; + } + + text = g_utf8_offset_to_pointer(col->text, len - fl); + string = g_string_append_len(string, col->text, text - col->text); + if (len < tree->columns[i].width) + g_string_append_printf(string, "%*s", tree->columns[i].width - len, ""); + } + return g_string_free(string, FALSE); +} + static void +tree_mark_columns(GntTree *tree, int pos, int y, chtype type) +{ + GntWidget *widget = GNT_WIDGET(tree); + int i; + int x = pos; + + for (i = 0; i < tree->ncol - 1; i++) + { + x += tree->columns[i].width; + mvwaddch(widget->window, y, x + i, type); + } +} + +static void redraw_tree(GntTree *tree) { int start; GntWidget *widget = GNT_WIDGET(tree); GntTreeRow *row; int pos; - gboolean deep; if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) pos = 0; @@ -172,37 +263,39 @@ wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); - deep = TRUE; + start = 0; + if (tree->show_title) + { + int i; + int x = pos; + + mvwhline(widget->window, pos + 1, pos, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + widget->priv.width - pos - 1); + + for (i = 0; i < tree->ncol; i++) + { + mvwprintw(widget->window, pos, x + i, tree->columns[i].title); + x += tree->columns[i].width; + } + if (pos) + tree_mark_columns(tree, pos, 0, ACS_TTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + tree_mark_columns(tree, pos, pos + 1, ACS_PLUS | COLOR_PAIR(GNT_COLOR_NORMAL)); + tree_mark_columns(tree, pos, pos, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL)); + start = 2; + } + row = tree->top; - for (start = pos; row && start < widget->priv.height - pos; + for (start = start + pos; row && start < widget->priv.height - pos; start++, row = get_next(row)) { - char str[2048]; + char *str; int wr; - char format[16] = ""; GntTextFormatFlags flags = row->flags; int attr = 0; - deep = TRUE; + str = update_row_text(tree, row); - if (row->parent == NULL && row->child) - { - if (row->collapsed) - { - strcpy(format, "+ "); - deep = FALSE; - } - else - strcpy(format, "- "); - } - else if (row->choice) - { - g_snprintf(format, sizeof(format) - 1, "[%c] ", row->isselected ? 'X' : ' '); - } - - g_snprintf(str, sizeof(str) - 1, "%s%s", format, row->text); - if ((wr = g_utf8_strlen(str, -1)) >= widget->priv.width - 1 - pos) { /* XXX: ellipsize */ @@ -238,6 +331,8 @@ mvwprintw(widget->window, start, pos, str); whline(widget->window, ' ', widget->priv.width - pos * 2 - g_utf8_strlen(str, -1)); tree->bottom = row; + g_free(str); + tree_mark_columns(tree, pos, start, ACS_VLINE | attr); } wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); @@ -245,6 +340,7 @@ { mvwhline(widget->window, start, pos, ' ', widget->priv.width - pos * 2); + tree_mark_columns(tree, pos, start, ACS_VLINE); start++; } @@ -267,7 +363,13 @@ if (widget->priv.height == 0) widget->priv.height = 10; /* XXX: Why?! */ if (widget->priv.width == 0) - widget->priv.width = 20; /* YYY: 'cuz ... */ + { + GntTree *tree = GNT_TREE(widget); + int i, width = 0; + for (i = 0; i < tree->ncol; i++) + width += tree->columns[i].width; + widget->priv.width = width + i; + } } static void @@ -353,9 +455,16 @@ gnt_tree_destroy(GntWidget *widget) { GntTree *tree = GNT_TREE(widget); + int i; g_hash_table_destroy(tree->hash); g_list_free(tree->list); + + for (i = 0; i < tree->ncol; i++) + { + g_free(tree->columns[i].title); + } + g_free(tree->columns); } static void @@ -437,6 +546,15 @@ } static void +free_tree_col(gpointer data) +{ + GntTreeCol *col = data; + + g_free(col->text); + g_free(col); +} + +static void free_tree_row(gpointer data) { GntTreeRow *row = data; @@ -444,20 +562,14 @@ if (!row) return; - g_free(row->text); + g_list_foreach(row->columns, (GFunc)free_tree_col, NULL); + g_list_free(row->columns); g_free(row); } GntWidget *gnt_tree_new() { - GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL); - GntTree *tree = GNT_TREE(widget); - - tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row); - GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW); - gnt_widget_set_take_focus(widget, TRUE); - - return widget; + return gnt_tree_new_with_columns(1); } void gnt_tree_set_visible_rows(GntTree *tree, int rows) @@ -500,24 +612,10 @@ g_signal_emit(tree, signals[SIG_SCROLLED], 0, count); } -static int -find_depth(GntTreeRow *row) +GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro) { - int dep = -1; + GntTreeRow *pr = NULL; - while (row) - { - dep++; - row = row->parent; - } - - return dep; -} - -GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro) -{ - GntTreeRow *row = g_new0(GntTreeRow, 1), *pr = NULL; - g_hash_table_replace(tree->hash, key, row); if (tree->root == NULL) @@ -575,7 +673,6 @@ } row->key = key; - row->text = g_strdup_printf("%*s%s", TAB_SIZE * find_depth(row), "", text); row->data = NULL; if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED)) @@ -591,10 +688,10 @@ return NULL; } -const char *gnt_tree_get_selection_text(GntTree *tree) +char *gnt_tree_get_selection_text(GntTree *tree) { if (tree->current) - return tree->current->text; + update_row_text(tree, tree->current); return NULL; } @@ -657,27 +754,32 @@ !!(GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); } -void gnt_tree_change_text(GntTree *tree, gpointer key, const char *text) +void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text) { - GntTreeRow *row = g_hash_table_lookup(tree->hash, key); + GntTreeRow *row; + GntTreeCol *col; + + g_return_if_fail(colno < tree->ncol); + + row = g_hash_table_lookup(tree->hash, key); if (row) { - g_free(row->text); - row->text = g_strdup_printf("%*s%s", TAB_SIZE * find_depth(row), "", text); + col = g_list_nth_data(row->columns, colno); + g_free(col->text); + col->text = g_strdup(text); if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) > 0) redraw_tree(tree); } } -GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, const char *text, void *parent, void *bigbro) +GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro) { - GntTreeRow *row; - - row = g_hash_table_lookup(tree->hash, key); - g_return_val_if_fail(!row || !row->choice, NULL); + GntTreeRow *r; + r = g_hash_table_lookup(tree->hash, key); + g_return_val_if_fail(!r || !r->choice, NULL); - row = gnt_tree_add_row_after(tree, key, text, parent, bigbro); + row = gnt_tree_add_row_after(tree, key, row, parent, bigbro); row->choice = TRUE; return row; @@ -716,3 +818,91 @@ redraw_tree(tree); /* XXX: It shouldn't be necessary to redraw the whole darned tree */ } +void gnt_tree_set_selected(GntTree *tree , void *key) +{ + int dist; + GntTreeRow *row = g_hash_table_lookup(tree->hash, key); + if (!row) + return; + + if (tree->top == NULL) + tree->top = row; + if (tree->bottom == NULL) + tree->bottom = row; + + tree->current = row; + if ((dist = get_distance(tree->current, tree->bottom)) < 0) + gnt_tree_scroll(tree, -dist); + else if ((dist = get_distance(tree->current, tree->top)) > 0) + gnt_tree_scroll(tree, -dist); + else + redraw_tree(tree); +} + +GntWidget *gnt_tree_new_with_columns(int col) +{ + GntWidget *widget = g_object_new(GNT_TYPE_TR... [truncated message content] |
From: <ro...@us...> - 2006-07-22 21:16:21
|
Revision: 16539 Author: roast Date: 2006-07-22 14:16:10 -0700 (Sat, 22 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16539&view=rev Log Message: ----------- xml logger writes the UTF-8 BOM, and xml parser/reader clobbers it Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/util.c Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-07-22 18:14:40 UTC (rev 16538) +++ branches/soc-2006-file-loggers/src/log.c 2006-07-22 21:16:10 UTC (rev 16539) @@ -1035,9 +1035,11 @@ if (!data->channel) return 0; g_string_printf(writebuf, + "%c%c%c" "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" "<chat service=\"%s\" account=\"%s\" version=\"0.3.1-04\"%s>\n" "\t<event time=\"%s\" type=\"logStart\" />\n", + 0xEF, 0xBB, 0xBF, prpl, gaim_account_get_username(log->account), log->type == GAIM_LOG_SYSTEM ? "gaim:logtype=\"system\"" : "", date); Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-07-22 18:14:40 UTC (rev 16538) +++ branches/soc-2006-file-loggers/src/util.c 2006-07-22 21:16:10 UTC (rev 16539) @@ -1522,6 +1522,15 @@ GString *loggedby = NULL; gboolean bad_formatting = FALSE; + const char bom_utf8[] = {0xEF, 0xBB, 0xBF, 0}; + + // clobber the UTF-8 BOM + if (c && *c) { + if(!g_ascii_strncasecmp(c, bom_utf8, 3)) { + c+=3; + } + } + while(!bad_formatting && c && *c) { if(*c == '<') { if (*(c+1) == '/') { /* list all expected closing tags */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-23 04:10:58
|
Revision: 16544 Author: roast Date: 2006-07-22 21:10:52 -0700 (Sat, 22 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16544&view=rev Log Message: ----------- made a non-destructive gaim_message_is_meify() that returns the same as gaim_message_meify(), but does not modify the message Modified Paths: -------------- branches/soc-2006-file-loggers/src/util.c branches/soc-2006-file-loggers/src/util.h Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-07-23 03:47:07 UTC (rev 16543) +++ branches/soc-2006-file-loggers/src/util.c 2006-07-23 04:10:52 UTC (rev 16544) @@ -4183,7 +4183,7 @@ } } -gboolean gaim_message_meify(char *message, size_t len) +gboolean gaim_message_is_meify(char *message, size_t len) { char *c; gboolean inside_html = FALSE; @@ -4206,11 +4206,29 @@ } if(*c && !g_ascii_strncasecmp(c, "/me ", 4)) { - memmove(c, c+4, len-3); return TRUE; } return FALSE; +} + +gboolean gaim_message_meify(char *message, size_t len) +{ + size_t length; + gboolean is_action; + + if (len == -1) + length = strlen(message); + else + length = len; + + is_action = gaim_message_is_meify(message, length); + + if (is_action) { + memmove(message, message+4, length-3); + } + + return is_action; } char *gaim_text_strip_mnemonic(const char *in) Modified: branches/soc-2006-file-loggers/src/util.h =================================================================== --- branches/soc-2006-file-loggers/src/util.h 2006-07-23 03:47:07 UTC (rev 16543) +++ branches/soc-2006-file-loggers/src/util.h 2006-07-23 04:10:52 UTC (rev 16544) @@ -994,6 +994,16 @@ * @param message The message to check * @param len The message length, or -1 * + * @return TRUE if it starts with /me, otherwise FALSE + */ +gboolean gaim_message_is_meify(char *message, size_t len); + +/** + * Trims the leading "/me " off of the message if it's there. + * + * @param message The message to check + * @param len The message length, or -1 + * * @return TRUE if it starts with /me, and it has been removed, otherwise FALSE */ gboolean gaim_message_meify(char *message, size_t len); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-07-25 02:46:37
|
Revision: 16567 Author: roast Date: 2006-07-24 19:46:26 -0700 (Mon, 24 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16567&view=rev Log Message: ----------- gaim_message_is_meify() renamed to gaim_message_is_action() Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/util.c branches/soc-2006-file-loggers/src/util.h Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-07-25 01:25:04 UTC (rev 16566) +++ branches/soc-2006-file-loggers/src/log.c 2006-07-25 02:46:26 UTC (rev 16567) @@ -1087,7 +1087,7 @@ g_string_printf(writebuf, "\t<message time=\"%s\" sender=\"%s\"%s%s auto=\"true\">%s</message>\n", date, from, recv_from_self ? " self=\"true\"" : "", - gaim_message_is_meify(msg_fixed, -1) ? " type=\"action\"": "", msg_fixed); + gaim_message_is_action(msg_fixed, -1) ? " type=\"action\"": "", msg_fixed); } else if (type & GAIM_MESSAGE_SEND || type & GAIM_MESSAGE_RECV) { gboolean recv_from_self = FALSE; @@ -1103,7 +1103,7 @@ g_string_printf(writebuf, "\t<message time=\"%s\" sender=\"%s\"%s%s>%s</message>\n", date, from, recv_from_self ? " self=\"true\"" : "", - gaim_message_is_meify(msg_fixed, -1) ? " type=\"action\"": "", msg_fixed); + gaim_message_is_action(msg_fixed, -1) ? " type=\"action\"": "", msg_fixed); } else { gaim_debug_error("log", "Unhandled message type."); Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-07-25 01:25:04 UTC (rev 16566) +++ branches/soc-2006-file-loggers/src/util.c 2006-07-25 02:46:26 UTC (rev 16567) @@ -4183,7 +4183,7 @@ } } -gboolean gaim_message_is_meify(char *message, size_t len) +gboolean gaim_message_is_action(char *message, size_t len) { char *c; gboolean inside_html = FALSE; @@ -4222,7 +4222,7 @@ else length = len; - is_action = gaim_message_is_meify(message, length); + is_action = gaim_message_is_action(message, length); if (is_action) { memmove(message, message+4, length-3); Modified: branches/soc-2006-file-loggers/src/util.h =================================================================== --- branches/soc-2006-file-loggers/src/util.h 2006-07-25 01:25:04 UTC (rev 16566) +++ branches/soc-2006-file-loggers/src/util.h 2006-07-25 02:46:26 UTC (rev 16567) @@ -994,9 +994,9 @@ * @param message The message to check * @param len The message length, or -1 * - * @return TRUE if it starts with /me, otherwise FALSE + * @return TRUE if it starts with "/me ", otherwise FALSE */ -gboolean gaim_message_is_meify(char *message, size_t len); +gboolean gaim_message_is_action(char *message, size_t len); /** * Trims the leading "/me " off of the message if it's there. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-08-08 13:20:41
|
Revision: 16672 Author: roast Date: 2006-08-08 06:20:32 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16672&view=rev Log Message: ----------- minor cleanup in log.[ch] Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/log.h Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-08-08 01:12:58 UTC (rev 16671) +++ branches/soc-2006-file-loggers/src/log.c 2006-08-08 13:20:32 UTC (rev 16672) @@ -49,7 +49,7 @@ static void log_get_log_sets_common(GHashTable *sets); static gsize xml_logger_write(GaimLog *log, GaimMessageFlags type, - const char *from, time_t time, const char *message); + const char *from, time_t time, const char *message); static void xml_logger_finalize(GaimLog *log); static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account); static GList *xml_logger_list_syslog(GaimAccount *account); @@ -57,7 +57,7 @@ static int xml_logger_total_size(GaimLogType type, const char *name, GaimAccount *account); static gsize html_logger_write(GaimLog *log, GaimMessageFlags type, - const char *from, time_t time, const char *message); + const char *from, time_t time, const char *message); static void html_logger_finalize(GaimLog *log); static GList *html_logger_list(GaimLogType type, const char *sn, GaimAccount *account); static GList *html_logger_list_syslog(GaimAccount *account); @@ -71,9 +71,8 @@ static void old_logger_get_log_sets(GaimLogSetCallback cb, GHashTable *sets); static void old_logger_finalize(GaimLog *log); -static gsize txt_logger_write(GaimLog *log, - GaimMessageFlags type, - const char *from, time_t time, const char *message); +static gsize txt_logger_write(GaimLog *log, GaimMessageFlags type, + const char *from, time_t time, const char *message); static void txt_logger_finalize(GaimLog *log); static GList *txt_logger_list(GaimLogType type, const char *sn, GaimAccount *account); static GList *txt_logger_list_syslog(GaimAccount *account); @@ -319,15 +318,15 @@ GaimLogLogger *gaim_log_logger_new(const char *id, const char *name, int functions, ...) { #if 0 - void(*create)(GaimLog *), - gsize(*write)(GaimLog *, GaimMessageFlags, const char *, time_t, const char *), - void(*finalize)(GaimLog *), - GList*(*list)(GaimLogType type, const char*, GaimAccount*), - char*(*read)(GaimLog*, GaimLogReadFlags*), - int(*size)(GaimLog*), - int(*total_size)(GaimLogType type, const char *name, GaimAccount *account), - GList*(*list_syslog)(GaimAccount *account), - void(*get_log_sets)(GaimLogSetCallback cb, GHashTable *sets)) + void(*create)(GaimLog *), + gsize(*write)(GaimLog *, GaimMessageFlags, const char *, time_t, const char *), + void(*finalize)(GaimLog *), + GList*(*list)(GaimLogType type, const char*, GaimAccount*), + char*(*read)(GaimLog*, GaimLogReadFlags*), + int(*size)(GaimLog*), + int(*total_size)(GaimLogType type, const char *name, GaimAccount *account), + GList*(*list_syslog)(GaimAccount *account), + void(*get_log_sets)(GaimLogSetCallback cb, GHashTable *sets)) { #endif GaimLogLogger *logger; @@ -570,53 +569,53 @@ gaim_prefs_add_string("/core/logging/format", "txt"); xml_logger = gaim_log_logger_new("xml", _("Unified Log Format (XML)"), 8, - NULL, - xml_logger_write, - xml_logger_finalize, - xml_logger_list, - xml_logger_read, - gaim_log_common_sizer, - xml_logger_total_size, - xml_logger_list_syslog); + NULL, + xml_logger_write, + xml_logger_finalize, + xml_logger_list, + xml_logger_read, + gaim_log_common_sizer, + xml_logger_total_size, + xml_logger_list_syslog); gaim_log_logger_add(xml_logger); html_logger = gaim_log_logger_new("html", _("HTML"), 8, - NULL, - html_logger_write, - html_logger_finalize, - html_logger_list, - html_logger_read, - gaim_log_common_sizer, - html_logger_total_size, - html_logger_list_syslog); + NULL, + html_logger_write, + html_logger_finalize, + html_logger_list, + html_logger_read, + gaim_log_common_sizer, + html_logger_total_size, + html_logger_list_syslog); gaim_log_logger_add(html_logger); txt_logger = gaim_log_logger_new("txt", _("Plain text"), 8, - NULL, - txt_logger_write, - txt_logger_finalize, - txt_logger_list, - txt_logger_read, - gaim_log_common_sizer, - txt_logger_total_size, - txt_logger_list_syslog); + NULL, + txt_logger_write, + txt_logger_finalize, + txt_logger_list, + txt_logger_read, + gaim_log_common_sizer, + txt_logger_total_size, + txt_logger_list_syslog); gaim_log_logger_add(txt_logger); old_logger = gaim_log_logger_new("old", _("Old Gaim"), 9, - NULL, - NULL, - old_logger_finalize, - old_logger_list, - old_logger_read, - old_logger_size, - old_logger_total_size, - NULL, - old_logger_get_log_sets); + NULL, + NULL, + old_logger_finalize, + old_logger_list, + old_logger_read, + old_logger_size, + old_logger_total_size, + NULL, + old_logger_get_log_sets); gaim_log_logger_add(old_logger); gaim_signal_register(handle, "log-timestamp", #if SIZEOF_TIME_T == 4 - gaim_marshal_POINTER__POINTER_INT, + gaim_marshal_POINTER__POINTER_INT, #elif SIZEOF_TIME_T == 8 gaim_marshal_POINTER__POINTER_INT64, #else @@ -628,18 +627,18 @@ #if SIZEOF_TIME_T == 4 gaim_value_new(GAIM_TYPE_INT)); #elif SIZEOF_TIME_T == 8 - gaim_value_new(GAIM_TYPE_INT64)); + gaim_value_new(GAIM_TYPE_INT64)); #else # error Unknown size of time_t #endif gaim_prefs_connect_callback(NULL, "/core/logging/format", - logger_pref_cb, NULL); + logger_pref_cb, NULL); gaim_prefs_trigger_callback("/core/logging/format"); logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, - (GEqualFunc)_gaim_logsize_user_equal, - (GDestroyNotify)_gaim_logsize_user_free_key, NULL); + (GEqualFunc)_gaim_logsize_user_equal, + (GDestroyNotify)_gaim_logsize_user_free_key, NULL); } void @@ -658,8 +657,8 @@ struct tm tm; date = gaim_signal_emit_return_1(gaim_log_get_handle(), - "log-timestamp", - log, when); + "log-timestamp", + log, when); if (date != NULL) return date; @@ -691,7 +690,7 @@ gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); tm = localtime(&log->time); - + { // build basename char * temp = g_strdup_printf("%s_%s", gaim_normalize(log->account, log->name), gaim_utf8_strftime("%Y-%m-%dT%H%M%S%z%Z", tm)); @@ -722,7 +721,7 @@ if (suffixchar == 'z' && g_file_test(path, G_FILE_TEST_EXISTS)) { /* we have a collision problem. not logging, and complain. */ gaim_conversation_write(log->conv, NULL, _("Logging of this conversation failed."), - GAIM_MESSAGE_ERROR, time(NULL)); + GAIM_MESSAGE_ERROR, time(NULL)); g_free(dir); g_free(path); g_free(extname); Modified: branches/soc-2006-file-loggers/src/log.h =================================================================== --- branches/soc-2006-file-loggers/src/log.h 2006-08-08 01:12:58 UTC (rev 16671) +++ branches/soc-2006-file-loggers/src/log.h 2006-08-08 13:20:32 UTC (rev 16672) @@ -94,26 +94,6 @@ GAIM_TOTAL_EVENTS } GaimEvents; -//typedef enum { -// GAIM_STATUS_ONLINE, /***< online */ -// GAIM_STATUS_OFFLINE, /***< offline */ -// GAIM_STATUS_AWAY, /***< away */ -// GAIM_STATUS_IDLE, /***< idle */ -// GAIM_STATUS_AVAILABLE, /***< available */ -// GAIM_STATUS_BUSY, /***< busy */ -// GAIM_STATUS_NOTATHOME, /***< notAtHome */ -// GAIM_STATUS_ONTHEPHONE, /***< onThePhone */ -// GAIM_STATUS_ONVACATION, /***< onVacation */ -// GAIM_STATUS_DONOTDISTURB, /***< doNotDisturb */ -// GAIM_STATUS_EXTENDEDAWAY, /***< extendedAway */ -// GAIM_STATUS_BERIGHTBACK, /***< beRightBack */ -// GAIM_STATUS_NOTAVAILABLE, /***< notAvailable */ -// GAIM_STATUS_NOTATHOME, /***< notAtHome */ -// GAIM_STATUS_NOTATMYDESK, /***< notAtMyDesk */ -// GAIM_STATUS_NOTINTHEOFFICE, /***< notInTheOffice */ -// GAIM_STATUS_STEPPEDOUT, /***< steppedOut */ -//} GaimStatusFlag; - #include "account.h" #include "conversation.h" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2006-08-09 04:21:45
|
Revision: 16675 Author: roast Date: 2006-08-08 21:21:36 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16675&view=rev Log Message: ----------- working event and status (aka action) logging framework try Modified Paths: -------------- branches/soc-2006-file-loggers/src/log.c branches/soc-2006-file-loggers/src/log.h Modified: branches/soc-2006-file-loggers/src/log.c =================================================================== --- branches/soc-2006-file-loggers/src/log.c 2006-08-09 03:41:45 UTC (rev 16674) +++ branches/soc-2006-file-loggers/src/log.c 2006-08-09 04:21:36 UTC (rev 16675) @@ -48,8 +48,11 @@ static void log_get_log_sets_common(GHashTable *sets); -static gsize xml_logger_write(GaimLog *log, GaimMessageFlags type, - const char *from, time_t time, const char *message); +static gsize xml_logger_write_message(GaimLog *log, GaimMessageFlags type, + const char *from, time_t time, const char *message); +static gsize xml_logger_write_action(GaimLog *log, GaimActionType action, + const char *from, time_t time, const char *data); +static gboolean xml_logger_append_footer(GIOChannel *channel); static void xml_logger_finalize(GaimLog *log); static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account); static GList *xml_logger_list_syslog(GaimAccount *account); @@ -79,6 +82,70 @@ static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags); static int txt_logger_total_size(GaimLogType type, const char *name, GaimAccount *account); +static GaimActionData supported_actions[] = { + { GAIM_ACTION_UNSET_ACTION, GAIM_ACTION_UNSET_ACTION, FALSE, NULL}, + { GAIM_ACTION_UNSET_STATUS, GAIM_ACTION_UNSET_STATUS, FALSE, NULL}, + { GAIM_ACTION_STATUS_ONLINE, GAIM_ACTION_UNSET_ACTION, TRUE, "online"}, + { GAIM_ACTION_STATUS_FREETOCHAT, GAIM_ACTION_STATUS_ONLINE, TRUE, "freeToChat"}, + { GAIM_ACTION_STATUS_MOBILE, GAIM_ACTION_STATUS_ONLINE, TRUE, "mobile"}, + { GAIM_ACTION_STATUS_OFFLINE, GAIM_ACTION_UNSET_ACTION, TRUE, "offline"}, + { GAIM_ACTION_STATUS_INVISIBLE, GAIM_ACTION_STATUS_OFFLINE, TRUE, "invisible"}, + { GAIM_ACTION_STATUS_AWAY, GAIM_ACTION_UNSET_ACTION, TRUE, "away"}, + { GAIM_ACTION_STATUS_BERIGHTBACK, GAIM_ACTION_STATUS_AWAY, TRUE, "beRightBack"}, + { GAIM_ACTION_STATUS_BUSY, GAIM_ACTION_STATUS_AWAY, TRUE, "busy"}, + { GAIM_ACTION_STATUS_DONOTDISTURB, GAIM_ACTION_STATUS_AWAY, TRUE, "doNotDisturb"}, + { GAIM_ACTION_STATUS_EXTENDEDAWAY, GAIM_ACTION_STATUS_AWAY, TRUE, "extendedAway"}, + { GAIM_ACTION_STATUS_GONEHOME, GAIM_ACTION_STATUS_AWAY, TRUE, "goneHome"}, + { GAIM_ACTION_STATUS_INAMEETING, GAIM_ACTION_STATUS_AWAY, TRUE, "inAMeeting"}, + { GAIM_ACTION_STATUS_NOTATHOME, GAIM_ACTION_STATUS_AWAY, TRUE, "notAtHome"}, + { GAIM_ACTION_STATUS_NOTATMYDESK, GAIM_ACTION_STATUS_AWAY, TRUE, "notAtMyDesk"}, + { GAIM_ACTION_STATUS_NOTAVAILABLE, GAIM_ACTION_STATUS_AWAY, TRUE, "notAvailable"}, + { GAIM_ACTION_STATUS_NOTINTHEOFFICE, GAIM_ACTION_STATUS_AWAY, TRUE, "notInTheOffice"}, + { GAIM_ACTION_STATUS_ONTHEPHONE, GAIM_ACTION_STATUS_AWAY, TRUE, "onThePhone"}, + { GAIM_ACTION_STATUS_ONVACATION, GAIM_ACTION_STATUS_AWAY, TRUE, "onVacation"}, + { GAIM_ACTION_STATUS_OUTTOLUNCH, GAIM_ACTION_STATUS_AWAY, TRUE, "outToLunch"}, + { GAIM_ACTION_STATUS_STEPPEDOUT, GAIM_ACTION_STATUS_AWAY, TRUE, "steppedOut"}, + { GAIM_ACTION_UNSET_EVENT, GAIM_ACTION_UNSET_EVENT, FALSE, NULL}, + { GAIM_ACTION_EVENT_LOGSTARTED, GAIM_ACTION_UNSET_ACTION, FALSE, "logStarted"}, + { GAIM_ACTION_EVENT_LOGENDED, GAIM_ACTION_UNSET_ACTION, FALSE, "logEnded"}, + { GAIM_ACTION_EVENT_WINDOWOPENED, GAIM_ACTION_UNSET_ACTION, FALSE, "windowOpened"}, + { GAIM_ACTION_EVENT_WINDOWCLOSED, GAIM_ACTION_UNSET_ACTION, FALSE, "windowClosed"}, + { GAIM_ACTION_EVENT_FILETRANSFERREQUESTED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferRequested"}, + { GAIM_ACTION_EVENT_FILETRANSFERREJECTED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferRejected"}, + { GAIM_ACTION_EVENT_FILETRANSFERACCEPTED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferAccepted"}, + { GAIM_ACTION_EVENT_FILETRANSFERSTARTED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferStarted"}, + { GAIM_ACTION_EVENT_FILETRANSFERABORTED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferAborted"}, + { GAIM_ACTION_EVENT_FILETRANSFERCOMPLETED, GAIM_ACTION_UNSET_ACTION, TRUE, "fileTransferCompleted"}, + { GAIM_ACTION_EVENT_AUTHORIZATIONREQUESTED, GAIM_ACTION_UNSET_ACTION, TRUE, "authorizationRequested"}, + { GAIM_ACTION_EVENT_AUTHORIZATIONDENIED, GAIM_ACTION_UNSET_ACTION, TRUE, "authorizationDenied"}, + { GAIM_ACTION_EVENT_AUTHORIZATIONCANCELLED, GAIM_ACTION_UNSET_ACTION, TRUE, "authorizationCancelled"}, + { GAIM_ACTION_EVENT_AUTHORZATIONGRANTED, GAIM_ACTION_UNSET_ACTION, TRUE, "authorizationGranted"}, + { GAIM_ACTION_EVENT_CHANNELMODES, GAIM_ACTION_UNSET_ACTION, TRUE, "channelModes"}, + { GAIM_ACTION_EVENT_CHANNELMODECHANGED, GAIM_ACTION_EVENT_CHANNELMODES, TRUE, "channelModeChanged"}, + { GAIM_ACTION_EVENT_CHANNELTOPIC, GAIM_ACTION_UNSET_ACTION, TRUE, "channelTopic"}, + { GAIM_ACTION_EVENT_CHANNELTOPICCHANGED, GAIM_ACTION_EVENT_CHANNELTOPIC, TRUE, "channelTopicChanged"}, + { GAIM_ACTION_EVENT_SUBJECT, GAIM_ACTION_UNSET_ACTION, TRUE, "subject"}, + { GAIM_ACTION_EVENT_SUBJECTCHANGED, GAIM_ACTION_EVENT_SUBJECT, TRUE, "subjectChanged"}, + { GAIM_ACTION_EVENT_USERFORMATTEDID, GAIM_ACTION_UNSET_ACTION, TRUE, "userFormattedId"}, + { GAIM_ACTION_EVENT_USERFORMATTEDIDCHANGED, GAIM_ACTION_EVENT_USERFORMATTEDID, TRUE, "userFormattedIdChanged"}, + { GAIM_ACTION_EVENT_USERALIAS, GAIM_ACTION_UNSET_ACTION, TRUE, "userAlias"}, + { GAIM_ACTION_EVENT_USERALIASCHANGED, GAIM_ACTION_EVENT_USERALIAS, TRUE, "userAliasChanged"}, + { GAIM_ACTION_EVENT_USERHANDLE, GAIM_ACTION_UNSET_ACTION, TRUE, "userHandle"}, + { GAIM_ACTION_EVENT_USERHANDLECHANGED, GAIM_ACTION_EVENT_USERHANDLE, TRUE, "userHandleChanged"}, + { GAIM_ACTION_EVENT_USERPERMISSIONS, GAIM_ACTION_UNSET_ACTION, TRUE, "userPermissions"}, + { GAIM_ACTION_EVENT_USERPERMISSIONS_PROMOTED, GAIM_ACTION_EVENT_USERPERMISSIONS, TRUE, "userPermissions/promoted"}, + { GAIM_ACTION_EVENT_USERPERMISSIONS_DEMOTED, GAIM_ACTION_EVENT_USERPERMISSIONS, TRUE, "userPermissions/demoted"}, + { GAIM_ACTION_EVENT_USERPERMISSIONS_VOICED, GAIM_ACTION_EVENT_USERPERMISSIONS, TRUE, "userPermissions/voiced"}, + { GAIM_ACTION_EVENT_USERPERMISSIONS_DEVOICED, GAIM_ACTION_EVENT_USERPERMISSIONS, TRUE, "userPermissions/devoiced"}, + { GAIM_ACTION_EVENT_USERJOINED, GAIM_ACTION_UNSET_ACTION, TRUE, "userJoined"}, + { GAIM_ACTION_EVENT_USERPARTED, GAIM_ACTION_UNSET_ACTION, TRUE, "userParted"}, + { GAIM_ACTION_EVENT_USERQUIT, GAIM_ACTION_UNSET_ACTION, TRUE, "userQuit"}, + { GAIM_ACTION_EVENT_USERKICKED, GAIM_ACTION_UNSET_ACTION, TRUE, "userKicked"}, + { GAIM_ACTION_EVENT_USERBANNED, GAIM_ACTION_UNSET_ACTION, TRUE, "userBanned"}, + { GAIM_ACTION_EVENT_USERKLINED, GAIM_ACTION_UNSET_ACTION, TRUE, "userKlined"}, + { GAIM_ACTION_EVENT_USERGLINED, GAIM_ACTION_UNSET_ACTION, TRUE, "userGlined"} +}; + /************************************************************************** * PUBLIC LOGGING FUNCTIONS *********************************************** **************************************************************************/ @@ -177,6 +244,34 @@ } +void gaim_log_write_action(GaimLog *log, GaimActionType action, + const char *from, time_t time, const char *data) +{ + struct _gaim_logsize_user *lu; + gsize written, total = 0; + gpointer ptrsize; + + g_return_if_fail(log); + g_return_if_fail(log->logger); + g_return_if_fail(log->logger->write_action); + + written = (log->logger->write_action)(log, action, from, time, data); + + lu = g_new(struct _gaim_logsize_user, 1); + + lu->name = g_strdup(gaim_normalize(log->account, log->name)); + lu->account = log->account; + + if(g_hash_table_lookup_extended(logsize_users, lu, NULL, &ptrsize)) { + total = GPOINTER_TO_INT(ptrsize); + total += written; + g_hash_table_replace(logsize_users, lu, GINT_TO_POINTER(total)); + } else { + g_free(lu->name); + g_free(lu); + } +} + char *gaim_log_read(GaimLog *log, GaimLogReadFlags *flags) { GaimLogReadFlags mflags; @@ -360,8 +455,10 @@ logger->list_syslog = va_arg(args, void *); if (functions >= 9) logger->get_log_sets = va_arg(args, void *); + if (functions >= 10) + logger->write_action = va_arg(args, void *); - if (functions > 9) + if (functions > 10) gaim_debug_info("log", "Dropping new functions for logger: %s (%s)\n", name, id); va_end(args); @@ -545,6 +642,52 @@ } /**************************************************************************** + * LOG ACTION SUBSYSTEM ***************************************************** + ****************************************************************************/ +GaimActionData* gaim_log_action_get_actiondata(GaimActionType action) { + int i = 0; + for (i = 0; i < sizeof(supported_actions); i++) { + if (supported_actions[i].action != action) { + continue; + } + else { + return &(supported_actions[i]); + } + } + return NULL; +} + +gboolean gaim_log_action_is_event(GaimActionType action) { + // for now, we know the boundaries of GaimActionType enum declaration + return action > GAIM_ACTION_UNSET_EVENT; +} + +gboolean gaim_log_action_is_status(GaimActionType action) { + // for now, we know the boundaries of GaimActionType enum declaration + return (action > GAIM_ACTION_UNSET_STATUS && action < GAIM_ACTION_UNSET_EVENT); +} + +gboolean gaim_log_action_requires_sender(GaimActionType action) { + GaimActionData *action_data = gaim_log_action_get_actiondata(action); + + if (action_data != NULL) { + return action_data->requires_sender; + } + + return FALSE; +} + +const char* gaim_log_action_ulf_value(GaimActionType action) { + GaimActionData *action_data = gaim_log_action_get_actiondata(action); + + if (action_data != NULL) { + return action_data->ulf_value; + } + + return NULL; +} + +/**************************************************************************** * LOG SUBSYSTEM ************************************************************ ****************************************************************************/ @@ -568,15 +711,17 @@ gaim_prefs_add_string("/core/logging/format", "txt"); - xml_logger = gaim_log_logger_new("xml", _("Unified Log Format (XML)"), 8, + xml_logger = gaim_log_logger_new("xml", _("Unified Log Format (XML)"), 10, NULL, - xml_logger_write, + xml_logger_write_message, xml_logger_finalize, xml_logger_list, xml_logger_read, gaim_log_common_sizer, xml_logger_total_size, - xml_logger_list_syslog); + xml_logger_list_syslog, + NULL, + xml_logger_write_action); gaim_log_logger_add(xml_logger); html_logger = gaim_log_logger_new("html", _("HTML"), 8, @@ -1016,39 +1161,23 @@ } */ -static gsize xml_logger_write(GaimLog *log, - GaimMessageFlags type, - const char *from, time_t time, const char *message) -{ - char *msg_fixed; - char *date = g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", localtime(&time))); +/** Returns the amount of data written to the file, and -1 if the file is unwritable. + * If the file is unwritable, then the integrity of log->logger_data is not guaranteed. */ +static gsize xml_logger_write_create(GaimLog *log, time_t time) { + if (!log->logger_data) { + /* This log is new. We could use the loggers 'new' function, but + * creating a new file there would result in empty files in the case + * that you open a convo with someone, but don't say anything. + */ - GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); - GaimLogCommonLoggerData *data = log->logger_data; - gsize written = 0, written_buf = 0; - GString *writebuf; - GIOStatus iostat; - GError *gerror = NULL; - gboolean log_corrected_html = gaim_prefs_get_bool("/core/logging/log_corrected_html"); - - char *from_normed = g_strdup(gaim_normalize(log->account, from)); - char *from_attributes; - if (strncmp(from, from_normed, strlen(from)) == 0) { - // if from is already normalized; leave senderformatted out - from_attributes = g_strconcat(" sender=\"", from_normed, "\"", NULL); - } else { - // from is NOT normalized; specifying senderformatted - from_attributes = g_strconcat(" sender=\"", from_normed, "\" senderformatted=\"", from, "\"", NULL); - } - - writebuf = g_string_new(""); - - /* This log is new. We could use the loggers 'new' function, but - * creating a new file there would result in empty files in the case - * that you open a convo with someone, but don't say anything. - */ - if (!log->logger_data) { + GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); + GaimLogCommonLoggerData *data = log->logger_data; + GString *writebuf = g_string_new(""); + char *date = g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", localtime(&time))); + gsize written = 0; const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); + GIOStatus iostat; + GError *gerror = NULL; char *account_normed = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); char *account_attributes; @@ -1067,8 +1196,11 @@ data = log->logger_data; // if file doesn't exist, die - if (!data->channel) return 0; + if (!data->channel) { + return -1; + } + // directly write the event to prevent calling xml_logger_write_event, which calls us back g_string_printf(writebuf, "%c%c%c" "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" @@ -1078,21 +1210,58 @@ account_attributes, log->type == GAIM_LOG_SYSTEM ? " gaim:logtype=\"system\"" : "", date); - iostat = g_io_channel_write_chars(data->channel, writebuf->str, -1, &written_buf, &gerror); + iostat = g_io_channel_write_chars(data->channel, writebuf->str, -1, &written, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not write to new file: %s\n", gerror->message); + gaim_debug_info("log", "xml_logger_write_common could not write to new file: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } - else written += written_buf; g_free(account_normed); g_free(account_attributes); + g_string_free(writebuf, TRUE); + return written; } + return 0; +} - /* if we can't write to the file, give up before we hurt ourselves */ - if(!data->channel) +static gsize xml_logger_write_message(GaimLog *log, + GaimMessageFlags type, + const char *from, time_t time, const char *message) +{ + char *date = g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", localtime(&time))); + + GaimLogCommonLoggerData *data; + gsize written = 0, written_buf = 0; + GString *writebuf; + GIOStatus iostat; + GError *gerror = NULL; + + char *from_normed = g_strdup(gaim_normalize(log->account, from)); + char *from_attributes; /**< The XML string of attributes for sender and senderformatted. */ + + gboolean log_corrected_html = gaim_prefs_get_bool("/core/logging/log_corrected_html"); + char *msg_fixed; + + if (strncmp(from, from_normed, strlen(from)) == 0) { + // if from is already normalized; leave senderformatted out + from_attributes = g_strconcat(" sender=\"", from_normed, "\"", NULL); + } else { + // from is NOT normalized; specifying senderformatted + from_attributes = g_strconcat(" sender=\"", from_normed, "\" senderformatted=\"", from, "\"", NULL); + } + + writebuf = g_string_new(""); + + // create the logfile if it doesn't exist + written = xml_logger_write_create(log, time); + /* if we can't write to the file, give up before we hurt ourselves + * if xml_logger_write_common returns -1, the log file is not available */ + if (written == -1) { + gaim_debug_info("log", "xml_logger_write_message could not create the new logfile\n"); return 0; + } + data = log->logger_data; if (log_corrected_html) { gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); @@ -1150,7 +1319,7 @@ iostat = g_io_channel_write_chars(data->channel, writebuf->str, -1, &written_buf, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not the message to the logfile: %s\n", gerror->message); + gaim_debug_info("log", "xml_logger_write_message could not the message to the logfile: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } @@ -1158,43 +1327,131 @@ g_free(date); if (log_corrected_html) { - // free only if we need to free this + // free only if we used this g_free(msg_fixed); } + xml_logger_append_footer(data->channel); + + g_free(from_normed); + g_free(from_attributes); + g_string_free(writebuf, TRUE); + return written; +} + +static gsize xml_logger_write_action(GaimLog *log, GaimActionType action, + const char *from, time_t time, const char *tagdata) { + char *date = g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", localtime(&time))); + + GaimLogCommonLoggerData *data = log->logger_data; + GIOStatus iostat; + GError *gerror = NULL; + + gsize written = 0; + GString *writebuf = g_string_new(""); + + char *from_attributes; + if (from) { + char *from_normed = g_strdup(gaim_normalize(log->account, from)); + + if (strncmp(from, from_normed, strlen(from)) == 0) { + // if from is already normalized; leave senderformatted out + from_attributes = g_strconcat(" sender=\"", from_normed, "\"", NULL); + } else { + // from is NOT normalized; specifying senderformatted + from_attributes = g_strconcat(" sender=\"", from_normed, "\" senderformatted=\"", from, "\"", NULL); + } + + g_free(from_normed); + } + else { + // there is no sender attribute for this action + from_attributes = g_strconcat("", NULL); + + if (gaim_log_action_requires_sender(action)) { + gaim_debug_error("log", "xml_logger_write_action is writing an action that does not have the required sender attribute\n"); + } + } + + // create the log file if it doesn't exist, and die if it fails + written = xml_logger_write_create(log, time); + if (written == -1) { + gaim_debug_info("log", "xml_logger_write_action could not create the new logfile\n"); + return 0; + } + + // create the log action + if (tagdata != NULL && strlen(tagdata) > 0) { + g_string_printf(writebuf, "\t<event time=\"%s\"%s type=\"%s\">%s</event>\n", date, from_attributes, + gaim_log_action_ulf_value(action), tagdata); + } + else { + g_string_printf(writebuf, "\t<event time=\"%s\"%s type=\"%s\" />\n", date, from_attributes, + gaim_log_action_ulf_value(action)); + } + + // write it + iostat = g_io_channel_write_chars(data->channel, writebuf->str, -1, &written, &gerror); + if (iostat == G_IO_STATUS_ERROR) { + gaim_debug_info("log", "xml_logger_write_action could not write the action to the log file: %s\n", gerror->message); + g_error_free(gerror); + gerror = NULL; + } + + xml_logger_append_footer(data->channel); + + g_free(date); + g_free(from_attributes); + g_string_free(writebuf, TRUE); + + return written; +} + +static gboolean xml_logger_append_footer(GIOChannel *channel) { + GIOStatus iostat; + GString *writebuf; + GError *gerror = NULL; + gsize written_buf = 0; + + if (!channel) { + return FALSE; + } + + writebuf = g_string_new(""); + // append suffix to file and seek back to keep a valid XML document out of the user space buffer g_string_printf(writebuf, "\t<event time=\"%s\" type=\"logEnd\" />\n" "</chat>\n", gaim_utf8_strftime("%Y-%m-%d %H:%M:%S%z", NULL)); - iostat = g_io_channel_write_chars(data->channel, writebuf->str, -1, &written_buf, &gerror); + iostat = g_io_channel_write_chars(channel, writebuf->str, -1, &written_buf, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not write the tail to the logfile: %s\n", gerror->message); + gaim_debug_info("log", "xml_logger_write_message could not write the tail to the logfile: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } - iostat = g_io_channel_seek_position(data->channel, -1*(gint64)(written_buf), G_SEEK_CUR, &gerror); + iostat = g_io_channel_seek_position(channel, -1*(gint64)(written_buf), G_SEEK_CUR, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not seek backwards to the beginning of the tail: %s\n", gerror->message); + gaim_debug_info("log", "xml_logger_write_message could not seek backwards to the beginning of the tail: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } - iostat = g_io_channel_flush(data->channel, &gerror); + iostat = g_io_channel_flush(channel, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not flush the logfile: %s\n", gerror->message); + gaim_debug_info("log", "xml_logger_write_message could not flush the logfile: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } - g_free(from_normed); - g_free(from_attributes); g_string_free(writebuf, TRUE); - return written; + + return TRUE; } + static void xml_logger_finalize(GaimLog *log) { GaimLogCommonLoggerData *data = log->logger_data; @@ -1399,7 +1656,7 @@ iostat = g_io_channel_flush(data->channel, &gerror); if (iostat == G_IO_STATUS_ERROR) { - gaim_debug_info("log", "xml_logger_write could not flush the logfile: %s\n", gerror->message); + gaim_debug_info("log", "html_logger_write could not flush the logfile: %s\n", gerror->message); g_error_free(gerror); gerror = NULL; } Modified: branches/soc-2006-file-loggers/src/log.h =================================================================== --- branches/soc-2006-file-loggers/src/log.h 2006-08-09 03:41:45 UTC (rev 16674) +++ branches/soc-2006-file-loggers/src/log.h 2006-08-09 04:21:36 UTC (rev 16675) @@ -36,6 +36,7 @@ typedef struct _GaimLogLogger GaimLogLogger; typedef struct _GaimLogCommonLoggerData GaimLogCommonLoggerData; typedef struct _GaimLogSet GaimLogSet; +typedef struct _GaimActionData GaimActionData; typedef enum { GAIM_LOG_IM, @@ -48,51 +49,72 @@ } GaimLogReadFlags; /** - * A list of recognizable events that are logged. + * A list of recognizable actions that are logged. */ typedef enum { - GAIM_EVENT_UNSET = 0, - GAIM_EVENT_LOGSTARTED, - GAIM_EVENT_LOGENDED, - GAIM_EVENT_WINDOWOPENED, - GAIM_EVENT_WINDOWCLOSED, - GAIM_EVENT_FILETRANSFERREQUESTED, - GAIM_EVENT_FILETRANSFERREJECTED, - GAIM_EVENT_FILETRANSFERACCEPTED, - GAIM_EVENT_FILETRANSFERSTARTED, - GAIM_EVENT_FILETRANSFERABORTED, - GAIM_EVENT_FILETRANSFERCOMPLETED, - GAIM_EVENT_AUTHORIZATIONREQUESTED, - GAIM_EVENT_AUTHORIZATIONDENIED, - GAIM_EVENT_AUTHORIZATIONCANCELLED, - GAIM_EVENT_AUTHORZATIONGRANTED, - GAIM_EVENT_CHANNELMODES, - GAIM_EVENT_CHANNELMODECHANGED, - GAIM_EVENT_CHANNELTOPIC, - GAIM_EVENT_CHANNELTOPICCHANGED, - GAIM_EVENT_SUBJECT, - GAIM_EVENT_SUBJECTCHANGED, - GAIM_EVENT_USERFORMATTEDID, - GAIM_EVENT_USERFORMATTEDIDCHANGED, - GAIM_EVENT_USERALIAS, - GAIM_EVENT_USERALIASCHANGED, - GAIM_EVENT_USERHANDLE, - GAIM_EVENT_USERHANDLECHANGED, - GAIM_EVENT_USERPERMISSIONS, - GAIM_EVENT_USERPERMISSIONS_PROMOTED, - GAIM_EVENT_USERPERMISSIONS_DEMOTED, - GAIM_EVENT_USERPERMISSIONS_VOICED, - GAIM_EVENT_USERPERMISSIONS_DEVOICED, - GAIM_EVENT_USERJOINED, - GAIM_EVENT_USERPARTED, - GAIM_EVENT_USERQUIT, - GAIM_EVENT_USERKICKED, - GAIM_EVENT_USERBANNED, - GAIM_EVENT_USERKLINED, - GAIM_EVENT_USERGLINED, - GAIM_TOTAL_EVENTS -} GaimEvents; + GAIM_ACTION_UNSET_ACTION = 0, + GAIM_ACTION_UNSET_STATUS, /**< Placeholder/Boundary of the first STATUS action types. */ + GAIM_ACTION_STATUS_ONLINE, + GAIM_ACTION_STATUS_FREETOCHAT, + GAIM_ACTION_STATUS_MOBILE, + GAIM_ACTION_STATUS_OFFLINE, + GAIM_ACTION_STATUS_INVISIBLE, + GAIM_ACTION_STATUS_AWAY, + GAIM_ACTION_STATUS_BERIGHTBACK, + GAIM_ACTION_STATUS_BUSY, + GAIM_ACTION_STATUS_DONOTDISTURB, + GAIM_ACTION_STATUS_EXTENDEDAWAY, + GAIM_ACTION_STATUS_GONEHOME, + GAIM_ACTION_STATUS_INAMEETING, + GAIM_ACTION_STATUS_NOTATHOME, + GAIM_ACTION_STATUS_NOTATMYDESK, + GAIM_ACTION_STATUS_NOTAVAILABLE, + GAIM_ACTION_STATUS_NOTINTHEOFFICE, + GAIM_ACTION_STATUS_ONTHEPHONE, + GAIM_ACTION_STATUS_ONVACATION, + GAIM_ACTION_STATUS_OUTTOLUNCH, + GAIM_ACTION_STATUS_STEPPEDOUT, + GAIM_ACTION_UNSET_EVENT, /**< Placeholder/Boundary of the first EVENT action types. */ + GAIM_ACTION_EVENT_LOGSTARTED, + GAIM_ACTION_EVENT_LOGENDED, + GAIM_ACTION_EVENT_WINDOWOPENED, + GAIM_ACTION_EVENT_WINDOWCLOSED, + GAIM_ACTION_EVENT_FILETRANSFERREQUESTED, + GAIM_ACTION_EVENT_FILETRANSFERREJECTED, + GAIM_ACTION_EVENT_FILETRANSFERACCEPTED, + GAIM_ACTION_EVENT_FILETRANSFERSTARTED, + GAIM_ACTION_EVENT_FILETRANSFERABORTED, + GAIM_ACTION_EVENT_FILETRANSFERCOMPLETED, + GAIM_ACTION_EVENT_AUTHORIZATIONREQUESTED, + GAIM_ACTION_EVENT_AUTHORIZATIONDENIED, + GAIM_ACTION_EVENT_AUTHORIZATIONCANCELLED, + GAIM_ACTION_EVENT_AUTHORZATIONGRANTED, + GAIM_ACTION_EVENT_CHANNELMODES, + GAIM_ACTION_EVENT_CHANNELMODECHANGED, + GAIM_ACTION_EVENT_CHANNELTOPIC, + GAIM_ACTION_EVENT_CHANNELTOPICCHANGED, + GAIM_ACTION_EVENT_SUBJECT, + GAIM_ACTION_EVENT_SUBJECTCHANGED, + GAIM_ACTION_EVENT_USERFORMATTEDID, + GAIM_ACTION_EVENT_USERFORMATTEDIDCHANGED, + GAIM_ACTION_EVENT_USERALIAS, + GAIM_ACTION_EVENT_USERALIASCHANGED, + GAIM_ACTION_EVENT_USERHANDLE, + GAIM_ACTION_EVENT_USERHANDLECHANGED, + GAIM_ACTION_EVENT_USERPERMISSIONS, + GAIM_ACTION_EVENT_USERPERMISSIONS_PROMOTED, + GAIM_ACTION_EVENT_USERPERMISSIONS_DEMOTED, + GAIM_ACTION_EVENT_USERPERMISSIONS_VOICED, + GAIM_ACTION_EVENT_USERPERMISSIONS_DEVOICED, + GAIM_ACTION_EVENT_USERJOINED, + GAIM_ACTION_EVENT_USERPARTED, + GAIM_ACTION_EVENT_USERQUIT, + GAIM_ACTION_EVENT_USERKICKED, + GAIM_ACTION_EVENT_USERBANNED, + GAIM_ACTION_EVENT_USERKLINED, + GAIM_ACTION_EVENT_USERGLINED +} GaimActionType; #include "account.h" #include "conversation.h" @@ -113,29 +135,29 @@ I don't think this is actually needed. */ void (*create)(GaimLog *log); - /** This is used to write to the log file */ + /** This is used to write a message to the log file. */ gsize (*write)(GaimLog *log, GaimMessageFlags type, const char *from, time_t time, const char *message); - /** Called when the log is destroyed */ + /** Called when the log is destroyed. */ void (*finalize)(GaimLog *log); - /** This function returns a sorted GList of available GaimLogs */ + /** This function returns a sorted GList of available GaimLogs. */ GList *(*list)(GaimLogType type, const char *name, GaimAccount *account); /** Given one of the logs returned by the logger's list function, - * this returns the contents of the log in GtkIMHtml markup */ + * this returns the contents of the log in GtkIMHtml markup. */ char *(*read)(GaimLog *log, GaimLogReadFlags *flags); /** Given one of the logs returned by the logger's list function, - * this returns the size of the log in bytes */ + * this returns the size of the log in bytes. */ int (*size)(GaimLog *log); /** Returns the total size of all the logs. If this is undefined a default - * implementation is used */ + * implementation is used. */ int (*total_size)(GaimLogType type, const char *name, GaimAccount *account); /** This function returns a sorted GList of available system GaimLogs */ @@ -150,6 +172,13 @@ * Loggers which implement this function must create a GaimLogSet, * then call @a cb with @a sets and the newly created GaimLogSet. */ void (*get_log_sets)(GaimLogSetCallback cb, GHashTable *sets); + + /** This is used to write an action (event or status) to the log file. */ + gsize (*write_action)(GaimLog *log, + GaimActionType action, + const char *from, + time_t time, + const char *tagdata); }; /** @@ -215,6 +244,18 @@ * IMPORTANT: Update that code if you add members here. */ }; +/** + * Describes a specific action type and its attributes. + */ +struct _GaimActionData { + GaimActionType action; /**< The action, which is an action or status. **/ + GaimActionType parent_action; /**< The parent action, if there is one. + * If not, this will be set to NULL or GAIM_ACTION_UNSET. */ + gboolean requires_sender; /**< Indicates whether a sender is required, + * or if the action must have an origin. */ + const char *ulf_value; /**< The corresponding ULF formatted attribute value. */ +}; + #ifdef __cplusplus extern "C" { #endif @@ -248,7 +289,7 @@ void gaim_log_free(GaimLog *log); /** - * Writes to a log file. Assumes you have checked preferences already. + * Writes messages to a log file. Assumes you have checked preferences already. * * @param log The log to write to * @param type The type of message being logged @@ -264,6 +305,22 @@ const char *message); /** + * Writes actions to a log file. Assumes you have checked preferences already. + * + * @param log The log to write to + * @param action The action that occured + * @param from For whom this acton occured, or @c NULL + * if action does not have an origin + * @param time A timestamp in UNIX time + * @param tagdata Any action-associated data to be saved in the action element + */ +void gaim_log_write_action(GaimLog *log, + GaimActionType action, + const char *from, + time_t time, + const char *tagdata); + +/** * Reads from a log * * @param log The log to read from @@ -505,6 +562,57 @@ GList *gaim_log_logger_get_options(void); /**************************************************************************/ +/** @name Action Utilities for Logging functions */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the corresponding GaimActionData struct of a GaimAction. + * + * @param action The action + * + * @return GaimActionData struct + */ +GaimActionData* gaim_log_action_get_actiondata(GaimActionType action); + +/** + * Returns true if the GaimActionType action is an event + * + * @param action The action + * + * @return True if action is an event + */ +gboolean gaim_log_action_is_event(GaimActionType action); + +/** + * Returns true if the GaimActionType action is an status + * + * @param action The action + * + * @return True if action is a status + */ +gboolean gaim_log_action_is_status(GaimActionType action); + +/** + * Returns true if the GaimAction requires a sender or a from. + * + * @param action The action + * + * @return True if <code>event</code> or <code>status</code> element requires a sender. + */ +gboolean gaim_log_action_requires_sender(GaimActionType action); + +/** + * Returns the corresponding ULF attribute value of an action. + * + * @param action The action + * + * @return The corresponding ULF attribute value + */ +const char* gaim_log_action_ulf_value(GaimActionType action); + +/*@}*/ +/**************************************************************************/ /** @name Log Subsystem */ /**************************************************************************/ /*@{*/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |