9fans.net/go@v0.0.5/draw/drawfcall/msg.go (about)

     1  package drawfcall
     2  
     3  import (
     4  	"fmt"
     5  	"image"
     6  	"io"
     7  )
     8  
     9  const (
    10  	_ = iota
    11  	Rerror
    12  	Trdmouse
    13  	Rrdmouse
    14  	Tmoveto
    15  	Rmoveto
    16  	Tcursor
    17  	Rcursor
    18  	Tbouncemouse
    19  	Rbouncemouse
    20  	Trdkbd
    21  	Rrdkbd
    22  	Tlabel
    23  	Rlabel
    24  	Tinit
    25  	Rinit
    26  	Trdsnarf
    27  	Rrdsnarf
    28  	Twrsnarf
    29  	Rwrsnarf
    30  	Trddraw
    31  	Rrddraw
    32  	Twrdraw
    33  	Rwrdraw
    34  	Ttop
    35  	Rtop
    36  	Tresize
    37  	Rresize
    38  	Tcursor2
    39  	Rcursor2
    40  	Tctxt
    41  	Rctxt
    42  	Trdkbd4
    43  	Rrdkbd4
    44  	Tmax
    45  )
    46  
    47  const MAXMSG = 4 << 20
    48  
    49  type Msg struct {
    50  	Type    uint8
    51  	Tag     uint8
    52  	Mouse   Mouse
    53  	Resized bool
    54  	Cursor  Cursor
    55  	Cursor2 Cursor2
    56  	Arrow   bool
    57  	Rune    rune
    58  	Winsize string
    59  	Label   string
    60  	Snarf   []byte
    61  	Error   string
    62  	ID      string
    63  	Data    []byte
    64  	Count   int
    65  	Rect    image.Rectangle
    66  }
    67  
    68  type Mouse struct {
    69  	image.Point
    70  	Buttons int
    71  	Msec    uint32
    72  }
    73  
    74  type Cursor struct {
    75  	image.Point
    76  	White [32]byte
    77  	Black [32]byte
    78  }
    79  
    80  type Cursor2 struct {
    81  	image.Point
    82  	White [128]byte
    83  	Black [128]byte
    84  }
    85  
    86  func stringsize(s string) int {
    87  	return 4 + len(s)
    88  }
    89  
    90  func bytesize(b []byte) int {
    91  	return 4 + len(b)
    92  }
    93  
    94  func (m *Msg) Size() int {
    95  	switch m.Type {
    96  	case Trdmouse,
    97  		Rbouncemouse,
    98  		Rmoveto,
    99  		Rcursor,
   100  		Rcursor2,
   101  		Trdkbd,
   102  		Trdkbd4,
   103  		Rlabel,
   104  		Rctxt,
   105  		Rinit,
   106  		Trdsnarf,
   107  		Rwrsnarf,
   108  		Ttop,
   109  		Rtop,
   110  		Rresize:
   111  		return 4 + 1 + 1
   112  	case Rrdmouse:
   113  		return 4 + 1 + 1 + 4 + 4 + 4 + 4 + 1
   114  	case Tbouncemouse:
   115  		return 4 + 1 + 1 + 4 + 4 + 4
   116  	case Tmoveto:
   117  		return 4 + 1 + 1 + 4 + 4
   118  	case Tcursor:
   119  		return 4 + 1 + 1 + 4 + 4 + 2*16 + 2*16 + 1
   120  	case Tcursor2:
   121  		return 4 + 1 + 1 + 4 + 4 + 2*16 + 2*16 + 4 + 4 + 4*32 + 4*32 + 1
   122  	case Rerror:
   123  		return 4 + 1 + 1 + stringsize(m.Error)
   124  	case Rrdkbd:
   125  		return 4 + 1 + 1 + 2
   126  	case Rrdkbd4:
   127  		return 4 + 1 + 1 + 4
   128  	case Tlabel:
   129  		return 4 + 1 + 1 + stringsize(m.Label)
   130  	case Tctxt:
   131  		return 4 + 1 + 1 + stringsize(m.ID)
   132  	case Tinit:
   133  		return 4 + 1 + 1 + stringsize(m.Winsize) + stringsize(m.Label)
   134  	case Rrdsnarf,
   135  		Twrsnarf:
   136  		return 4 + 1 + 1 + bytesize(m.Snarf)
   137  	case Rrddraw,
   138  		Twrdraw:
   139  		return 4 + 1 + 1 + bytesize(m.Data)
   140  	case Trddraw,
   141  		Rwrdraw:
   142  		return 4 + 1 + 1 + 4
   143  	case Tresize:
   144  		return 4 + 1 + 1 + 4*4
   145  	}
   146  	return 0
   147  }
   148  
   149  func (m *Msg) Marshal() []byte {
   150  	n := m.Size()
   151  	if n < 6 {
   152  		return nil
   153  	}
   154  	b := make([]byte, 0, n)
   155  	b = pbit32(b, n)
   156  	b = pbit8(b, m.Tag)
   157  	b = pbit8(b, m.Type)
   158  
   159  	switch m.Type {
   160  	case Rerror:
   161  		b = pstring(b, m.Error)
   162  	case Rrdmouse:
   163  		b = pbit32(b, m.Mouse.X)
   164  		b = pbit32(b, m.Mouse.Y)
   165  		b = pbit32(b, m.Mouse.Buttons)
   166  		b = pbit32(b, int(m.Mouse.Msec))
   167  		b = append(b, boolbyte(m.Resized))
   168  		b[19], b[22] = b[22], b[19]
   169  	case Tbouncemouse:
   170  		b = pbit32(b, m.Mouse.X)
   171  		b = pbit32(b, m.Mouse.Y)
   172  		b = pbit32(b, m.Mouse.Buttons)
   173  	case Tmoveto:
   174  		b = pbit32(b, m.Mouse.X)
   175  		b = pbit32(b, m.Mouse.Y)
   176  	case Tcursor:
   177  		b = pbit32(b, m.Cursor.X)
   178  		b = pbit32(b, m.Cursor.Y)
   179  		b = append(b, m.Cursor.White[:]...)
   180  		b = append(b, m.Cursor.Black[:]...)
   181  		b = append(b, boolbyte(m.Arrow))
   182  	case Tcursor2:
   183  		b = pbit32(b, m.Cursor.X)
   184  		b = pbit32(b, m.Cursor.Y)
   185  		b = append(b, m.Cursor.White[:]...)
   186  		b = append(b, m.Cursor.Black[:]...)
   187  		b = pbit32(b, m.Cursor2.X)
   188  		b = pbit32(b, m.Cursor2.Y)
   189  		b = append(b, m.Cursor2.White[:]...)
   190  		b = append(b, m.Cursor2.Black[:]...)
   191  		b = append(b, boolbyte(m.Arrow))
   192  	case Rrdkbd:
   193  		b = pbit16(b, uint16(m.Rune))
   194  	case Rrdkbd4:
   195  		b = pbit32(b, int(m.Rune))
   196  	case Tlabel:
   197  		b = pstring(b, m.Label)
   198  	case Tctxt:
   199  		b = pstring(b, m.ID)
   200  	case Tinit:
   201  		b = pstring(b, m.Winsize)
   202  		b = pstring(b, m.Label)
   203  	case Rrdsnarf, Twrsnarf:
   204  		b = pbytes(b, m.Snarf)
   205  	case Rrddraw, Twrdraw:
   206  		b = pbit32(b, len(m.Data))
   207  		b = append(b, m.Data...)
   208  	case Trddraw, Rwrdraw:
   209  		b = pbit32(b, m.Count)
   210  	case Tresize:
   211  		b = pbit32(b, m.Rect.Min.X)
   212  		b = pbit32(b, m.Rect.Min.Y)
   213  		b = pbit32(b, m.Rect.Max.X)
   214  		b = pbit32(b, m.Rect.Max.Y)
   215  	}
   216  	if len(b) != n {
   217  		println(len(b), n, m.String())
   218  		panic("size mismatch")
   219  	}
   220  	return b
   221  }
   222  
   223  func boolbyte(b bool) byte {
   224  	if b {
   225  		return 1
   226  	}
   227  	return 0
   228  }
   229  
   230  func ReadMsg(r io.Reader) ([]byte, error) {
   231  	size := make([]byte, 4)
   232  	_, err := io.ReadFull(r, size)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	n, _ := gbit32(size[:])
   237  	buf := make([]byte, n)
   238  	copy(buf, size)
   239  	_, err = io.ReadFull(r, buf[4:])
   240  	if err != nil {
   241  		if err == io.EOF {
   242  			err = io.ErrUnexpectedEOF
   243  		}
   244  		return nil, err
   245  	}
   246  	return buf, nil
   247  }
   248  
   249  func (m *Msg) Unmarshal(b []byte) error {
   250  	if len(b) < 6 {
   251  		return fmt.Errorf("short packet")
   252  	}
   253  
   254  	nn, b := gbit32(b)
   255  	if nn != 4+len(b) {
   256  		return fmt.Errorf("invalid size")
   257  	}
   258  
   259  	m.Tag, b = gbit8(b)
   260  	m.Type, b = gbit8(b)
   261  	switch m.Type {
   262  	default:
   263  		return fmt.Errorf("invalid type %d", int(m.Type))
   264  	case Trdmouse,
   265  		Rbouncemouse,
   266  		Rmoveto,
   267  		Rcursor,
   268  		Rcursor2,
   269  		Trdkbd,
   270  		Trdkbd4,
   271  		Rlabel,
   272  		Rctxt,
   273  		Rinit,
   274  		Trdsnarf,
   275  		Rwrsnarf,
   276  		Ttop,
   277  		Rtop,
   278  		Rresize:
   279  		// nothing
   280  	case Rerror:
   281  		m.Error, b = gstring(b)
   282  	case Rrdmouse:
   283  		m.Mouse.X, b = gbit32(b)
   284  		m.Mouse.Y, b = gbit32(b)
   285  		m.Mouse.Buttons, b = gbit32(b)
   286  		b[1], b[4] = b[4], b[1]
   287  		var msec int
   288  		msec, b = gbit32(b)
   289  		m.Mouse.Msec = uint32(msec)
   290  		m.Resized = b[0] != 0
   291  		b = b[1:]
   292  	case Tbouncemouse:
   293  		m.Mouse.X, b = gbit32(b)
   294  		m.Mouse.Y, b = gbit32(b)
   295  		m.Mouse.Buttons, b = gbit32(b)
   296  	case Tmoveto:
   297  		m.Mouse.X, b = gbit32(b)
   298  		m.Mouse.Y, b = gbit32(b)
   299  	case Tcursor:
   300  		m.Cursor.X, b = gbit32(b)
   301  		m.Cursor.Y, b = gbit32(b)
   302  		copy(m.Cursor.White[:], b[:])
   303  		copy(m.Cursor.Black[:], b[32:])
   304  		b = b[64:]
   305  		var n byte
   306  		n, b = gbit8(b)
   307  		m.Arrow = n != 0
   308  	case Tcursor2:
   309  		m.Cursor.X, b = gbit32(b)
   310  		m.Cursor.Y, b = gbit32(b)
   311  		copy(m.Cursor.White[:], b[:])
   312  		copy(m.Cursor.Black[:], b[32:])
   313  		b = b[64:]
   314  		m.Cursor2.X, b = gbit32(b)
   315  		m.Cursor2.Y, b = gbit32(b)
   316  		copy(m.Cursor2.White[:], b[:])
   317  		copy(m.Cursor2.Black[:], b[128:])
   318  		b = b[256:]
   319  		var n byte
   320  		n, b = gbit8(b)
   321  		m.Arrow = n != 0
   322  	case Rrdkbd:
   323  		var r uint16
   324  		r, b = gbit16(b)
   325  		m.Rune = rune(r)
   326  	case Rrdkbd4:
   327  		var r int
   328  		r, b = gbit32(b)
   329  		m.Rune = rune(r)
   330  	case Tlabel:
   331  		m.Label, b = gstring(b)
   332  	case Tctxt:
   333  		m.ID, b = gstring(b)
   334  	case Tinit:
   335  		m.Winsize, b = gstring(b)
   336  		m.Label, b = gstring(b)
   337  	case Rrdsnarf,
   338  		Twrsnarf:
   339  		m.Snarf, b = gbytes(b)
   340  	case Rrddraw,
   341  		Twrdraw:
   342  		var n int
   343  		n, b = gbit32(b)
   344  		m.Data = b[:n]
   345  		b = b[n:]
   346  	case Trddraw,
   347  		Rwrdraw:
   348  		m.Count, b = gbit32(b)
   349  	case Tresize:
   350  		m.Rect.Min.X, b = gbit32(b)
   351  		m.Rect.Min.Y, b = gbit32(b)
   352  		m.Rect.Max.X, b = gbit32(b)
   353  		m.Rect.Max.Y, b = gbit32(b)
   354  	}
   355  
   356  	if len(b) != 0 {
   357  		return fmt.Errorf("junk at end of packet %d %s", len(b), m)
   358  	}
   359  	return nil
   360  }
   361  
   362  func (m *Msg) String() string {
   363  	s := fmt.Sprintf("tag=%d ", m.Tag)
   364  	switch m.Type {
   365  	default:
   366  		s += fmt.Sprintf("unknown msg type=%d", m.Type)
   367  	case Rerror:
   368  		s += fmt.Sprintf("Rerror error='%s'", m.Error)
   369  	case Trdmouse:
   370  		s += fmt.Sprintf("Trdmouse")
   371  	case Rrdmouse:
   372  		s += fmt.Sprintf("Rrdmouse x=%d y=%d buttons=%d msec=%d resized=%v",
   373  			m.Mouse.X, m.Mouse.Y,
   374  			m.Mouse.Buttons, m.Mouse.Msec, m.Resized)
   375  	case Tbouncemouse:
   376  		s += fmt.Sprintf("Tbouncemouse x=%d y=%d buttons=%d",
   377  			m.Mouse.X, m.Mouse.Y, m.Mouse.Buttons)
   378  	case Rbouncemouse:
   379  		s += fmt.Sprintf("Rbouncemouse")
   380  	case Tmoveto:
   381  		s += fmt.Sprintf("Tmoveto x=%d y=%d", m.Mouse.X, m.Mouse.Y)
   382  	case Rmoveto:
   383  		s += fmt.Sprintf("Rmoveto")
   384  	case Tcursor:
   385  		s += fmt.Sprintf("Tcursor arrow=%v", m.Arrow)
   386  	case Rcursor:
   387  		s += fmt.Sprintf("Rcursor")
   388  	case Tcursor2:
   389  		s += fmt.Sprintf("Tcursor2 arrow=%v", m.Arrow)
   390  	case Rcursor2:
   391  		s += fmt.Sprintf("Rcursor2")
   392  	case Trdkbd:
   393  		s += fmt.Sprintf("Trdkbd")
   394  	case Rrdkbd:
   395  		s += fmt.Sprintf("Rrdkbd rune=%c", m.Rune)
   396  	case Trdkbd4:
   397  		s += fmt.Sprintf("Trdkbd4")
   398  	case Rrdkbd4:
   399  		s += fmt.Sprintf("Rrdkbd4 rune=%c", m.Rune)
   400  	case Tlabel:
   401  		s += fmt.Sprintf("Tlabel label='%s'", m.Label)
   402  	case Rlabel:
   403  		s += fmt.Sprintf("Rlabel")
   404  	case Tctxt:
   405  		s += fmt.Sprintf("Tctxt id='%s'", m.ID)
   406  	case Rctxt:
   407  		s += fmt.Sprintf("Rctxt")
   408  	case Tinit:
   409  		s += fmt.Sprintf("Tinit label='%s' winsize='%s'", m.Label, m.Winsize)
   410  	case Rinit:
   411  		s += fmt.Sprintf("Rinit")
   412  	case Trdsnarf:
   413  		s += fmt.Sprintf("Trdsnarf")
   414  	case Rrdsnarf:
   415  		s += fmt.Sprintf("Rrdsnarf snarf='%s'", m.Snarf)
   416  	case Twrsnarf:
   417  		s += fmt.Sprintf("Twrsnarf snarf='%s'", m.Snarf)
   418  	case Rwrsnarf:
   419  		s += fmt.Sprintf("Rwrsnarf")
   420  	case Trddraw:
   421  		s += fmt.Sprintf("Trddraw %d", m.Count)
   422  	case Rrddraw:
   423  		s += fmt.Sprintf("Rrddraw %d %x", len(m.Data), m.Data)
   424  	case Twrdraw:
   425  		s += fmt.Sprintf("Twrdraw %d %x", len(m.Data), m.Data)
   426  	case Rwrdraw:
   427  		s += fmt.Sprintf("Rwrdraw %d", m.Count)
   428  	case Ttop:
   429  		s += fmt.Sprintf("Ttop")
   430  	case Rtop:
   431  		s += fmt.Sprintf("Rtop")
   432  	case Tresize:
   433  		s += fmt.Sprintf("Tresize %v", m.Rect)
   434  	case Rresize:
   435  		s += fmt.Sprintf("Rresize")
   436  	}
   437  	return s
   438  }