#!/usr/bin/perl

#imitate Form.pm for testing purposes:
 my $self = {invnumber=>"123456789012"};
 bless $self;
 *OUT = *STDOUT;
 sub cleanup {}
 sub error { shift; die @_ }
 while(<>) {
  while (/<\?lsmb (.+?) \?>/) {
   $var = $1;


################################################################################
#
#add this to Form.pm in the section, where <?lsmb variable ?> processing is done
#near line 1170 after "$var = $1;" (which is easy to find because it exists
#only one time in the file)
# 

        if ( $var =~ /^barcode (.+)/) {
            my $barcode = $self->convert_barcode($1,$i);   #see subroutine below !
            s/<\?lsmb barcode.*\?>/$barcode/m;
            next;
        }

 #parameters should be in the following format:
 #at first the LedgerSMB varibale name, which contents is to be encoded 
 # or directly a string to be encoded (only digits for most encodings)
 # it's value must comply with the requirements of GNU barcode
 #
 #then there may follow a mixture of space separated arguments:
 # the encoding as supported by GNU barcode - run barcode --help
 #	almost any encoding is accepted except:
 #	  pure numbers -> eg. use code128 instead of just"128"
 #	  "interleaved 2 of 5" -> use the abbreviation "i25" instead
 # the size <width>x<height> in mm as described under GNU barcode's geometry option
 #	but without margins - please do the placement in LaTeX instead !
 # the command "rot" or "rotate" in order to rotate the barcode 90 degree
 # the command "no-pic" or "no picture" suppresses the output of the
 #	LaTeX-picture-environment header & footer in case you want to embed this into
 #	your own picture environment 
 #
 # Examples:
 #
 # <?lsmb barcode invnumber ean13 120x40 ?>
 #
 # or
 #
 # \unitlength1mm
 # \begin{picture}(0,0)(-177,20)
 #   <?lsmb barcode 12345 rotate no-pic ?>
 # \end{picture}                       ^
 #				       |
 #                                     |
 # NOTE: the trailing space after parameters before ?> is important !

 }
 print OUT $_;
}


################################################################################
#
# also include this function, of course:
#

sub convert_barcode {
 my ($self, $parameters, $i ) = @_ ;
 my $alphanumeric; 		#normally don't accept alphanumeric digits
 my $encoding = "i25";		#defaults to interleaved 2 of 5 because I like this small and compact barcode 
 my $size = "25x10"; 		#defaults to 25x10 points
 my @offset = (0, 0);

 if($parameters =~ s/ (isbn|code\d+[bc]*|128raw|cbr|codabar|pls|plessey)//) {
   $encoding = $1;
   $alphanumeric = 1   }					#allow alphanumeric digits for these encodings in general
 elsif($parameters =~ s/ (ean-?\d*|upc-?[ae]?|i25|msi)//) {
   $encoding  = $1
 }
 if($parameters =~ s/ (\d+x\d+)([+-]\d+)?([+-]\d+)?//) {		 
  $size = $1;
  $offset[0] = eval "0$2";
  $offset[1] = eval "0$3";
 }
 my $r	     = ($parameters =~ s/rot(ate)?// )	  ? 1 : 0;	 #rotate barcode 90 degrees ?
 my $pic     = ($parameters =~ s/no.?pic(ture)?//)? 0 : 1;	 #output picture environment header & footer by default
 $parameters =~ s/\s+$//;					 #remove trailing whitespaces
 my $varname = $parameters;			 		 #the rest is regarded as the name of the varible
 my $code;
 if(exists $self->{$varname}) {					 #get the value of the LedgerSMB Variable
  $code = ( defined $i ) ? $self->{$varname}[$i] : $self->{$varname}  }
 else {
  $code = $varname;	 	 # or try to use it directly - maybe it's a fixed barcode
 }
					    
 unless($alphanumeric) {	 # do some sanity checking
  return if($code =~ /\D/)
 }
 return if (!$code);
 
 my $lastthickness;
 my $barcode;
 
 $BC = "/usr/local/bin/barcode";
 
 unless (-x $BC) {
  $self->cleanup;
  $self->error("Can't find $BC .\n");
 }
 $BC .= " -E -n -e $encoding -g $size -b \"$code\" |";

 open BC or ( chop $BC, $self->cleanup, $self->error("Error while trying to run\n $BC\n$!") );

 unless (eval '<BC> =~ /%!PS-Adobe/ && <BC> =~ /%%Creator: libbarcode/' ) {
  $self->cleanup;
  $self->error("The output of the barcode generator is not in the right libbarcode EPS format\n") }

 my $r_inv = $r-1; 				#invert $r
    $r_inv*=-1;
 local $_;
 while(<BC>) {
#                                           $1    $2
  if ($pic && $_ =~ /%%BoundingBox: 0 0 (\d+) (\d+)/) {
   my $w=$1;
   my $h=$2; $h-=20;				#remove top and bottom margins
   my $dimension = ($r) ? "$h,$w" : "$w,$h";	#rotate or not rotate dimensions
   local $"=","; 
   $barcode .= '\unitlength1mm' . "\n" .
	 "\\begin{picture}($dimension)(@offset)\n";
 }
#                  $1          $2          $3          $4
#                height       xpos        ypos       width 
  while ( /\[\s?([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\]/gx ) {
    unless( $4==$lastthickness ) {
     $barcode .= "\\linethickness{$4mm}\n";
     $lastthickness = $4
    }
    my $yp=$3-10;					#remove y-offset because we've removed margins
    my $putx = $2*$r_inv+$yp*$r;
    my $puty = $2*$r + $yp*$r_inv;
    $barcode .= "\\put($putx,$puty){\\line($r,$r_inv){$1}}\n"
  } 
  if ($pic && /% End barcode/) {
    $barcode .= "\\end{picture}\n"
  } 
 }
 close BC;
 return $barcode;
}

