#!/usr/bin/perl use Gimp qw(:consts spawn_options=no-data); use Getopt::Std; #use Config '%Config'; $VERSION=2.0; getopts('rw:'); if (@ARGV<1) { my $me = $0; $me =~ s,.*[/\\],,; print STDERR <procedural_db_query ($_,"","","","","",""); } @matches or die "No matching function found\n"; @matches = sort @matches; %pf_type2string = ( &PDB_INT8 => 'INT8', &PDB_INT16 => 'INT16', &PDB_INT32 => 'INT32', &PDB_FLOAT => 'FLOAT', &PDB_STRING => 'STRING', &PDB_INT8ARRAY => 'INT8ARRAY', &PDB_INT16ARRAY => 'INT16ARRAY', &PDB_INT32ARRAY => 'INT32ARRAY', &PDB_FLOATARRAY => 'FLOATARRAY', &PDB_STRINGARRAY => 'STRINGARRAY', &PDB_COLOR => 'COLOUR', &PDB_IMAGE => 'IMAGE', &PDB_LAYER => 'LAYER', &PDB_CHANNEL => 'CHANNEL', &PDB_DRAWABLE => 'DRAWABLE', &PDB_DISPLAY => 'DISPLAY', &PDB_SELECTION => 'SELECTION', &PDB_PARASITE => 'PARASITE', &PDB_STATUS => 'STATUS', &PDB_REGION => 'REGION', &PDB_BOUNDARY => 'BOUNDARY', &PDB_PATH => 'PATH', ); sub type2str { $pf_type2string{$_[0]} ? $pf_type2string{$_[0]} : "UNKNOWN($_[0])"; } my %plugin_info; #'extension_db_browser' => ARRAY(0x8290e98) # 0 '/Xtns/DB Browser' # 1 undef # 2 '/usr/app/lib/gimp/1.1/plug-ins/dbbrowser' # 3 '' # 4 936739664 sub get_plugininfo { eval { my ($a, $b, $c, $d, $e, $f) = Gimp->plugins_query(""); for $i (0..$#$a) { $plugin_info{$f->[$i]} = [map $_->[$i], $a, $b, $c, $d, $e]; } } } sub format_html { $created_by = "

This page was created by gimpdoc, written by ". "Marc Lehmann <pcg\@goof.com>"; $nbsp = " "; ($b1,$b0)=('',''); ($sh1,$sh0)=('
',"
"); ($tt1,$tt0)=('',''); $br = "
"; $theader = <TYPENAMEDESCRIPTION EOF $tr = ""; $tend = ""; $body = ''; $section = sub { "
$_[0]
$_[1]"; }; $header = <<'EOF'; Gimp PDB documentation - $name$body $prev_fun << INDEX >> $next_fun

$name ($date)

NAME
$name - $blurb
SYNOPSIS
$vals$name$args
DESCRIPTION
$help EOF $trailer = <<'EOF';
AUTHOR
$author
(c)$date $copyright
$created_by EOF *escape = sub { $_[0] =~ s/&/&/; $_[0] =~ s//>/; # FIX: the following three lines are only required for my m4 macro package. $_[0] =~ s/{/_lbr/; $_[0] =~ s/}/{}_rbr{}/; $_[0] =~ s/_lbr/{}_lbr{}/; # do a best effort to replace function names by links $_[0] =~ s{\b([a-z_]+_[a-z_]+)\b}{ my $proc = $1; if (grep $_ eq $proc, @matches) { "$proc"; } else { $proc; } }ge; }; *table_line = sub { my ($a,$b,$c) = @_; for ($a,$b,$c) { escape($_) }; "$a$b$c"; }; } sub format_roff { $nbsp = "\\ "; ($b1,$b0)=("\\fB","\\fR"); ($sh1,$sh0)=('.SH ',"\n"); ($tt1,$tt0)=('',''); $br = "\n.br\n"; $theader = <major_version.".".Gimp->minor_version; sub gen_va(\@\@) { my @vals = @{+shift}; my @args = @{+shift}; my($vals,$args); if (@vals == 0) { $vals = ""; } elsif (@vals == 1) { $vals = "$vals[0][1]$nbsp=$nbsp"; } else { $vals = "(".join(",",map $_->[1],@vals).")$nbsp=$nbsp"; } if (@args == 0) { $args = ""; } else { $args = "$nbsp(".join(",",map $_->[1],@args).")"; } ($vals,$args); } sub isarray { return 1 if $_[0] == &PDB_INT8ARRAY; return 1 if $_[0] == &PDB_INT16ARRAY; return 1 if $_[0] == &PDB_INT32ARRAY; return 1 if $_[0] == &PDB_FLOATARRAY; return 1 if $_[0] == &PDB_STRINGARRAY; return 0; } sub killcounts(\@) { my $a = shift; my $roa=0; for(local $_=0; $_<$#$a; $_++) { if (isarray ($a->[$_+1][0]) && $a->[$_][0] == &PDB_INT32) { splice @$a, $_, 1; $roa=1; } } $roa; } sub weight { my ($v,$n,$a)=@$_; my $w = $#$v + $#$a; $w-- if $n =~ s/^\$\w+//; $w += 1-1/(1+length $n); if ($n =~ / ([A-Z][a-z]+)$/) { $w += 1 unless $1 eq ucfirst $a->[0][1]; } $w; } sub gen_alternatives(\@$\@) { my @vals = @{+shift}; my $name = shift; my @args = @{+shift}; killcounts(@vals); killcounts(@args); my @new = [\@vals,$name,\@args]; my @res; do { my @prev = @new; @new = (); for my $alt (@prev) { my @vals = @{$alt->[0]}; my $name = $alt->[1]; my @args = @{$alt->[2]}; # try to get rid of array counts unless ($name =~ /[$ ]/) { for my $class (qw( Gimp Layer Image Drawable Selection Channel Display Palette Plugin Gradients Edit Progress Region Tile PixelRgn GImpDrawable Patterns GimpParasite )) { my @pre = @{$class."::PREFIXES"}; prefix: for (@pre) { my $n2 = $name; if ($_ && $n2 =~ s/^$_//) { for my $p (@pre) { last if $_ eq $p; last prefix if Gimp::_gimp_procedure_available($p.$n2); } if ($class eq "Drawable" && @args && $args[0][0] == &PDB_DRAWABLE) { push @new, [\@vals,"\$drawable->$n2",[@args[1..$#args]]]; } elsif ($class eq "Layer" && @args && $args[0][0] == &PDB_LAYER) { push @new, [\@vals,"\$layer->$n2",[@args[1..$#args]]]; } elsif ($class eq "Channel" && @args && $args[0][0] == &PDB_CHANNEL) { push @new, [\@vals,"\$channel->$n2",[@args[1..$#args]]]; } elsif ($class eq "Image" && @args && $args[0][0] == &PDB_IMAGE) { push @new, [\@vals,"\$image->$n2",[@args[1..$#args]]]; } elsif (@args < 1 or ($args[0][0] != &PDB_IMAGE && $args[0][0] != &PDB_DRAWABLE && $args[0][0] != &PDB_CHANNEL && $args[0][0] != &PDB_LAYER)) { if ($class =~ /Gimp|Gradient|Palette|Edit|Patterns|GimpParasite|PixelRgn/) { push @new, [\@vals,"${class}->$n2",\@args]; } else { push @new, [\@vals,"$n2$nbsp$class",\@args]; } } last prefix; } } } } if (@args && $args[0][0] == &PDB_INT32 && $args[0][1] eq "run_mode") { push @new, [\@vals,,$name,[@args[1..$#args]]]; } if (@args>1 && $args[0][0] == &PDB_IMAGE && $args[1][0] == &PDB_DRAWABLE) { push @new, [\@vals,,$name,[@args[1..$#args]]]; } } push @res, @new; } while @new; map { my($vals,$args)=gen_va(@{$_->[0]},@{$_->[2]}); "${tt1}$vals${b1}$_->[1]$b0$args$tt0"; } map $_->[1], sort { $a->[0] <=> $b->[0] } map [weight($_),$_], @res; } sub gen_desc { my $name = shift; my ($blurb, $help, $author, $copyright, $date, $type, $nargs, $nvals) = Gimp->procedural_db_proc_info ($name); my @args = map [Gimp->procedural_db_proc_arg ($name, $_)],0..($nargs-1); my @vals = map [Gimp->procedural_db_proc_val ($name, $_)],0..($nvals-1); my $r; my($vals,$args)=gen_va(@vals,@args); my($menu_path, $accelerator, $path, $image_types, $mtime) = @{$plugin_info{$name}}; for ($blurb, $help, $author, $copyright, $date, $menu_path, $accelerator, $path, $image_types) { escape($_); } $r = eval "\"$header\""; $r .= $section->("MENUPATH", $menu_path) if $menu_path; $r .= $section->("IMAGETYPES", $image_types) if $image_types; $r .= $section->("ACCELERATOR", $accelerator) if $accelerator; if ($nargs) { $r .= "${sh1}INPUT ARGUMENTS$sh0$theader"; for (@args) { $r .= table_line(type2str($_->[0]),$_->[1],$_->[2]); } $r .= $tend; } if ($nvals) { $r .= "${sh1}RETURN VALUES$sh0$theader"; for (@vals) { $r .= table_line(type2str($_->[0]),$_->[1],$_->[2]); } $r .= $tend; } my @alts = gen_alternatives @vals,$name,@args; if (@alts) { @alts = @alts[0..5] if @alts > 6; $r .= "${sh1}SOME SYNTAX ALTERNATIVES$sh0". join($br, @alts). "\n"; } $r .= $section->("INSTALLATION PATH", $path) if $path; $r .= eval "\"$trailer\""; $r; } get_plugininfo; if ($opt_w) { format_html; $|=1; use POSIX 'strftime'; my $today = strftime ("%Y-%m-%d %H:%M:%SZ", gmtime time); open HTML,">$opt_w/index.html" or die "Unable to create '$opt_w/index.html': $!\n"; print "$opt_w/index.html"; my %done; print HTML <Gimp PDB Documentation, created on $today by gimpdoc$body

Gimp PDB Documentation

The following pages contain a htmlified version of the Gimp PDB documentation. They were automatically generated on $today from $version, using the program gimpdoc (part of the $version distribution). If you have any questions please direct them to Marc Lehmann <pcg\@goof.com>. EOF my($listing,$head); for $group (qw( script-fu- file_ extension_ plug_in_ perl_fu_ gimp_drawable_ gimp_channel_ gimp_layer_ gimp_image_ gimp_ ),'.') { my $some; my $glisting; for (grep /^$group/, @matches) { next if $done{$_}; $done{$_}++; my $blurb = (Gimp->procedural_db_proc_info($_))[0]; $blurb = substr($blurb,0,47)."..." if length($blurb)>50; escape($blurb); $some=1; $glisting .= "$_$blurb"; } if ($some) { my $xgroup = $group; $xgroup =~ y/-_/ /; $xgroup =~ s/\b(.)/uc($1)/ge; $xgroup = "Ungrouped Functions" if $xgroup eq "."; $head = "

$xgroup

".$head; $listing = "

$xgroup

". "
FunctionDescription". $glisting. "
". $listing; } } print HTML "$head$listing$created_by"; close HTML; print "\n"; for $_ (0..$#matches) { $prev_fun = $matches[$_-1]; $next_fun = $matches[$_+1-@matches]; $name = $matches[$_]; open HTML,">$opt_w/$name.html" or die "Unable to create '$opt_w/$name.html': $!\n"; print "$opt_w/$name.html"; print HTML gen_desc($name); close HTML; print "\n"; } } else { format_roff; $filter = "| tbl | nroff -man | ( '$ENV{PAGER}' 2>/dev/null || less || pg || more )"; $filter = ">&STDOUT" if $opt_r; open PAGER,$filter or die "unable to open pipe to the pager ($filter)\n"; if(@matches>1) { print PAGER ".TH gimpdoc gimpdoc\n.SH MATCHING FUNCTIONS\n",join("\n.br\n",@matches),"\n"; } for $name (@matches) { print PAGER gen_desc($name); } } Gimp::end; close PAGER;