Files
go3270/example3/example3.go
T
Matthew R. Wilson b6fa48f37f Alternate screen size support.
This is a relatively big new feature, which introduces small breaking changes
to the API:

 * NegotiateTelnet() now returns (DevInfo, error) instead of just error.  The
   function signature for the Tx type now has one additional DevInfo parameter.
 * RunTransactions() requires one additional parameter, the DevInfo (which is
   allowed to be nil).

Otherwise, existing behavior continues to work as-is and everything still
defaults to operating on the default 24x80 terminal size.

See example5 for a larger-terminal-aware application.

Pending some time to make sure no new bugs cropped up in this release and that
the alternate screen size support works in the wild, I anticipate this will
become the v1.0.0 release of go3270.
2025-06-29 12:58:18 -07:00

109 lines
2.7 KiB
Go

// This file is part of https://github.com/racingmars/go3270/
// Copyright 2020 by Matthew R. Wilson, licensed under the MIT license. See
// LICENSE in the project root for license information.
// This example demonstrates updating portions of the screen while waiting
// for a client response.
package main
import (
"fmt"
"net"
"time"
"github.com/racingmars/go3270"
)
var screen = go3270.Screen{
{Row: 0, Col: 35, Intense: true, Content: "3270 Clock"},
{Row: 1, Col: 0, Color: go3270.White,
Content: "------------------------------------------------------------------------------"},
{Row: 5, Col: 5, Color: go3270.Turquoise, Content: "The current UTC time is:"},
{Row: 5, Col: 30, Color: go3270.Yellow, Intense: true, Content: "XX:XX:XX"},
{Row: 22, Col: 0, Content: "PF3 Exit"},
}
var refresh = go3270.Screen{
screen[3], // Copy the time field that we want to update
}
func main() {
ln, err := net.Listen("tcp", ":3270")
if err != nil {
panic(err)
}
fmt.Println("LISTENING ON PORT 3270 FOR CONNECTIONS")
fmt.Println("Press Ctrl-C to end server.")
for {
conn, err := ln.Accept()
if err != nil {
panic(err)
}
go handle(conn)
}
}
// handle is the handler for individual user connections.
func handle(conn net.Conn) {
defer conn.Close()
// Always begin new connection by negotiating the telnet options
if _, err := go3270.NegotiateTelnet(conn); err != nil {
fmt.Println(err)
return
}
// First, let's send the initial screen and wait forever for the user to
// press PF3, and when we get it, send a message on the done channel.
done := func() chan bool {
done := make(chan bool)
// This will run in a goroutine so it can block waiting for the
// response, while the rest of the code below (which refreshes the
// screen every second) can continue to run.
go func() {
// Loop forever, sending the background screen until user exits.
for {
screen[3].Content = time.Now().UTC().Format("15:04:05")
response, err := go3270.ShowScreenOpts(screen, nil, conn,
go3270.ScreenOpts{CursorRow: 23, CursorCol: 0})
if err != nil {
// User dropped connection, maybe? We'll end things.
done <- true
return
}
if response.AID == go3270.AIDPF3 {
// User wants to quit.
done <- true
return
}
}
}()
return done
}()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
// User pressed PF3 (or we need to quit for some other reason)
return
case <-ticker.C:
// Send the updated time, without clearing the screen
refresh[0].Content = time.Now().UTC().Format("15:04:05")
_, err := go3270.ShowScreenOpts(refresh, nil, conn,
go3270.ScreenOpts{NoClear: true, NoResponse: true})
if err != nil {
// Bail out
return
}
}
}
}