===== tools/pygrub/src/pygrub 1.3 vs edited =====
--- 1.3/tools/pygrub/src/pygrub	2005-04-27 17:57:44 +09:00
+++ edited/tools/pygrub/src/pygrub	2005-05-21 22:33:09 +09:00
@@ -4,6 +4,8 @@
 #
 # Copyright 2005 Red Hat, Inc.
 # Jeremy Katz <katzj@redhat.com>
+# 
+# Copyright (C) 2005 Nguyen Anh Quynh <aquynh@gmail.com>
 #
 # This software may be freely redistributed under the terms of the GNU
 # general public license.
@@ -16,60 +18,71 @@
 import os, sys, string, struct, tempfile
 import logging
 
-import curses, _curses, curses.wrapper
+import curses, curses.wrapper
 import getopt
 
-sys.path = [ '/usr/lib/python' ] + sys.path
+sys.path = sys.path + [ '/usr/lib/python' ]
 
 import grub.GrubConf
 import grub.fsys
 
 PYGRUB_VER = 0.02
+SIZEY = 10
+SIZEX = 74
+TOPY = 2
+TOPX = 1
 
-
-def draw_window():
+def draw_window(cf):
     stdscr = curses.initscr()
-    curses.use_default_colors()
+    # curses.use_default_colors()
     try:
         curses.curs_set(0)
     except _curses.error:
         pass
 
-    stdscr.addstr(1, 4, "pyGRUB  version %s" %(PYGRUB_VER,))
+    color = cf.get_color()
+    if color != "self.color":  # show grub menu with color
+        if curses.has_colors():
+            curses.start_color()
+            menucolor = color[0]
+            itemcolor = color[1]
+            exec("curses.init_pair(1, curses.COLOR_%s, curses.COLOR_%s)" %(menucolor[0].upper(), menucolor[1].upper()))
+            exec("curses.init_pair(2, curses.COLOR_%s, curses.COLOR_%s)" %(itemcolor[0].upper(), itemcolor[1].upper()))
+        else:
+            color = "self.color"
+
+    stdscr.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,))
 
-    win = curses.newwin(10, 74, 2, 1)
+    win = curses.newwin(SIZEY, SIZEX, TOPY, TOPX)
     win.box()
     win.refresh()
 
-    stdscr.addstr(12, 5, "Use the U and D keys to select which entry is highlighted.")
-    stdscr.addstr(13, 5, "Press enter to boot the selected OS. 'e' to edit the")
-    stdscr.addstr(14, 5, "commands before booting, 'a' to modify the kernel arguments ")
-    stdscr.addstr(15, 5, "before booting, or 'c' for a command line.")
-    stdscr.addch(12, 13, curses.ACS_UARROW)
-    stdscr.addch(12, 19, curses.ACS_DARROW)
-    (y, x) = stdscr.getmaxyx()
-    stdscr.move(y - 1, x - 1)
+    stdscr.addstr(SIZEY + TOPY, TOPX + 4, "Use the U and D keys to select which entry is highlighted.")
+    stdscr.addstr(TOPY + SIZEY + 1, TOPX + 4, "Press enter to boot the selected OS. 'e' to edit the")
+    stdscr.addstr(TOPY + SIZEY + 2, TOPX + 4, "commands before booting, 'a' to modify the kernel arguments ")
+    stdscr.addstr(TOPY + SIZEY + 3, TOPX + 4, "before booting, or 'c' for a command line.")
+    stdscr.addstr(TOPY + SIZEY + 4, TOPX + 4, "Press 'q' to quit.")
+    stdscr.addch(TOPY + SIZEY, TOPX + 12, curses.ACS_UARROW)
+    stdscr.addch(TOPY + SIZEY, TOPX + 18, curses.ACS_DARROW)
 
     stdscr.refresh()
     return (stdscr, win)
 
-def fill_entries(win, cfg, selected):
-    y = 0
+def fill_entries(win, cfg, top, selected):
+    color = cf.get_color()
+    if color != "self.color":  # show grub menu with color
+        menucolor = curses.color_pair(1)
+        itemcolor = curses.color_pair(2)
+    else:
+        menucolor = 0
+        itemcolor = curses.A_REVERSE
 
-    for i in cfg.images:
-        if (0, y) > win.getmaxyx():
-            break
-        if y == selected:
-            attr = curses.A_REVERSE
+    for i in range(top, min(top + SIZEY - 2, len(cfg.images))):
+        if i == selected:
+            attr = itemcolor
         else:
-            attr = 0
-        win.addstr(y + 1, 2, i.title.ljust(70), attr)
-        y += 1
-    win.refresh()
-
-def select(win, line):
-    win.attron(curses.A_REVERSE)
-    win.redrawln(line + 1, 1)
+            attr = menucolor
+        win.addstr(i - top + 1, 2, ' ' + cfg.images[i].title.ljust(SIZEX - 5)[:SIZEX - 5], attr)
     win.refresh()
 
 def is_disk_image(file):
@@ -77,18 +90,19 @@
     buf = os.read(fd, 512)
     os.close(fd)
 
-    if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
+    if len(buf) == 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
         return True
     return False
 
 def get_config(fn):
+
     if not os.access(fn, os.R_OK):
         raise RuntimeError, "Unable to access %s" %(fn,)
 
     cf = grub.GrubConf.GrubConfigFile()
 
     if is_disk_image(fn):
-        raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
+        raise RuntimeError, "Appears to be a full disk image... unable to handle this yet"
 
     # open the image and read the grub config
     fs = None
@@ -103,7 +117,7 @@
         elif fs.file_exist("/boot/grub/grub.conf"):
             grubfile = "/boot/grub/grub.conf"
         else:
-            raise RuntimeError, "we couldn't find /boot/grub{menu.lst,grub.conf} " + \
+            raise RuntimeError, "We couldn't find /boot/grub/{menu.lst,grub.conf} " + \
                                 "in the image provided. halt!"
         f = fs.open_file(grubfile)
         buf = f.read()
@@ -136,24 +150,28 @@
 def main(cf = None):
     mytime = 0
 
-    (stdscr, win) = draw_window()
+    (stdscr, win) = draw_window(cf)
     stdscr.timeout(1000)
     selected = cf.default
+    top = 0
+    stdscr.addstr(SIZEY + TOPY + 8, TOPX + 4, "Will boot selected entry in %2d seconds"
+                  %(int(cf.timeout) - mytime))
     
     while (mytime < int(cf.timeout)):
-        if cf.timeout != -1 and mytime != -1: 
-            stdscr.addstr(20, 5, "Will boot selected entry in %2d seconds"
-                          %(int(cf.timeout) - mytime))
-        else:
-            stdscr.addstr(20, 5, " " * 80)
             
-        fill_entries(win, cf, selected)
+        fill_entries(win, cf, top, selected)
         c = stdscr.getch()
-        if mytime != -1:
-            mytime += 1
-#        if c == ord('q'):
-#            selected = -1
-#            break
+        if (c == -1):
+            if mytime != -1:
+                mytime += 1
+                stdscr.addstr(SIZEY + TOPY + 8, TOPX + 4, "Will boot selected entry in %2d seconds"
+                              %(int(cf.timeout) - mytime))
+        elif mytime != -1:
+            stdscr.addstr(SIZEY + TOPY + 8, TOPX + 4, " " * 80)
+            mytime = -1
+        if c == ord('q'):
+           selected = -1
+           break
         elif c == ord('c'):
             # FIXME: needs to go to command line mode
             continue
@@ -164,30 +182,36 @@
             # FIXME: needs to go to edit mode
             continue
         elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')):
-            break
+            if not cf.images[selected].get_kernel() == None:    # is this an illegal kernel ?
+                break
         elif c == curses.KEY_UP:
-            mytime = -1
-            selected -= 1
+            if selected == top:
+                if top > 0:
+                    # bound at the top
+                    top -= 1
+                    selected = top
+            else:
+                selected -= 1
         elif c == curses.KEY_DOWN:
-            mytime = -1
-            selected += 1
-        else:
-            pass
+            if selected == len(cf.images) - 1:
+                continue
+            if selected == top + SIZEY - 3:
+                if top + SIZEY - 2 < len(cf.images):
+                    # bound at the bottom
+                    top +=1
+                    selected = top + SIZEY - 3
+            else:
+                selected += 1
 
-        # bound at the top and bottom
-        if selected < 0:
-            selected = 0
-        elif selected >= len(cf.images):
-            selected = len(cf.images) - 1
-
-    if selected >= 0:
-        return selected
+    return selected
 
 if __name__ == "__main__":
     sel = None
+    cf = None
     
     def run_main(scr, *args):
         global sel
+        global cf
         sel = main(cf)
 
     def usage():
@@ -229,13 +253,15 @@
     cf = get_config(file)
     if interactive:
         curses.wrapper(run_main)
+        if sel == -1:   # user has chosen to quit
+            sys.exit(1)
     else:
         sel = cf.default
 
     # set the entry to boot as requested
     if entry is not None:
         idx = get_entry_idx(cf, entry)
-        if idx is not None and idx > 0 and idx < len(cf.images):
+        if idx is not None and idx >= 0 and idx < len(cf.images):
             sel = idx
 
     img = cf.images[sel]
@@ -244,35 +270,29 @@
     if img.initrd:
         print "  initrd: %s" %(img.initrd[1],)
 
-    if is_disk_image(file):
-        raise RuntimeError, "unable to handle full disk images yet"
-
     # read the kernel and initrd onto the hostfs
     fs = None
     for fstype in grub.fsys.fstypes.values():
         if fstype.sniff_magic(file):
             fs = fstype.open_fs(file)
             break
-
-    if fs is None:
-        raise RuntimeError, "Unable to open filesystem"
+    else:
+        raise RuntimeError, "Unable to open filesystem or filesystem not supported"
 
     kernel = fs.open_file(img.kernel[1],).read()
     (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.")
     os.write(tfd, kernel)
     os.close(tfd)
-    sxp = "linux (kernel %s)" %(fn,)
+    sxp = "linux (kernel %s) " %(fn,)
 
     if img.initrd:
         initrd = fs.open_file(img.initrd[1],).read()
         (tfd, fn) = tempfile.mkstemp(prefix="initrd.")
         os.write(tfd, initrd)
         os.close(tfd)
-        sxp += "(ramdisk %s)" %(fn,)
-    else:
-        initrd = None
-    sxp += "(args '%s')" %(img.args,)
+        sxp += "(ramdisk %s) " %(fn,)
+
+    sxp += "(args '%s')\n" %(img.args,)
 
     sys.stdout.flush()
     os.write(fd, sxp)
-    
