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 }