Roxen.git / server / modules / graphics / graphic_text.pike

version» Context lines:

Roxen.git/server/modules/graphics/graphic_text.pike:1: - constant cvs_version="$Id: graphic_text.pike,v 1.189 1999/10/04 10:27:10 nilsson Exp $"; + constant cvs_version="$Id: graphic_text.pike,v 1.190 1999/11/28 02:52:24 nilsson Exp $";   constant thread_safe=1;      #include <config.h>   #include <module.h>   #include <stat.h>   inherit "module";   inherit "roxenlib";      #ifndef VAR_MORE   #define VAR_MORE 0   #endif /* VAR_MORE */    - #define old_rxml_compat 1 +     -  + // ------------------- Module registration --------------------- +    array register_module()   {    return ({ MODULE_PARSER,    "Graphics text", -  "Generates graphical texts.<p>" -  "See <tt>&lt;gtext help&gt;&lt;/gtext&gt;</tt> for " -  "more information.", +  "Generates graphical texts.",    0, 1    });   }    -  +    void create()   {    defvar("colorparse", 1, "Parse tags for document colors", TYPE_FLAG,    "If set, parse the specified tags for document colors.");       defvar("colorparsing", ({"body", "td", "layer", "ilayer", "table"}),    "Tags to parse for color",    TYPE_STRING_LIST,    "Which tags should be parsed for document colors? "    "This will affect documents without gtext as well as documents "
Roxen.git/server/modules/graphics/graphic_text.pike:47:    " dramatically. You can try this out with the &lt;gauge&gt; tag.",    0, lambda(){return !query("colorparse");});       defvar("deflen", 300, "Default maximum text-length", TYPE_INT|VAR_MORE,    "The module will, per default, not try to render texts "    "longer than this. This is a safeguard for things like "    "&lt;gh1&gt;&lt;/gh&gt;, which would otherwise parse the"    " whole document. This can be overrided with maxlen=... in the "    "tag.");    -  defvar("gif", 0, "Append .fmt (gif, jpeg etc) to all images", +  defvar("ext", 0, "Append .fmt (gif, jpeg etc) to all images",    TYPE_FLAG|VAR_MORE,    "Append .gif, .png, .gif etc to all images made by gtext. "    "Normally this will only waste bandwidth");   }    - static private mapping cached_args = ([ ]); +     -  + // ------------------- The actual graphics routines ---------------------- +    #define MAX(a,b) ((a)<(b)?(b):(a)) -  + #define MIN(a,b) ((a)<(b)?(a):(b))      static private mapping (int:array(array(int))) matrixes = ([]);   array (array(int)) make_matrix(int size)   {    if(matrixes[size]) return matrixes[size];    array res;    int i;    int j;    res = allocate(size, allocate)(size);    for(i=0; i<size; i++)    for(j=0; j<size; j++)    res[i][j] = (int)MAX((float)size/2.0-sqrt((size/2-i)*(size/2-i) + (size/2-j)*(size/2-j)),0);    return matrixes[size] = res;   }    - object blur(object img, int amnt) + object blur(object img, int amnt)   {    img->setcolor(0,0,0);    img = img->autocrop(amnt, 0,0,0,0, 0,0,0);       for(int i=0; i<amnt; i++)    img = img->apply_matrix( make_matrix((int)sqrt(img->ysize()+20)));    return img;   }    - object outline(object on, object with, + object outline(object on, object with,    array (int) color, int radie, int x, int y)   {    int steps=10;    for(int j=0; j<=steps; j++)    on->paste_alpha_color(with, @color,    (int)(0.5+x-(sin((float)j/steps*3.145*2)*radie)),    (int)(0.5+y-(cos((float)j/steps*3.145*2)*radie)));    return on;   }      constant white = ({ 255,255,255 });   constant lgrey = ({ 200,200,200 });   constant grey = ({ 128,128,128 });   constant black = ({ 0,0,0 });   constant wwwb = ({ lgrey,lgrey,grey,black });    - object bevel(object in, int width, int|void invert) + object bevel(object in, int width, int|void invert)   {    int h=in->ysize();    int w=in->xsize();       object corner = Image.Image(width+1,width+1);    object corner2 = Image.Image(width+1,width+1);    object pix = Image.Image(1,1);       for(int i=-1; i<=width; i++) {    corner->line(i,width-i,i,-1, @white);
Roxen.git/server/modules/graphics/graphic_text.pike:141:    in->paste_mask(corner, corner->color(95,95,95), -1, in->ysize()-width);    in->paste_mask(corner, corner->invert()->color(128,128,128),    -1, in->ysize()-width);    corner=0;    in->paste_mask(corner2, corner2->color(70,70,70), -1, -1);       corner2 = pix = 0;    return in;   }    -  - object make_text_image(mapping args, object font, string text,object id) + object make_text_image(mapping args, object font, string text, RequestID id)   { -  // object text_alpha=font->write(@(text/"\n")); +     if( args->encoding )    text = roxen.decode_charset(args->encoding,text);    object text_alpha=font->write(@(text/"\n"));    int xoffset=0, yoffset=0;       if(!text_alpha->xsize() || !text_alpha->ysize())    text_alpha = Image.Image(10,10, 0,0,0);    - // perror("Making image of '%s', args=%O\n", text, args); -  +     if(int op=((((int)args->opaque)*255)/100)) // Transparent text...    text_alpha=text_alpha->color(op,op,op);       int txsize=text_alpha->xsize();    int tysize=text_alpha->ysize(); // Size of the text, in pixels.       int xsize=txsize; // image size, in pixels    int ysize=tysize;    - // perror("Xsize=%d; ysize=%d\n",xsize,ysize); -  +     if(args->bevel)    {    xoffset += (int)args->bevel;    yoffset += (int)args->bevel;    xsize += ((int)args->bevel)*2;    ysize += ((int)args->bevel)*2;    }       if(args->spacing)    {
Roxen.git/server/modules/graphics/graphic_text.pike:238:    }       if(args->border)    {    xoffset += (int)args->border;    yoffset += (int)args->border;    xsize += ((int)args->border)*2;    ysize += ((int)args->border)*2;    }    -  +     array (int) bgcolor = parse_color(args->bg);    array (int) fgcolor = parse_color(args->fg);       object background,foreground;    -  +     if(args->texture)    {    object t = roxen.load_image(args->texture,id);    if( t )    {    foreground = t;    if(args->tile)    {    object b2 = Image.Image(xsize,ysize);    for(int x=0; x<xsize; x+=foreground->xsize())
Roxen.git/server/modules/graphics/graphic_text.pike:380:    if( args->rescale )    {    xs = txsize;    ys = tysize;    }       if(args->size) { xs=(int)args->size; ys=(int)(args->size/",")[-1]; }    if(args->xsize) xs=(int)args->xsize;    if(args->ysize) ys=(int)args->ysize;    -  +     if( xs != background->xsize() ||    ys != background->ysize() )    {    if(!args->rescale)    background = background->copy(0,0,xs-1,ys-1);    else    background = background->scale(xs, ys);    }       if(args->turbulence)
Roxen.git/server/modules/graphics/graphic_text.pike:402:    array (float|array(int)) arg=({});    foreach((args->turbulence/";"), string s)    {    array q= s/",";    if(sizeof(q)<2) args+=({ ((float)s)||0.2, ({ 255,255,255 }) });    arg+=({ ((float)q[0])||0.2, parse_color(q[1]) });    }    background=background->turbulence(arg);    }    -  +     if(args->bevel)    background = bevel(background,(int)args->bevel,!!args->pressed);       if(args->textbox) // Draw a text-box on the background.    {    int alpha,border;    string bg;    alpha = (int)args->textbox;    sscanf(args->textbox, "%*[^,],%s", bg);    sscanf(bg,"%s,%d", bg,border);
Roxen.git/server/modules/graphics/graphic_text.pike:438:    object ta = text_alpha->copy();    for (j=0;j<bl;j++)    ta=ta->apply_matrix(({    ({6,7,7,7,6}),({7,8,8,8,7}),({7,8,8,8,7}),({7,8,8,8,7}),({6,7,7,7,6})    }));    background->paste_alpha_color(ta,@clr,xoffset+sdist,yoffset+sdist);    fgcolor=bgcolor;    }    }    -  +     if(args->shadow)    {    int sd = ((int)args->shadow+10)*2;    int sdist = ((int)(args->shadow/",")[-1])+2;    object ta = text_alpha->copy();    ta = ta->color(256-sd,256-sd,256-sd);    array sc = parse_color(args->scolor||"black");    background->paste_alpha_color(ta,sc[0],sc[1],sc[2],    xoffset+sdist,yoffset+sdist);    }    - #define MIN(x,y) ((x)<(y)?(x):(y)) -  +     if(args->bshadow)    {    int sdist = (int)(args->bshadow)+1;    int xs,ys;    xs = text_alpha->xsize()+sdist*2+4;    ys = text_alpha->ysize()+sdist*2+4;    object ta = Image.Image(xs+sdist*2,ys+sdist*2);    array sc = parse_color(args->scolor||"black");       ta->paste_alpha_color(text_alpha,255,255,255,sdist,sdist);
Roxen.git/server/modules/graphics/graphic_text.pike:483:    xoffset-amnt, yoffset-amnt);    }       if(args->chisel)    foreground=text_alpha->apply_matrix(({ ({8,1,0}),    ({1,0,-1}),    ({0,-1,-8}) }),    128,128,128, 15 )    ->color(@fgcolor);    -  +     if(!foreground) foreground=Image.Image(txsize, tysize, @fgcolor);    if(args->textscale)    {    string c1="black",c2="black",c3="black",c4="black";    sscanf(args->textscale, "%s,%s,%s,%s", c1, c2, c3, c4);    foreground->tuned_box(0,0, txsize,tysize,    ({parse_color(c1),parse_color(c2),parse_color(c3),    parse_color(c4)}));    }    if(args->outline)    outline(background, text_alpha, parse_color((args->outline/",")[0]),    ((int)(args->outline/",")[-1])+1, xoffset, yoffset);       if(args->textbelow)    {    array color = parse_color(args->textbelow); - // foreground = foreground->autocrop(); - // text_alpha = text_alpha->autocrop(); +        background->setcolor( @color );    int oby = background->ysize();    background = background->copy(0,0,    max(background->xsize()-1,    foreground->xsize()-1),    background->ysize()-1    +foreground->ysize());    background->paste_mask( foreground, text_alpha,    (background->xsize()-foreground->xsize())/2,    oby );    } else    background->paste_mask(foreground, text_alpha, xoffset, yoffset);       foreground = text_alpha = 0;    -  // handled by the image cache nowdays. :-) - // if((float)args->scale>0.0) - // if((float)args->scale <= 2.0) - // background = background->scale((float)args->scale); -  -  +     if(args->rotate)    {    string c;    if(sscanf(args->rotate, "%*d,%s", c)==2)    background->setcolor(@parse_color(c));    else    background->setcolor(@bgcolor);    background = background->rotate((float)args->rotate);    }       if(args->crop) background = background->autocrop();    return background;   }    -  +  + // -------------------- Image cache functions -------------------- +    roxen.ImageCache image_cache;      void start(int|void val, object|void conf)   {    image_cache = roxen.ImageCache( "gtext", draw_callback );   }      constant nbsp = iso88591["&nbsp;"];   constant replace_from = indices( iso88591 )+ ({"&ss;","&lt;","&gt;","&amp;",});   constant replace_to = values( iso88591 ) + ({ nbsp, "<", ">", "&", });      #define simplify_text( from ) replace(from,replace_from,replace_to)    -  - mixed draw_callback(mapping args, string text, object id) + mixed draw_callback(mapping args, string text, RequestID id)   {    array err;    mixed data;    int elapsed;    string orig_text = text;    object img;       if( objectp( text ) )    {    if( !args->text )
Roxen.git/server/modules/graphics/graphic_text.pike:686:    data = ({ res, ({ len, img->ysize() }) });    }       return    ([    "data":data[0],    "meta":    ([    "xsize":data[1][0],    "ysize":data[1][1], -  "type":"image/gif", +  "type":(args->format?id->conf->type_from_filename("x."+args->format):"image/gif"),    ])    ]);   }    -  +    mapping find_internal(string f, object rid)   { -  if( strlen(f)>4 && query("gif") && f[-4]=='.') // Remove .ext +  if( strlen(f)>4 && query("ext") && f[-4]=='.') // Remove .ext    f = f[..strlen(f)-5];    if( strlen(f) && f[0]=='$' )    {    array id_text = f/"/";    if( sizeof(id_text)==2 )    { // It's a gtext-id    string second_key = roxen->argcache->store( (["":id_text[1]]) );    return image_cache->http_file_answer( id_text[0][1..] +"$"+ second_key, rid );    }    }    return image_cache->http_file_answer( f, rid );   }    - string magic_javascript_header(object id) - { -  if(!id->supports->netscape_javascript || !id->supports->images) return ""; -  return -  ("<script>\n" -  "function i(ri,hi,txt)\n" -  "{\n" -  " document.images[ri].src = hi.src;\n" -  " setTimeout(\"top.window.status = '\"+txt+\"'\", 100);\n" -  "}\n" -  "</script>"); +     -  + // -------------- helpfunctions to gtext tags and containers ----------------- +  + constant filearg=({"background","texture","magic-texture","magic-background","magic-bg","alpha"}); + constant textarg=({"afont", +  "alpha", +  "bevel", +  "bg", +  "black", +  "bold", +  "border", +  "bshadow", +  "chisel", +  "crop", +  "encoding", +  "fadein", +  "fg", +  "fs", +  "font", +  "font_size", +  "format", +  "ghost", +  "glow", +  "italic", +  "light", +  "mirrortile", +  "more", +  "narrow", +  "nfont", +  "notrans", +  "opaque", +  "outline", +  "pressed", +  "quant", +  "rescale", +  "rotate", +  "scale", +  "scolor", +  "scroll", +  "shadow", +  "size", +  "spacing", +  "talign", +  "tile", +  "textbox", +  "textbelow", +  "textscale", +  "turbulence", +  "verbatim", +  "xpad", +  "xsize", +  "xspacing", +  "ypad", +  "ysize", +  "yspacing" + }); +  + mapping mk_gtext_arg(mapping arg, RequestID id) { +  +  mapping defines=id->misc->defines; +  mapping p=([]); //Picture rendering arguments. +  +  foreach(filearg, string tmp) +  if(arg[tmp]) { +  p[tmp]=fix_relative(arg[tmp],id); +  m_delete(arg,tmp);    }    -  +  foreach(textarg, string tmp) +  if(arg[tmp]) { +  p[tmp]=arg[tmp],id; +  m_delete(arg,tmp); +  }    - string magic_image(string url, int xs, int ys, string sn, -  string image_1, string image_2, string alt, -  string mess,object id,string input,string extra_args,string lp, string img_extra_args) - { -  if(!id->supports->images) return (lp?lp:"")+alt+(lp?"</a>":""); -  if(!id->supports->netscape_javascript) -  return (!input)? -  ("<a "+extra_args+"href=\""+url+"\"><img src=\""+image_1+"\" name="+sn+" border=0 "+img_extra_args+" " -  "alt=\""+alt+"\"></a>"): -  ("<input type=image "+extra_args+" src=\""+image_1+"\" name="+input+">"); +  if(defines->fg && !p->fg) p->fg=defines->fg; +  if(defines->bg && !p->bg) p->bg=defines->bg; +  if(defines->nfont && !p->nfont) p->nfont=defines->nfont; +  if(defines->afont && !p->afont) p->afont=defines->afont; +  if(defines->font && !p->font) p->font=defines->font; +  if(defines->bold && !p->bold) p->bold=defines->bold; +  if(defines->italic && !p->italic) p->italic=defines->italic; +  if(defines->black && !p->black) p->black=defines->black; +  if(defines->narrow && !p->narrow) p->narrow=defines->narrow;    -  return -  ("<script>\n" -  " "+sn+"l = new Image("+xs+", "+ys+");"+sn+"l.src = \""+image_1+"\";\n" -  " "+sn+"h = new Image("+xs+", "+ys+");"+sn+"h.src = \""+image_2+"\";\n" -  "</script>"+ -  ("<a "+extra_args+"href=\""+url+"\" "+ -  (input?"onClick='document.forms[0].submit();' ":"") -  +"onMouseover=\"i('"+sn+"',"+sn+"h,'"+(mess||url)+"'); return true;\"\n" -  "onMouseout=\"top.window.status='';document.images['"+sn+"'].src = "+sn+"l.src;\"><img "+img_extra_args+" " -  "width="+xs+" height="+ys+" src=\""+image_1+"\" name="+sn+ -  " border=0 alt=\""+alt+"\" ></a>")); +  return p;   }    -  + string fix_text(string c, mapping m, RequestID id) {    - string extra_args(mapping in) +  if(m->nowhitespace)    { -  string s=""; -  foreach(indices(in), string i) -  { -  switch(i) -  { -  case "target": -  case "hspace": -  case "vspace": -  case "onclick": -  case "class": -  case "id": -  s+=i+"='"+in[i]+"' "; -  m_delete(in, i); -  break; +  sscanf(c,"%*[ \n\r\t]%s",c); +  sscanf(reverse(c),"%*[ \n\r\t]%s",c); +  c=reverse(c); +  m_delete(m, "nowhitespace");    } -  +  +  if(!m->noparse && !m->preparse) +  c = parse_rxml(c, id); +  else { +  m_delete(m, "noparse"); +  m_delete(m, "preparse");    } -  return s; +  +  c = c[..(((int)m->maxlen||QUERY(deflen))-1)]; +  m_delete(m, "maxlen"); +  +  return c;   }    - string tag_gtext_url(string t, mapping arg, string ctn, -  object id, object foo, mapping defines) - { -  int short=!!arg->short; -  if(arg->help) return "Arguments are identical to the argumets to &lt;gtext&gt;. This tag returns a url-prefix that can be used to generate gtexts."; -  m_delete(arg, "short"); m_delete(arg, "maxlen"); -  m_delete(arg,"magic"); m_delete(arg,"submit"); -  extra_args(arg); m_delete(arg,"split"); -  if(defines->fg && !arg->fg) arg->fg=defines->fg; -  if(defines->bg && !arg->bg) arg->bg=defines->bg; -  if(defines->nfont && !arg->nfont) arg->nfont=defines->nfont; -  if(defines->afont && !arg->afont) arg->afont=defines->afont; -  if(defines->font && !arg->font) arg->font=defines->font; +     -  if(arg->background) -  arg->background = fix_relative(arg->background,id); -  if(arg->texture) -  arg->texture = fix_relative(arg->texture,id); -  if(arg->magic_texture) -  arg->magic_texture=fix_relative(arg->magic_texture,id); -  if(arg->magic_background) -  arg->magic_background=fix_relative(arg->magic_background,id); -  if(arg->magicbg) -  arg->magicbg = fix_relative(arg->magicbg,id); -  if(arg->alpha) -  arg->alpha = fix_relative(arg->alpha,id); + // ----------------- gtext tags and containers -------------------    -  if(!short) -  return query_internal_location()+image_cache->store( ({arg,ctn}), id )+ -  (query("gif")?".foo":""); + string tag_gtext_url(string t, mapping arg, string c, RequestID id) { +  c=fix_text(c,arg,id); +  mapping p=mk_gtext_arg(arg,id); +  if(arg->href && !p->fg) p->fg=id->misc->defines->link||"#0000ff"; +  string ext=""; +  if(query("ext")) ext="."+(p->format || "gif"); +  if(!arg->short) +  return query_internal_location()+image_cache->store( ({p,c}), id )+ext;    else -  return image_cache->store( ({arg,ctn}), id )+(query("gif")?".foo":""); +  return "+"+image_cache->store( ({p,c}), id )+ext;   }    - string tag_gtext_id(string t, mapping arg, object id, -  object foo, mapping defines) - { -  int short=!!arg->short; -  if(arg->help) return "Arguments are identical to the argumets to &lt;gtext&gt;. This tag returns a url-prefix that can be used to generate gtexts."; -  m_delete(arg, "short"); m_delete(arg, "maxlen"); -  m_delete(arg,"magic"); m_delete(arg,"submit"); -  extra_args(arg); m_delete(arg,"split"); -  if(defines->fg && !arg->fg) arg->fg=defines->fg; -  if(defines->bg && !arg->bg) arg->bg=defines->bg; -  if(defines->nfont && !arg->nfont) arg->nfont=defines->nfont; -  if(defines->afont && !arg->afont) arg->afont=defines->afont; -  if(defines->font && !arg->font) arg->font=defines->font; -  -  if(arg->background) -  arg->background = fix_relative(arg->background,id); -  if(arg->texture) -  arg->texture = fix_relative(arg->texture,id); -  if(arg->magic_texture) -  arg->magic_texture=fix_relative(arg->magic_texture,id); -  if(arg->magic_background) -  arg->magic_background=fix_relative(arg->magic_background,id); -  if(arg->magicbg) -  arg->magicbg = fix_relative(arg->magicbg,id); -  if(arg->alpha) -  arg->alpha = fix_relative(arg->alpha,id); -  -  // arg->text = ctn; -  -  if(!short) -  return query_internal_location()+"$"+image_cache->store( arg, id )+"/"; + string tag_gtext_id(string t, mapping arg, RequestID id) { +  mapping p=mk_gtext_arg(arg,id); +  if(arg->href && !p->fg) p->fg=id->misc->defines->link||"#0000ff"; +  if(!arg->short) +  return query_internal_location()+"$"+image_cache->store(p, id)+"/";    else -  return "+"+image_cache->store( arg, id )+"/"; +  return "+"+image_cache->store(p, id )+"/";   }    - string tag_graphicstext(string t, mapping arg, string contents, -  object id, object foo, mapping defines) + string tag_graphicstext(string t, mapping arg, string c, RequestID id)   { -  if((contents-" ")=="") +  mapping defines=id->misc->defines; +  if((c-" ")=="")    return ""; - //Allow <accessed> and others inside <gtext>. -  if(arg->nowhitespace) -  { -  sscanf(contents,"%*[ \n\r\t]%s",contents); -  sscanf(reverse(contents),"%*[ \n\r\t]%s",contents); -  contents=reverse(contents); -  } -  if(arg->help) -  return "This tag calls &lt;gtext&gt; with different default values."; -  if(arg->background) -  arg->background = fix_relative(arg->background,id); -  if(arg->texture) -  arg->texture = fix_relative(arg->texture,id); -  if(arg->magic_texture) -  arg->magic_texture=fix_relative(arg->magic_texture,id); -  if(arg->magic_background) -  arg->magic_background=fix_relative(arg->magic_background,id); -  if(arg->magicbg) -  arg->magicbg = fix_relative(arg->magicbg,id); -  if(arg->alpha) -  arg->alpha = fix_relative(arg->alpha,id); +     -  string gif=""; -  if(query("gif")) gif="."+(arg->format?arg->format[..2]:"gif"); +  c=fix_text(c,arg,id); +  mapping p=mk_gtext_arg(arg,id);    -  if( !arg->noparse && !arg->preparse ) -  contents = parse_rxml(contents, id); -  else -  { -  m_delete( arg, "noparse" ); -  m_delete( arg, "preparse" ); -  } +  string ext=""; +  if(query("ext")) ext="."+(p->format || "gif");    -  string lp, url, ea; -  string pre, post, defalign, gt, rest, magic; -  int i; -  string split; +  string lp="%s", url="", ea="";    -  contents = contents[..(((int)arg->maxlen||QUERY(deflen))-1)]; -  m_delete(arg, "maxlen"); -  -  if(arg->magic) -  { -  magic=replace(arg->magic,"'","`"); -  m_delete(arg,"magic"); -  } -  +     int input;    if(arg->submit)    {    input=1;    m_delete(arg,"submit");    }    -  +  if(!arg->noxml) { arg["/"]="/"; m_delete(arg, "noxml"); } +  if(!arg->border) arg->border=arg->border||"0";    -  ea = extra_args(arg); -  -  // Modify the 'arg' mapping... +     if(arg->href)    {    url = arg->href; -  lp = "<a href=\""+arg->href+"\" "+ea+">"; -  if(!arg->fg) arg->fg=defines->link||"#0000ff"; +  lp = make_container("a",arg,"%s"); //This anchor might have some extra args. +  if(!p->fg) p->fg=defines->link||"#0000ff";    m_delete(arg, "href");    }    -  if(defines->fg && !arg->fg) arg->fg=defines->fg; -  if(defines->bg && !arg->bg) arg->bg=defines->bg; -  if(defines->nfont && !arg->nfont) arg->nfont=defines->nfont; -  if(defines->afont && !arg->afont) arg->afont=defines->afont; -  if(defines->font && !arg->font) arg->font=defines->font; -  if(defines->bold && !arg->bold) arg->bold=defines->bold; -  if(defines->italic && !arg->italic) arg->italic=defines->italic; -  if(defines->black && !arg->black) arg->black=defines->black; -  if(defines->narrow && !arg->narrow) arg->narrow=defines->narrow; -  +     if(arg->split)    { -  if ((split=arg->split) == "split") -  split = " "; +  string res="",split=arg->split; +  if(lower_case(split)=="split") split=" ";    m_delete(arg,"split"); -  } -  -  // Support for <gh 2> like things. -  for(i=2; i<10; i++) -  if(arg[(string)i]) +  c=replace(c, "\n", " "); +  int setalt=!arg->alt; +  foreach(c/split-({""}), string word)    { -  arg->scale = (string)(1.0 / ((float)i*0.6)); -  m_delete(arg, (string)i); -  break; -  } -  -  // Support for <gh1> like things. -  if(sscanf(t, "%s%d", t, i)==2) -  if(i > 1) arg->scale = (string)(1.0 / ((float)i*0.6)); -  -  string na = arg->name, al=arg->align; -  m_delete(arg, "name"); m_delete(arg, "align"); -  -  // Now the 'arg' mapping is modified enough.. -  gt=contents; -  rest=""; -  -  switch(t) -  { - #if old_rxml_compat -  case "gh1": case "gh2": case "gh3": case "gh4": -  case "gh5": case "gh6": case "gh7": - #endif -  case "gh": pre="<p>"; post="<br>"; defalign="top"; break; -  case "gtext": -  pre=""; post=""; defalign="bottom"; -  break; -  case "anfang": -  gt=contents[0..0]; rest=contents[1..]; -  pre="<br clear=left>"; post=""; defalign="left"; -  break; -  } -  -  if(split) -  { -  string word; -  array res = ({ pre }); -  if(lp) res+=({ lp }); -  -  gt=replace(gt, "\n", " "); -  -  foreach(gt/split-({""}), word) -  { -  string fn = image_cache->store( ({arg,word}),id ); +  string fn = image_cache->store( ({ p, word }),id );    mapping size = image_cache->metadata( fn, id, 1 ); -  mapping tag = -  ([ -  "alt":(arg->alt||word), -  "src":query_internal_location()+fn+gif, -  ]); -  if(!arg->noxml) tag+=(["/":"/"]); +  if(setalt) arg->alt=word; +  arg->src=query_internal_location()+fn+ext;    if( size )    { -  tag->width = (string)size->xsize; -  tag->height = (string)size->ysize; +  arg->width = (string)size->xsize; +  arg->height = (string)size->ysize;    } -  res += ({ make_tag( "img", tag )+" " }); +  res+=make_tag( "img", arg )+" ";    } -  if(lp) res += ({ "</a>"+post }); -  return res*""; +  return sprintf(lp,res);    }    -  string num = image_cache->store( ({arg,gt}),id ); +  string num = image_cache->store( ({ p, c }), id );    mapping size = image_cache->metadata( num, id, 1 ); -  +  if(!arg->alt) arg->alt=replace(c,"\"","'");    -  if(magic) +  arg->src=query_internal_location()+num+ext; +  if(size) { +  arg->width=size->xsize; +  arg->height=size->ysize; +  } +  +  if(arg->magic)    { -  string res = ""; -  if(!arg->fg) arg->fg=defines->link||"#0000ff"; -  arg = mkmapping(indices(arg), values(arg)); -  if(arg->fuzz) -  if(arg->fuzz != "fuzz") -  arg->glow = arg->fuzz; -  else -  arg->glow = arg->fg; -  arg->fg = defines->alink||"#ff0000"; -  if(arg->magicbg) arg->background = arg->magicbg; -  if(arg->bevel) arg->pressed=1; +  string magic=replace(arg->magic,"'","`"); +  m_delete(arg,"magic");    -  foreach(glob("magic_*", indices(arg)), string q) +  if(!arg->fg) p->fg=defines->alink||"#ff0000"; +  if(p->bevel) p->pressed=1; +  +  if(arg->fuzz) p->glow = arg->fuzz!="fuzz"?arg->fuzz:p->fg; +  if(arg["magic-bg"]) p->background = p["magic-bg"]; +  m_delete(p,"fuzz"); +  m_delete(p,"magic-bg"); +  +  foreach(glob("magic-*", indices(arg)), string q)    { -  arg[q[6..]]=arg[q]; +  p[q[6..]]=arg[q];    m_delete(arg, q);    }    -  string num2 = image_cache->store( ({ arg, gt }),id ); +  string num2 = image_cache->store( ({ p, c }),id );    size = image_cache->metadata( num2, id ); -  +  if(size) { +  arg->width=MAX(arg->xsize,size->xsize); +  arg->height=MAX(arg->ysize,size->ysize); +  }    -  +  if(!id->supports->images) return sprintf(lp,arg->alt); +  +  string sn="i"+defines->mi++; +  if(!id->supports->netscape_javascript) { +  return (!input)? +  ("<a "+ea+"href=\""+url+"\">"+make_tag("img",arg+(["name":sn]))+"</a>"): +  make_tag("input",arg+(["type":"image"])); +  } +  +  arg->name=sn; +  string res="<script>\n";    if(!defines->magic_java) -  res = magic_javascript_header(id); +  res += "function i(ri,hi,txt)\n" +  "{\n" +  " document.images[ri].src = hi.src;\n" +  " setTimeout(\"top.window.status = '\"+txt+\"'\", 100);\n" +  "}\n";    defines->magic_java="yes"; -  if(!size) size = ([ ]); -  return replace(res + -  magic_image(url||"", size->xsize, size->ysize, "i"+(defines->mi++), -  query_internal_location()+num+gif, -  query_internal_location()+num2+gif, -  (arg->alt?arg->alt:replace(gt, "\"","'")), -  (magic=="magic"?0:magic), -  id,input?na||"submit":0,ea,lp, -  " align="+(al || defalign)), -  "</script><script>",""); +  +  return +  res+ +  " "+sn+"l = new Image("+arg->width+", "+arg->height+");"+sn+"l.src = \""+arg->src+"\";\n" +  " "+sn+"h = new Image("+arg->width+", "+arg->height+");"+sn+"h.src = \""+query_internal_location()+num2+ext+"\";\n" +  "</script>"+ +  "<a "+ea+"href=\""+url+"\" "+ +  (input?"onClick='document.forms[0].submit();' ":"") +  +"onMouseover=\"i('"+sn+"',"+sn+"h,'"+(magic=="magic"?url:magic)+"'); return true;\"\n" +  "onMouseout=\"top.window.status='';document.images['"+sn+"'].src = "+sn+"l.src;\">" +  +make_tag("img",arg)+"</a>";    } -  +     if(input) -  return (pre+"<input type=image name=\""+na+"\" border=0 alt=\""+ -  (arg->alt?arg->alt:replace(gt,"\"","'"))+ -  "\" src="+query_internal_location()+num+gif -  +" align="+(al || defalign)+ea+ -  (size?(" width="+size->xsize+" height="+size->ysize):"")+">"+ -  rest+post); +  return make_tag("input",arg+(["type":"image"]));    -  return (pre+(lp?lp:"") -  + "<img border=0 alt=\"" -  + (arg->alt?arg->alt:replace(gt,"\"","'")) -  + "\" src=\"" -  + query_internal_location()+num+gif+"\" "+ea -  + " align="+(al || defalign) -  + (size?(" width="+size->xsize+" height="+size->ysize):"")+(arg->nomxl?"":" /")+">"+ -  rest+(lp?"</a>":"")+post); +  return sprintf(lp,make_tag("img",arg));   }    -  + array(string) tag_gh(string t, mapping m, string c, RequestID id) { +  int i; +  if(sscanf(t, "%s%d", t, i)==2 && i>1) +  m->scale = (string)(1.0 / ((float)i*0.6)); +  for(i=2; i<10; i++) +  if(m[(string)i]) +  { +  m->scale = (string)(1.0 / ((float)i*0.6)); +  break; +  } +  if(!m->valign) m->valign="top"; +  return ({ "<p>"+tag_graphicstext("",m,c,id)+"<br>" }); + } +  + array(string) tag_anfang(string t, mapping m, string c, RequestID id) { +  if(!m->align) m->align="left"; +  return ({ "<br clear=\"left\">"+tag_graphicstext("",m,c[0..0],id)+c[1..] }); + } +  +  + // ------------ Wiretap code to find HTML-colours --------------------- +    inline string ns_color(array (int) col)   {    if(!arrayp(col)||sizeof(col)!=3)    return "#000000";    return sprintf("#%02x%02x%02x", col[0],col[1],col[2]);   }    -  - string|array (string) tag_body(string t, mapping args, object id, object file, + string|array (string) tag_body(string t, mapping args, RequestID id, object file,    mapping defines)   {    int cols,changed; -  if(args->help) return "This tag is parsed by &lt;gtext&gt; to get the document colors."; +     if(args->bgcolor||args->text||args->link||args->alink    ||args->background||args->vlink)    cols=1;      #define FIX(Y,Z,X) do{if(!args->Y || args->Y==""){if(cols){defines->X=Z;args->Y=Z;changed=1;}}else{defines->X=args->Y;if(QUERY(colormode)&&args->Y[0]!='#'){args->Y=ns_color(parse_color(args->Y));changed=1;}}}while(0)       if(!search((id->client||({}))*"","Mosaic"))    {    FIX(bgcolor,"#bfbfbf",bg);    FIX(text, "#000000",fg);
Roxen.git/server/modules/graphics/graphic_text.pike:1086:    FIX(bgcolor,"#c0c0c0",bg);    FIX(text, "#000000",fg);    FIX(link, "#0000ee",link);    FIX(alink, "#ff0000",alink);    FIX(vlink, "#551a8b",vlink);    }    if(changed && QUERY(colormode))    return ({make_tag("body", args) });   }    -  - string|array(string) tag_fix_color(string tagname, mapping args, object id, + string|array(string) tag_fix_color(string tagname, mapping args, RequestID id,    object file, mapping defines)   {    int changed;    -  if(args->help) return "This tag is parsed by &lt;gtext&gt; to get the document colors."; +     if(!id->misc->colors)    id->misc->colors = ({ ({ defines->fg, defines->bg, tagname }) });    else    id->misc->colors += ({ ({ defines->fg, defines->bg, tagname }) });   #undef FIX   #define FIX(X,Y) if(args->X && args->X!=""){defines->Y=args->X;if(QUERY(colormode) && args->X[0]!='#'){args->X=ns_color(parse_color(args->X));changed = 1;}}       FIX(bgcolor,bg);    FIX(text,fg);    FIX(color,fg);   #undef FIX       if(changed && QUERY(colormode))    return ({ make_tag(tagname, args) });    return 0;   }    - string|void pop_color(string tagname,mapping args,object id,object file, + string|void pop_color(string tagname,mapping args,RequestID id,object file,    mapping defines)   { -  if(args->help) return "This end-tag is parsed by &lt;gtext&gt; to get the document colors."; +     array c = id->misc->colors;    if(!c ||!sizeof(c))    return;       int i;    tagname = tagname[1..];       for(i=0;i<sizeof(c);i++)    if(c[-i-1][2]==tagname)    {    defines->fg = c[-i-1][0];    defines->bg = c[-i-1][1];    break;    }    c = c[..sizeof(c)-i-2];    id->misc->colors = c;   }    -  +  + // --------------- tag and container registration ---------------------- +    mapping query_tag_callers()   {    mapping tags = ([ "gtext-id":tag_gtext_id ]);    if(query("colorparse"))    foreach(query("colorparsing"), string t)    {    switch(t)    {    case "body":    tags[t] = tag_body;    break;    default:    tags[t] = tag_fix_color;    tags["/"+t]=pop_color;    }    }    return tags;   }    -  +    mapping query_container_callers()   { -  return ([ "anfang":tag_graphicstext, -  "gtext-url":tag_gtext_url, "gh":tag_graphicstext, - #if old_rxml_compat -  "gh1":tag_graphicstext, "gh2":tag_graphicstext, -  "gh3":tag_graphicstext, "gh4":tag_graphicstext, -  "gh5":tag_graphicstext, "gh6":tag_graphicstext, - #endif -  "gtext":tag_graphicstext, ]); +  return ([ "anfang":tag_anfang, +  "gtext-url":tag_gtext_url, "gh":tag_gh, +  "gh1":tag_gh, "gh2":tag_gh, +  "gh3":tag_gh, "gh4":tag_gh, +  "gh5":tag_gh, "gh6":tag_gh, +  "gtext":tag_graphicstext ]);   }