浏览代码

Added StartTime, Fixed menu, Fixed input.

Door.TimeUsed() shows how much time was used in the door.
Input now handles the stray EINTR messages.
Menu works again with Menu.AddSelection.

I'm ready to remove MenuOption and MenuOptions.
Steve Thielemann 3 年之前
父节点
当前提交
9495ee62f8
共有 4 个文件被更改,包括 45 次插入19 次删除
  1. 6 0
      door/door.go
  2. 7 7
      door/input.go
  3. 11 2
      door/menu.go
  4. 21 10
      testdoor/testdoor.go

+ 6 - 0
door/door.go

@@ -58,6 +58,7 @@ type Door struct {
 	WRITEFD      int
 	Disconnected bool
 	TimeOut      time.Time // Fixed point in time, when time expires
+	StartTime    time.Time
 	pushback     *list.List
 }
 
@@ -66,6 +67,10 @@ func (d *Door) TimeLeft() time.Duration {
 	return d.TimeOut.Sub(time.Now())
 }
 
+func (d *Door) TimeUsed() time.Duration {
+	return time.Now().Sub(d.StartTime)
+}
+
 // Read the BBS door file.  We only support door32.sys.
 func (d *Door) ReadDropfile(filename string) {
 	file, err := os.Open(filename)
@@ -103,6 +108,7 @@ func (d *Door) ReadDropfile(filename string) {
 	d.WRITEFD = d.config.comm_handle
 
 	// Calculate the time when time expires.
+	d.StartTime = time.Now()
 	d.TimeOut = time.Now().Add(time.Duration(d.config.time_left) * time.Minute)
 }
 

+ 7 - 7
door/input.go

@@ -313,22 +313,22 @@ func (d *Door) WaitKey(secs int64, usecs int64) int {
 		return -2
 	}
 
-	// var fdsetRead, fdsetWrite, fdsete syscall.FdSet
 	var fdsetRead syscall.FdSet
-	// fdsetWrite := syscall.FdSet
+
+retry:
 	clearAll(&fdsetRead)
-	// clearAll(&fdsetWrite)
-	// clearAll(&fdsete)
 	set(&fdsetRead, d.READFD)
-	// timeout := syscall.Timeval{Sec: 0, Usec: 100}
+
 	timeout := syscall.Timeval{Sec: secs, Usec: usecs}
 	v, err := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
 
 	if v == -1 {
 		errno, ok := err.(syscall.Errno)
 		if ok && errno == syscall.EINTR {
-			// Should I retry my syscall.Select here?
-			return -1
+			// Should I retry my syscall.Select here?  Yes! -1 is not return value.
+			fmt.Printf("WaitKey: EINTR\n")
+			goto retry
+			// return -1
 		}
 
 		/*

+ 11 - 2
door/menu.go

@@ -61,6 +61,13 @@ func MakeMenuRender(c1, c2, c3, c4 string) func(string) string {
 	return f
 }
 
+func (m *Menu) AddSelection(key string, text string) {
+	key = key[:1] // Make sure it is just 1 character
+	m.Options = append(m.Options, rune(key[0]))
+	linetext := "[" + key + "] " + text + strings.Repeat(" ", m.Width-(4+len(text)))
+	m.Lines = append(m.Lines, Line{Text: linetext, RenderF: m.UnselectedR})
+}
+
 // Should I be using this, or write a function like the original --
 // m.AddSelection("K", "Text") to build?  (And throw away the
 // redundant) MenuOptions/MenuOption parts?  They do let me create
@@ -170,8 +177,10 @@ func (m *Menu) Choose(d *Door) int {
 		default:
 			// Is the key in the list of options?
 			if event < 0x1000 {
-				for x, option := range m.MenuOptions {
-					if unicode.ToUpper(rune(option.Ch)) == unicode.ToUpper(rune(event)) {
+				// fmt.Printf("Event: %d\n", event)
+				for x, option := range m.Options {
+					// fmt.Printf("Checking %d, %d\n", x, option)
+					if unicode.ToUpper(option) == unicode.ToUpper(rune(event)) {
 						if m.Chosen == x {
 							return x + 1
 						}

+ 21 - 10
testdoor/testdoor.go

@@ -12,6 +12,12 @@ func pctUpdate(pct *int64) func() int64 {
 	}
 }
 
+func press_a_key(d *door.Door) {
+	d.Write(door.Reset + door.CRNL + "Press a key to continue...")
+	d.Key()
+	d.Write(door.CRNL)
+}
+
 func main() {
 	fmt.Println("Starting testdoor.go")
 	d := door.Door{}
@@ -91,9 +97,7 @@ func main() {
 
 	}
 
-	d.Write(door.Reset + door.CRNL + "Press a key to continue...")
-	d.Key()
-	d.Write(door.CRNL)
+	press_a_key(&d)
 
 	m := door.Menu{Panel: door.Panel{Width: 25,
 		X:           5,
@@ -110,11 +114,17 @@ func main() {
 		door.ColorText("BOLD WHI ON BLUE"),
 		door.ColorText("BOLD YEL ON BLUE"),
 		door.ColorText("BOLD CYAN ON BLUE"))
-	m.MenuOptions = []door.MenuOption{{rune('1'), "Play A Game"},
-		{rune('A'), "Ask BUGZ for Help"},
-		{rune('D'), "Drop to DOS"},
-		{rune('Q'), "Quit"}}
-	m.Build()
+	m.AddSelection("1", "Play A Game")
+	m.AddSelection("A", "Ask BUGZ for Help")
+	m.AddSelection("D", "Drop to DOS")
+	m.AddSelection("Q", "Quit")
+	/*
+		m.MenuOptions = []door.MenuOption{{rune('1'), "Play A Game"},
+			{rune('A'), "Ask BUGZ for Help"},
+			{rune('D'), "Drop to DOS"},
+			{rune('Q'), "Quit"}}
+		m.Build()
+	*/
 
 	// Yes, the render functions are working
 	/*
@@ -155,8 +165,7 @@ func main() {
 	d.Write(door.Reset + door.CRNL + door.CRNL)
 	d.Write(fmt.Sprintf("You chose %d from the menu."+door.CRNL, item))
 
-	d.Write(door.Reset + door.CRNL + "Press a key to continue...")
-	d.Key()
+	press_a_key(&d)
 
 	message = fmt.Sprintf("Returning %s to the BBS..."+door.CRNL, name)
 	d.Write(message)
@@ -167,6 +176,8 @@ func main() {
 
 	message = fmt.Sprintf("You had %0.2f minutes / %0.2f seconds remaining!"+door.CRNL, left.Minutes(), left.Seconds())
 	d.Write(message)
+	left = d.TimeUsed()
+	d.Write(fmt.Sprintf("You used %0.2f seconds, or %0.2f minutes."+door.CRNL, left.Seconds(), left.Minutes()))
 
 	fmt.Println("Ending testdoor.go")
 }