/* Copyright (C) 2001-2002 Kenichi Suto
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "defs.h"
#include "global.h"
#include "xml.h"
#include "link.h"
#include "select.h"
#include "eb.h"
#define IMAGE_TYPE_JPEG 1
#define IMAGE_TYPE_COLOR_BMP 2
#define IMAGE_TYPE_MONO_BMP 3
#define IMAGE_TYPE_GRAY_BMP 4
#ifndef HAVE_WCTYPE_H
static gint iswalpha(GdkWChar c)
{
GdkWChar wc_buff[2];
char *p;
wc_buff[0] = c;
wc_buff[1] = 0x00000000;
p = gdk_wcstombs(wc_buff);
return(isalpha(*p));
}
#endif
static void print_color(GdkGC *gc){
GdkGCValues gcv;
gdk_gc_get_values(gc, &gcv);
// g_print("gcv.foreground = %x\n",gcv.foreground);
g_print("gcv.foreground.pixel = %04x\n",(guint)gcv.foreground.pixel);
g_print("gcv.foreground.red = %04x\n",gcv.foreground.red);
g_print("gcv.foreground.green = %04x\n",gcv.foreground.green);
g_print("gcv.foreground.blue = %04x\n",gcv.foreground.blue);
// g_print("gcv.background = %x\n",gcv.background);
g_print("gcv.background.pixel = %04x\n",(guint)gcv.background.pixel);
g_print("gcv.background.red = %04x\n",gcv.background.red);
g_print("gcv.background.green = %04x\n",gcv.background.green);
g_print("gcv.background.blue = %04x\n",gcv.background.blue);
}
gint calculate_gaiji_size(gint height){
gint size=16;
/*
if(height <= 20)
size = 16;
else if(height <= 27)
size = 24;
else if(height <= 39)
size = 30;
else
size = 48;
*/
if(height < 24)
size = 16;
else if(height < 30)
size = 24;
else if(height < 48)
size = 30;
else
size = 48;
return(size);
}
void load_xbm(BOOK_INFO *binfo, gchar *name, GdkGC *gc, GdkPixmap **pixmap, GdkBitmap **bitmap, gint *w, gint *h){
GtkStyle *style;
gint x, y, width, height, depth;
gint w_width, w_height;
guchar *data = NULL;
GdkGCValues gcv;
GList **gaiji_cache;
GList *gaiji_item;
GAIJI_CACHE *gaiji_p;
gint found=0;
gint char_no;
gint size;
g_assert(gc != NULL);
g_assert(pixmap != NULL);
g_assert(bitmap != NULL);
// g_print("load_xbm %s\n", name);
gdk_gc_get_values(gc, &gcv);
#ifdef OLD_GAIJI
char_no = strtol(&name[1], NULL, 16);
found = 0;
if(name[0] == 'h'){
gaiji_p = binfo->gaiji_narrow;
} else {
gaiji_p = binfo->gaiji_wide;
}
while(gaiji_p != NULL){
if(gaiji_p->code == char_no){
found = 1;
break;
}
gaiji_p = gaiji_p->next;
}
#else
char_no = strtol(&name[1], NULL, 16);
found = 0;
// size = calculate_gaiji_size(font_normal->ascent+font_normal->descent);
size = calculate_gaiji_size(font_height);
size = check_gaiji_size(binfo, size);
if(name[0] == 'h'){
switch(size){
case 16:
gaiji_cache = &(binfo->gaiji_narrow16);
break;
case 24:
gaiji_cache = &(binfo->gaiji_narrow24);
break;
case 30:
gaiji_cache = &(binfo->gaiji_narrow30);
break;
case 48:
gaiji_cache = &(binfo->gaiji_narrow48);
break;
}
} else {
switch(size){
case 16:
gaiji_cache = &(binfo->gaiji_wide16);
break;
case 24:
gaiji_cache = &(binfo->gaiji_wide24);
break;
case 30:
gaiji_cache = &(binfo->gaiji_wide30);
break;
case 48:
gaiji_cache = &(binfo->gaiji_wide48);
break;
}
}
gaiji_item = g_list_first(*gaiji_cache);
while(gaiji_item != NULL){
gaiji_p = gaiji_item->data;
if(gaiji_p->code == char_no){
found = 1;
break;
}
gaiji_item = g_list_next(gaiji_item);
}
#endif
if(found){
*pixmap = NULL;
data = gaiji_p->data;
width = gaiji_p->width;
height = gaiji_p->height;
style = gtk_widget_get_style(window);
gdk_window_get_geometry (window->window, &x, &y, &w_width, &w_height, &depth);
*pixmap = gdk_pixmap_create_from_data (window->window,
data,
width, height,
depth,
&gcv.foreground,
&gcv.background);
*bitmap = NULL;
*bitmap = gdk_bitmap_create_from_data (window->window,
data,
width,
height);
} else {
*pixmap = NULL;
// XReadBitmapFileData(filename, &width, &height, &data, &x_hot, &y_hot);
data = read_gaiji_as_bitmap(binfo, name, size, &width, &height);
if(data == NULL){
fprintf(stderr, "failed to read gaiji : %s\n", name);
return;
}
style = gtk_widget_get_style(window);
gdk_window_get_geometry (window->window, &x, &y, &w_width, &w_height, &depth);
*pixmap = gdk_pixmap_create_from_data (window->window,
data,
width, height,
depth,
&gcv.foreground,
&gcv.background);
*bitmap = NULL;
*bitmap = gdk_bitmap_create_from_data (window->window,
data,
width,
height);
gaiji_p = (GAIJI_CACHE *)calloc(sizeof(GAIJI_CACHE), 1);
if(gaiji_p == NULL){
fprintf(stderr, "No memory\n");
exit(1);
}
gaiji_p->code = char_no;
gaiji_p->data = data;
gaiji_p->width = width;
gaiji_p->height = height;
*gaiji_cache = g_list_append(*gaiji_cache, gaiji_p);
}
*w = width;
*h = height;
return;
}
static void draw_string(CANVAS *canvas, DRAW_TEXT *text, LINK *link)
{
GdkWChar *wc_buff;
GdkWChar *wc_p;
GdkWChar wc;
GdkWChar *word_p;
GdkFont *font;
gint length;
gint width;
gint word_w;
gint wc_buff_size;
gint i;
gint x,y;
gint save_x, save_y;
char *char_p;
g_assert(canvas != NULL);
g_assert(text != NULL);
#if 0
{
gchar *t;
t = g_strndup(text->text, text->length);
g_print("draw_string %s\n", t);
free(t);
}
#endif
x = canvas->x;
y = canvas->y;
if((link != NULL) && (link->type & LINK_TYPE_EMPHASIS)){
font = font_bold;
} else if((link != NULL) && (link->type & LINK_TYPE_ITALIC)){
font = font_italic;
} else if((link != NULL) && (link->type & LINK_TYPE_SUBSCRIPT)){
font = font_superscript;
} else if((link != NULL) && (link->type & LINK_TYPE_SUPERSCRIPT)){
font = font_superscript;
} else {
font = font_normal;
}
wc_buff_size = text->length * sizeof(GdkWChar)+1;
wc_buff = malloc(wc_buff_size);
length = gdk_mbstowcs(wc_buff, text->text, wc_buff_size - 1);
wc_p = wc_buff;
if((link != NULL) && (link->type & LINK_TYPE_CENTER)){
gint w=0;
for(i=0;i<length;i++){
w += gdk_text_width_wc(font, wc_p, 1);
wc_p ++;
}
if(w < (canvas->width - h_border * 2)){
x = h_border + ((canvas->width - h_border * 2) - w) / 2;
}
wc_p = wc_buff;
}
for(i=0;i<length;i++){
// 改行
if(*wc_p == '\n'){
x = h_border + canvas->indent * font_width;
// x = h_border;
y = y + canvas->line_height + v_space;
canvas->line_height = font_height;
wc_p ++;
continue;
}
// キャンバスのサイズを超えるようなら改行する
width = gdk_text_width_wc(font, wc_p, 1);
if((x + width + h_border) > canvas->width) {
x = h_border + canvas->indent * font_width;
// x = h_border;
y = y + canvas->line_height + v_space;
canvas->line_height = font_height;
}
// 英単語の途中で改行されないようにする
char_p = (char *)wc_p;
if(isalpha(*char_p)){
word_p = wc_p;
word_w = 0;
while(1){
char_p = (char *)word_p;
if(!isalpha(*char_p))
break;
word_w += gdk_text_width_wc(font, word_p, 1);
word_p ++;
}
if((x + word_w + h_border) > canvas->width) {
// x = h_border;
x = h_border + canvas->indent * font_width;
y = y + canvas->line_height + v_space;
}
}
if(canvas->pixmap != NULL){
if((link != NULL) && (link->type & LINK_TYPE_SUPERSCRIPT)){
gdk_draw_text_wc(canvas->pixmap,
font,
canvas->gc,
x, y-6, wc_p, 1);
} else {
gdk_draw_text_wc(canvas->pixmap,
font,
canvas->gc,
x, y, wc_p, 1);
}
wc = *wc_p;
if(canvas->content_area)
add_location_char(canvas->content_area, wc,
x,
y - font_ascent,
width+h_space, font_height,
font, link);
if((link != NULL) && (canvas->content_area != NULL) &&
((link->type & LINK_TYPE_JUMP) ||
(link->type & LINK_TYPE_WAVE) ||
(link->type & LINK_TYPE_MPEG))){
save_x = x;
save_y = y - font_ascent;
x = x + width + h_space;
link->start_x = save_x;
link->start_y = save_y;
link->end_x = x - 1;
link->end_y = y + font_descent;
set_link(canvas->content_area, link);
} else {
x = x + width + h_space;
}
} else {
x = x + width + h_space;
}
wc_p ++;
}
canvas->x = x;
canvas->y = y;
}
static void draw_gaiji(CANVAS *canvas, BOOK_INFO *binfo, LINK *link, gchar *code)
{
gint width;
gint height;
GdkPixmap *gaiji_pixmap = NULL;
GdkBitmap *mask;
gint x, y, yy;
gint save_x, save_y;
g_assert(canvas != NULL);
g_assert(binfo != NULL);
g_assert(code != NULL);
x = canvas->x;
y = canvas->y;
/*
if(code[0] == 'h'){
width = font_height / 2;
} else {
width = font_height;
}
*/
load_xbm(binfo, code, canvas->gc, &gaiji_pixmap, &mask, &width, &height);
if((x + width + h_border) > canvas->width){
x = h_border + canvas->indent * font_width;
// x = h_border;
y = y + canvas->line_height + v_space;
// canvas->line_height = font_height;
canvas->line_height = height;
}
/*
if(height > font_ascent)
yy = y - font_ascent;
else
*/
yy = y + font_descent - height;
if(canvas->pixmap != NULL){
gdk_draw_pixmap(canvas->pixmap,
canvas->gc,
gaiji_pixmap,
0,0,
x,
//y - font_ascent,
yy,
width,
height);
if(gaiji_pixmap != NULL)
gdk_pixmap_unref(gaiji_pixmap);
if(mask != NULL)
gdk_bitmap_unref(mask);
if(canvas->content_area)
add_location_gaiji(canvas->content_area, code,
x,
yy,
// y - font_ascent,
// x, y - height + 2,
// width, font_height, link);
width, height, link);
if((link != NULL) &&
((link->type & LINK_TYPE_JUMP) ||
(link->type & LINK_TYPE_WAVE))){
save_x = x;
// save_y = y - font_ascent;
save_y = yy;
x = x + width + h_space;
// set_link(save_x, save_y, x-1, y, page, offset);
link->start_x = save_x;
link->start_y = save_y;
link->end_x = x - 1;
link->end_y = save_y + height;
if(canvas->content_area != NULL)
set_link(canvas->content_area, link);
} else {
x = x + width + h_space;
}
} else {
x = x + width + h_space;
}
canvas->x = x;
canvas->y = y;
}
// imlibがキャッシュしているようなので、ファイル名を変える。
// キャッシュは有限? でないとリークする。
static int image_count=0;
static void draw_graphic(CANVAS *canvas, BOOK_INFO *binfo, gint type, gint page, gint offset, gint width, gint height)
{
char filename[512];
GdkPixmap *image=NULL;
GdkBitmap *mask=NULL;
GdkWindowPrivate *private;
gint x, y;
gint l_width, l_height;
EB_Error_Code error_code=EB_SUCCESS;
g_assert(canvas != NULL);
g_assert(binfo != NULL);
x = canvas->x;
y = canvas->y;
// いったんファイルに落とす
sprintf(filename, "%s/%d-%d.img", tmp_dir, getpid(), image_count);
image_count++;
switch(type){
case IMAGE_TYPE_COLOR_BMP:
case IMAGE_TYPE_JPEG:
error_code = ebook_output_color(binfo, filename, page, offset);
break;
case IMAGE_TYPE_MONO_BMP:
error_code = ebook_output_mono(binfo, filename, page, offset, width, height);
break;
case IMAGE_TYPE_GRAY_BMP:
error_code = ebook_output_gray(binfo, filename, page, offset, width, height);
break;
}
if(error_code != EB_SUCCESS){
return;
}
gdk_imlib_load_file_to_pixmap(filename, &image, &mask);
g_assert(image != NULL);
// g_assert(mask != NULL);
gdk_pixmap_ref(image);
// 改行したほうが見やすい?
x = h_border;
y = y + canvas->line_height + v_space;
private = (GdkWindowPrivate *)image;
l_width = private->width;
l_height = private->height;
if(canvas->pixmap != NULL){
gdk_draw_pixmap(canvas->pixmap,
canvas->gc,
image,
0,0,
x, (y - font_height),
l_width,
l_height);
}
gdk_imlib_free_pixmap(image);
if((image != NULL) && (private->ref_count > 0))
gdk_pixmap_unref(image);
// gdk_bitmap_unref(mask);
// unlink(filename);
// x = h_border;
// x = h_border + canvas->indent * font_width;
x = x + l_width;
// y = y + l_height;
if(canvas->line_height < l_height)
canvas->line_height = l_height;
if(x > canvas->max_width)
canvas->max_width = x;
canvas->x = x;
canvas->y = y;
return;
}
void draw_content(CANVAS *canvas, DRAW_TEXT *text, BOOK_INFO *binfo, LINK *link){
gchar *p;
gchar start_tag[512];
gchar end_tag[512];
gchar tag_name[512];
gchar attr[512];
gchar code[16];
gchar body[65536];
gchar *content;
gint content_length;
gint body_length;
gint l_page=0, l_offset=0, l_size=0;
gint l_width, l_height;
gint l_indent;
LINK l_link;
DRAW_TEXT l_text;
GdkColor color_save;
GdkGCValues gcv;
g_assert(canvas != NULL);
g_assert(text != NULL);
g_assert(text->text != NULL);
l_link.type=0;
l_link.page=0;
l_link.offset=0;
l_link.size=0;
body_length = 0;
p = text->text;
if(text->length >= 65536){
g_print("Text too long. Truncated to 65535 bytes. (Original %d bytes)\n", text->length);
text->length = 65535;
text->text[65535] = '\0';
}
#if 0
{
gchar *tmp;
tmp = g_strndup(text->text, text->length);
g_print("text(length = %d) = \n%s\n\n", text->length, tmp);
free(tmp);
}
#endif
while((p - text->text) < text->length){
if(*p == '<'){
if(body_length != 0){
l_text.text = body;
l_text.length = body_length;
draw_string(canvas, &l_text, link);
body_length = 0;
}
get_start_tag(p, start_tag);
get_tag_name(start_tag, tag_name);
if((strcmp(tag_name, "reference") == 0) ||
(strcmp(tag_name, "candidate") == 0)){
get_end_tag(p, tag_name, end_tag);
get_attr(end_tag, "page", attr);
l_page = strtol(attr, NULL, 16);
get_attr(end_tag, "offset", attr);
l_offset = strtol(attr, NULL, 16);
get_content(p, tag_name, &content, &content_length);
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_JUMP | link->type;
} else {
l_link.type = LINK_TYPE_JUMP;
}
l_link.page = l_page;
l_link.offset = l_offset;
if(canvas->pixmap != NULL){
gdk_gc_get_values(canvas->gc, &gcv);
color_save = gcv.foreground;
gdk_gc_set_foreground(canvas->gc,
&colors[COLOR_BLUE]);
}
l_text.text = content;
l_text.length = content_length;
draw_content(canvas, &l_text, binfo, &l_link);
if(canvas->pixmap != NULL){
gdk_gc_set_foreground(canvas->gc, &color_save);
}
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "keyword") == 0){
get_content(p, tag_name, &content, &content_length);
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_KEYWORD | link->type;
} else {
l_link.type = LINK_TYPE_KEYWORD;
}
if(canvas->pixmap != NULL){
gdk_gc_get_values(canvas->gc, &gcv);
color_save = gcv.foreground;
gdk_gc_set_foreground(canvas->gc,
&colors[COLOR_BROWN]);
}
l_text.text = content;
l_text.length = content_length;
draw_content(canvas, &l_text, binfo, &l_link);
if(canvas->pixmap != NULL){
gdk_gc_set_foreground(canvas->gc, &color_save);
}
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "modification") == 0){
get_content(p, tag_name, &content, &content_length);
get_attr(start_tag, "method", attr);
if(link) {
l_link = *link;
if(attr[0] == '3')
l_link.type = LINK_TYPE_EMPHASIS | link->type;
else
l_link.type = LINK_TYPE_ITALIC | link->type;
} else {
if(attr[0] == '3')
l_link.type = LINK_TYPE_EMPHASIS;
else
l_link.type = LINK_TYPE_ITALIC;
}
l_text.text = content;
l_text.length = content_length;
draw_content(canvas, &l_text, binfo, &l_link);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "gaiji") == 0){
get_attr(start_tag, "code", code);
draw_gaiji(canvas, binfo, link, code);
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "indent") == 0){
get_attr(start_tag, "position", attr);
l_indent = strtol(attr, NULL, 10);
// インデントの引数は位置?
// 改行したばかり、または、文字が重ならないなら
// 指定位置にセット
if((canvas->x == h_border + canvas->indent * font_width) ||
(canvas->x < h_border + l_indent * font_width))
canvas->x = h_border + l_indent * font_width;
canvas->indent = l_indent;
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "emphasis") == 0){
get_content(p, tag_name, &content, &content_length);
l_text = *text;
l_text.text = content;
l_text.length = content_length;
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_EMPHASIS | link->type;
} else {
l_link.type = LINK_TYPE_EMPHASIS;
}
draw_content(canvas, &l_text, binfo, &l_link);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "subscript") == 0){
get_content(p, tag_name, &content, &content_length);
l_text = *text;
l_text.text = content;
l_text.length = content_length;
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_SUBSCRIPT | link->type;
} else {
l_link.type = LINK_TYPE_SUBSCRIPT;
}
draw_content(canvas, &l_text, binfo, &l_link);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "superscript") == 0){
get_content(p, tag_name, &content, &content_length);
l_text = *text;
l_text.text = content;
l_text.length = content_length;
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_SUPERSCRIPT | link->type;
} else {
l_link.type = LINK_TYPE_SUPERSCRIPT;
}
draw_content(canvas, &l_text, binfo, &l_link);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "center") == 0){
get_content(p, tag_name, &content, &content_length);
l_text = *text;
l_text.text = content;
l_text.length = content_length;
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_CENTER | link->type;
} else {
l_link.type = LINK_TYPE_CENTER;
}
draw_content(canvas, &l_text, binfo, &l_link);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "nonewline") == 0){
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "/nonewline") == 0){
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "narrow") == 0){
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "/narrow") == 0){
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "jpeg") == 0){
get_attr(start_tag, "page", attr);
l_page = strtol(attr, NULL, 16);
get_attr(p, "offset", attr);
l_offset = strtol(attr, NULL, 16);
draw_graphic(canvas, binfo, IMAGE_TYPE_JPEG, l_page, l_offset, 0, 0);
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "bmp") == 0){
get_attr(start_tag, "page", attr);
l_page = strtol(attr, NULL, 16);
get_attr(p, "offset", attr);
l_offset = strtol(attr, NULL, 16);
draw_graphic(canvas, binfo, IMAGE_TYPE_COLOR_BMP, l_page, l_offset, 0, 0);
skip_start_tag(&p, tag_name);
} else if(strcmp(tag_name, "mono") == 0){
get_attr(start_tag, "width", attr);
l_width = strtol(attr, NULL, 10);
get_attr(start_tag, "height", attr);
l_height = strtol(attr, NULL, 10);
get_end_tag(p, tag_name, end_tag);
get_attr(end_tag, "page", attr);
l_page = strtol(attr, NULL, 16);
get_attr(end_tag, "offset", attr);
l_offset = strtol(attr, NULL, 16);
draw_graphic(canvas, binfo, IMAGE_TYPE_MONO_BMP, l_page, l_offset, l_width, l_height);
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "wave") == 0){
get_end_tag(p, tag_name, end_tag);
get_attr(end_tag, "page", attr);
l_page = strtol(attr, NULL, 16);
get_attr(end_tag, "offset", attr);
l_offset = strtol(attr, NULL, 16);
get_attr(end_tag, "size", attr);
l_size = strtol(attr, NULL, 10);
get_content(p, tag_name, &content, &content_length);
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_WAVE | link->type;
} else {
l_link.type = LINK_TYPE_WAVE;
}
l_link.page = l_page;
l_link.offset = l_offset;
l_link.size = l_size;
if(canvas->pixmap != NULL){
gdk_gc_get_values(canvas->gc, &gcv);
color_save = gcv.foreground;
gdk_gc_set_foreground(canvas->gc,
&colors[COLOR_GREEN]);
}
l_text.text = content;
l_text.length = content_length;
draw_content(canvas, &l_text, binfo, &l_link);
if(canvas->pixmap != NULL){
gdk_gc_set_foreground(canvas->gc, &color_save);
}
skip_end_tag(&p, tag_name);
} else if(strcmp(tag_name, "mpeg") == 0){
get_attr(start_tag, "filename", attr);
// get_content(p, tag_name, &content, &content_length);
if(link) {
l_link = *link;
l_link.type = LINK_TYPE_MPEG | link->type;
} else {
l_link.type = LINK_TYPE_MPEG;
}
l_link.page = l_page;
l_link.offset = l_offset;
l_link.size = l_size;
sprintf(l_link.filename, "%s", attr);
if(canvas->pixmap != NULL){
gdk_gc_get_values(canvas->gc, &gcv);
color_save = gcv.foreground;
gdk_gc_set_foreground(canvas->gc,
&colors[COLOR_GREEN]);
}
l_text.text = _(" [Movie] ");
l_text.length = strlen(l_text.text);
draw_content(canvas, &l_text, binfo, &l_link);
if(canvas->pixmap != NULL){
gdk_gc_set_foreground(canvas->gc, &color_save);
}
skip_start_tag(&p, tag_name);
} else {
// fprintf(stderr, "warning: unknown tag <%s> found. Treated as plain text\n", tag_name);
body[body_length] = *p;
body_length ++;
body[body_length] = '\0';
p++;
}
} else {
body[body_length] = *p;
body_length ++;
body[body_length] = '\0';
p++;
}
}
if(body_length != 0){
l_text.text = body;
l_text.length = body_length;
draw_string(canvas, &l_text, link);
}
}
syntax highlighted by Code2HTML, v. 0.9.1