#!/usr/bin/ruby -w
# uglysym.rb -- fixing textposition for gschem symbols created by old tragesym
# Copyright: S. Salewski, mail@ssalewski.de
# License: GPL
#
# I just started learning Ruby, so do not expect too nice code!
# Improvements welcome.
#
Version = '0.01 (11-APR-2009)'
#

$lines = Array.new
$changes = 0

TMP = 'tmp'
def WriteSymbolToFile(filename)
  if $changes <= 0 then return end
  if ! File.exist?(TMP)
    Dir.mkdir(TMP)
  end
  nf = TMP + '/' + filename
  if File.exist?(nf)
    print 'File ', nf, " already exits -- not overwritten!\n" 
  else
    begin
      File.open(nf, "w") do |file|
        file.puts($lines)
      end
    rescue => e
      puts e.message
    end
  end
end

def ReplacePositionLine(i, pintype, coldx, coldy)
  x, y, color, size, visibility, show_name_value, angle, alignment, num_lines = $lines[i][2..-2].split(' ').collect {|s| eval(s)}
  if ($changes < 0) or (num_lines != 1) or ((angle != 0) and (angle != 90)) # restrict our fixes
    return
  end
  text = $lines[i + 1] [0..3]
  # position data was extracted from tragesym_0.14 generated symbols by next line -- and copied in
  # print [x - coldx, y - coldy, alignment].join(', '), ' # ', [pintype, angle, text].join(', '), "\n"

  if pintype == 'leftpin' and angle == 0 
    if text == 'pinn'
      x, y, alignment = -100, 50, 6 # leftpin, 0, pinn
    elsif text == 'pins'
      x, y, alignment = -100, -50, 8 # leftpin, 0, pins
    elsif text == 'pinl'
      x, y, alignment = 50, 0, 0 # leftpin, 0, pinl
    elsif text == 'pint'
      x, y, alignment = 50, 0, 2 # leftpin, 0, pint
    else
      return
    end
  elsif  pintype == 'rightpin' and angle == 0 
   if text == 'pinn'
      x, y, alignment =  100, 50, 0 # rightpin, 0, pinn
    elsif text == 'pins'
      x, y, alignment = 100, -50, 2 # rightpin, 0, pins
    elsif text == 'pinl'
      x, y, alignment = -50, 0, 6 # rightpin, 0, pinl
    elsif text == 'pint'
      x, y, alignment = -50, 0, 8 # rightpin, 0, pint
    else
      return
    end
  elsif pintype == 'toppin' and angle == 0 
    if text == 'pinn'
      x, y, alignment = 50, 100, 0 # toppin, 0, pinn
    elsif text == 'pins'
      x, y, alignment = -50, 100, 6 # toppin, 0, pins
    elsif text == 'pinl'
      x, y, alignment = 0, -50, 5 # toppin, 0, pinl
    elsif text == 'pint'
      x, y, alignment = 0, -200, 5 # toppin, 0, pint
    else
      return
    end
  elsif  pintype == 'bottompin' and angle == 0 
   if text == 'pinn'
      x, y, alignment = 50, -100, 2 # bottompin, 0, pinn 
    elsif text == 'pins'
      x, y, alignment = -50, -100, 8 # bottompin, 0, pins
    elsif text == 'pinl'
      x, y, alignment = 0, 50, 3 # bottompin, 0, pinl
    elsif text == 'pint'
      x, y, alignment = 0, 200, 3 # bottompin, 0, pint
    else
      return
    end
  elsif pintype == 'toppin' and angle == 90
    if text == 'pinn'
      x, y, alignment = -50, 100, 0 # toppin, 90, pinn
    elsif text == 'pins'
      x, y, alignment = 50, 100, 2 # toppin, 90, pins
    elsif text == 'pinl'
      x, y, alignment = 0, -50, 6 # toppin, 90, pinl
    elsif text == 'pint'
      x, y, alignment = 0, -50, 8 # toppin, 90, pint
    else
      return
    end
  elsif  pintype == 'bottompin' and angle == 90
   if text == 'pinn'
      x, y, alignment =  -50, -100, 6 # bottompin, 90, pinn
    elsif text == 'pins'
      x, y, alignment = 50, -100, 8 # bottompin, 90, pins
    elsif text == 'pinl'
      x, y, alignment = 0, 50, 0 # bottompin, 90, pinl
    elsif text == 'pint'
      x, y, alignment = 0, 50, 2 # bottompin, 90, pint
    else
      return
    end
  else
    return
  end
  x += coldx
  y += coldy
  newpos = ['T', x, y, color, size, visibility, show_name_value, angle, alignment, num_lines].join(' ') + "\n"
  if newpos != $lines[i]
    $changes += 1
    $lines[i] = newpos
  end

end

PL = 300 # restrict fixes to pinlenght 300, you may change it to 200 or other values
def ProcessSymbol()
  i = 0
  while i < $lines.length
    if $lines[i][0,1] == 'P'
      x1, y1, x2, y2, color, pintype, whichend = $lines[i][2..-1].split(' ').collect {|s| eval(s)}
      if whichend == 0 and pintype == 0 # not tested for whichend != 0 or bus pins
      # if whichend != 0 then x1, y1, x2, y2 = x2, y2, x1, y1 # not tested, may work?
        if ((x1 - x2).abs == PL and (y1 - y2) == 0) or ((x1 - x2) == 0 and (y1 - y2).abs == PL)
          if x1 > x2 
            pintype = 'rightpin'
          elsif x1 < x2
            pintype = 'leftpin'
          elsif y1 > y2
            pintype = 'toppin'
          elsif y1 < y2
            pintype = 'bottompin'
          else
            $changes = -1; return;
          end
          i += 1
          if $lines[i][0,1] != '{' then $changes = -1; return; end
          i += 1
          while $lines[i][0,1] != '}'
            ReplacePositionLine(i, pintype, x2, y2) # set positions relative to cold end of pin
            i += 2
          end
        end
      end
    end
    i += 1
  end
end

def ProcessInputFile(name)
  begin
    File.open(name, 'r') do |f|
      while l = f.gets
        $lines << l
      end
    end
  rescue => e
    puts e.message
  end
end

def main
  if (ARGV[0] == nil) or (ARGV[0] == '-h') or (ARGV[0] == '--help')
    puts 'Plain Ruby script to fix the position of pinnumbers (of vertical and horizontal'
    puts 'pins) of gschem symbols generated with old gEDA/tragesym symbol generator.'
    puts 'Usage: ruby uglysym.rb MySym.sym (patterns like *.sym should work too)'
    puts 'The fixed version is copied to ./tmp directory with same filename.'
    puts 'Check this new version carefully by using diff, gsymcheck and gschem before'
    puts 'replacing the original. The fixed version should look identical to output of'
    puts 'tragesym 0.14 of gEDA 1.5.2.'
  else
    ARGV.each do |name|
      $lines = Array.new
      $changes = 0
      ProcessInputFile(name)
      ProcessSymbol()
      if $changes < 0
        print 'File ', name, "may be corrupt -- skipped!\n"
      else
        WriteSymbolToFile(name)
      end
    end
    #puts 'OK!'
  end
end

# Start processing after all functions are read
main

