function write;

object get_widget_from( string what )
{
  array err;
  mixed res;
  err = catch {
    res= compile_string( "object foo(){ return "+what+"; }")()->foo();
  };
  if(!res)
    werror("Error while compiling or running "+what+"\n: %s\n", err?err[0]:"No return value");
  return res;
}

string file_name(string from)
{
  return ((MIME.encode_base64((Crypto.md5()->update(from)->
			       digest()),1)-"=")-"/")[..40]
    +".gif";
}

object ex;
string source;
int start_indent;
array(int) istack = ({});

void push_indent()
{
  istack += ({ start_indent });
}

void pop_indent()
{
  if(sizeof(istack)) start_indent = istack[-1];
  istack = istack[..sizeof(istack)-2];
}

string indent(string what, int|void limit)
{
  if(!limit) limit=40;
  string res="";
  string line="";
  int nobr;
  for(int i=0;i<strlen(what); i++)
  {
    line += what[i..i];
    switch(what[i])
    {
     case '(': push_indent(); start_indent=strlen(line); break;
     case '"': nobr = !nobr; break;
     case ')': pop_indent(); if(!(strlen(what)>i+1 && what[i+1]=='-')) break;
     case '}': pop_indent(); res += line+"\n"; line=" "*start_indent; break;
     case '{': push_indent(); start_indent += 2;
     case ';': res += line+"\n"; line=" "*start_indent; break;
     case ' ':
     case ',':
     case '>':
       if(!nobr)
       {
	 if(strlen(line) >= limit) 
	 {
	   if(strlen(line) > limit)
	   {
	     if(limit < 50) limit=strlen(line);
// 	     // break the line if possible;
// 	     string leftovers;
// 	     int pop_levels;
// 	     for(int j = strlen(line)-1; j>20; j--)
// 	     {
// 	       switch(line[j])
// 	       {
// 		case '(': pop_levels++; break;
// 		case '"': nobr = !nobr; break;
// 		case ')':
// 		  pop_levels--;
// 		  if(!(strlen(what)>j+1 && what[j+1]=='-'))
// 		    break;
// 		  if(!nobr)
// 		  {
// 		    leftovers = line[j+1..];
// 		    line = line[..j];
// 		  }
// 		  break;
// 	       }
// 	       if(leftovers)
// 		 break;
// 	     }
// 	     while(--pop_levels>0)
// 	       pop_indent();
// // 	     werror("lo=%O; li=%O\n", leftovers, line);
// 	     res += line+"\n";
// 	     line = " "*start_indent+(leftovers||"");
//  	     limit = min(strlen(line),50);
// 	     if(strlen(line)>limit-5)
// 	       limit+=5;
	   } //else {
	   res += line+"\n";
	   line = " "*start_indent;
	     //	   }
	 }
       }
    }
  }
  return res+line;
}

string tags(string source)
{
  return ("<table cellpadding=1 bgcolor=black><tr><td><table bgcolor=#e0e0e0 cellpadding=8 cellspacing=0 border=0><tr><td><img src="+file_name(source)+">"
	"</td></td><tr><td><font size=-1><pre>"+
	replace(indent(source), ({"<",">","&"}), ({"&lt;", "&gt;", "&amp;"}))+
	"</pre></font></td></tr></table></td></tr></table>");
}

void grab(object w)
{
  object i = GTK.GdkImage();
  if(w->xsize() == 40 || w->ysize() == 40 )
  {
    werror("Image dimensions are 0x0!\n");
    exit(1);
  }
  i->grab( w, 20,20, w->xsize()-40, w->ysize()-40);
  object i = Image.PNM.decode( i->get_pnm() );

  mkdir("docs");
  rm("docs/"+file_name(source));
  Stdio.write_file("docs/"+file_name(source), i->togif_fs());
  write(tags( source ));
  _exit(0);
}

int main(int argc, array (string) argv)
{
  object w;
  if(!write) write = Stdio.stdout->write;
  source = argv[1];
  if(file_stat( "docs/"+file_name(argv[1])))
  {
    werror("Image for '"+argv[1]+"' already exists\n");
    write(tags(argv[1]));
    _exit(0);
  }
  GTK.setup_gtk( "make_gtkexample", 1 );
  if(argc == 2)
  {
    w = GTK.Window( GTK.WINDOW_TOPLEVEL );
    w->set_title("Example image generation");
    w->add( ex=get_widget_from( argv[1] )->show() );
    w->border_width(20);
    w->show();
  } else {
    w = get_widget_from( argv[1] )->show();
    w->border_width(20);
    w->show();
  }
  call_out(grab,0.4,w);
  return -1;
}
