Browse Source

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 years ago
parent
commit
9495ee62f8
4 changed files with 45 additions and 19 deletions
  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")
 }