#!/usr/bin/ruby

=begin
Time-stamp: <04/09/29 22:22:22 shaolin>

MATSUBAYASHI 'Shaolin' Kohji <shaolin@vinelinux.org>

  Very sorry, the source code is too crazy and dirty.
  I didn't have much time to clean it up to be more ruby-ish so....
=end


require 'gtk'
require 'lglade'


if $DEBUG
  PIXMAPDIR = "pixmaps/"
  XYBINDIR  = "./"
  SBINDIR   = "./"
  ETCDIR    = "/tmp/"
else
  PIXMAPDIR = "/usr/share/pixmaps/xybin/"
  XYBINDIR  = "/usr/share/xybin/"
  SBINDIR   = "/usr/sbin/"
  ETCDIR    = "/etc/"
end


=begin
== class Message
* ad-hoc message hash
=end

class Message

  def initialize

    tmp = ENV["LANG"]
    case tmp
      when "ja_JP", "ja_JP.eucJP", "ja_JP.ujis"
        lang = "ja"
      else
        lang = "en"
    end

    @message = Hash::new

    create(lang)

  end


  def create(lang)

    stuff = Array::new

    if File::exist?(XYBINDIR+"#{lang}.xybin")

      f = open(XYBINDIR+"#{lang}.xybin")

      while tmp = f.gets

        tmp.chomp!
        next if tmp == ""

        stuff[0] = ""
        stuff[1] = ""

	stuff = tmp.split("\t")
	if stuff[1] != nil
          @message[stuff[0]] = stuff[1]
        else

        longmess = ""
        while mess = f.gets
          mess.chomp!
          if mess == "end"
            @message[stuff[0]] = longmess
            break
          end
          if mess == ""
            longmess += "\n"
          else
            longmess += mess
          end
        end
        end

      end

      f.close

    end

  end


  def get(key)
    return @message[key]
  end


end


=begin
== class Partmap
* Read partition maps for xybin
=end

class Partmap

  def initialize
    @partlist=Array::new
  end


  def read

    @partlist.clear

    f = open("|"+SBINDIR+"list_all_disks 2>/dev/null")

    while x = f.gets
      x.chomp!
      y = x.split("\t")
      if (y[1] == "Apple_Bootstrap")
        print "First stage bootstrap found: "+y[0]+
              " (Apple_Bootstrap, \""+y[3]+"\")\n"
        @partlist.push(Array["bootstrap",y[0],"Vine Linux Boot","",y[5]])
      end
      if (y[1] == "Apple_Boot")
        print "MacOS X bootloader found: "+y[0]+" (type UFS)\n"
        @partlist.push(Array["OSX",y[0],"UFS bootstrap","UFS",y[5]])
      end
      if (y[1] == "Apple_UNIX_SVR2" && y[2] != "swap")
        print "Linux partition found: "+y[0]+" ("+y[2]+")\n"
        @partlist.push(Array["Linux",y[0],y[2],"",y[5]])
      end
      if (y[1] == "Apple_HFS" && y[4] == "HFS")
        if (y[3] != "Vine Linux Boot")
          print "MacOS partition found: "+y[0]+" (type HFS, \""+y[3]+"\")\n"
          @partlist.push(Array["MacOS",y[0],y[3],"HFS",y[5]])
        end
        print "First stage bootstrap found: "+y[0]+
              " (Apple_HFS, \""+y[3]+"\")\n"
        @partlist.push(Array["bootstrap",y[0],y[3],"",y[5]])
      end
      if (y[1] == "Apple_HFS" && y[4] == "HFS_embedded")
        print "MacOS partition found: "+y[0]+" (type HFS+, \""+y[3]+"\")\n"
        @partlist.push(Array["MacOS",y[0],y[3],"HFS+",y[5]])
        print "MacOS X partition found: "+y[0]+" (type HFS+)\n"
        @partlist.push(Array["OSX",y[0],y[3],"HFS+",y[5]])
      end
    end

    f.close
  end

  def getlist
    return @partlist
  end

  def printout
    for tmp in @partlist
      print "\t["+tmp[0]+", "+tmp[1]+", "+tmp[2]+", "+tmp[3]+", "+tmp[4]+"]\n"
    end
  end

end


=begin
== class Xybin
* The program itself, though very dirty
=end

class Xybin


  def initialize

    @mode="Edit"	# Edit or Add

    @yabootconf = ""	# yaboot.conf contents

    @magicboot=""	# bootstrap partition
    @magicbootlist=Hash::new	# [MenuItem, value]
    @magicbootnum=Hash::new	# [MenuItem, number]

    @defaultos=""	# default OS to boot (linux, macos, macosx, ...)
    @defaultoslist=Hash::new
    @defaultosnum=Hash::new

    @entryoslist=Hash::new
    @entryosnum=Hash::new

    @linux=Array::new	# array holds linux menus (label,root,kernel,append)
    @linuxpartlist=Hash::new
    @linuxpartnum=Hash::new
    @default=""		# default entry to boot

    @kernellist=Hash::new
    @kernelnum=Hash::new

    @macospart=""	# MacOS parition
    @macospartlist=Hash::new
    @macospartnum=Hash::new
    @bootmacos="no"	# flag whether MacOS is selected

    @macosxpart=""	# MacOS X partition
    @macosxpartlist=Hash::new
    @macosxpartnum=Hash::new
    @bootmacosx="no"	# flag whether MacOS X is selected
    @brokenosx="yes"	# HFS+: yes, UFS: no

    @bootlist = Array::new
    # [ Is_Default, Label, OSType, Partition, Kernel, Arguments ]
    @bootlistnum = 0

    @delay="10"		# timeout (in seconds) to boot into default os
    @timeout="300"	# timeout (in tenths of a second) to load kernel image
    @enablecdboot="no"
    @enablenetboot="no"
    @enableofboot="no"

    tmp = ENV["LANG"]
    case tmp
      when "ja_JP", "ja_JP.eucJP", "ja_JP.ujis"
        @lang = "ja"
      else
        @lang = "en"
    end

    prepare_window_Scan()
    @window_Scan.show

    th = Thread.start do
      sleep 1
      @partmap = Partmap.new
      @partmap.read

      @window_Scan.destroy

      prepare_window_Main()
      @window_Main.show

      read_yaboot_conf
      set_bootlist
      set_clist
      set_menu_bootstrap(@partmap.getlist)
      set_menu_defaultos
      set_options

      if @bootlist.size == 0 || @linux.size == 0
        @button_Execute.set_sensitive(false)
      end

      th.exit
    end

    @message = Message.new

  end


  def gtk_main_quit
    Gtk.main_quit
  end


  def set_options
      @spinbutton_delay.set_value(@delay.to_i)
      timeout_in_s = @timeout.to_i / 10
      @spinbutton_timeout.set_value(timeout_in_s)

      @checkbutton_cdboot.set_active(true)  if @enablecdboot=="yes"
      @checkbutton_netboot.set_active(true) if @enablenetboot=="yes"
      @checkbutton_ofboot.set_active(true)  if @enableofboot=="yes"
  end


  def set_menu_kernels
    @kernellist.clear
    @kernelnum.clear
    i = 0
    menu = Gtk::Menu::new()
    for tmp in open("|/bin/ls -r /boot/vmlinux*").readlines
      tmp.chomp!
      menuitem = Gtk::MenuItem::new(tmp)
      menuitem.signal_connect("activate") do |i| set_kernel(i) end
      menuitem.show
      menu.append(menuitem)
      @kernellist[menuitem] = tmp
      @kernelnum[menuitem] = i
      i += 1
    end
    @optionmenu_Kernel.set_menu(menu)
    @optionmenu_Kernel.show
  end

  def set_kernel(i)
  end


  def set_menu_bootstrap(x)
    @magicbootlist.clear
    @magicbootnum.clear
    i = 0
    menu = Gtk::Menu::new()
    tmp = x.clone
    while b = tmp.shift
      if b[0] == "bootstrap"
        menuitem = Gtk::MenuItem::new(b[1]+" ("+b[2]+", "+b[4]+")")
        menuitem.signal_connect("activate") do |i| set_bootstrap(i) end
        menuitem.show
        menu.append(menuitem)
        @magicbootlist[menuitem] = b[1]
        @magicbootnum[menuitem] = i
        i += 1
      end
    end

    @optionmenu_Bootstrap.set_menu(menu)
    @optionmenu_Bootstrap.show

    if @magicboot != ""
      if @magicbootlist.invert[@magicboot].nil?
        @magicboot = @magicbootlist[@magicbootnum.invert[0]]
      else
        @optionmenu_Bootstrap.set_history(@magicbootnum[@magicbootlist.invert[@magicboot]])
      end
    else
      @magicboot = @magicbootlist[@magicbootnum.invert[0]]
    end
  end

  def set_bootstrap(i)
    tmp=i.to_s
    @magicboot = @magicbootlist[@optionmenu_Bootstrap.get_menu.get_active]
  end


  def set_menu_defaultos

    if @optionmenu_DefaultOS.get_menu.nil?
      @defaultoslist.clear
      @defaultosnum.clear
      menu = Gtk::Menu::new()

      menuitem = Gtk::MenuItem::new("Linux")
      menuitem.signal_connect("activate") do |i| set_defaultos(i) end
      menuitem.show
      menu.append(menuitem)
      @defaultoslist[menuitem] = "linux"
      @defaultosnum[menuitem] = 0

      menuitem = Gtk::MenuItem::new("MacOS")
      menuitem.signal_connect("activate") do |i| set_defaultos(i) end
      menuitem.show
      menu.append(menuitem)
      @defaultoslist[menuitem] = "macos"
      @defaultosnum[menuitem] = 1

      menuitem = Gtk::MenuItem::new("MacOS X")
      menuitem.signal_connect("activate") do |i| set_defaultos(i) end
      menuitem.show
      menu.append(menuitem)
      @defaultoslist[menuitem] = "macosx"
      @defaultosnum[menuitem] = 2

      @optionmenu_DefaultOS.set_menu(menu)
      @optionmenu_DefaultOS.show
    end

    if @linux.size > 0
      @defaultoslist.invert["linux"].set_sensitive(true)
    else
      @defaultoslist.invert["linux"].set_sensitive(false)
    end

    if @bootmacos == "yes"
      @defaultoslist.invert["macos"].set_sensitive(true)
    else
      @defaultoslist.invert["macos"].set_sensitive(false)
    end

    if @bootmacosx == "yes"
      @defaultoslist.invert["macosx"].set_sensitive(true)
    else
      @defaultoslist.invert["macosx"].set_sensitive(false)
    end

    if @defaultos != ""
      if ! @defaultoslist.invert[@defaultos].nil?
      @optionmenu_DefaultOS.set_history(@defaultosnum[@defaultoslist.invert[@defaultos]])
      end
    end
  end

  def set_defaultos(i)
    @defaultos = @defaultoslist[@optionmenu_DefaultOS.get_menu.get_active]
    set_clist
    on_clist_Main_unselect_row
  end


  def prepare_window_Scan

    scan = GladeXML.new(XYBINDIR+"scan-#{@lang}.glade") {|handler| method(handler)}

    @window_Scan = scan.getWidget("window_Scan")
    @pixmap_Scan = scan.getWidget("pixmap_Scan")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_Scan.window,
                      nil, PIXMAPDIR+"xybin.xpm")
    @pixmap_Scan.set(pix, mask)

  end


  def prepare_window_About

    about = GladeXML.new(XYBINDIR+"about.glade") {|handler| method(handler)}

    @window_About = about.getWidget("window_About")
    @pixmap_About = about.getWidget("pixmap_About")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_About.window,
                      nil, PIXMAPDIR+"vinelogo-trans-mini.xpm")
    @pixmap_About.set(pix, mask)

  end

  def on_button_About_OK_clicked
    @window_About.destroy
  end


  def prepare_window_Main

    main = GladeXML.new(XYBINDIR+"main-#{@lang}.glade") {|handler| method(handler)}

    @window_Main          = main.getWidget("window_Main")
    @optionmenu_Bootstrap = main.getWidget("optionmenu_Bootstrap")
    @optionmenu_DefaultOS = main.getWidget("optionmenu_DefaultOS")
    @clist_Main           = main.getWidget("clist_Main")
    @clist_Main.set_selection_mode(Gtk::SELECTION_SINGLE)
    @button_Edit          = main.getWidget("button_Edit")
    @button_Add           = main.getWidget("button_Add")
    @button_Delete        = main.getWidget("button_Delete")
    @button_Debug         = main.getWidget("button_Debug")
    @button_Execute       = main.getWidget("button_Execute")

    @spinbutton_delay     = main.getWidget("spinbutton_delay")
    @spinbutton_timeout   = main.getWidget("spinbutton_timeout")

    @checkbutton_cdboot   = main.getWidget("checkbutton_cdboot")
    @checkbutton_netboot  = main.getWidget("checkbutton_netboot")
    @checkbutton_ofboot   = main.getWidget("checkbutton_ofboot")

    @button_Debug.show if $DEBUG
  end


  def prepare_window_Entry

    entry = GladeXML.new(XYBINDIR+"entry-#{@lang}.glade") {|handler| method(handler)}

    @window_Entry          = entry.getWidget("window_Entry")
    @optionmenu_EntryOS    = entry.getWidget("optionmenu_EntryOS")
    @checkbutton_Default   = entry.getWidget("checkbutton_Default")
    @notebook_Entry        = entry.getWidget("notebook_Entry")
    @entry_LinuxLabel      = entry.getWidget("entry_LinuxLabel")
    @optionmenu_LinuxRoot  = entry.getWidget("optionmenu_LinuxRoot")
    @optionmenu_Kernel     = entry.getWidget("optionmenu_Kernel")
    @entry_LinuxArgs       = entry.getWidget("entry_LinuxArgs")
    @optionmenu_MacOSPart  = entry.getWidget("optionmenu_MacOSPart")
    @optionmenu_MacOSXPart = entry.getWidget("optionmenu_MacOSXPart")

    set_menu_entryos()
    set_menu_linuxroot(@partmap.getlist)
    set_menu_kernels()
    set_menu_macospart(@partmap.getlist)
    set_menu_macosxpart(@partmap.getlist)
  end


  def prepare_window_Format

    format = GladeXML.new(XYBINDIR+"format-#{@lang}.glade") {|handler| method(handler)}

    @window_Format = format.getWidget("window_Format")
    @text_Format   = format.getWidget("text_Format")
    @pixmap_Format = format.getWidget("pixmap_Format")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_Format.window,
                      nil, PIXMAPDIR+"gnome-warning.xpm")
    @pixmap_Format.set(pix, mask)

  end


  def prepare_window_Preview

    preview = GladeXML.new(XYBINDIR+"preview-#{@lang}.glade") {|handler| method(handler)}

    @window_Preview            = preview.getWidget("window_Preview")
    @text_Preview              = preview.getWidget("text_Preview")
    @text_Preview_yabootconf   = preview.getWidget("text_Preview_yabootconf")
    @pixmap_Preview            = preview.getWidget("pixmap_Preview")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_Preview.window,
                      nil, PIXMAPDIR+"gnome-warning.xpm")
    @pixmap_Preview.set(pix, mask)

  end


  def prepare_window_Stop

    stop = GladeXML.new(XYBINDIR+"stop-#{@lang}.glade") {|handler| method(handler)}

    @window_Stop = stop.getWidget("window_Stop")
    @text_Stop   = stop.getWidget("text_Stop")
    @pixmap_Stop = stop.getWidget("pixmap_Stop")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_Stop.window,
                      nil, PIXMAPDIR+"gnome-error.xpm")
    @pixmap_Stop.set(pix, mask)

  end


  def prepare_window_Done

    done = GladeXML.new(XYBINDIR+"done-#{@lang}.glade") {|handler| method(handler)}

    @window_Done = done.getWidget("window_Done")
    @text_Done   = done.getWidget("text_Done")
    @pixmap_Done = done.getWidget("pixmap_Done")

    pix, mask = Gdk::Pixmap.create_from_xpm(@window_Done.window,
                      nil, PIXMAPDIR+"fruity-computer.xpm")
    @pixmap_Done.set(pix, mask)

  end


  def on_button_Done_Done_clicked
    gtk_main_quit
  end

  def set_menu_entryos

    if @optionmenu_EntryOS.get_menu.nil?
      @entryoslist.clear
      @entryosnum.clear
      menu = Gtk::Menu::new()

      menuitem = Gtk::MenuItem::new("Linux")
      menuitem.signal_connect("activate") do |i| set_entryos(i) end
      menuitem.show
      menu.append(menuitem)
      @entryoslist[menuitem] = "linux"
      @entryosnum[menuitem] = 0

      menuitem = Gtk::MenuItem::new("MacOS")
      menuitem.signal_connect("activate") do |i| set_entryos(i) end
      menuitem.show
      menu.append(menuitem)
      @entryoslist[menuitem] = "macos"
      @entryosnum[menuitem] = 1

      menuitem = Gtk::MenuItem::new("MacOS X")
      menuitem.signal_connect("activate") do |i| set_entryos(i) end
      menuitem.show
      menu.append(menuitem)
      @entryoslist[menuitem] = "macosx"
      @entryosnum[menuitem] = 2

      @optionmenu_EntryOS.set_menu(menu)
      @optionmenu_EntryOS.show
    end
  end

  def set_entryos(i)
    if @entryoslist[i] == "linux"
      @checkbutton_Default.set_sensitive(true)
    else
      @checkbutton_Default.set_active(false)
      @checkbutton_Default.set_sensitive(false)
    end
    @notebook_Entry.set_page(@entryosnum[i])
  end


  def set_menu_linuxroot(x)
    @linuxpartlist.clear
    @linuxpartnum.clear
    i = 0
    menu = Gtk::Menu::new()
    tmp = x.clone
    while b = tmp.shift
      if b[0] == "Linux"
        menuitem = Gtk::MenuItem::new(b[1]+" ("+b[2]+", "+b[4]+")")
        menuitem.signal_connect("activate") do |i| set_linuxroot(i) end
        menuitem.show
        menu.append(menuitem)
        @linuxpartlist[menuitem] = b[1]
        @linuxpartnum[menuitem] = i
        i += 1
      end
    end
    @optionmenu_LinuxRoot.set_menu(menu)
    @optionmenu_LinuxRoot.show
  end

  def set_linuxroot(i)
  end


  def set_menu_macospart(x)
    @macospartlist.clear
    @macospartnum.clear
    i=0
    menu = Gtk::Menu::new()
    tmp = x.clone
    while b = tmp.shift
      if b[0] == "MacOS"
        menuitem = Gtk::MenuItem::new(b[1]+" ("+b[2]+", "+b[4]+")")
        menuitem.signal_connect("activate") do |i| set_macos(i) end
        menuitem.show
        menu.append(menuitem)
        @macospartlist[menuitem] = b[1]
        @macospartnum[menuitem] = i
        i += 1
      end
    end

    @optionmenu_MacOSPart.set_menu(menu)
    @optionmenu_MacOSPart.show

    if @macospart != ""
      if @macospartlist.invert[@macospart].nil?
        @macospart = @macospartlist[@macospartnum.invert[0]]
      else
        @optionmenu_MacOSPart.set_history(@macospartnum[@macospartlist.invert[@macospart]])
      end
    end

  end

  def set_macos(i)
    @macospart = @macospartlist[@optionmenu_MacOSPart.get_menu.get_active]
  end


  def set_menu_macosxpart(x)
    @macosxpartlist.clear
    @macosxpartnum.clear
    i = 0
    menu = Gtk::Menu::new()
    tmp = x.clone
    while b = tmp.shift
      if b[0] == "OSX"
        if b[3] == "UFS"
          menuitem = Gtk::MenuItem::new(b[1]+" ("+b[2]+")")
        else
          menuitem = Gtk::MenuItem::new(b[1]+" ("+b[2]+", "+b[4]+")")
        end
        menuitem.signal_connect("activate") do |i| set_macosx(i) end
        menuitem.show
        menu.append(menuitem)
        @macosxpartlist[menuitem] = b[1]
        @macosxpartnum[menuitem] = i
        i += 1
      end
    end

    @optionmenu_MacOSXPart.set_menu(menu)
    @optionmenu_MacOSXPart.show

    if @macosxpart != ""
      if @macosxpartlist.invert[@macosxpart].nil?
        @macosxpart = @macosxpartlist[@macosxpartnum.invert[0]]
        @brokenosx = "yes"
#        for tmp in @partmap.getlist
#          if tmp[0] == "OSX" && tmp[1] == @macosxpart && tmp[3] == "UFS"
#            @brokenosx = "no"
#          end
#        end
      else
        @optionmenu_MacOSXPart.set_history(@macosxpartnum[@macosxpartlist.invert[@macosxpart]])
      end
    end
  end

  def set_macosx(i)
    @macosxpart = @macosxpartlist[@optionmenu_MacOSXPart.get_menu.get_active]
  end


  def set_linux
    @linux.clear
    for tmp in @bootlist
      if tmp[2] == "Linux"
        label  = tmp[1]
        root   = tmp[3]
        kernel = tmp[4]
        append = tmp[5]
        @linux.push(Array[label,root,kernel,append])
      end
    end
  end


  def set_bootlist
    defaultfound = false
    @bootlist.clear

    l = Array::new
    for tmp in @linux
      l.clear
      if tmp[0] == @default
        is_default = "*"	# Is_Default
        defaultfound = true
      else
        is_default = ""
      end
      label     = tmp[0]	# Label
      ostype    = "Linux"	# OSType
      partition = tmp[1]	# Partition (for Linux)
      kernel    = tmp[2]	# Kernel
      arguments = tmp[3]	# Arguments

      @bootlist.push(Array[is_default,label,ostype,partition,kernel,arguments])
    end

    if ! defaultfound
      if @bootlist.size > 0
        @bootlist[0][0] = "*"
        @default = @bootlist[0][1]
      end
    end

    if @bootmacos == "yes"
      l.clear
      if @defaultos == "macos"
        is_default = "**"	# Is_Default
      else
        is_default = ""
      end
      label     = "(MacOS)"	# Label
      ostype    = "MacOS"	# OSType
      partition = @macospart	# Partition (for MacOS)
      kernel    = ""
      arguments = ""

      @bootlist.push(Array[is_default,label,ostype,partition,kernel,arguments])
    end

    if @bootmacosx == "yes"
      l.clear
      if @defaultos == "macosx"
        is_default = "**"	# Is_Default
      else
        is_default = ""
      end
      label     = "(MacOS X)"	# Label
      ostype    = "MacOSX"	# OSType
      partition = @macosxpart	# Partition (for MacOS X)
      kernel    = ""
      arguments = ""

      @bootlist.push(Array[is_default,label,ostype,partition,kernel,arguments])
    end

  end


  def set_clist

    @clist_Main.freeze
    @clist_Main.clear

    for tmp in @bootlist
      case tmp[2]
        when "MacOS"
          if @defaultos == "macos"
            tmp[0] = "**"
          else
            tmp[0] = ""
          end
        when "MacOSX"
          if @defaultos == "macosx"
            tmp[0] = "**"
          else
            tmp[0] = ""
          end
      end
      @clist_Main.append(tmp)
    end

    @clist_Main.thaw

  end


  def read_yaboot_conf

    label=""
    root=""
    kernel=""
    append=""

    if test("r?", "#{ETCDIR}yaboot.conf")

      f = File::open("#{ETCDIR}yaboot.conf")

      while x=f.gets
        x.chomp!
	#next unless x.include?("=")

	if x =~ /^boot=([a-z0-9\/]+)/
		@magicboot = $1

	elsif x =~ /^defaultos=(\w+)/
		@defaultos = $1

	elsif x =~ /^delay=([0-9]+)/
		@delay = $1

	elsif x =~ /^enablecdboot/
		@enablecdboot = "yes"

	elsif x =~ /^enablenetboot/
		@enablenetboot = "yes"

	elsif x =~ /^enableofboot/
		@enableofboot = "yes"

	elsif x =~ /^timeout=([0-9]+)/
		@timeout = $1

	elsif x =~ /^timeout=([0-9]+)/
		@timeout = $1

	elsif x =~ /^default=(\w+)/
		@default = $1

	elsif x =~ /^image=([\S]+:[0-9]+)?,([a-z0-9\.\-\/]+)/
		kernel = $2

	elsif x =~ /^\s+label=([a-z0-9\.\-\/]+)/
		label = $1

	elsif x =~ /^\s+root=([a-z0-9\/]+)/
		root = $1

	elsif x =~ /^\s+append="([ a-z0-9\:\,\.\-\=\/]+)"/
		append = $1

	elsif x =~ /^macos=([a-z0-9\/]+)/
		@macospart = $1
		@bootmacos = "yes"

	elsif x =~ /^macosx=([a-z0-9\/]+)/
		@macosxpart = $1
		@bootmacosx = "yes"

	elsif x =~ /^brokenosx/
		@brokenosx = "yes"

	end

        if (label!="" && root!="" && kernel!="" && append!="")
	  @linux.push(Array[label,root,kernel,append])
	  label=""
	  root=""
	  kernel=""
	  append=""
	end

      end

      f.close

    else

      @enablecdboot="yes"
      @enablenetboot="yes"
      @enableofboot="yes"

    end

    if @defaultos == ""
      if @bootmacosx == "yes"
        @defaultos = "macosx"
      end
      if @bootmacos == "yes"
        @defaultos = "macos"
      end
      if @linux.size > 0
        @defaultos = "linux"
      end
    end

  end


  def generate_yaboot_conf

    @yabootconf = ""

    @yabootconf +=
      "\n###############################################################\n"+
      "## yaboot.conf for ybin and yaboot >= 0.6\n"+
      "## generated by xybin for Vine Linux.\n"+
      "## see man yaboot.conf for more details.\n"+
      "\n\n"+

      "## bootstrap partition\n"+
      "##  - its type must be Apple_HFS or Apple_Bootstrap\n\n"+
      "boot="+@magicboot+"\n"+
      "\n"+

      "\n###############################################################\n"+
      "## First stage bootloader options\n"+
      "##\n\n"+

      "## default os to boot\n\n"+
      "defaultos="+@defaultos+"\n\n"+

      "## timeout (in seconds) to boot into default os\n\n"+
      "delay="+@delay+"\n\n"+

      "## other options - see man yaboot.conf for details\n\n"+
      "protect\n"

    @yabootconf += "enablecdboot\n"  if @enablecdboot == "yes"
    @yabootconf += "enablenetboot\n" if @enablenetboot == "yes"
    @yabootconf += "enableofboot\n"  if @enableofboot == "yes"

    @yabootconf += "\n"+

      "\n###############################################################\n"+
      "## Second stage linux bootloader options\n"+
      "##\n\n"+

      "install=/usr/lib/yaboot/yaboot\n"+
      "magicboot=/usr/lib/yaboot/ofboot\n\n"+

      "## init messages to show\n"+
      "## you can customize the message as you wish\n\n"+
      "init-message=\"\\nWelcome to Vine Linux!\\n\\n"+
                     "Hit <TAB> for boot options.\\n\\n\"\n\n"+

      "## timeout (in tenth of a second) to load default kernel image\n\n"+
      "timeout="+@timeout+"\n\n"+

      "## default Linux label to boot (only by pressing return key)\n\n"+
      "default="+@default+"\n\n"+

      "## image is the kernel itself, commonly kept in /boot.\n"+
      "## Note that /boot should generally not be its own paritions\n"+
      "## on powerpcs, it's not necessary and compilicats things.\n"+
      "## /boot should never be an HFS filesystem. You may point image=\n"+
      "## to a symbolic link as long as the symlink does not cross\n"+
      "## partition boundaries.\n\n"

    lnum = 0
    for l in @linux

      lnum+=1
      tmp = open("|/usr/sbin/ofpath "+l[1])
      @yabootconf += "image="+tmp.gets.chomp!
      @yabootconf += ","+l[2]
      tmp.close
      @yabootconf += "\n"+
        "\tlabel="+l[0]+"\n"+
        "\troot="+l[1]+"\n"+
        "\tread-only\n"+
        "\tappend=\" "+l[3]+"\"\n\n"

    end

    @yabootconf += "\n"

    if @bootmacos == "yes"
      @yabootconf += "## MacOS partition\n\n"+
                     "macos="+@macospart+"\n\n"
    end

    if @bootmacosx == "yes"
      @yabootconf += "## MacOSX partition\n\n"+
                     "macosx="+@macosxpart+"\n"
      if @brokenosx == "yes"
        @yabootconf += "brokenosx\n"
      end
      @yabootconf += "\n"
    end

  end


  def write_yaboot_conf()

    if @yabootconf == ""
      generate_yaboot_conf()
    end

    if File::exist?(ETCDIR+"yaboot.conf")
      print ETCDIR+"yaboot.conf already exists. backing it up... "
      system "mv #{ETCDIR}yaboot.conf #{ETCDIR}/yaboot.conf.backup"
      print "DONE.\n"
    else
      print ETCDIR+"yaboot.conf not found. creating a new one.\n"
    end

    print "generating #{ETCDIR}yaboot.conf ... "
    f = open(ETCDIR+"yaboot.conf", "w")
    f.puts(@yabootconf)
    f.close

    print "DONE.\n"

  end


  def do_ybin()
    print "executing ybin ...\n"
    prepare_xybin_log()
    if $DEBUG
      print "DEBUG: not really executing ybin.\n"
      status = true
    else
      status = system "/usr/sbin/ybin -v 2>&1 | tee -a /tmp/xybin.log"
    end
    print "DONE.\n"

    if status
      xybin_succeeded()
    else
      xybin_failed()
    end
  end


  def xybin_succeeded()
    prepare_window_Done()
    @text_Done.set_point(@text_Done.get_length)
    @text_Done.backward_delete(@text_Done.get_length)
    message = @message.get("Congraturations")
    @text_Done.insert(nil,nil,nil,message)
    @text_Done.set_word_wrap(true)
    @window_Done.show
  end


  def xybin_failed()
    prepare_window_Stop()
    @text_Stop.set_point(@text_Stop.get_length)
    @text_Stop.backward_delete(@text_Stop.get_length)
    message = @message.get("XybinFailed")
    @text_Stop.insert(nil,nil,nil,message)
    @text_Stop.set_word_wrap(true)
    @window_Stop.show
  end


  def prepare_xybin_log()
    f = open("/tmp/xybin.log", "w")
    f.puts("--------")
    f.puts("ybin execution log by xybin")
    f.puts(open("|/bin/date").gets)
    f.puts("--------")
    f.close
  end


  def on_about_xybin_Main_activate

    prepare_window_About()
    @window_About.show

  end


  def on_button_Edit_clicked

    @mode = "Edit"

    prepare_window_Entry()

    @optionmenu_EntryOS.set_sensitive(false)
    @entryoslist.invert["linux"].set_sensitive(false)
    @entryoslist.invert["macos"].set_sensitive(false)
    @entryoslist.invert["macosx"].set_sensitive(false)

    is_default = @bootlist[@bootlistnum][0]
    label      = @bootlist[@bootlistnum][1]
    ostype     = @bootlist[@bootlistnum][2]
    partition  = @bootlist[@bootlistnum][3]
    kernel     = @bootlist[@bootlistnum][4]
    arguments  = @bootlist[@bootlistnum][5]

    @entry_LinuxLabel.set_text(label)

    if ostype == "Linux"

      @entryoslist.invert["linux"].set_sensitive(true)
      @optionmenu_EntryOS.set_history(@entryosnum[@entryoslist.invert["linux"]])
      set_entryos(@entryoslist.invert["linux"])

      if ! @linuxpartlist.invert[partition].nil?
        @optionmenu_LinuxRoot.set_history(@linuxpartnum[@linuxpartlist.invert[partition]])
      end

      if ! @kernellist.invert[kernel].nil?
        @optionmenu_Kernel.set_history(@kernelnum[@kernellist.invert[kernel]])
      end

      @entry_LinuxArgs.set_text(arguments.to_s)
      if is_default == "*"
        @checkbutton_Default.set_active(true)
      else
        @checkbutton_Default.set_active(false)
      end

    elsif @bootlist[@bootlistnum][2] == "MacOS"

      @entryoslist.invert["macos"].set_sensitive(true)
      @optionmenu_EntryOS.set_history(@entryosnum[@entryoslist.invert["macos"]])
      set_entryos(@entryoslist.invert["macos"])

      if ! @macospartlist.invert[partition].nil?
        @optionmenu_MacOSPart.set_history(@macospartnum[@macospartlist.invert[partition]])
      end

    else

      @entryoslist.invert["macosx"].set_sensitive(true)
      @optionmenu_EntryOS.set_history(@entryosnum[@entryoslist.invert["macosx"]])
      set_entryos(@entryoslist.invert["macosx"])

      if ! @macosxpartlist.invert[partition].nil?
      @optionmenu_MacOSXPart.set_history(@macosxpartnum[@macosxpartlist.invert[partition]])
      end

    end

    @window_Entry.show
  end


  def on_button_Add_clicked

    @mode = "Add"

    prepare_window_Entry()

    @entry_LinuxLabel.set_text("")
    @entry_LinuxArgs.set_text("")

    @optionmenu_EntryOS.set_sensitive(true)
    @optionmenu_EntryOS.set_history(@entryosnum[@entryoslist.invert["linux"]])
    set_entryos(@entryoslist.invert["linux"])

    if @linux.size == 0
      @checkbutton_Default.set_active(true)
      @entry_LinuxLabel.set_text("linux")
    end

    @entryoslist.invert["linux"].set_sensitive(true)
    @entryoslist.invert["macos"].set_sensitive(true)
    @entryoslist.invert["macosx"].set_sensitive(true)

    for tmp in @bootlist
      if tmp[2] == "MacOS"
        @entryoslist.invert["macos"].set_sensitive(false)
      end
      if tmp[2] == "MacOSX"
        @entryoslist.invert["macosx"].set_sensitive(false)
      end
    end

    set_linux
    set_clist
    set_menu_defaultos
    on_clist_Main_unselect_row

    @window_Entry.show

  end


  def on_button_Delete_clicked
    ostype = @bootlist[@bootlistnum][2]
    if ostype == "MacOS"
      @bootmacos="no"
    elsif ostype == "MacOSX"
      @bootmacosx="no"
    end
    @bootlist.delete_at(@bootlistnum)
    set_linux
    set_clist
    set_menu_defaultos
    if @bootlist.size == 0 || @linux.size == 0
      @button_Execute.set_sensitive(false)
    end
    on_clist_Main_unselect_row
  end


  def show_preview

    @text_Preview_yabootconf.freeze

    font = Gdk::Font.font_load("-alias-fixed-medium-r-normal--12-*-*-*-*-*-*-*")

    @text_Preview_yabootconf.insert(font, nil, nil, @yabootconf)

    @text_Preview_yabootconf.thaw
    @text_Preview_yabootconf.show

    message = @message.get("PreviewMess")
    @text_Preview.insert(nil,nil,nil,message)
    @text_Preview.set_word_wrap(true)
  end


  def on_button_Preview_Proceed_clicked
    @window_Preview.destroy
    show_format
  end

  def on_button_Preview_Cancel_clicked
    @window_Preview.destroy
  end


  def show_format

    for tmp in @partmap.getlist
      if tmp[0] == "bootstrap" && tmp[1] == @magicboot
        hfsname = tmp[2]
        if hfsname == "--"
          hfsname = "Vine Linux Boot"
        end
        size    = tmp[4]
      end
    end

    prepare_window_Format

    @text_Format.set_point(@text_Format.get_length)
    @text_Format.backward_delete(@text_Format.get_length)
    message = @message.get("FormatMess1")+
              "\n"+
              "\t#{@magicboot}\t(\"#{hfsname}\", #{size})\n"+
              "\n"+
              @message.get("FormatMess2")
    @text_Format.insert(nil,nil,nil,message)
    @text_Format.set_word_wrap(true)
    @window_Format.show
  end


  def format_bootstrap
    print "Formatting #{@magicboot}... "
    if $DEBUG
      print "\nDEBUG: hformat -l \"Vine Linux Boot\" #{@magicboot}\n"
    else
      system "hformat -l \"Vine Linux Boot\" #{@magicboot}"
    end
    print "DONE.\n"
  end

  def on_button_Format_Format_clicked
    format_bootstrap()
    on_button_Format_No_clicked
  end

  def on_button_Format_No_clicked
    @window_Format.destroy
    write_yaboot_conf()
    do_ybin()
  end

  def on_button_Format_Cancel_clicked
    @window_Format.destroy
  end

  def on_button_Execute_clicked
    @delay = @spinbutton_delay.get_value_as_int.to_s
    timeout = @spinbutton_timeout.get_value_as_int * 10
    @timeout = timeout.to_s

    if @checkbutton_cdboot.active
      @enablecdboot="yes"
    else
      @enablecdboot="no"
    end

    if @checkbutton_netboot.active
      @enablenetboot="yes"
    else
      @enablenetboot="no"
    end

    if @checkbutton_ofboot.active
      @enableofboot="yes"
    else
      @enableofboot="no"
    end

    generate_yaboot_conf()
    prepare_window_Preview()
    show_preview()
  end


  def on_button_Stop_OK_clicked
    @window_Stop.destroy
  end

  def on_clist_Main_select_row
    @button_Edit.set_sensitive(true)
    @button_Delete.set_sensitive(true)
    @clist_Main.each_selection do |row|
      @bootlistnum = row
    end
  end

  def on_clist_Main_unselect_row
    @button_Edit.set_sensitive(false)
    @button_Delete.set_sensitive(false)
  end


  def on_button_Entry_OK_clicked

    linuxok    = true

    entryos    = @entryoslist[@optionmenu_EntryOS.get_menu.get_active]
    label      = @entry_LinuxLabel.get_text
    linuxpart  = @linuxpartlist[@optionmenu_LinuxRoot.get_menu.get_active]
    kernel     = @kernellist[@optionmenu_Kernel.get_menu.get_active]
    arguments  = @entry_LinuxArgs.get_text
    macospart  = @macospartlist[@optionmenu_MacOSPart.get_menu.get_active]
    macosxpart = @macosxpartlist[@optionmenu_MacOSXPart.get_menu.get_active]

    if entryos == "linux" && label == ""
      linuxok = false
      prepare_window_Stop()
      @text_Stop.set_point(@text_Stop.get_length)
      @text_Stop.backward_delete(@text_Stop.get_length)
      message=@message.get("NullLabel")
      @text_Stop.insert(nil,nil,nil,message)
      @text_Stop.set_word_wrap(true)
      @window_Stop.show
      @entry_LinuxLabel.grab_focus
      @entry_LinuxLabel.select_region(0,@entry_LinuxLabel.get_text.size)
    end

    if @mode == "Add"

      case entryos

        when "linux" 
          for tmp in @linux
            if tmp[0] == label
              prepare_window_Stop()
              linuxok = false
              @text_Stop.set_point(@text_Stop.get_length)
              @text_Stop.backward_delete(@text_Stop.get_length)
              message=@message.get("SameLabel")
              @text_Stop.insert(nil,nil,nil,message)
              @text_Stop.set_word_wrap(true)
              @window_Stop.show
              @entry_LinuxLabel.grab_focus
              @entry_LinuxLabel.select_region(0, @entry_LinuxLabel.get_text.size)
            end
          end
          if linuxok == true
            @linux.push(Array[label,linuxpart,kernel,arguments])
            if @checkbutton_Default.active?
              @default=label
            end
            if @defaultos==""
              @defaultos = "linux"
            end
          end

        when "macos"
          @bootmacos="yes"
          @macospart=macospart
          if @defaultos==""
            @defaultos = "macos"
          end

        when "macosx"
          @bootmacosx="yes"
          @macosxpart=macosxpart
          @brokenosx="yes"
          for tmp in @partmap.getlist
            if tmp[0] == "OSX" && tmp[1] == macosxpart && tmp[3] == "UFS"
              @brokenosx="no"
#            else
#              @brokenosx="yes"
            end
          end
          if @defaultos==""
            @defaultos = "macosx"
          end

      end

      set_bootlist
      set_clist

    elsif @mode == "Edit"

      case @bootlist[@bootlistnum][2]

        when "Linux"
          i = 0
          for tmp in @linux
            if tmp[0] == label && i != @bootlistnum
              prepare_window_Stop()
              linuxok = false
              @text_Stop.set_point(@text_Stop.get_length)
              @text_Stop.backward_delete(@text_Stop.get_length)
              message="This label name already exists. Use other name."
              @text_Stop.insert(nil,nil,nil,message)
              @text_Stop.set_word_wrap(true)
              @window_Stop.show
              @entry_LinuxLabel.grab_focus
              @entry_LinuxLabel.select_region(0, @entry_LinuxLabel.get_text.size)
            end
            i += 1
          end
          if linuxok == true
            if @checkbutton_Default.active?
              @default=label
            else
              @default="linux"
            end
            @bootlist[@bootlistnum][1] = label
            @bootlist[@bootlistnum][3] = linuxpart
            @bootlist[@bootlistnum][4] = kernel
            @bootlist[@bootlistnum][5] = arguments
            set_linux
          end

        when "MacOS"
          @macospart = macospart
           @bootlist[@bootlistnum][3] = macospart

        when "MacOSX"
          @macosxpart = macosxpart
          @bootlist[@bootlistnum][3] = macosxpart
          @brokenosx="yes"
          for tmp in @partmap.getlist
            if tmp[0] == "OSX" && tmp[1] == macosxpart && if tmp[3] == "UFS"
                @brokenosx="no"
#            else
#                @brokenosx="yes"
            end
          end
        end
      end

      set_bootlist
      set_clist
      @clist_Main.select_row(@bootlistnum,0)

    end

    if linuxok == true
      set_menu_defaultos

      if @bootlist.size > 0 && @linux.size > 0
        @button_Execute.set_sensitive(true)
      end

      @window_Entry.destroy
    end

  end


  def on_button_Entry_Cancel_clicked
    @window_Entry.destroy
  end


  def on_button_Debug_clicked

    print "ΥƥΥѡƥ\n"
    @partmap.printout

    print "@magicbootlist (bootstrap ѡƥθ)"
    print "  "+@magicbootlist.size.to_s+"\n"
    for tmp in @magicbootlist.keys
      print "\t"+@magicbootlist[tmp]+"\n"
    end

    print "@magicboot (򤵤Ƥ bootstrap ѡƥ)\n"
    print "\t"+@magicboot+"\n"

    print "@defaultos (ǥեȵư OS)\n"
    print "\t"+@defaultos+"\n"

    print "@linuxpartlist (Linux root ѡƥθ)"
    print "  "+@linuxpartlist.size.to_s+"\n"
    for tmp in @linuxpartlist.keys
      print "\t"+@linuxpartlist[tmp]+"\n"
    end

    print "@linux (Linux ȥ)"
    tmp=@linux.clone
    print "  "+tmp.size.to_s+"\n"
    while x = tmp.shift
      print "\t label="+x[0]+"\n"
      print "\t  root="+x[1]+"\n"
      print "\tkernel="+x[2]+"\n"
      print "\tappend="+x[3]+"\n"
    end

    print "@default (ǥեȵư Linux ȥ)\n"
    print "\t"+@default+"\n"

    print "@macospartlist (MacOS ѡƥθ)"
    print "  "+@macospartlist.size.to_s+"\n"
    for tmp in @macospartlist.keys
      print "\t"+@macospartlist[tmp]+"\n"
    end

    print "@bootmacos = "+@bootmacos+", "
    if @bootmacos == "yes"
      print "MacOS ϵưꥹȤˤޤ\n"
      print "@macospart (MacOS Υѡƥ)\n"
      print "\t"+@macospart+"\n"
    else
      print "MacOS ϵưꥹȤˤޤ\n"
    end

    print "@macosxpartlist (MacOS X ѡƥθ)\n"
    print "  "+@macosxpartlist.size.to_s+"\n"
    for tmp in @macosxpartlist.keys
      print "\t"+@macosxpartlist[tmp]+"\n"
    end

    print "@bootmacosx = "+@bootmacosx+", "
    if @bootmacosx == "yes"
      print "MacOSX ϵưꥹȤˤޤ\n"
      print "@macosxpart (MacOS X Υѡƥ)\n"
      print "\t"+@macosxpart+"\n"
    else
      print "MacOSX ϵưꥹȤˤޤ\n"
    end

    print "@bootlist (clist: ᥤ󥦥ɥɽ륨ȥ)"
    tmp=@bootlist.clone
    print "  "+tmp.size.to_s+"\n"
    while x = tmp.shift
      print "\t"+x[0]+","+x[1]+","+x[2]+","+x[3]+","+x[4]+","+x[5]+"\n"
    end

  end


end


begin

  xybin=Xybin.new

end

Gtk.main
