1 /*
2  * Copyright © 2015 David Herrmann <dh.herrmann@gmail.com>
3  * Copyright © 2018 Christian Persch
4  *
5  * This library is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library.  If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <assert.h>
22 
23 /*
24  * vte_seq_arg_t:
25  *
26  * A type to hold a CSI, OSC or DCS parameter.
27  *
28  * Parameters can be final or nonfinal.
29  *
30  * Final parameters are those that occur at the end of the
31  * parameter list, or the end of a subparameter list.
32  *
33  * Nonfinal parameters are those that have subparameters
34  * after them.
35  *
36  * Parameters have default value or have a nondefault value.
37  */
38 typedef int vte_seq_arg_t;
39 
40 #define VTE_SEQ_ARG_FLAG_VALUE    (1 << 16)
41 #define VTE_SEQ_ARG_FLAG_NONFINAL (1 << 17)
42 #define VTE_SEQ_ARG_FLAG_MASK     (VTE_SEQ_ARG_FLAG_VALUE | VTE_SEQ_ARG_FLAG_NONFINAL)
43 #define VTE_SEQ_ARG_VALUE_MASK    (0xffff)
44 
45 /*
46  * VTE_SEQ_ARG_INIT_DEFAULT:
47  *
48  * Returns: a parameter with default value
49  */
50 #define VTE_SEQ_ARG_INIT_DEFAULT (0)
51 
52 /*
53  * VTE_SEQ_ARG_INIT:
54  * @value:
55  *
56  * Returns: a parameter with value @value
57  */
58 #define VTE_SEQ_ARG_INIT(value) ((value & VTE_SEQ_ARG_VALUE_MASK) | VTE_SEQ_ARG_FLAG_VALUE)
59 
60 /*
61  * vte_seq_arg_init:
62  * @value:
63  *
64  * Returns: a #vte_seq_arg_t for @value, or with default value if @value is -1
65  */
vte_seq_arg_init(int value)66 static constexpr inline vte_seq_arg_t vte_seq_arg_init(int value)
67 {
68         if (value == -1)
69                 return VTE_SEQ_ARG_INIT_DEFAULT;
70         else
71                 return VTE_SEQ_ARG_INIT(value);
72 }
73 
74 /*
75  * vte_seq_arg_push:
76  * @arg:
77  * @c: a value between 3/0 and 3/9 ['0' .. '9']
78  *
79  * Multiplies @arg by 10 and adds the numeric value of @c.
80  *
81  * After this, @arg has a value.
82  */
vte_seq_arg_push(vte_seq_arg_t * arg,uint32_t c)83 static inline void vte_seq_arg_push(vte_seq_arg_t* arg,
84                                     uint32_t c)
85 {
86         auto value = *arg & VTE_SEQ_ARG_VALUE_MASK;
87         value = value * 10 + (c - '0');
88 
89         /*
90          * VT510 tells us to clamp all values to [0, 9999], however, it
91          * also allows commands with values up to 2^15-1. We simply use
92          * 2^16 as maximum here to be compatible to all commands, but
93          * avoid overflows in any calculations.
94          */
95         if (value > 0xffff)
96                 value = 0xffff;
97 
98         *arg = value | VTE_SEQ_ARG_FLAG_VALUE;
99 }
100 
101 /*
102  * vte_seq_arg_finish:
103  * @arg:
104  * @finalise:
105  *
106  * Finishes @arg; after this no more vte_seq_arg_push() calls
107  * are allowed.
108  *
109  * If @nonfinal is %true, marks @arg as a nonfinal parameter, is,
110  * there are more subparameters after it.
111  */
vte_seq_arg_finish(vte_seq_arg_t * arg,bool nonfinal=false)112 static inline void vte_seq_arg_finish(vte_seq_arg_t* arg,
113                                       bool nonfinal = false)
114 {
115         if (nonfinal)
116                 *arg |= VTE_SEQ_ARG_FLAG_NONFINAL;
117 }
118 
vte_seq_arg_refinish(vte_seq_arg_t * arg,bool nonfinal=false)119 static inline void vte_seq_arg_refinish(vte_seq_arg_t* arg,
120                                         bool nonfinal = false)
121 {
122         if (nonfinal)
123                 *arg |= VTE_SEQ_ARG_FLAG_NONFINAL;
124         else
125                 *arg &= ~VTE_SEQ_ARG_FLAG_NONFINAL;
126 }
127 
128 /*
129  * vte_seq_arg_started:
130  * @arg:
131  *
132  * Returns: whether @arg has nondefault value
133  */
vte_seq_arg_started(vte_seq_arg_t arg)134 static constexpr inline bool vte_seq_arg_started(vte_seq_arg_t arg)
135 {
136         return arg & VTE_SEQ_ARG_FLAG_VALUE;
137 }
138 
139 /*
140  * vte_seq_arg_default:
141  * @arg:
142  *
143  * Returns: whether @arg has default value
144  */
vte_seq_arg_default(vte_seq_arg_t arg)145 static constexpr inline bool vte_seq_arg_default(vte_seq_arg_t arg)
146 {
147         return !(arg & VTE_SEQ_ARG_FLAG_VALUE);
148 }
149 
150 /*
151  * vte_seq_arg_nonfinal:
152  * @arg:
153  *
154  * Returns: whether @arg is a nonfinal parameter, i.e. there
155  * are more subparameters after it
156  */
vte_seq_arg_nonfinal(vte_seq_arg_t arg)157 static constexpr inline int vte_seq_arg_nonfinal(vte_seq_arg_t arg)
158 {
159         return (arg & VTE_SEQ_ARG_FLAG_NONFINAL);
160 }
161 
162 /*
163  * vte_seq_arg_value:
164  * @arg:
165  * @default_value: (defaults to -1)
166  *
167  * Returns: the value of @arg, or @default_value if @arg has default value
168  */
vte_seq_arg_value(vte_seq_arg_t arg,int default_value=-1)169 static constexpr inline int vte_seq_arg_value(vte_seq_arg_t arg,
170                                               int default_value = -1)
171 {
172         return (arg & VTE_SEQ_ARG_FLAG_VALUE) ? (arg & VTE_SEQ_ARG_VALUE_MASK) : default_value;
173 }
174 
175 /*
176  * vte_seq_arg_value_final:
177  * @arg:
178  * @default_value: (defaults to -1)
179  *
180  * Returns: the value of @arg, or @default_value if @arg has default value or is not final
181  */
vte_seq_arg_value_final(vte_seq_arg_t arg,int default_value=-1)182 static constexpr inline int vte_seq_arg_value_final(vte_seq_arg_t arg,
183                                                     int default_value = -1)
184 {
185         return ((arg & VTE_SEQ_ARG_FLAG_MASK) == VTE_SEQ_ARG_FLAG_VALUE) ? (arg & VTE_SEQ_ARG_VALUE_MASK) : default_value;
186 }
187