#
# This script (getGeo) takes a geometry string with flag and a toplevel
# window and returns the proper geometry string to send to the 'wm'
# command.
# This is needed because the 'wm' geo command accepts either grid units
# or pixals, depending of if the window is 'gridded'.
#
# we recognize the following flags (as part of the incoming geo):
#
#  p (or nil) in pixal units
#  g          in grid units
#  c          in the same units as the window in question
#
# The flag is taken as the first character of a geo string, i.e. fwxh+x+y
# (We pass through the x/y part and it may be nil)
#
# The "args" argument provides:
# a) a font to set x & y units (-font <font>) and/or
# b) the raw units (-xy <x>x<y>) (for example -xy 16x8) and/or
# c) the name of the window that controls the size (usually $w.text) (-window <name>)
# d) force ouput to pixial or grid (-out <p or g>)
# e) specify the boader size (1*its value) (-bd <val>)

# If the window is 'gridded' the -font and -xy options are ignored in favor
# of the 'wm grid' info. If both -font and -xy are provided, the last one
# wins.
# if -o is not provided the output is provided as needed for w.
#

# The window must be a toplevel (wm only works on toplevel windows)
#
proc getGeo {geo w args} {
  set possible {-xy -font -out -bd -window}
  foreach var $possible {
    set [string range $var 1 end] {}
  }
  set bd   0
  
  foreach {opt value} [concat {*}$args] {
    set tar [lsearch -glob -all -inline $possible "$opt*"]
    if {$tar == -1 || [llength $tar] != 1} {
      error "getGeo: option ($opt) must be one of $possible"
    }
    set [string range $tar 1 end] $value
  }

  set flag [string index $geo 0]
  if {[string is integer $flag] || $flag == "-"} {
    # the nil flag case
    set flag "p"
  } else {
    set geo [string range $geo 1 end]
  }
  lassign [wm grid $w] bw bh wI hI
  if {$flag == "c"} {
      set flag [expr {$wI == {} ? "p" : "g"}]
  }
  frputs wI hI geo
  if {![regexp {^([0-9-]+)x([0-9-]+)(.*)} $geo m ww h ex]} {
    return -code error "Ill formed geometry ($geo)."
  }
  switch -exact $flag[expr {$out != {} ? $out : $wI == {} ? "p" : "g"}] {
    pp -
    gg {return $geo}
    gp {
      if {$wI == {} } {
	if {$window != {}} {
	  set bd   [$window cget -bd]
	  set font [$window cget -font]
	}
	set bw [set bh 0]
	if {$font != {}} {
	  set wI [font measure $font "O"]
	  set hI [font metric $font -l]
	  # could add paranioa here
	} elseif {$xy != {}} {
	  lassign [split $xy x] wI hI
	} else {
	  return -code error "$w not gridded and neither -xy nor -font,\
                   \ncan't convert grid units to pixals."
	}
      }
      frputs w bw wI h bh hI
      return [expr {($ww - $bw) * $wI} +\
		  $bd + $bd]x[expr {($h - $bh) * $hI + $bd + $bd}]$ex
    }
    pg {
      frputs m w wI bw h hI bh ex
      if {$wI == {}} {
	return -code error "$w not gridded\
	    \ncan't convert pixals to grid units."
      }
      return [expr {($ww / $wI) + $bw}]x[expr {($h / $hI) + $bh}]$ex
    }
    default {return -code error "Flag must be one of {p g c}, not ($flag)."}
  }
}

