github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xgbgen/go_event.go (about) 1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 // Event types 8 func (e *Event) Define(c *Context) { 9 c.Putln("// %s is the event number for a %s.", e.SrcName(), e.EvType()) 10 c.Putln("const %s = %d", e.SrcName(), e.Number) 11 c.Putln("") 12 c.Putln("type %s struct {", e.EvType()) 13 if !e.NoSequence { 14 c.Putln("Sequence uint16") 15 } 16 for _, field := range e.Fields { 17 field.Define(c) 18 } 19 c.Putln("}") 20 c.Putln("") 21 22 // Read defines a function that transforms a byte slice into this 23 // event struct. 24 e.Read(c) 25 26 // Write defines a function that transforms this event struct into 27 // a byte slice. 28 e.Write(c) 29 30 // Makes sure that this event type is an Event interface. 31 c.Putln("// SequenceId returns the sequence id attached to the %s event.", 32 e.SrcName()) 33 c.Putln("// Events without a sequence number (KeymapNotify) return 0.") 34 c.Putln("// This is mostly used internally.") 35 c.Putln("func (v %s) SequenceId() uint16 {", e.EvType()) 36 if e.NoSequence { 37 c.Putln("return uint16(0)") 38 } else { 39 c.Putln("return v.Sequence") 40 } 41 c.Putln("}") 42 c.Putln("") 43 c.Putln("// String is a rudimentary string representation of %s.", 44 e.EvType()) 45 c.Putln("func (v %s) String() string {", e.EvType()) 46 EventFieldString(c, e.Fields, e.SrcName()) 47 c.Putln("}") 48 c.Putln("") 49 50 // Let's the XGB event loop read this event. 51 c.Putln("func init() {") 52 if c.protocol.isExt() { 53 c.Putln("xgb.NewExtEventFuncs[\"%s\"][%d] = %sNew", 54 c.protocol.ExtXName, e.Number, e.EvType()) 55 } else { 56 c.Putln("xgb.NewEventFuncs[%d] = %sNew", e.Number, e.EvType()) 57 } 58 c.Putln("}") 59 c.Putln("") 60 } 61 62 func (e *Event) Read(c *Context) { 63 c.Putln("// %sNew constructs a %s value that implements xgb.Event from "+ 64 "a byte slice.", e.EvType(), e.EvType()) 65 c.Putln("func %sNew(buf []byte) xgb.Event {", e.EvType()) 66 c.Putln("v := %s{}", e.EvType()) 67 c.Putln("b := 1 // don't read event number") 68 c.Putln("") 69 for i, field := range e.Fields { 70 if i == 1 && !e.NoSequence { 71 c.Putln("v.Sequence = xgb.Get16(buf[b:])") 72 c.Putln("b += 2") 73 c.Putln("") 74 } 75 field.Read(c, "v.") 76 c.Putln("") 77 } 78 c.Putln("return v") 79 c.Putln("}") 80 c.Putln("") 81 } 82 83 func (e *Event) Write(c *Context) { 84 c.Putln("// Bytes writes a %s value to a byte slice.", e.EvType()) 85 c.Putln("func (v %s) Bytes() []byte {", e.EvType()) 86 c.Putln("buf := make([]byte, %s)", e.Size()) 87 c.Putln("b := 0") 88 c.Putln("") 89 c.Putln("// write event number") 90 c.Putln("buf[b] = %d", e.Number) 91 c.Putln("b += 1") 92 c.Putln("") 93 for i, field := range e.Fields { 94 if i == 1 && !e.NoSequence { 95 c.Putln("b += 2 // skip sequence number") 96 c.Putln("") 97 } 98 field.Write(c, "v.") 99 c.Putln("") 100 } 101 c.Putln("return buf") 102 c.Putln("}") 103 c.Putln("") 104 } 105 106 // EventCopy types 107 func (e *EventCopy) Define(c *Context) { 108 c.Putln("// %s is the event number for a %s.", e.SrcName(), e.EvType()) 109 c.Putln("const %s = %d", e.SrcName(), e.Number) 110 c.Putln("") 111 c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType()) 112 c.Putln("") 113 114 // Read defines a function that transforms a byte slice into this 115 // event struct. 116 e.Read(c) 117 118 // Write defines a function that transoforms this event struct into 119 // a byte slice. 120 e.Write(c) 121 122 // Makes sure that this event type is an Event interface. 123 c.Putln("// SequenceId returns the sequence id attached to the %s event.", 124 e.SrcName()) 125 c.Putln("// Events without a sequence number (KeymapNotify) return 0.") 126 c.Putln("// This is mostly used internally.") 127 c.Putln("func (v %s) SequenceId() uint16 {", e.EvType()) 128 if e.Old.(*Event).NoSequence { 129 c.Putln("return uint16(0)") 130 } else { 131 c.Putln("return v.Sequence") 132 } 133 c.Putln("}") 134 c.Putln("") 135 c.Putln("func (v %s) String() string {", e.EvType()) 136 EventFieldString(c, e.Old.(*Event).Fields, e.SrcName()) 137 c.Putln("}") 138 c.Putln("") 139 140 // Let's the XGB event loop read this event. 141 c.Putln("func init() {") 142 if c.protocol.isExt() { 143 c.Putln("xgb.NewExtEventFuncs[\"%s\"][%d] = %sNew", 144 c.protocol.ExtXName, e.Number, e.EvType()) 145 } else { 146 c.Putln("xgb.NewEventFuncs[%d] = %sNew", e.Number, e.EvType()) 147 } 148 c.Putln("}") 149 c.Putln("") 150 } 151 152 func (e *EventCopy) Read(c *Context) { 153 c.Putln("// %sNew constructs a %s value that implements xgb.Event from "+ 154 "a byte slice.", e.EvType(), e.EvType()) 155 c.Putln("func %sNew(buf []byte) xgb.Event {", e.EvType()) 156 c.Putln("return %s(%sNew(buf).(%s))", 157 e.EvType(), e.Old.(*Event).EvType(), e.Old.(*Event).EvType()) 158 c.Putln("}") 159 c.Putln("") 160 } 161 162 func (e *EventCopy) Write(c *Context) { 163 c.Putln("// Bytes writes a %s value to a byte slice.", e.EvType()) 164 c.Putln("func (v %s) Bytes() []byte {", e.EvType()) 165 c.Putln("return %s(v).Bytes()", e.Old.(*Event).EvType()) 166 c.Putln("}") 167 c.Putln("") 168 } 169 170 // EventFieldString works for both Event and EventCopy. It assembles all of the 171 // fields in an event and formats them into a single string. 172 func EventFieldString(c *Context, fields []Field, evName string) { 173 c.Putln("fieldVals := make([]string, 0, %d)", len(fields)) 174 if evName != "KeymapNotify" { 175 c.Putln("fieldVals = append(fieldVals, "+ 176 "xgb.Sprintf(\"Sequence: %s\", v.Sequence))", "%d") 177 } 178 for _, field := range fields { 179 switch f := field.(type) { 180 case *PadField: 181 continue 182 case *SingleField: 183 switch f.Type.(type) { 184 case *Base: 185 case *Resource: 186 case *TypeDef: 187 default: 188 continue 189 } 190 191 switch field.SrcType() { 192 case "string": 193 format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)", 194 field.SrcName(), "%s", field.SrcName()) 195 c.Putln("fieldVals = append(fieldVals, %s)", format) 196 case "bool": 197 format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)", 198 field.SrcName(), "%t", field.SrcName()) 199 c.Putln("fieldVals = append(fieldVals, %s)", format) 200 default: 201 format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)", 202 field.SrcName(), "%d", field.SrcName()) 203 c.Putln("fieldVals = append(fieldVals, %s)", format) 204 } 205 } 206 } 207 c.Putln("return \"%s {\" + xgb.StringsJoin(fieldVals, \", \") + \"}\"", 208 evName) 209 }