Changeset 3adef45a9e5b72edb4099a59e2a3e00f544ef7e0

Show
Ignore:
Timestamp:
10/25/09 14:24:52 (4 years ago)
Author:
Benjamin Herr <ben@…>
git-author:
Benjamin Herr <ben@0x539.de> / 2009-10-25T14:24:03Z+0100
Parents:
d96f21af85f2fb0eeb992b52e58b03c317bf0a49
Children:
e275a84b1e164b543ad6bc2d139b84410e06693b
git-committer:
Benjamin Herr <ben@0x539.de> / 2009-10-25T14:24:52Z+0100
Message:

htmlexport: added syntax highlighting

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • code/commands/file-commands.cpp

    rd96f21a r3adef45  
    234234#include "util/i18n.hpp" 
    235235 
     236struct 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 
     246typedef 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 
     251Glib::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 
     271unsigned int color_to_rgb(GdkColor* color) 
     272{ 
     273        return ((color->red   & 0xff00) << 8) 
     274             |  (color->green & 0xff00) 
     275             | ((color->blue  & 0xff00) >> 8); 
     276} 
     277 
    236278// write the Gtk::TextBuffer from document into content, inserting <span/>s for 
    237279// line breaks and authorship of chunks of text, also save all users 
     
    240282                 xmlpp::Element* content, 
    241283                 std::set<InfTextUser*>& users, 
    242                  unsigned int& line_counter) { 
    243   using namespace Gobby; 
    244   users.clear(); 
    245   line_counter = 1; 
     284                 priority_tag_set& tags, 
     285                 unsigned int& line_counter) 
     286{ 
     287        using namespace Gobby; 
     288        users.clear(); 
     289        tags.clear(); 
     290        line_counter = 1; 
    246291        xmlpp::Element* last_node = content; 
    247292        xmlpp::Element* line_no = last_node->add_child("span"); 
     
    252297        InfTextGtkBuffer* inf_buffer 
    253298                = INF_TEXT_GTK_BUFFER( 
    254                                 inf_session_get_buffer(INF_SESSION(document.get_session()))); 
    255  
    256         InfTextUser* user = 0; 
     299                        inf_session_get_buffer(INF_SESSION(document.get_session()))); 
    257300 
    258301        GtkTextIter begin; 
    259302        gtk_text_buffer_get_start_iter(buffer, &begin); 
    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 
    263333                InfTextUser* new_user 
    264334                        = inf_text_gtk_buffer_get_author(inf_buffer, &begin); 
    265  
    266335                if (new_user) { 
    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); 
    288341                } 
    289342 
     
    293346                // split text by newlines so we can insert line number elements 
    294347                gchar* text = gtk_text_iter_get_text(&begin, &next); 
    295                 try { 
     348                try 
     349                { 
    296350                        gchar const* last_pos = text; 
    297                         for (gchar const* i = text; *i; ++i) { 
     351                        for (gchar const* i = last_pos; *i; ++i) { 
    298352                                if (*i != '\n') 
    299353                                        continue; 
     
    307361 
    308362                                // drop author <span/> for a moment for the line number <span/> 
    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)); 
    327368                        } 
     369 
    328370                        last_node->add_child_text(Glib::ustring(last_pos)); 
    329                 } catch (...) { 
     371                } 
     372                catch(...) 
     373                { 
    330374                        g_free(text); 
    331375                        throw; 
    332376                } 
    333377                g_free(text); 
     378                last_node = last_node->get_parent(); 
    334379 
    335380                begin = next; 
     
    359404        char session_info[] = "<placeholder for session info and path>"; 
    360405 
    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"); 
    366412        g_assert(p); 
    367413        node->add_child_text( 
    368                 Glib::ustring::compose(Glib::ustring(translated, p), session_info, time_str)); 
     414                uprintf(Glib::ustring(translated, p).c_str(), session_info, time_str)); 
    369415 
    370416        xmlpp::Element* link = node->add_child("a"); 
     
    372418        link->add_child_text(PACKAGE_STRING); 
    373419 
    374         if (*p != 0) 
     420        if (*p != '\0') 
    375421                node->add_child_text( 
    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 
     426void 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        { 
    387432                gdouble hue = inf_text_user_get_hue(*i); 
    388433                hue = std::fmod(hue, 1); 
     
    391436                c.set_hsv(360.0 * hue, 0.35, 1.0); 
    392437                gchar const* name = inf_user_get_name(INF_USER(*i)); 
    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 
    406440                xmlpp::Element* item = list->add_child("li"); 
    407                 item->set_attribute("class", Glib::ustring::compose("user_%1", id)); 
    408441                item->add_child_text(name); 
     442                item->set_attribute( 
     443                        "style", 
     444                        uprintf("background-color: #%06x;\n", rgb)); 
     445        } 
     446} 
     447 
     448void 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"); 
    409493        } 
    410494} 
     
    440524 
    441525        std::set<InfTextUser*> users; 
     526        priority_tag_set tags; 
    442527        unsigned int line_counter; 
    443         dump_buffer(document, content, users, line_counter); 
     528        dump_buffer(document, content, users, tags, line_counter); 
    444529 
    445530        h2->add_child_text(_("Participants")); 
     
    449534 
    450535        style->set_attribute("type", "text/css"); 
    451         add_user_colours(style, user_list, users); 
     536        dump_user_list(user_list, users); 
     537        dump_tags_style(style, tags); 
    452538        if (!user_list->cobj()->children) { 
    453539                body->remove_child(h2); 
     
    474560 
    475561        style->add_child_text( 
    476                 Glib::ustring::compose( 
     562                uprintf( 
    477563                        ".line_no {\n" 
    478564                        "  position:               absolute;\n" 
    479565                        "  float:                  left;\n" 
    480566                        "  clear:                  left;\n" 
    481                         "  margin-left:            -%1em;\n" 
     567                        "  margin-left:            -%1$uem;\n" 
    482568                        "  color:                  gray;\n" 
    483569                        "}\n" 
    484570                        ".document {\n" 
    485                         "  padding-left:            %1em\n" 
     571                        "  padding-left:            %1$uem\n" 
    486572                        "}\n", 
    487573          static_cast<unsigned int>(std::log(line_counter)/std::log(10))+1));