| | 236 | struct TagComparator |
| | 237 | { |
| | 238 | bool operator()(GtkTextTag* first, GtkTextTag* second) const |
| | 239 | { |
| | 240 | return gtk_text_tag_get_priority(first) < |
| | 241 | gtk_text_tag_get_priority(second); |
| | 242 | } |
| | 243 | }; |
| | 244 | |
| | 245 | // Sort tags by priority, so that we declare them in order |
| | 246 | typedef std::set<GtkTextTag*, TagComparator> priority_tag_set; |
| | 247 | |
| | 248 | // We don't use Glib::ustring::compose for now because |
| | 249 | // it's formatting support does not compile properly under |
| | 250 | // Windows. See https://bugzilla.gnome.org/show_bug.cgi?id=599340 |
| | 251 | Glib::ustring uprintf(gchar const* fmt, ...) |
| | 252 | { |
| | 253 | va_list args; |
| | 254 | va_start(args, fmt); |
| | 255 | gchar* str = g_strdup_vprintf(fmt, args); |
| | 256 | va_end(args); |
| | 257 | Glib::ustring result; |
| | 258 | try |
| | 259 | { |
| | 260 | result = str; |
| | 261 | } |
| | 262 | catch (...) |
| | 263 | { |
| | 264 | g_free(str); |
| | 265 | throw; |
| | 266 | } |
| | 267 | g_free(str); |
| | 268 | return result; |
| | 269 | } |
| | 270 | |
| | 271 | unsigned int color_to_rgb(GdkColor* color) |
| | 272 | { |
| | 273 | return ((color->red & 0xff00) << 8) |
| | 274 | | (color->green & 0xff00) |
| | 275 | | ((color->blue & 0xff00) >> 8); |
| | 276 | } |
| | 277 | |
| 260 | | |
| 261 | | while (!gtk_text_iter_is_end(&begin)) { |
| 262 | | // check author, insert new <span/> if necessary |
| | 303 | { |
| | 304 | GtkTextIter end; |
| | 305 | gtk_text_buffer_get_end_iter(buffer, &end); |
| | 306 | gtk_source_buffer_ensure_highlight( |
| | 307 | GTK_SOURCE_BUFFER(buffer), |
| | 308 | &begin, |
| | 309 | &end); |
| | 310 | } |
| | 311 | |
| | 312 | while(!gtk_text_iter_is_end(&begin)) |
| | 313 | { |
| | 314 | GSList* current_tags = gtk_text_iter_get_tags(&begin); |
| | 315 | Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> > handle( |
| | 316 | current_tags, Glib::OWNERSHIP_SHALLOW); |
| | 317 | Glib::ustring classes; |
| | 318 | for(GSList* tag = current_tags; tag != 0; tag = tag->next) |
| | 319 | { |
| | 320 | if(!classes.empty()) |
| | 321 | classes += ' '; |
| | 322 | gchar* tag_name = g_strdup_printf( |
| | 323 | "tag_%p", static_cast<void*>(tag->data)); |
| | 324 | classes += tag_name; |
| | 325 | g_free(tag_name); |
| | 326 | tags.insert(GTK_TEXT_TAG(tag->data)); |
| | 327 | } |
| | 328 | |
| | 329 | last_node = last_node->add_child("span"); |
| | 330 | if (!classes.empty()) |
| | 331 | last_node->set_attribute("class", classes); |
| | 332 | |
| 267 | | guint new_id = inf_user_get_id(INF_USER(new_user)); |
| 268 | | if (!user || user != new_user) { |
| 269 | | if (user) |
| 270 | | last_node = last_node->get_parent(); |
| 271 | | |
| 272 | | last_node = last_node->add_child("span"); |
| 273 | | last_node->set_attribute( |
| 274 | | "class", |
| 275 | | Glib::ustring::compose("user_%1", new_id)); |
| 276 | | last_node->set_attribute( |
| 277 | | "title", |
| 278 | | Glib::ustring::compose(_("written by: %1"), |
| 279 | | inf_user_get_name(INF_USER(new_user)))); |
| 280 | | } |
| 281 | | |
| 282 | | user = new_user; |
| 283 | | users.insert(user); |
| 284 | | } else { |
| 285 | | if (user) |
| 286 | | last_node = last_node->get_parent(); |
| 287 | | user = 0; |
| | 336 | last_node->set_attribute( |
| | 337 | "title", |
| | 338 | uprintf(_("written by: %s"), |
| | 339 | inf_user_get_name(INF_USER(new_user)))); |
| | 340 | users.insert(new_user); |
| 309 | | if (user) |
| 310 | | last_node = last_node->get_parent(); |
| 311 | | line_no = last_node->add_child("span"); |
| 312 | | line_no->set_attribute("class", "line_no"); |
| 313 | | line_no->set_attribute( |
| 314 | | "id", |
| 315 | | Glib::ustring::compose("line_%1", line_counter)); |
| 316 | | if (user) { |
| 317 | | last_node = last_node->add_child("span"); |
| 318 | | last_node->set_attribute( |
| 319 | | "class", |
| 320 | | Glib::ustring::compose("user_%1", |
| 321 | | inf_user_get_id(INF_USER(user)))); |
| 322 | | last_node->set_attribute( |
| 323 | | "title", |
| 324 | | Glib::ustring::compose(_("written by: %1"), |
| 325 | | inf_user_get_name(INF_USER(user)))); |
| 326 | | } |
| | 363 | line_no = last_node->add_child("span"); |
| | 364 | line_no->set_attribute("class", "line_no"); |
| | 365 | line_no->set_attribute( |
| | 366 | "id", |
| | 367 | uprintf("line_%d", line_counter)); |
| 361 | | // %1 is information about the document's location, session name, |
| 362 | | // %2 is current date as formatted by %c, |
| 363 | | // %3 is a link to the gobby site |
| 364 | | char const* translated = _("Document generated from %1 at %2 by %3"); |
| 365 | | char const* p = std::strstr(translated, "%3"); |
| | 406 | // %1$s is information about the document's location, session name, |
| | 407 | // %2$s is current date as formatted by %c, |
| | 408 | // %3$s is a link to the gobby site |
| | 409 | char const* translated = |
| | 410 | _("Document generated from %1$s at %2$s by %3$s"); |
| | 411 | char const* p = std::strstr(translated, "%3$s"); |
| 376 | | Glib::ustring::compose(p+2 , session_info, time_str)); |
| 377 | | } |
| 378 | | |
| 379 | | // put author colours into the css, list each author before the actual text |
| 380 | | void add_user_colours(xmlpp::Element* css, |
| 381 | | xmlpp::Element* list, |
| 382 | | const std::set<InfTextUser*>& users) { |
| 383 | | for (std::set<InfTextUser*>::const_iterator i = users.begin(); |
| 384 | | i != users.end(); |
| 385 | | ++i) { |
| 386 | | guint id = inf_user_get_id(INF_USER(*i)); |
| | 422 | uprintf(p+4 , session_info, time_str)); |
| | 423 | } |
| | 424 | |
| | 425 | // list each author before the actual text |
| | 426 | void dump_user_list(xmlpp::Element* list, |
| | 427 | const std::set<InfTextUser*>& users) { |
| | 428 | for(std::set<InfTextUser*>::const_iterator i = users.begin(); |
| | 429 | i != users.end(); |
| | 430 | ++i) |
| | 431 | { |
| 393 | | unsigned int rgb = |
| 394 | | ((c.get_red() & 0xff00) << 8) |
| 395 | | | (c.get_green() & 0xff00) |
| 396 | | | ((c.get_blue() & 0xff00) >> 8); |
| 397 | | |
| 398 | | css->add_child_text(Glib::ustring::compose( |
| 399 | | ".user_%1 {\n" |
| 400 | | " background-color: #%2;\n" |
| 401 | | "}\n", |
| 402 | | id, |
| 403 | | Glib::ustring::format(std::hex, |
| 404 | | std::setw(6), |
| 405 | | std::setfill(L'0'), rgb))); |
| | 438 | const unsigned int rgb = color_to_rgb(c.gobj()); |
| | 439 | |
| | 442 | item->set_attribute( |
| | 443 | "style", |
| | 444 | uprintf("background-color: #%06x;\n", rgb)); |
| | 445 | } |
| | 446 | } |
| | 447 | |
| | 448 | void dump_tags_style(xmlpp::Element* css, |
| | 449 | const priority_tag_set& tags) |
| | 450 | { |
| | 451 | for(priority_tag_set::const_iterator i = tags.begin(); i != tags.end(); ++i) |
| | 452 | { |
| | 453 | GdkColor* fg, * bg; |
| | 454 | gint weight; |
| | 455 | gboolean underline; |
| | 456 | PangoStyle style; |
| | 457 | gboolean fg_set, bg_set, weight_set, underline_set, style_set; |
| | 458 | g_object_get(G_OBJECT(*i), |
| | 459 | "background-gdk", &bg, |
| | 460 | "foreground-gdk", &fg, |
| | 461 | "weight", &weight, |
| | 462 | "underline", &underline, |
| | 463 | "style", &style, |
| | 464 | "background-set", &bg_set, |
| | 465 | "foreground-set", &fg_set, |
| | 466 | "weight-set", &weight_set, |
| | 467 | "underline-set", &underline_set, |
| | 468 | "style-set", &style_set, |
| | 469 | NULL); |
| | 470 | const unsigned int bg_rgb = color_to_rgb(bg); |
| | 471 | const unsigned int fg_rgb = color_to_rgb(fg); |
| | 472 | gdk_color_free(fg); |
| | 473 | gdk_color_free(bg); |
| | 474 | css->add_child_text( |
| | 475 | uprintf(".tag_%p {\n", static_cast<void*>(*i))); |
| | 476 | if(fg_set) |
| | 477 | css->add_child_text(uprintf( |
| | 478 | " color: #%06x;\n", |
| | 479 | fg_rgb)); |
| | 480 | if(bg_set) |
| | 481 | css->add_child_text(uprintf( |
| | 482 | " background-color: #%06x;\n", |
| | 483 | bg_rgb)); |
| | 484 | if(weight_set) |
| | 485 | css->add_child_text(uprintf( |
| | 486 | " font-weight: %d;\n", |
| | 487 | weight)); |
| | 488 | if(underline_set) |
| | 489 | css->add_child_text(uprintf( |
| | 490 | " text-decoration: %s;\n", |
| | 491 | underline ? "underline" : "none")); |
| | 492 | css->add_child_text("}\n"); |