9fans.net/go@v0.0.7/cmd/samterm/io.go (about)

     1  package main
     2  
     3  import (
     4  	"log"
     5  
     6  	"9fans.net/go/draw"
     7  	"9fans.net/go/plan9/client"
     8  )
     9  
    10  var (
    11  	protodebug bool
    12  	cursorfd   int
    13  	plumbfd    *client.Fid
    14  	got        int
    15  	block      int
    16  	kbdc       rune
    17  	resized    bool
    18  
    19  	externcmd   []rune
    20  	plumbc      chan string
    21  	hostp       []byte
    22  	hostc       chan []byte
    23  	mousectl    *draw.Mousectl
    24  	mousep      *draw.Mouse
    25  	keyboardctl *draw.Keyboardctl
    26  )
    27  
    28  func initio() {
    29  	if protodebug {
    30  		print("mouse\n")
    31  	}
    32  	mousectl = display.InitMouse()
    33  	if mousectl == nil {
    34  		log.Fatalf("mouse init failed")
    35  	}
    36  	mousep = &mousectl.Mouse
    37  	if protodebug {
    38  		print("kbd\n")
    39  	}
    40  	keyboardctl = display.InitKeyboard()
    41  	if keyboardctl == nil {
    42  		log.Fatalf("keyboard init failed")
    43  	}
    44  	if protodebug {
    45  		print("hoststart\n")
    46  	}
    47  	hoststart()
    48  	if protodebug {
    49  		print("plumbstart\n")
    50  	}
    51  	if err := plumbstart(); err != nil {
    52  		if protodebug {
    53  			print("extstart\n")
    54  		}
    55  		extstart()
    56  	}
    57  	if protodebug {
    58  		print("initio done\n")
    59  	}
    60  }
    61  
    62  func getmouse() {
    63  	mousectl.Read()
    64  }
    65  
    66  func mouseunblock() {
    67  	got &^= 1 << RMouse
    68  }
    69  
    70  func kbdblock() { /* ca suffit */
    71  	block = 1<<RKeyboard | 1<<RPlumb
    72  }
    73  
    74  func button(but int) int {
    75  	getmouse()
    76  	return mousep.Buttons & (1 << (but - 1))
    77  }
    78  
    79  func externload(cmd string) {
    80  	// TODO(rsc): drawtopwindow()
    81  	externcmd = []rune(cmd)
    82  	got |= 1 << RPlumb
    83  }
    84  
    85  func waitforio() int {
    86  	if got&^block != 0 {
    87  		return got &^ block
    88  	}
    89  
    90  again:
    91  	hostc := hostc
    92  	if block&(1<<RHost) != 0 {
    93  		hostc = nil
    94  	}
    95  	plumbc := plumbc
    96  	if block&(1<<RPlumb) != 0 {
    97  		plumbc = nil
    98  	}
    99  	kbdch := keyboardctl.C
   100  	if block&(1<<RKeyboard) != 0 {
   101  		kbdch = nil
   102  	}
   103  	mousec := mousectl.C
   104  	if block&(1<<RMouse) != 0 {
   105  		mousec = nil
   106  	}
   107  	resizec := mousectl.Resize
   108  	if block&(1<<RResize) != 0 {
   109  		resizec = nil
   110  	}
   111  
   112  	display.Flush()
   113  	select {
   114  	case hostp = <-hostc:
   115  		block = 0
   116  		got |= 1 << RHost
   117  	case cmd := <-plumbc:
   118  		externload(cmd)
   119  		got |= 1 << RPlumb
   120  	case r := <-kbdch:
   121  		kbdc = r
   122  		got |= 1 << RKeyboard
   123  	case mousectl.Mouse = <-mousec:
   124  		got |= 1 << RMouse
   125  	case <-resizec:
   126  		resized = true
   127  		/* do the resize in line if we've finished initializing and we're not in a blocking state */
   128  		if hasunlocked && block == 0 && RESIZED() {
   129  			resize()
   130  		}
   131  		goto again
   132  	}
   133  	return got
   134  }
   135  
   136  func rcvchar() int {
   137  	if got&(1<<RHost) == 0 {
   138  		return -1
   139  	}
   140  	c := hostp[0]
   141  	hostp = hostp[1:]
   142  	if len(hostp) == 0 {
   143  		got &^= 1 << RHost
   144  	}
   145  	return int(c)
   146  }
   147  
   148  func rcvstring() []byte {
   149  	got &^= 1 << RHost
   150  	return hostp
   151  }
   152  
   153  func getch() int {
   154  	var c int
   155  	for c = rcvchar(); c == -1; c = rcvchar() {
   156  		block = ^(1 << RHost)
   157  		waitforio()
   158  		block = 0
   159  	}
   160  	return c
   161  }
   162  
   163  func externchar() rune {
   164  	for got&(1<<RPlumb)&^block != 0 {
   165  		if len(externcmd) == 0 {
   166  			got &^= 1 << RPlumb
   167  			break
   168  		}
   169  		r := externcmd[0]
   170  		externcmd = externcmd[1:]
   171  		return r
   172  	}
   173  	return -1
   174  }
   175  
   176  var kpeekc rune = -1
   177  
   178  func ecankbd() bool {
   179  	if kpeekc >= 0 {
   180  		return true
   181  	}
   182  	select {
   183  	default:
   184  		return false
   185  	case r := <-keyboardctl.C:
   186  		kpeekc = r
   187  		return true
   188  	}
   189  }
   190  
   191  func ekbd() rune {
   192  	if kpeekc >= 0 {
   193  		c := kpeekc
   194  		kpeekc = -1
   195  		return c
   196  	}
   197  	return <-keyboardctl.C
   198  }
   199  
   200  func kbdchar() rune {
   201  	if c := externchar(); c > 0 {
   202  		return c
   203  	}
   204  	if got&(1<<RKeyboard) != 0 {
   205  		c := kbdc
   206  		kbdc = -1
   207  		got &^= 1 << RKeyboard
   208  		return c
   209  	}
   210  
   211  Loop:
   212  	for {
   213  		select {
   214  		default:
   215  			break Loop
   216  		case cmd := <-plumbc:
   217  			externload(cmd)
   218  			c := externchar()
   219  			if c > 0 {
   220  				return c
   221  			}
   222  		}
   223  	}
   224  	if !ecankbd() {
   225  		return -1
   226  	}
   227  	return ekbd()
   228  }
   229  
   230  func qpeekc() rune {
   231  	return kbdc
   232  }
   233  
   234  func RESIZED() bool {
   235  	if resized {
   236  		if err := display.Attach(draw.RefNone); err != nil {
   237  			panic("can't reattach to window: " + err.Error())
   238  		}
   239  		resized = false
   240  		return true
   241  	}
   242  	return false
   243  }