Skip to content

Commit

Permalink
merge github.com/fhs/9fans-go plan9 branch
Browse files Browse the repository at this point in the history
Fixes #28.
  • Loading branch information
rsc committed Apr 6, 2024
2 parents 6b41da1 + df43687 commit 4083899
Show file tree
Hide file tree
Showing 21 changed files with 831 additions and 343 deletions.
4 changes: 0 additions & 4 deletions acme/acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ var fsys *client.Fsys
var fsysErr error
var fsysOnce sync.Once

func mountAcme() {
fsys, fsysErr = client.MountService("acme")
}

// AutoExit sets whether to call os.Exit the next time the last managed acme window is deleted.
// If there are no acme windows at the time of the call, the exit does not happen until one
// is created and then deleted.
Expand Down
11 changes: 11 additions & 0 deletions acme/acme_p9p.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build !plan9

package acme

import "9fans.net/go/plan9/client"

func mountAcme() {
fs, err := client.MountService("acme")
fsys = fs
fsysErr = err
}
11 changes: 11 additions & 0 deletions acme/acme_plan9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package acme

import (
"9fans.net/go/plan9/client"
)

func mountAcme() {
// Already mounted at /mnt/acme
fsys = &client.Fsys{Mtpt: "/mnt/acme"}
fsysErr = nil
}
66 changes: 62 additions & 4 deletions draw/alloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package draw

import (
"fmt"
"os"
"runtime"
"strings"
)

// AllocImage allocates a new Image on display d.
Expand All @@ -28,7 +30,6 @@ import (
// used to paint a region red:
//
// red, err := display.AllocImage(draw.Rect(0, 0, 1, 1), draw.RGB24, true, draw.Red)
//
func (d *Display) AllocImage(r Rectangle, pix Pix, repl bool, color Color) (*Image, error) {
d.mu.Lock()
defer d.mu.Unlock()
Expand Down Expand Up @@ -104,11 +105,68 @@ func allocImage(d *Display, ai *Image, r Rectangle, pix Pix, repl bool, val Colo
return i, nil
}

/*
func namedimage(d *Display, name string) (*Image, nil) {
panic("namedimage")
func namedImage(d *Display, ai *Image, name string) (i *Image, err error) {
n := len(name)
if n >= 256 {
return nil, fmt.Errorf("namedImage: name too long")
}
// flush pending data so we don't get error allocating the image
d.flush(false)
a := d.bufimage(1 + 4 + 1 + n)
d.imageid++
id := d.imageid
a[0] = 'n'
bplong(a[1:], id)
a[5] = byte(n)
copy(a[6:], name)
if err := d.flush(false); err != nil {
fmt.Fprintf(os.Stderr, "namedImage: %v\n", err)
return nil, err
}

a = d.bufimage(1)
a[0] = 'I'
if err := d.flush(false); err != nil {
fmt.Fprintf(os.Stderr, "cannot read image info: %v\n", err)
return nil, err
}
info := make([]byte, 12*12)
n, err = d.conn.ReadDraw(info)
if err != nil {
return nil, err
}
if n < len(info) {
return nil, fmt.Errorf("short info from rddraw")
}

pix, err := ParsePix(strings.TrimSpace(string(info[2*12 : 3*12])))
if err != nil {
a := d.bufimage(1 + 4)
a[0] = 'f'
bplong(a[1:], id)
d.flush(false)
return nil, fmt.Errorf("bad channel %q from devdraw", info[2*12:3*12])
}
i = ai
if i == nil {
i = new(Image)
}
*i = Image{
Display: d,
id: id,
Pix: pix,
Depth: pix.Depth(),
Repl: atoi(info[3*12:]) > 0,
R: ator(info[4*12:]),
Clipr: ator(info[8*12:]),
Screen: nil,
next: nil,
}
runtime.SetFinalizer(i, (*Image).Free)
return i, nil
}

/*
func nameimage(i *Image, name string, in bool) error {
a := i.Display.bufimage(1+4+1+1+len(name))
a[0] = 'N'
Expand Down
2 changes: 2 additions & 0 deletions draw/drawfcall/mux.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build !plan9

package drawfcall

import (
Expand Down
264 changes: 264 additions & 0 deletions draw/drawfcall/mux_plan9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
package drawfcall

import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"image"
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
)

type Conn struct {
ctl *os.File
data *os.File
cons *bufio.Reader
consctl *os.File
mouse *os.File
snarf *os.File
cursor *os.File
n int // connection number
initCtl []byte
oldLabel string

readData []byte
ctlWasRead bool
lk sync.Mutex
}

func New() (*Conn, error) {
ctl, err := os.OpenFile("/dev/draw/new", os.O_RDWR, 0)
if err != nil {
return nil, err
}

var b [12*12 + 1]byte
nr, err := ctl.Read(b[:])
if err != nil {
return nil, err
}
f := strings.Fields(string(b[:nr]))
if len(f) != 12 {
return nil, fmt.Errorf("bad ctl file")
}
n, err := strconv.Atoi(f[0])
if err != nil {
return nil, err
}

data, err := os.OpenFile(fmt.Sprintf("/dev/draw/%v/data", n), os.O_RDWR, 0)
if err != nil {
return nil, err
}
cons, err := os.Open("/dev/cons")
if err != nil {
return nil, err
}

consctl, err := os.OpenFile("/dev/consctl", os.O_WRONLY, 0)
if err != nil {
return nil, err
}
_, err = consctl.WriteString("rawon")
if err != nil {
return nil, err
}

mouse, err := os.OpenFile("/dev/mouse", os.O_RDWR, 0)
if err != nil {
return nil, err
}
snarf, err := os.Open("/dev/snarf")
if err != nil {
return nil, err
}
cursor, err := os.OpenFile("/dev/cursor", os.O_WRONLY, 0)
if err != nil {
return nil, err
}

return &Conn{
ctl: ctl,
data: data,
cons: bufio.NewReader(cons),
consctl: consctl,
mouse: mouse,
snarf: snarf,
cursor: cursor,
initCtl: b[:nr],
n: n,
}, nil
}

func (c *Conn) Close() error {
return c.ctl.Close()
}

func (c *Conn) Init(label, winsize string) error {
if b, err := ioutil.ReadFile("/dev/label"); err == nil {
c.oldLabel = string(b)
}
// Ignore error because we may not be running in rio
ioutil.WriteFile("/dev/label", []byte(label), 0600)
return nil
}

func atoi(s string) (n int) {
n, _ = strconv.Atoi(s)
return
}

func (c *Conn) ReadMouse() (m Mouse, resized bool, err error) {
var buf [1 + 5*12]byte
var nr int

nr, err = c.mouse.Read(buf[:])
if err != nil {
return
}
f := strings.Fields(string(buf[:nr]))
if len(f) != 5 {
err = errors.New("bad mouse event")
return
}
m.Point = image.Pt(atoi(f[1]), atoi(f[2]))
m.Buttons = atoi(f[3])
m.Msec = atoi(f[4])
if f[0] == "r" {
resized = true
}
return
}

func (c *Conn) ReadKbd() (r rune, err error) {
r, _, err = c.cons.ReadRune()
return
}

func (c *Conn) MoveTo(p image.Point) error {
_, err := fmt.Fprintf(c.mouse, "m%11d %11d ", p.X, p.Y)
return err
}

func (c *Conn) Cursor(cursor *Cursor) error {
if cursor == nil {
// Revert to default cursor (Arrow)
_, err := c.cursor.Write([]byte{0})
return err
}
b := make([]byte, 2*4+len(cursor.Clr)+len(cursor.Set))
i := 0
binary.LittleEndian.PutUint32(b[i:], uint32(cursor.Point.X))
i += 4
binary.LittleEndian.PutUint32(b[i:], uint32(cursor.Point.Y))
i += 4
i += copy(b[i:], cursor.Clr[:])
i += copy(b[i:], cursor.Set[:])
_, err := c.cursor.Write(b)
return err
}

func (c *Conn) BounceMouse(m *Mouse) error {
panic("unimplemented")
}

func (c *Conn) Label(label string) error {
panic("unimplemented")
}

// Return values are bytes copied, actual size, error.
func (c *Conn) ReadSnarf(b []byte) (int, int, error) {
_, err := c.snarf.Seek(0, 0)
if err != nil {
return 0, 0, err
}
n, err := c.snarf.Read(b)
return n, n, err
}

func (c *Conn) WriteSnarf(snarf []byte) error {
// /dev/snarf updates when the file is closed, so we must open it for each call
f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0)
if err != nil {
return err
}
_, err = f.Write(snarf)
if err != nil {
return err
}
return f.Close()
}

func (c *Conn) Top() error {
panic("unimplemented")
}

func (c *Conn) Resize(r image.Rectangle) error {
panic("unimplemented")
}

func (c *Conn) ReadDraw(b []byte) (n int, err error) {
c.lk.Lock()
if len(c.readData) > 0 {
n = copy(b, c.readData)
c.readData = c.readData[n:]
c.lk.Unlock()
return n, nil
}
c.lk.Unlock()
return c.data.Read(b[:])
}

func bplong(b []byte, n uint32) {
binary.LittleEndian.PutUint32(b, n)
}

func (c *Conn) WriteDraw(b []byte) (int, error) {
i := 0
Loop:
for i < len(b) {
switch b[i] {
case 'J': // set image 0 to screen image
i++

case 'I': // get image info: 'I'
c.lk.Lock()
if !c.ctlWasRead {
c.readData = append(c.readData, c.initCtl...)
c.ctlWasRead = true
} else {
b := make([]byte, 12*12)
n, err := c.ctl.Read(b)
if err != nil {
c.lk.Unlock()
return 0, err
}
c.readData = append(c.readData, b[:n]...)
}
c.lk.Unlock()
i++

case 'q': // query: 'Q' n[1] queryspec[n]
if bytes.Equal(b, []byte{'q', 1, 'd'}) {
dpi := fmt.Sprintf("%12d", 100)
c.lk.Lock()
c.readData = append(c.readData, []byte(dpi)...)
c.lk.Unlock()
}
i += 1 + 1 + int(b[1])

default:
break Loop
}
}
if len(b[i:]) == 0 {
return i, nil
}
n, err := c.data.Write(b[i:])
return n + i, err
}
Loading

0 comments on commit 4083899

Please sign in to comment.