You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
994 lines
21 KiB
994 lines
21 KiB
/* |
|
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors |
|
* Copyright (C) 2007-2022 Kim Woelders |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
* of this software and associated documentation files (the "Software"), to |
|
* deal in the Software without restriction, including without limitation the |
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|
* sell copies of the Software, and to permit persons to whom the Software is |
|
* furnished to do so, subject to the following conditions: |
|
* |
|
* The above copyright notice and this permission notice shall be included in |
|
* all copies of the Software, its documentation and marketing & publicity |
|
* materials, and acknowledgment shall be given in the documentation, materials |
|
* and software packages that this Software was used. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
*/ |
|
#include "config.h" |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include "dox.h" |
|
|
|
#define DEFAULT_LINKCOLOR_R 30 |
|
#define DEFAULT_LINKCOLOR_G 50 |
|
#define DEFAULT_LINKCOLOR_B 160 |
|
|
|
typedef enum _type { |
|
IMG, |
|
BR, |
|
FONT, |
|
P, |
|
TEXT, |
|
PAGE |
|
} Type; |
|
|
|
typedef struct _img { |
|
char *src; |
|
char *src2; |
|
char *src3; |
|
int x, y; |
|
char *link; |
|
int w, h; |
|
} Img_; |
|
|
|
typedef struct _font { |
|
char *face; |
|
int r, g, b; |
|
} Font_; |
|
|
|
typedef struct _p { |
|
float align; |
|
} P_; |
|
|
|
typedef struct _object { |
|
Type type; |
|
void *object; |
|
} Object; |
|
|
|
typedef struct _page { |
|
char *name; |
|
int count; |
|
Object *obj; |
|
int columns; |
|
int padding; |
|
int linkr, linkg, linkb; |
|
char *background; |
|
} Page; |
|
|
|
static int num_pages = 0; |
|
static Page *page = NULL; |
|
static char *fdat_ptr = NULL; |
|
static int fdat_size = 0; |
|
static char *fdat = NULL; |
|
|
|
static int |
|
fdgetc(void) |
|
{ |
|
int val; |
|
|
|
if (fdat_ptr >= (fdat + fdat_size)) |
|
return EOF; |
|
val = (int)(*fdat_ptr); |
|
fdat_ptr++; |
|
return val; |
|
} |
|
|
|
static void |
|
fdjump(int count) |
|
{ |
|
fdat_ptr += count; |
|
if (fdat_ptr < fdat) |
|
fdat_ptr = fdat; |
|
if (fdat_ptr >= (fdat + fdat_size)) |
|
fdat_ptr = (fdat + fdat_size) - 1; |
|
} |
|
|
|
static void |
|
AddPage(Object * obj) |
|
{ |
|
num_pages++; |
|
page = EREALLOC(Page, page, num_pages); |
|
page[num_pages - 1].name = NULL; |
|
page[num_pages - 1].count = 0; |
|
page[num_pages - 1].obj = NULL; |
|
page[num_pages - 1].columns = 1; |
|
page[num_pages - 1].background = NULL; |
|
page[num_pages - 1].padding = 2; |
|
page[num_pages - 1].linkr = DEFAULT_LINKCOLOR_R; |
|
page[num_pages - 1].linkg = DEFAULT_LINKCOLOR_G; |
|
page[num_pages - 1].linkb = DEFAULT_LINKCOLOR_B; |
|
|
|
if ((obj) && (obj->type == PAGE) && (obj->object)) |
|
{ |
|
Page *pg; |
|
|
|
pg = (Page *) (obj->object); |
|
if (pg->name) |
|
page[num_pages - 1].name = pg->name; |
|
page[num_pages - 1].columns = pg->columns; |
|
page[num_pages - 1].padding = pg->padding; |
|
page[num_pages - 1].linkr = pg->linkr; |
|
page[num_pages - 1].linkg = pg->linkg; |
|
page[num_pages - 1].linkb = pg->linkb; |
|
if (pg->background) |
|
page[num_pages - 1].background = pg->background; |
|
} |
|
} |
|
|
|
static void |
|
AddObject(Object * obj) |
|
{ |
|
page[num_pages - 1].count++; |
|
page[num_pages - 1].obj = |
|
EREALLOC(Object, page[num_pages - 1].obj, page[num_pages - 1].count); |
|
page[num_pages - 1].obj[page[num_pages - 1].count - 1].type = obj->type; |
|
page[num_pages - 1].obj[page[num_pages - 1].count - 1].object = obj->object; |
|
} |
|
|
|
static void |
|
BuildObj(Object * obj, char *var, char *param) |
|
{ |
|
static Page *pg = NULL; |
|
static P_ *p = NULL; |
|
static Font_ *fn = NULL; |
|
static Img_ *img = NULL; |
|
|
|
switch (obj->type) |
|
{ |
|
case IMG: |
|
img = (Img_ *) obj->object; |
|
if (!img) |
|
{ |
|
img = EMALLOC(Img_, 1); |
|
obj->object = img; |
|
img->src = NULL; |
|
img->src2 = NULL; |
|
img->src3 = NULL; |
|
img->x = 0; |
|
img->y = 0; |
|
img->link = NULL; |
|
img->w = 0; |
|
img->h = 0; |
|
} |
|
if (!strcmp(var, "x")) |
|
img->x = atoi(param); |
|
else if (!strcmp(var, "y")) |
|
img->y = atoi(param); |
|
else if (!strcmp(var, "src")) |
|
img->src = strdup(param); |
|
else if (!strcmp(var, "src2")) |
|
img->src2 = strdup(param); |
|
else if (!strcmp(var, "src3")) |
|
img->src3 = strdup(param); |
|
else if (!strcmp(var, "href")) |
|
img->link = strdup(param); |
|
break; |
|
case BR: |
|
break; |
|
case FONT: |
|
fn = (Font_ *) obj->object; |
|
if (!fn) |
|
{ |
|
fn = EMALLOC(Font_, 1); |
|
obj->object = fn; |
|
fn->face = NULL; |
|
fn->r = 0; |
|
fn->g = 0; |
|
fn->b = 0; |
|
} |
|
if (!strcmp(var, "face")) |
|
fn->face = strdup(param); |
|
else if (!strcmp(var, "color")) |
|
{ |
|
char hex[3] = "00"; |
|
|
|
if (param[0] == '#') |
|
{ |
|
hex[0] = param[1]; |
|
hex[1] = param[2]; |
|
sscanf(hex, "%x", &(fn->r)); |
|
hex[0] = param[3]; |
|
hex[1] = param[4]; |
|
sscanf(hex, "%x", &(fn->g)); |
|
hex[0] = param[5]; |
|
hex[1] = param[6]; |
|
sscanf(hex, "%x", &(fn->b)); |
|
} |
|
} |
|
break; |
|
case P: |
|
p = (P_ *) obj->object; |
|
if (!p) |
|
{ |
|
p = EMALLOC(P_, 1); |
|
obj->object = p; |
|
p->align = 0; |
|
} |
|
if (!strcmp(var, "align")) |
|
{ |
|
if ((strlen(param) > 0) && (param[strlen(param) - 1] == '%')) |
|
param[strlen(param) - 1] = 0; |
|
p->align = atof(param); |
|
} |
|
break; |
|
case TEXT: |
|
break; |
|
case PAGE: |
|
pg = (Page *) obj->object; |
|
if (!pg) |
|
{ |
|
pg = EMALLOC(Page, 1); |
|
obj->object = pg; |
|
pg->columns = 1; |
|
pg->padding = 1; |
|
pg->name = NULL; |
|
pg->background = NULL; |
|
pg->linkr = DEFAULT_LINKCOLOR_R; |
|
pg->linkg = DEFAULT_LINKCOLOR_G; |
|
pg->linkb = DEFAULT_LINKCOLOR_B; |
|
} |
|
if (!strcmp(var, "columns")) |
|
pg->columns = atoi(param); |
|
else if (!strcmp(var, "padding")) |
|
pg->padding = atoi(param); |
|
else if (!strcmp(var, "name")) |
|
pg->name = strdup(param); |
|
else if (!strcmp(var, "background")) |
|
pg->background = strdup(param); |
|
else if (!strcmp(var, "linkcolor")) |
|
{ |
|
char hex[3] = "00"; |
|
|
|
if (param[0] == '#') |
|
{ |
|
hex[0] = param[1]; |
|
hex[1] = param[2]; |
|
sscanf(hex, "%x", &(pg->linkr)); |
|
hex[0] = param[3]; |
|
hex[1] = param[4]; |
|
sscanf(hex, "%x", &(pg->linkg)); |
|
hex[0] = param[5]; |
|
hex[1] = param[6]; |
|
sscanf(hex, "%x", &(pg->linkb)); |
|
} |
|
} |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
static int |
|
GetNextTag(Object * obj) |
|
{ |
|
char s[65536]; |
|
int i = 0, wd = 0; |
|
int val; |
|
char intag = 0; |
|
char havobj = 0; |
|
|
|
for (;;) |
|
{ |
|
val = fdgetc(); |
|
if (val == EOF) |
|
return 0; |
|
if (intag) |
|
{ |
|
if (val == '>') |
|
intag = 0; |
|
s[i++] = (char)val; |
|
if (s[i - 1] == '\n') |
|
s[i - 1] = ' '; |
|
if (s[i - 1] == '>') |
|
s[i - 1] = ' '; |
|
if (s[i - 1] == ' ') |
|
{ |
|
if (i == 1) |
|
i = 0; |
|
else |
|
{ |
|
s[i - 1] = 0; |
|
if (!havobj) |
|
{ |
|
if (wd == 0) |
|
{ |
|
if (!strcmp(s, "page")) |
|
obj->type = PAGE; |
|
else if (!strcmp(s, "img")) |
|
obj->type = IMG; |
|
else if (!strcmp(s, "br")) |
|
obj->type = BR; |
|
else if (!strcmp(s, "font")) |
|
obj->type = FONT; |
|
else if (!strcmp(s, "p")) |
|
obj->type = P; |
|
havobj = 1; |
|
} |
|
i = 0; |
|
} |
|
else |
|
{ |
|
char w1[1024]; |
|
char w2[1024]; |
|
int j = 0; |
|
|
|
w1[0] = 0; |
|
w2[0] = 0; |
|
while ((s[j]) && (s[j] != '=')) |
|
{ |
|
w1[j] = s[j]; |
|
j++; |
|
} |
|
w1[j] = 0; |
|
if (j < (int)strlen(s)) |
|
strcpy(w2, &(s[j + 1])); |
|
BuildObj(obj, w1, w2); |
|
i = 0; |
|
} |
|
wd++; |
|
} |
|
} |
|
if (!intag) |
|
return 1; |
|
} |
|
if (val == '<') |
|
intag = 1; |
|
} |
|
return 1; |
|
} |
|
|
|
static char * |
|
GetTextUntilTag(void) |
|
{ |
|
char s[65536]; |
|
int i = 0; |
|
int val; |
|
|
|
for (;;) |
|
{ |
|
val = fdgetc(); |
|
if (val == EOF) |
|
{ |
|
s[i] = 0; |
|
if (strlen(s) < 1) |
|
return NULL; |
|
return strdup(s); |
|
} |
|
s[i++] = (char)val; |
|
if (s[i - 1] == '\n') |
|
s[i - 1] = ' '; |
|
if ((i == 1) && (s[0] == ' ')) |
|
i--; |
|
else if (s[i - 1] == '<') |
|
{ |
|
s[i - 1] = 0; |
|
fdjump(-1); |
|
if (strlen(s) < 1) |
|
return NULL; |
|
return strdup(s); |
|
} |
|
if ((i > 2) && (s[i - 2] == ' ') && (s[i - 1] == ' ')) |
|
i--; |
|
if (i > 65530) |
|
return NULL; |
|
} |
|
return NULL; |
|
} |
|
|
|
void |
|
GetObjects(FILE * f) |
|
{ |
|
static char have_font = 0; |
|
static char in_para = 0; |
|
Object obj; |
|
char *txt; |
|
char buf[4096]; |
|
int count; |
|
|
|
fdat = NULL; |
|
fdat_size = 0; |
|
while ((count = fread(buf, 1, 4096, f)) > 0) |
|
{ |
|
if (!fdat) |
|
fdat = EMALLOC(char, count); |
|
|
|
else |
|
fdat = EREALLOC(char, fdat, fdat_size + count); |
|
|
|
memcpy(fdat + fdat_size, buf, count); |
|
fdat_size += count; |
|
} |
|
fdat_ptr = fdat; |
|
|
|
if (page) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < num_pages; i++) |
|
{ |
|
int j; |
|
|
|
Efree(page[i].name); |
|
Efree(page[i].background); |
|
for (j = 0; j < page[i].count; j++) |
|
{ |
|
switch (page[i].obj[j].type) |
|
{ |
|
case IMG: |
|
Efree(((Img_ *) page[i].obj[j].object)->src); |
|
Efree(((Img_ *) page[i].obj[j].object)->src2); |
|
Efree(((Img_ *) page[i].obj[j].object)->src3); |
|
Efree(((Img_ *) page[i].obj[j].object)->link); |
|
break; |
|
case BR: |
|
break; |
|
case FONT: |
|
Efree(((Font_ *) page[i].obj[j].object)->face); |
|
break; |
|
case P: |
|
break; |
|
case TEXT: |
|
break; |
|
case PAGE: |
|
break; |
|
} |
|
Efree(page[i].obj[j].object); |
|
} |
|
Efree(page[i].obj); |
|
} |
|
Efree(page); |
|
num_pages = 0; |
|
page = NULL; |
|
have_font = 0; |
|
in_para = 0; |
|
} |
|
|
|
obj.type = P; |
|
obj.object = NULL; |
|
for (;;) |
|
{ |
|
if ((have_font) && (in_para)) |
|
{ |
|
txt = GetTextUntilTag(); |
|
if (txt) |
|
{ |
|
obj.type = TEXT; |
|
free(obj.object); |
|
obj.object = (void *)txt; |
|
} |
|
else |
|
{ |
|
if (!GetNextTag(&obj)) |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
if (!GetNextTag(&obj)) |
|
break; |
|
} |
|
if (obj.type == PAGE) |
|
{ |
|
in_para = 0; |
|
have_font = 0; |
|
AddPage(&obj); |
|
} |
|
else if (page) |
|
AddObject(&obj); |
|
if (obj.type == IMG) |
|
in_para = 0; |
|
if (obj.type == P) |
|
in_para = 1; |
|
if (obj.type == FONT) |
|
have_font = 1; |
|
obj.object = NULL; |
|
} |
|
Efree(fdat); |
|
} |
|
|
|
int |
|
FixPage(int p) |
|
{ |
|
if (p < 0) |
|
return 0; |
|
if (p >= num_pages) |
|
return num_pages - 1; |
|
return p; |
|
} |
|
|
|
int |
|
GetPage(char *name) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < num_pages; i++) |
|
{ |
|
if ((page[i].name) && (!strcmp(name, page[i].name))) |
|
return i; |
|
} |
|
return -1; |
|
} |
|
|
|
void |
|
GetLinkColors(int page_num, int *r, int *g, int *b) |
|
{ |
|
if (page_num < 0) |
|
{ |
|
*r = DEFAULT_LINKCOLOR_R; |
|
*g = DEFAULT_LINKCOLOR_G; |
|
*b = DEFAULT_LINKCOLOR_B; |
|
} |
|
else |
|
{ |
|
*r = page[page_num].linkr; |
|
*g = page[page_num].linkg; |
|
*b = page[page_num].linkb; |
|
} |
|
} |
|
|
|
static void |
|
CalcOffset(Page * pg, int col_w, int x, int y, int th, int *pxspace, int *poff) |
|
{ |
|
int xspace, off; |
|
int sx, sy, ssx, ssy; |
|
Img_ *img; |
|
int j; |
|
|
|
off = 0; |
|
sx = x + off; |
|
sy = y; |
|
ssx = sx + col_w - 1; |
|
ssy = sy + th - 1; |
|
for (j = 0; j < pg->count; j++) |
|
{ |
|
if (pg->obj[j].type != IMG) |
|
continue; |
|
|
|
img = (Img_ *) pg->obj[j].object; |
|
if ((img->w > 0) && (img->h > 0)) |
|
{ |
|
int ix, iy, iix, iiy; |
|
|
|
ix = img->x; |
|
iy = img->y; |
|
iix = img->x + img->w - 1; |
|
iiy = img->y + img->h - 1; |
|
|
|
if ((iy <= ssy) && (iiy >= sy)) |
|
{ |
|
if ((ix >= sx) && (ix <= ssx)) |
|
{ |
|
if ((iix >= sx) && (iix <= ssx)) |
|
{ |
|
if (((ix + iix) / 2) > ((sx + ssx) / 2)) |
|
ssx = ix - 1; |
|
else |
|
sx = iix + 1; |
|
} |
|
else |
|
{ |
|
ssx = ix - 1; |
|
} |
|
} |
|
else if ((iix >= sx) && (iix <= ssx)) |
|
{ |
|
sx = iix + 1; |
|
} |
|
} |
|
} |
|
} |
|
off = sx - x; |
|
xspace = (ssx - sx) + 1; |
|
if (xspace < 0) |
|
xspace = 0; |
|
|
|
*pxspace = xspace; |
|
*poff = off; |
|
} |
|
|
|
static void |
|
next_y(int w __UNUSED__, int h, int col_w, int *px, int *py, int *pcol, |
|
const Page * pg, const TextState * ts, const char *txt __UNUSED__) |
|
{ |
|
int x = *px; |
|
int y = *py; |
|
int col = *pcol; |
|
int y_max; |
|
|
|
y += ts->height; |
|
|
|
/* y_max = h - (pg->padding + ts->height); */ |
|
/* Allow descent to enter padding area */ |
|
y_max = h - (pg->padding + ts->xfontset_ascent); |
|
|
|
if (y >= y_max) |
|
{ |
|
col = (col + 1) % pg->columns; |
|
if (col > 0) |
|
{ |
|
/* Goto top of next col */ |
|
y = pg->padding; |
|
x += col * col_w + pg->padding; |
|
} |
|
else |
|
{ |
|
/* Goto bottom of first col (hack) */ |
|
x = pg->padding; |
|
y = y_max; |
|
} |
|
|
|
*px = x; |
|
*pcol = col; |
|
} |
|
|
|
*py = y; |
|
} |
|
|
|
Link * |
|
RenderPage(Window win, int page_num, int w, int h) |
|
{ |
|
Link *ll = NULL; |
|
Page *pg; |
|
TextState ts; |
|
int i, col_w, col; |
|
int x, y; |
|
int justification = 0; |
|
int firstp = 1; |
|
Imlib_Image im; |
|
int wastext = 0; |
|
|
|
memset(&ts, 0, sizeof(ts)); |
|
pg = &(page[page_num]); |
|
x = pg->padding; |
|
y = pg->padding; |
|
col = 0; |
|
col_w = ((w - (pg->padding * (pg->columns + 1))) / pg->columns); |
|
|
|
if (pg->background) |
|
{ |
|
im = ImageLoadDoc(pg->background); |
|
if (im) |
|
{ |
|
imlib_context_set_image(im); |
|
imlib_context_set_drawable(win); |
|
imlib_render_image_on_drawable_at_size(0, 0, w, h); |
|
imlib_free_image(); |
|
} |
|
} |
|
for (i = 0; i < pg->count; i++) |
|
{ |
|
char s[32768], ss[32768], wd[4096], *txt; |
|
Img_ *img; |
|
Font_ *fn; |
|
P_ *p; |
|
int wc, eol, eot; |
|
int islink = 0, lx, lw; |
|
|
|
switch (pg->obj[i].type) |
|
{ |
|
default: |
|
break; |
|
case IMG: |
|
img = (Img_ *) pg->obj[i].object; |
|
if (img->src) |
|
{ |
|
im = ImageLoadDoc(img->src); |
|
if (im) |
|
{ |
|
imlib_context_set_image(im); |
|
img->w = imlib_image_get_width(); |
|
img->h = imlib_image_get_height(); |
|
imlib_context_set_drawable(win); |
|
imlib_render_image_on_drawable_at_size(img->x, img->y, |
|
img->w, img->h); |
|
imlib_free_image(); |
|
} |
|
if (img->link) |
|
{ |
|
Link *l; |
|
|
|
l = EMALLOC(Link, 1); |
|
l->name = strdup(img->link); |
|
l->x = img->x; |
|
l->y = img->y; |
|
l->w = img->w; |
|
l->h = img->h; |
|
l->next = ll; |
|
ll = l; |
|
} |
|
} |
|
break; |
|
case BR: |
|
if (!wastext) |
|
next_y(w, h, col_w, &x, &y, &col, pg, &ts, "<BR>"); |
|
wastext = 0; |
|
break; |
|
case FONT: |
|
fn = (Font_ *) pg->obj[i].object; |
|
ts.fontname = NULL; |
|
ESetColor(&ts.fg_col, 0, 0, 0); |
|
ESetColor(&ts.bg_col, 0, 0, 0); |
|
ts.effect = 0; |
|
if (ts.efont) |
|
Efont_free(ts.efont); |
|
ts.efont = NULL; |
|
if (ts.xfontset) |
|
XFreeFontSet(disp, ts.xfontset); |
|
ts.xfontset = NULL; |
|
ts.xfontset_ascent = 0; |
|
ts.height = 0; |
|
ts.fontname = fn->face; |
|
ESetColor(&ts.fg_col, fn->r, fn->g, fn->b); |
|
TextStateLoadFont(&ts); |
|
break; |
|
case P: |
|
p = (P_ *) pg->obj[i].object; |
|
if (p) |
|
justification = (int)((p->align / 100) * 1024); |
|
else |
|
justification = 0; |
|
if (!firstp) |
|
next_y(w, h, col_w, &x, &y, &col, pg, &ts, "<P>"); |
|
else |
|
firstp = 0; |
|
break; |
|
case TEXT: |
|
txt = (char *)pg->obj[i].object; |
|
wc = 1; |
|
ss[0] = 0; |
|
s[0] = 0; |
|
eol = 0; |
|
eot = 0; |
|
for (;;) |
|
{ |
|
char *txt_disp; |
|
int tw, th, xspace; |
|
int off, j; |
|
char link_txt[1024]; |
|
char link_link[1024]; |
|
int spaceflag, oldwc = 0, linkwc; |
|
|
|
wd[0] = 0; |
|
spaceflag = 1; |
|
#ifdef USE_WORD_MB |
|
if (MB_CUR_MAX > 1) /* If multibyte locale,... */ |
|
word_mb(txt, wc, wd, &spaceflag); |
|
else |
|
#endif |
|
word(txt, wc, wd); |
|
if (!wd[0]) |
|
eol = 1; |
|
|
|
wc++; |
|
eot++; |
|
strcpy(ss, s); |
|
if ((eot != 1) && spaceflag) |
|
strcat(s, " "); |
|
|
|
linkwc = -1; |
|
if (wd[0] == '_') |
|
{ |
|
link_txt[0] = '\0'; |
|
link_link[0] = '\0'; |
|
islink = 1; |
|
oldwc = wc; |
|
TextSize(&ts, s, &lx, &th); |
|
} |
|
|
|
if (islink == 1) |
|
{ |
|
if (eol || ((wd[0] != '_') && spaceflag)) /* if NO link tag, ... */ |
|
{ |
|
link_txt[0] = '\0'; |
|
link_link[0] = '\0'; |
|
islink = 0; |
|
wc = oldwc; |
|
#ifdef USE_WORD_MB |
|
spaceflag = 1; |
|
if (MB_CUR_MAX > 1) |
|
word_mb(txt, wc - 1, wd, &spaceflag); |
|
else |
|
#endif |
|
word(txt, wc - 1, wd); |
|
} |
|
else |
|
{ |
|
int k, linkflg; |
|
|
|
j = 0; |
|
linkflg = 0; |
|
if (wd[0] == '_') |
|
{ |
|
j++; |
|
linkflg++; |
|
} |
|
|
|
k = strlen(link_txt); |
|
for (; wd[j] != '(' && wd[j] != '\0'; j++, k++) |
|
{ |
|
if (wd[j] == '_') |
|
link_txt[k] = ' '; |
|
else |
|
link_txt[k] = wd[j]; |
|
if (linkflg) |
|
wd[j - 1] = link_txt[k]; |
|
else |
|
wd[j] = link_txt[k]; |
|
} |
|
link_txt[k] = '\0'; |
|
if (linkflg) |
|
wd[j - 1] = '\0'; |
|
|
|
if (wd[j] == '(') |
|
{ |
|
wd[j++] = '\0'; |
|
strcpy(link_link, wd + j); |
|
k = strlen(link_link) - 1; |
|
if (k <= 0) |
|
continue; |
|
for (j = k; j > 0 && link_link[j] != ')'; j--) |
|
; |
|
link_link[j] = '\0'; |
|
strcpy(wd, link_txt); |
|
if (j < k) |
|
strcat(wd, link_link + j + 1); |
|
islink = 2; |
|
linkwc = wc; |
|
} |
|
else |
|
continue; |
|
} |
|
} |
|
|
|
strcat(s, wd); |
|
|
|
CalcOffset(pg, col_w, x, y, ts.height, &xspace, &off); |
|
|
|
TextSize(&ts, s, &tw, &th); |
|
txt_disp = ss; |
|
if (eot == 1) |
|
txt_disp = s; |
|
if (((tw > xspace) || (eol)) && (strlen(txt_disp) > 0)) |
|
{ |
|
if (txt_disp[strlen(txt_disp) - 1] == ' ') |
|
txt_disp[strlen(txt_disp) - 1] = 0; |
|
|
|
if ((eot == 1) && (tw > xspace)) |
|
{ |
|
char p1[4096]; |
|
int point = 0, cnt = 0, ii, len; |
|
|
|
while (txt_disp[(point + cnt)]) |
|
{ |
|
len = |
|
mblen(txt_disp + point + cnt, MB_CUR_MAX); |
|
if (len < 0) |
|
{ |
|
cnt++; |
|
continue; |
|
} |
|
else |
|
for (ii = 0; ii < len; ii++, cnt++) |
|
p1[cnt] = txt_disp[point + cnt]; |
|
p1[cnt] = 0; |
|
TextSize(&ts, p1, &tw, &th); |
|
if ((tw > xspace) |
|
|| (!txt_disp[(point + cnt)])) |
|
{ |
|
if (txt_disp[(point + cnt)]) |
|
{ |
|
point = point + cnt - len; |
|
p1[cnt - len] = 0; |
|
cnt = 0; |
|
} |
|
else |
|
{ |
|
point = point + cnt; |
|
p1[cnt] = 0; |
|
cnt = 0; |
|
} |
|
wastext = 1; |
|
TextDraw(&ts, win, p1, x + off, y, |
|
xspace, 99999, justification); |
|
next_y(w, h, col_w, &x, &y, &col, |
|
pg, &ts, p1); |
|
CalcOffset(pg, col_w, x, y, ts.height, |
|
&xspace, &off); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if ((tw > xspace) && (eot != 1)) |
|
wc--; |
|
wastext = 1; |
|
TextDraw(&ts, win, txt_disp, x + off, y, |
|
xspace, 99999, justification); |
|
if (islink > 1 && linkwc > wc) |
|
{ |
|
islink = 0; |
|
link_link[0] = '\0'; |
|
link_txt[0] = '\0'; |
|
wc = oldwc - 1; |
|
} |
|
|
|
if (islink > 1) |
|
{ |
|
int rr, gg, bb; |
|
int extra; |
|
GC gc; |
|
XGCValues gcv; |
|
|
|
gc = XCreateGC(disp, win, 0, &gcv); |
|
EGetColor(&ts.fg_col, &rr, &gg, &bb); |
|
ESetColor(&ts.fg_col, pg->linkr, pg->linkg, |
|
pg->linkb); |
|
EAllocColor(&ts.fg_col); |
|
XSetForeground(disp, gc, ts.fg_col.pixel); |
|
TextSize(&ts, txt_disp, &tw, &th); |
|
extra = ((xspace - tw) * justification) >> 10; |
|
TextDraw(&ts, win, link_txt, |
|
x + off + lx + extra, y, 99999, 99999, |
|
0); |
|
TextSize(&ts, link_txt, &lw, &th); |
|
XDrawLine(disp, win, gc, |
|
x + off + lx + extra, |
|
y + ts.xfontset_ascent, |
|
x + off + lx + lw + extra, |
|
y + ts.xfontset_ascent); |
|
ESetColor(&ts.fg_col, rr, gg, bb); |
|
islink = 0; |
|
XFreeGC(disp, gc); |
|
{ |
|
Link *l; |
|
|
|
l = EMALLOC(Link, 1); |
|
l->name = strdup(link_link); |
|
l->x = x + off + lx + extra; |
|
l->y = y; |
|
l->w = lw; |
|
l->h = ts.height; |
|
l->next = ll; |
|
ll = l; |
|
} |
|
link_link[0] = '\0'; |
|
link_txt[0] = '\0'; |
|
} |
|
next_y(w, h, col_w, &x, &y, &col, |
|
pg, &ts, txt_disp); |
|
} |
|
eot = 0; |
|
s[0] = 0; |
|
} |
|
if (eol) |
|
break; |
|
} |
|
|
|
break; |
|
} |
|
} |
|
|
|
if (ts.efont) |
|
Efont_free(ts.efont); |
|
if (ts.xfontset) |
|
XFreeFontSet(disp, ts.xfontset); |
|
|
|
return ll; |
|
}
|
|
|