Patch title: Release 89 bulk changes
Abstract:
File: /protocol/http/default.page
Key:
    Removed line
    Added line
module "/pliant/language/context.pli"
module "/pliant/language/unsafe.pli"
module "/pliant/language/stream.pli"
module "/pliant/admin/file.pli"
module "/pliant/graphic/image/prototype.pli"
module "/pliant/graphic/image/pixmap.pli"
module "/pliant/graphic/image/resampling.pli"
module "/pliant/graphic/image/sharpening.pli"
module "/pliant/graphic/image/antialiasing.pli"
module "/pliant/graphic/color/gamut.pli"
module "/pliant/graphic/filter/io.pli"
module "/pliant/math/transform.pli"
module "/pliant/graphic/vector/outline.pli"
module "/pliant/graphic/vector/font.pli"
module "/pliant/graphic/misc/float.pli"
module "/pliant/util/encoding/http.pli"
module "/pliant/util/encoding/date.pli"
module "/pliant/protocol/http/style/common.pli"
module "cache.pli"

module "/pliant/appli/source_browser.pli"


constant page_datetime (file_query "/pliant/protocol/http/default.page" standard):datetime
constant pixel_limit 2^20
constant common_path "/common/"+string:pliant_release_number+"/"


function javascript browser s
  arg Str browser ; arg_rw Stream s
  s writeline "function refresh(focus) {"
  # s writeline "  if(document.pliant._pliant_reload.value=='true') {"
  # s writeline "    window.status='Pliant reload'"
  # s writeline "    window.location.reload(true)"
  # s writeline "    return"
  # s writeline "  }"
  s writeline "  if(focus) window.focus()"
  s writeline "  if(window.name.substring(0,6)=='_back_' && window.name.substring(7,8)=='_') {"
  s writeline "    var count = window.name.charCodeAt(6)-64"
  s writeline "    window.name = window.name.substring(8,window.name.length)"
  s writeline "    history.go(-count)"
  s writeline "    window.history.go(-count)"
  s writeline "    return"
  s writeline "  }"
  s writeline "  if(window.name.substring(0,8)=='_reload_') {"
  s writeline "    window.name = window.name.substring(8,window.name.length)"
  s writeline "    window.location = window.location.href"
  s writeline "    return"
  s writeline "  }"
  s writeline "  while(window.name.substring(0,4)=='_xy_' && window.name.substring(12,13)=='_') {"
  s writeline "    var spos = window.name.substring(4,12)"
  s writeline "    var xpos = (spos.charCodeAt(0)-65)*17576+(spos.charCodeAt(1)-65)*676+(spos.charCodeAt(2)-65)*26+spos.charCodeAt(3)-65"
  s writeline "    var ypos = (spos.charCodeAt(4)-65)*17576+(spos.charCodeAt(5)-65)*676+(spos.charCodeAt(6)-65)*26+spos.charCodeAt(7)-65"
  s writeline "    window.scrollTo(xpos,ypos)"
  s writeline "    window.name = window.name.substring(13,window.name.length)"
  s writeline "  }"
  s writeline "}"

  if browser="konqueror"
    s writeline "var current"
    s writeline "function textin(f) {"
    s writeline "  current = f.value"
    s writeline "}"
    s writeline "function textout(f) {"
    s writeline "  if(f.value!=current && f.name.substring(0,1)=='/') {"
    s writeline "    f.name = 'data'+f.name"
    s writeline "  }"
    s writeline "}"
    s writeline "function selectin(f) {"
    s writeline "  current = f.selectedIndex"
    s writeline "}"
    s writeline "function selectout(f) {"
    s writeline "  if(f.selectedIndex!=current && f.name.substring(0,1)=='/') {"
    s writeline "    f.name = 'data'+f.name"
    s writeline "  }"
    s writeline "}"
  else
    s writeline "function change(f) {"
    s writeline "  if(f.name.substring(0,1)=='/') {"
    s writeline "    f.name = 'data'+f.name"
    s writeline "  }"
    s writeline "}"

    s writeline "function complete(f) {"
    # s writeline "  document.pliant._pliant_reload.value = 'true'"
    if browser="konqueror"
      s writeline "  document.pliant.encoding = 'application/x-www-form-urlencoded'"
    s writeline "  var more = true"
    s writeline "  while(more) {"
    s writeline "    more = false"
    s writeline "    for(var i = 0; i<f.length; i++) {"
    s writeline "      if(f.elements[lb]i[rb].name.substring(0,1)=='/') {"
    s writeline "        if(f.elements[lb]i[rb].type=='select-one') {"
    s writeline "          f.elements[lb]i[rb].options[lb]0[rb].value = ''"
    s writeline "          f.elements[lb]i[rb].selectedIndex = 0"
    s writeline "        } else {"
    s writeline "          f.elements[lb]i[rb].value = ''"
    s writeline "        }[lf]"
    s writeline "        f.elements[lb]i[rb].name = ''"
    s writeline "        more = true"
    s writeline "      }"
    s writeline "      if(f.elements[lb]i[rb].name.substring(0,12)=='file upload ') {"
    s writeline "        if(f.elements[lb]i[rb].value!='') {"
    if browser="opera"
      s writeline "          document.pliant.enctype = 'multipart/form-data'"
    else
      s writeline "          document.pliant.encoding = 'multipart/form-data'"
    s writeline "        }[lf]"
    s writeline "      }"
    s writeline "    }"
    s writeline "  }"
    if browser="ie"
      s writeline "  f._pliant_x.value = document.body.scrollLeft"
      s writeline "  f._pliant_y.value = document.body.scrollTop"
    else
      s writeline "  f._pliant_x.value = window.pageXOffset"
      s writeline "  f._pliant_y.value = window.pageYOffset"
    s writeline "  return true"
    s writeline "}"

    s writeline "function button_pressed(context,target) {"
    s writeline "  document.pliant._.name = context"
    s writeline "  complete(document.pliant)"
    s writeline "  if(target) document.pliant.target=target"
    s writeline "  else document.pliant.target=window.name"
    s writeline "  document.pliant.submit()"
    s writeline "  if(target) window.setTimeout('document.pliant.target=window.name;',0)"
    s writeline "}"

    s writeline "function relative_x(x,id) {"
    s writeline "  var o = document.getElementById(id);"
    s writeline "  var a = x-o.offsetLeft;"
    s writeline "  while(o != null) {"
    s writeline "    if (o.nodeName == 'table' || o.nodeName == 'TABLE' || o.nodeName == 'td' || o.nodeName == 'TD') {"
    s writeline "      a = a-o.offsetLeft"
    s writeline "    }"
    s writeline "    o = o.parentNode"
    s writeline "  }"
    s writeline "  return a;"
    s writeline "}"
    s writeline "function relative_y(y,id) {"
    s writeline "  var o = document.getElementById(id);"
    s writeline "  var a = y-o.offsetTop;"
    s writeline "  while(o != null) {"
    s writeline "    if (o.nodeName == 'table' || o.nodeName == 'TABLE' || o.nodeName == 'td' || o.nodeName == 'TD') {"
    s writeline "      a = a-o.offsetTop"
    s writeline "    }"
    s writeline "    o = o.parentNode"
    s writeline "  }"
    s writeline "  return a;"
    s writeline "}"


method img clear p
  oarg_rw ImagePixmap img ; arg ColorRGB888 p
  for (var Int y) 0 img:size_y-1
    img fill 0 y img:size_x addressof:p

method img circle cx cy r p
  oarg_rw ImagePixmap img ; arg Int cx cy r ; arg ColorRGB888 p
  for (var Int y) cy-r cy+r
    if y>=0 and y<img:size_y
      for (var Int x) cx-r cx+r
        if x>=0 and x<img:size_x
          if (x-cx)*(x-cx)+(y-cy)*(y-cy)<=r*r
            (img pixel x y) map ColorRGB888 := p


method p index_x x -> i
  arg ImagePrototype p ; arg Float x ; arg Int i
  i := cast (x-p:x0)/(p:x1-p:x0)*p:size_x-0.499 Int

method p index_y y -> i
  arg ImagePrototype p ; arg Float y ; arg Int i
  i := cast (y-p:y0)/(p:y1-p:y0)*p:size_y-0.499 Int

function past src sx0 sy0 sx1 sy1 dest dx0 dy0 dx1 dy1
  oarg ImagePixmap src ; arg Float sx0 sy0 sx1 sy1 ; oarg_rw ImagePixmap dest ; arg Float dx0 dy0 dx1 dy1
  var Link:ImageResampling rs :> new ImageResampling
  rs bind src sx0 sy0 sx1 sy1 (cast (dx1-dx0)/(dest:x1-dest:x0)*dest:size_x Int) (cast (dy1-dy0)/(dest:y1-dest:y0)*dest:size_y Int)
  var Int tx := dest index_x dx0
  var Int ty := dest index_y dy0
  var Int ix0 := max 0 -tx
  var Int iy0 := max 0 -ty
  var Int ix1 := min rs:size_x dest:size_x-tx
  var Int iy1 := min rs:size_y dest:size_y-ty
  var Address buf := memory_allocate dest:line_size null
  if rs:gamut:transparency=1
    var Address tbuf := memory_allocate rs:line_size null
    for (var Int iy) iy0 iy1-1
      rs read ix0 iy ix1-ix0 tbuf
      var Address s := tbuf
      dest read ix0+tx iy+ty ix1-ix0 buf
      var Address d := buf
      for (var Int ix) ix0 ix1-1
        if (s map uInt8 3)>128
          memory_copy s d 3
        s := s translate Byte rs:pixel_size
        d := d translate Byte dest:pixel_size
      dest write ix0+tx iy+ty ix1-ix0 buf
    memory_free tbuf
  else
    for (var Int iy) iy0 iy1-1
      rs read ix0 iy ix1-ix0 buf
      dest write ix0+tx iy+ty ix1-ix0 buf
  memory_free buf

function past src sx0 sy0 sx1 sy1 dest dx0 dy0 dx1 dy1 color
  oarg ImagePixmap src ; arg Float sx0 sy0 sx1 sy1 ; oarg_rw ImagePixmap dest ; arg Float dx0 dy0 dx1 dy1 ; arg ColorRGB888 color
  var Link:ImageResampling rs :> new ImageResampling
  rs bind src sx0 sy0 sx1 sy1 (cast (dx1-dx0)/(dest:x1-dest:x0)*dest:size_x+0.499 Int) (cast (dy1-dy0)/(dest:y1-dest:y0)*dest:size_y+0.499 Int)
  var Int tx := dest index_x dx0
  var Int ty := dest index_y dy0
  var Int ix0 := max 0 -tx
  var Int iy0 := max 0 -ty
  var Int ix1 := min rs:size_x dest:size_x-tx
  var Int iy1 := min rs:size_y dest:size_y-ty
  var Address sbuf := memory_allocate rs:line_size null
  var Address dbuf := memory_allocate dest:line_size null
  for (var Int iy) iy0 iy1-1
    rs read ix0 iy ix1-ix0 sbuf
    var Address s := sbuf
    dest read ix0+tx iy+ty ix1-ix0 dbuf
    var Address d := dbuf
    for (var Int ix) ix0 ix1-1
      if (s map uInt8 3)>128
        var Int k := s map uInt8 1
        if k>128
          for (var Int i) 0 2
            var Int u := addressof:color map uInt8 i
            d map uInt8 i := u+(255-u)*(k-128)\127
        else
          for (var Int i) 0 2
            var Int u := addressof:color map uInt8 i
            d map uInt8 i := u*k\128
      s := s translate Byte rs:pixel_size
      d := d translate Byte dest:pixel_size
    dest write ix0+tx iy+ty ix1-ix0 dbuf
  memory_free sbuf
  memory_free dbuf

function transparency src -> dest
  oarg_rw ImagePixmap src ; arg Link:ImagePixmap dest
  dest :> new ImagePixmap
  dest setup (image_prototype src:x0 src:y0 src:x1 src:y1 src:size_x src:size_y color_gamut:"rgba") ""
  var Address sbuf := memory_allocate src:line_size null
  var Address dbuf := memory_allocate dest:line_size null
  var ColorRGB888 t := color rgb 255 255 255
  for (var Int y) 0 dest:size_y-1
    src read 0 y src:size_x sbuf
    var Address s := sbuf
    var Address d := dbuf
    for (var Int x) 0 src:size_x-1
      memory_copy s d 3
      d map uInt8 3 := shunt (memory_different s 3 addressof:t 3) 255 0
      s := s translate Byte src:pixel_size
      d := d translate Byte dest:pixel_size
    dest write 0 y dest:size_x dbuf
  memory_free sbuf
  memory_free dbuf

function dull img f color
  oarg_rw ImagePixmap img ; arg Float f ; arg ColorRGB888 color
  var Address buf := memory_allocate img:line_size null
  for (var Int y) 0 img:size_y-1
    img read 0 y img:size_x buf
    var Address p := buf
    for (var Int x) 0 img:size_x-1
      for (var Int d) 0 2
        p map uInt8 d := cast (p map uInt8 d)*(1-f)+(addressof:color map uInt8 d)*(f) Int
      p := p translate Byte img:pixel_size
    img write 0 y img:size_x buf
  memory_free buf

function blur img distance -> blured
  arg Link:ImagePixmap img ; arg Float distance ; arg Link:ImagePixmap blured
  var Address src_line := memory_allocate img:line_size null
  var Address dest_line := memory_allocate img:line_size null
  blured :> img
  for (var Int lap) 1 (cast distance*img:size_x/(abs img:x1-img:x0) Int)
    var Link:ImageSharpening op :> new ImageSharpening
    op bind img -1    
    var Link:ImagePixmap next :> new ImagePixmap
    next setup blured ""
    for (var Int y) 0 blured:size_y-1
      op read 0 y op:size_x src_line
      next write 0 y blured:size_x src_line
    blured :> next
  memory_free src_line
  memory_free dest_line

function shade img scolor blur ftx fty bgcolor
  oarg_rw ImagePixmap img ; arg ColorRGB888 scolor ; arg Float blur ftx fty ; arg ColorRGB888 bgcolor
  var Link:ImagePixmap shade :> new ImagePixmap
  shade setup (image_prototype img:x0 img:y0 img:x1 img:y1 img:size_x img:size_y img:gamut) ""
  var Address src_line := memory_allocate img:line_size null
  var Address dest_line := memory_allocate img:line_size null
  for (var Int y) 0 img:size_y-1
    img read 0 y img:size_x src_line
    for (var Int x) 0 img:size_x-1
      var Address src := src_line translate Byte x*img:pixel_size
      var Address dest := dest_line translate Byte x*shade:pixel_size
      if (memory_different src 3 addressof:bgcolor 3)
        memory_copy addressof:scolor dest 3
      else
        memory_copy addressof:bgcolor dest 3
      shade write 0 y shade:size_x dest_line
  shade :> blur shade blur
  var Int tx := cast ftx*img:size_x/(abs img:x1-img:x0) Int
  var Int ty := cast fty*img:size_y/(abs img:y1-img:y0) Int
  for (var Int y) 0 shade:size_y-1
    if y+ty>=0 and y+ty<img:size_y
      shade read 0 y shade:size_x src_line
      img read 0 y+ty img:size_x dest_line
      for (var Int x) 0 img:size_x-1
        if x+tx>=0 and x+tx<img:size_x
          var Address src := src_line translate Byte x*shade:pixel_size
          var Address dest := dest_line translate Byte (x+tx)*img:pixel_size
          if not (memory_different dest 3 addressof:bgcolor 3)
            memory_copy src dest 3
      img write 0 y+ty img:size_x dest_line
  memory_free src_line
  memory_free dest_line


function icon_file name -> file
  arg Str name file
  if (name 0 1)="/" and (name search "/icon/" -1)<>(-1)
    file := name
  else
    file := "/pliant/protocol/http/icon/"+name

function draw_corner corner options aa -> img
  arg Int corner ; arg Str options ; arg Int aa ; arg Link:ImagePixmap img
  img :> new ImagePixmap
  var Int size := options option "size" Int 5
  var ImagePrototype proto := image_prototype 0 0 1 1 size*aa size*aa color_gamut:"rgb"
  if 1n*proto:size_x*proto:size_y>=pixel_limit
    img :> null map ImagePixmap
    return
  img setup proto ""
  img clear (color hexa (options option "bgcolor" Str "FFFFFF"))
  var ColorRGB888 color := color hexa (options option "color" Str "808080")
  img circle (shunt (corner .and. 1)<>0 -1 size*aa) (shunt (corner .and. 2)<>0 -1 size*aa) size*aa color

function draw_border corner options aa -> img
  arg Int corner ; arg Str options ; arg Int aa ; arg Link:ImagePixmap img
  var Link:ImagePixmap b :> new ImagePixmap
  if (b load icon_file:(options option "button" Str "button.png") "")=failure or b:pixel_size<>4
    img :> null map ImagePixmap
    return
  if not ((options (options option_position "bsize" options:len) options:len) parse word:"bsize" (var Float size_x) (var Float size_y) any)
    size_x := b:x1-b:x0
    size_y := b:y1-b:y0
  b x0 := 0 ; b x1 := size_x
  b y0 := 0 ; b y1 := size_y
  if not ((options (options option_position "margin" options:len) options:len) parse word:"margin" (var Float left) (var Float top) (var Float right) (var Float bottom) any)
    left := 0.25*size_x
    top := 0.25*size_y
    right := 0.25*size_x
    bottom := 0.25*size_y
  var Int ix := corner%3
  var Int iy := corner\3
  var Float x0 := shunt ix=0 0 ix=1 left size_x-right
  var Float y0 := shunt iy=0 0 iy=1 top size_y-right
  var Float x1 := shunt ix=0 left ix=1 size_x-right size_x
  var Float y1 := shunt iy=0 top iy=1 size_y-bottom size_y
  img :> new ImagePixmap
  var ImagePrototype proto := image_prototype x0 y0 x1 y1 72 72 4 4 image_adjust_extend color_gamut:"rgb"
  if 1n*proto:size_x*proto:size_y>=pixel_limit
    img :> null map ImagePixmap
    return
  img setup proto ""
  img clear (color hexa (options option "bgcolor" Str "FFFFFF"))
  var ColorRGB888 color := color hexa (options option "color" Str "808080")
  past b proto:x0 proto:y0 proto:x1 proto:y1 img proto:x0 proto:y0 proto:x1 proto:y1 color

function draw_text label options style_options aa -> img
  arg Str label options style_options ; arg Int aa ; arg Link:ImagePixmap img
  if not ((options (options option_position "font" options:len) options:len) parse word:"font" (var Str face) (var Float size) any)
    face := ""
  var Link:Font f :> font face
  if not exists:f
    img :> null map ImagePixmap
    return
  var CBool shaded := ((options (options option_position "shade" options:len) options:len) parse word:"shade" (var Str scolor) (var Float blur) (var Float tx) (var Float ty) any)
  if not shaded
    tx := 0 ; ty := 0
  img :> new ImagePixmap
  f bbox label null (var Float x0) (var Float y0) (var Float x1) (var Float y1) ; x0 *= size ; y0 *= size ; x1 *= size ; y1 *= size
  var ImagePrototype proto := image_prototype x0+(min tx 0) y0+(min ty 0) x1+(max tx 0) y1+(max ty 0) 72 72 4 4 image_adjust_extend color_gamut:"rgb"
  if 1n*proto:size_x*proto:size_y>=pixel_limit
    img :> null map ImagePixmap
    return
  img setup proto ""
  var ColorRGB888 bgcolor := color hexa (options option "bgcolor" Str "FFFFFF")
  img clear bgcolor
  var ColorRGB888 color := color hexa (options option "color" Str "000000")
  img text label f null undefined (transform 0 0 size size 0 0) addressof:color
  if shaded 
    shade img (color hexa scolor) blur tx ty bgcolor

function draw_button label options style_options aa -> img
  arg Str label ; arg Str options style_options ; arg Int aa ; arg Link:ImagePixmap img
  if not ((options (options option_position "font" options:len) options:len) parse word:"font" (var Str face) (var Float size) any)
    face := ""
  var Link:Font f :> font face
  if not exists:f
    img :> null map ImagePixmap
    return
  f bbox label null (var Float x0) (var Float y0) (var Float x1) (var Float y1) ; x0 *= size ; y0 *= size ; x1 *= size ; y1 *= size
  var Float extend := options option "extend" Float
  var Float shift := 0
  if extend=defined and x1-x0<extend
    if (options option "center")
      shift := (extend-(x1-x0))/2
    x1 := x0+extend
  var Float dx := x1-x0
  var Float dy := y1-y0
  var Link:ImagePixmap b :> new ImagePixmap
  if (b load icon_file:(options option "button" Str "button.png") "")=failure or b:pixel_size<>4
    img :> null map ImagePixmap
    return
  if not ((options (options option_position "bsize" options:len) options:len) parse word:"bsize" (var Float size_x) (var Float size_y) any)
    size_x := b:x1-b:x0
    size_y := b:y1-b:y0
  b x0 := 0 ; b x1 := size_x
  b y0 := 0 ; b y1 := size_y
  if not ((options (options option_position "margin" options:len) options:len) parse word:"margin" (var Float left) (var Float top) (var Float right) (var Float bottom) any)
    left := 0.25*size_x
    top := 0.25*size_y
    right := 0.25*size_x
    bottom := 0.25*size_y
  var Float sx := size_x-left-right
  var Float sy := size_y-top-bottom
  img :> new ImagePixmap
  var ImagePrototype proto := image_prototype 0 0 left+dx+right top+dy+bottom 72 72 4 4 image_adjust_extend color_gamut:"rgb"
  if 1n*proto:size_x*proto:size_y>=pixel_limit
    img :> null map ImagePixmap
    return
  img setup proto ""
  img clear (color hexa (options option "bgcolor" Str "FFFFFF"))
  var ColorRGB888 bcolor := color hexa (options option "bcolor" Str "808080")
  for (var Int iy) 0 2
    for (var Int ix) 0 2
      past b (shunt ix=0 0 ix=1 left left+sx) (shunt iy=0 0 iy=1 top top+sy) (shunt ix=0 left ix=1 left+sx left+sx+right) (shunt iy=0 top iy=1 top+sy top+sy+bottom) img (shunt ix=0 0 ix=1 left left+dx) (shunt iy=0 0 iy=1 top top+dy) (shunt ix=0 left ix=1 left+dx left+dx+right) (shunt iy=0 top iy=1 top+dy top+dy+bottom) bcolor
  var ColorRGB888 tcolor := color hexa (options option "tcolor" Str "000000")
  img text label f null undefined (transform left-x0+shift top-y0 size size 0 0) addressof:tcolor

function draw_icon icon_name options style_options aa -> img
  arg Str icon_name ; arg Str options style_options ; arg Int aa ; arg Link:ImagePixmap img
  var Link:ImagePixmap icon :> new ImagePixmap
  if (icon load icon_file:icon_name "")=failure
    img :> null map ImagePixmap
    return
  if icon:pixel_size=3
    icon :> transparency icon
  var ColorRGB888 bcolor := color hexa (options option "bcolor" Str "808080")
  var Float dull := options option "dull" Float 0
  if dull<>0
    dull icon dull bcolor
  if not ((options (options option_position "isize" options:len) options:len) parse word:"isize" (var Float dx) (var Float dy) any)
    dx := icon:x1-icon:x0
    dy := icon:y1-icon:y0
  icon x0 := 0 ; icon x1 := dx
  icon y0 := 0 ; icon y1 := dy
  var Link:ImagePixmap b :> new ImagePixmap
  if (b load icon_file:(options option "button" Str "button.png") "")=failure or b:pixel_size<>4
    img :> null map ImagePixmap
    return
  if not ((options (options option_position "bsize" options:len) options:len) parse word:"bsize" (var Float size_x) (var Float size_y) any)
    size_x := b:x1-b:x0
    size_y := b:y1-b:y0
  b x0 := 0 ; b x1 := size_x
  b y0 := 0 ; b y1 := size_y
  if not ((options (options option_position "margin" options:len) options:len) parse word:"margin" (var Float left) (var Float top) (var Float right) (var Float bottom) any)
    left := 0.25*size_x
    top := 0.25*size_y
    right := 0.25*size_x
    bottom := 0.25*size_y
  var Float sx := size_x-left-right
  var Float sy := size_y-top-bottom
  img :> new ImagePixmap
  var ImagePrototype proto := image_prototype 0 0 left+dx+right top+dy+bottom 72 72 4 4 image_adjust_extend color_gamut:"rgb"
  if 1n*proto:size_x*proto:size_y>=pixel_limit
    img :> null map ImagePixmap
    return
  img setup proto ""
  img clear (color hexa (options option "bgcolor" Str "FFFFFF"))
  for (var Int iy) 0 2
    for (var Int ix) 0 2
      past b (shunt ix=0 0 ix=1 left left+sx) (shunt iy=0 0 iy=1 top top+sy) (shunt ix=0 left ix=1 left+sx left+sx+right) (shunt iy=0 top iy=1 top+sy top+sy+bottom) img (shunt ix=0 0 ix=1 left left+dx) (shunt iy=0 0 iy=1 top top+dy) (shunt ix=0 left ix=1 left+dx left+dx+right) (shunt iy=0 top iy=1 top+dy top+dy+bottom) bcolor
  past icon 0 0 dx dy img left top left+dx top+dy


method page bitmap_cache_redraw path -> redraw
  arg_rw HtmlPage page ; arg Str path ; arg CBool redraw
  var ExtendedStatus status := page image_cache_send path
  redraw := status=failure and status:message="no such image in the cache"

method page bitmap_cache_record path img aa
  arg_rw HtmlPage page ; arg Str path ; oarg ImagePixmap img ; arg Int aa
  if not exists:img
    return
  # FIXME: race condition
  var Link:ImageAntiAliasing final :> new ImageAntiAliasing
  final bind img aa aa
  image_cache_record final path "png" "no_lazy"
  image_cache_send path

if not (http_request modified_since page_datetime)
  reset_http_answer
  http_request send_header "status [dq]304 Not modified[dq] static nochunked"
  http_request send_footer
  return

var Str ext := virtual_path
ext := ext (ext search_last "/" -1)+1 ext:len
ext := ext (ext search_last "." ext:len) ext:len
if (virtual_path eparse "/common/icon/" any:(var Str icon))
if (virtual_path eparse pattern:common_path "icon/" any:(var Str icon))
  reset_http_answer
  http_request send_static_file "/pliant/protocol/http/icon/"+icon ""
eif virtual_path="/common/pliant.js"
eif virtual_path=common_path+"pliant.js"
  reset_http_answer
  http_request send_header "mime [dq]application/x-javascript[dq] datetime "+string:page_datetime+" static"
  javascript page:http_request:browser_model http_request:answer_stream
  http_request send_footer
eif (virtual_path parse "/common/corner " (var Int corner) any:(var Str opt))
eif (virtual_path parse pattern:common_path "corner " (var Int corner) any:(var Str opt))
  if bitmap_cache_redraw:virtual_path
    bitmap_cache_record virtual_path (draw_corner corner opt 4) 4
eif (virtual_path parse "/common/border " (var Int corner) any:(var Str opt))
eif (virtual_path parse pattern:common_path "border " (var Int corner) any:(var Str opt))
  if bitmap_cache_redraw:virtual_path
    bitmap_cache_record virtual_path (draw_border corner opt 4) 4
eif (virtual_path parse "/common/text" (var Str label) any:(var Str opt))
eif (virtual_path parse pattern:common_path "text" (var Str label) any:(var Str opt))
  if bitmap_cache_redraw:virtual_path
    bitmap_cache_record virtual_path (draw_text label opt http_request:style_options 4) 4
eif (virtual_path parse "/common/button" (var Str label) any:(var Str opt))
eif (virtual_path parse pattern:common_path "button" (var Str label) any:(var Str opt))
  if bitmap_cache_redraw:virtual_path
    bitmap_cache_record virtual_path (draw_button label opt http_request:style_options 4) 4
eif (virtual_path parse "/common/icon" (var Str icon) any:(var Str opt))
eif (virtual_path parse pattern:common_path "icon" (var Str icon) any:(var Str opt))
  if bitmap_cache_redraw:virtual_path
    bitmap_cache_record virtual_path (draw_icon icon opt http_request:style_options 4) 4
eif (virtual_path parse "/common/image/" any:(var Str id) "." any:(var Str format))
eif (virtual_path parse pattern:common_path "image/" any:(var Str id) "." any:(var Str format))
  var ExtendedStatus status := image_cache_send id
  if status=failure
    console "failed to send image: " status:message eol
eif virtual_path="/common/misc/signature.html"
eif virtual_path=common_path+"misc/signature.html"
  [The form you submitted seems to be corrupted.]
eif virtual_path="/common/misc/obsolete.html"
eif virtual_path=common_path+"misc/obsolete.html"
  [The button you selected vanished on the server, probably due to just applied update.]
eif virtual_path="/common/misc/not_allowed.html"
eif virtual_path=common_path+"misc/not_allowed.html"
  [You currently don't have read right on the requested URL.]
eif (ext=".pli" or ext=".remote" or ext=".page" or ext=".style") and allowed:"browse_source"
  reset_http_answer
  http_request send_header "mime [dq]text/html[dq] static"
  source_listing virtual_path http_request:server http_request:answer_stream
  http_request send_footer
else
  reset_http_answer