@@ -95,67 +95,72 @@ enum ANSI_ESCAPE: ansi_escape_code {
95
95
ANSI_BG_WHITE = 47 ,
96
96
};
97
97
98
+ struct pango_tag {
99
+ const char * str;
100
+ int len;
101
+ };
102
+
103
+ constexpr int strlen_constexpr (const char * str, int count = 0 ) {
104
+ return (*str == ' \0 ' ) ? count : strlen_constexpr (str + 1 , count + 1 );
105
+ }
106
+
107
+ constexpr pango_tag PangoTag (const char * str) {
108
+ return { str, strlen_constexpr (str) };
109
+ }
110
+
111
+ constexpr pango_tag FONT_TAGS[] = {
112
+ PangoTag (" <span foreground='black'>" ),
113
+ PangoTag (" <span foreground='red'>" ),
114
+ PangoTag (" <span foreground='green'>" ),
115
+ PangoTag (" <span foreground='yellow'>" ),
116
+ PangoTag (" <span foreground='blue'>" ),
117
+ PangoTag (" <span foreground='magenta'>" ),
118
+ PangoTag (" <span foreground='cyan'>" ),
119
+ PangoTag (" <span foreground='white'>" )
120
+ };
121
+
122
+ constexpr pango_tag BG_TAGS[] = {
123
+ PangoTag (" <span background='black'>" ),
124
+ PangoTag (" <span background='red'>" ),
125
+ PangoTag (" <span background='green'>" ),
126
+ PangoTag (" <span background='yellow'>" ),
127
+ PangoTag (" <span background='blue'>" ),
128
+ PangoTag (" <span background='magenta'>" ),
129
+ PangoTag (" <span background='cyan'>" ),
130
+ PangoTag (" <span background='white'>" )
131
+ };
132
+
98
133
// Get opening markup tag from ANSI escape sequence
99
- static const char * GetOpeningTag (ansi_escape_code code) {
100
- switch (code) {
101
- case ANSI_BOLD:
102
- return " <b>" ;
103
- case ANSI_ITALIC:
104
- return " <i>" ;
105
- case ANSI_UNDERLINE:
106
- return " <u>" ;
107
- case ANSI_STRIKETHROUGH:
108
- return " <s>" ;
109
- case ANSI_FONT_BLACK:
110
- return " <span foreground='black'>" ;
111
- case ANSI_FONT_RED:
112
- return " <span foreground='red'>" ;
113
- case ANSI_FONT_GREEN:
114
- return " <span foreground='green'>" ;
115
- case ANSI_FONT_YELLOW:
116
- return " <span foreground='yellow'>" ;
117
- case ANSI_FONT_BLUE:
118
- return " <span foreground='blue'>" ;
119
- case ANSI_FONT_MAGENTA:
120
- return " <span foreground='magenta'>" ;
121
- case ANSI_FONT_CYAN:
122
- return " <span foreground='cyan'>" ;
123
- case ANSI_FONT_WHITE:
124
- return " <span foreground='white'>" ;
125
- case ANSI_BG_BLACK:
126
- return " <span background='black'>" ;
127
- case ANSI_BG_RED:
128
- return " <span background='red'>" ;
129
- case ANSI_BG_GREEN:
130
- return " <span background='green'>" ;
131
- case ANSI_BG_YELLOW:
132
- return " <span background='yellow'>" ;
133
- case ANSI_BG_BLUE:
134
- return " <span background='blue'>" ;
135
- case ANSI_BG_MAGENTA:
136
- return " <span background='magenta'>" ;
137
- case ANSI_BG_CYAN:
138
- return " <span background='cyan'>" ;
139
- case ANSI_BG_WHITE:
140
- return " <span background='white'>" ;
141
- }
142
- return " " ;
134
+ static const pango_tag GetOpeningTag (ansi_escape_code code) {
135
+ if (code == ANSI_BOLD)
136
+ return PangoTag (" <b>" );
137
+ else if (code == ANSI_ITALIC)
138
+ return PangoTag (" <i>" );
139
+ else if (code == ANSI_UNDERLINE)
140
+ return PangoTag (" <u>" );
141
+ else if (code == ANSI_STRIKETHROUGH)
142
+ return PangoTag (" <s>" );
143
+ else if (ANSI_FONT_BLACK <= code && code <= ANSI_FONT_WHITE)
144
+ return FONT_TAGS[code - ANSI_FONT_BLACK];
145
+ else if (ANSI_BG_BLACK <= code && code <= ANSI_BG_WHITE)
146
+ return BG_TAGS[code - ANSI_BG_BLACK];
147
+ return PangoTag (" " );
143
148
}
144
149
145
150
// Get closing markup tag from ANSI escape sequence
146
- static const char * GetClosingTag (ansi_escape_code code) {
151
+ static const pango_tag GetClosingTag (ansi_escape_code code) {
147
152
if (code == ANSI_BOLD)
148
- return " </b>" ;
153
+ return PangoTag ( " </b>" ) ;
149
154
else if (code == ANSI_ITALIC)
150
- return " </i>" ;
155
+ return PangoTag ( " </i>" ) ;
151
156
else if (code == ANSI_UNDERLINE)
152
- return " </u>" ;
157
+ return PangoTag ( " </u>" ) ;
153
158
else if (code == ANSI_STRIKETHROUGH)
154
- return " </s>" ;
159
+ return PangoTag ( " </s>" ) ;
155
160
else if ((ANSI_FONT_BLACK <= code && code <= ANSI_FONT_WHITE) ||
156
161
(ANSI_BG_BLACK <= code && code <= ANSI_BG_WHITE))
157
- return " </span>" ;
158
- return " " ;
162
+ return PangoTag ( " </span>" ) ;
163
+ return PangoTag ( " " ) ;
159
164
}
160
165
161
166
#define MAX_STACK_SIZE 64
@@ -167,7 +172,7 @@ class TagStack {
167
172
int m_top;
168
173
169
174
public:
170
- TagStack () : m_top(-1 ) {}
175
+ TagStack () : m_tags(), m_top(-1 ) {}
171
176
172
177
void Push (ansi_escape_code code) {
173
178
if (m_top < MAX_STACK_SIZE - 1 )
@@ -178,58 +183,44 @@ class TagStack {
178
183
179
184
void Clear () { m_top = -1 ; }
180
185
181
- // Get length of stacked opening tags
182
- int OpeningTagLength () {
183
- if (m_top < 0 )
184
- return 0 ;
186
+ using GetTagFunc = const pango_tag (*)(ansi_escape_code);
187
+
188
+ // Get length of stacked tags
189
+ int GetTagLength (GetTagFunc GetTag) const {
185
190
int len = 0 ;
186
- for ( ansi_escape_code* code = m_tags; code < m_tags + Size (); code++) {
187
- const char * closing_tag = GetOpeningTag (* code);
188
- len += strlen (closing_tag) ;
191
+ ansi_escape_code* max_tag = m_tags + m_top;
192
+ for (ansi_escape_code* code = m_tags; code <= max_tag; code++) {
193
+ len += GetTag (*code). len ;
189
194
}
190
195
return len;
191
196
}
192
197
193
- // Get length of stacked closing tags
194
- int ClosingTagLength () {
195
- if (m_top < 0 )
196
- return 0 ;
197
- int len = 0 ;
198
- for (ansi_escape_code* code = m_tags; code < m_tags + Size (); code++) {
199
- const char * closing_tag = GetClosingTag (*code);
200
- len += strlen (closing_tag);
201
- }
202
- return len;
198
+ inline int OpeningTagLength () const {
199
+ return GetTagLength (GetOpeningTag);
203
200
}
204
201
205
- // Copy stacked opening tags to char*
206
- int CopyOpeningTag (char * output) {
207
- if (m_top < 0 )
208
- return 0 ;
209
- int len = 0 ;
210
- for (ansi_escape_code* code = m_tags; code < m_tags + Size (); code++) {
211
- const char *opening_tag = GetOpeningTag (*code);
212
- int opening_tag_len = strlen (opening_tag);
213
- memcpy (output, opening_tag, opening_tag_len);
214
- output += opening_tag_len;
215
- len += opening_tag_len;
216
- }
217
- return len;
202
+ inline int ClosingTagLength () const {
203
+ return GetTagLength (GetClosingTag);
218
204
}
219
205
220
- // Copy stacked closing tags to char*
221
- int CopyClosingTag (char * output) {
222
- if (m_top < 0 )
223
- return 0 ;
224
- int len = 0 ;
225
- for (ansi_escape_code* code = m_tags + m_top; code >= m_tags; code--) {
226
- const char *closing_tag = GetClosingTag (*code);
227
- int closing_tag_len = strlen (closing_tag);
228
- memcpy (output, closing_tag, closing_tag_len);
229
- output += closing_tag_len;
230
- len += closing_tag_len;
206
+ // Copy stacked tags to char*
207
+ int CopyTag (char * output, GetTagFunc GetTag, bool reverse) const {
208
+ char * start = output;
209
+ for (int i = 0 ; i <= m_top; i++) {
210
+ int idx = reverse ? m_top - i : i;
211
+ const pango_tag opening_tag = GetTag (m_tags[idx]);
212
+ memcpy (output, opening_tag.str , opening_tag.len );
213
+ output += opening_tag.len ;
231
214
}
232
- return len;
215
+ return static_cast <int >(output - start);
216
+ }
217
+
218
+ inline int CopyOpeningTag (char * output) const {
219
+ return CopyTag (output, GetOpeningTag, false );
220
+ }
221
+
222
+ inline int CopyClosingTag (char * output) const {
223
+ return CopyTag (output, GetClosingTag, true );
233
224
}
234
225
};
235
226
@@ -256,35 +247,29 @@ int ConvertAnsiToPangoLength(TagStack* stack, const char *input) {
256
247
len += closing_tag_len;
257
248
closing_tag_len = 0 ;
258
249
} else {
259
- const char *opening_tag = GetOpeningTag (code);
260
- len += strlen (opening_tag);
261
- const char *closing_tag = GetClosingTag (code);
262
- closing_tag_len += strlen (closing_tag);
250
+ len += GetOpeningTag (code).len ;
251
+ closing_tag_len += GetClosingTag (code).len ;
263
252
}
264
253
if (c == ' m' )
265
254
break ;
266
255
}
267
256
}
257
+ continue ;
268
258
} else if (*p == ' &' ) {
269
- p++;
270
259
len += 5 ; // &
271
260
} else if (*p == ' <' ) {
272
- p++;
273
261
len += 4 ; // <
274
262
} else if (*p == ' >' ) {
275
- p++;
276
263
len += 4 ; // >
277
264
} else if (*p == ' \' ' ) {
278
- p++;
279
265
len += 6 ; // '
280
266
} else if (*p == ' "' ) {
281
- p++;
282
267
len += 6 ; // "
283
268
} else {
284
269
// Copy regular characters
285
- p++;
286
270
len++;
287
271
}
272
+ p++;
288
273
}
289
274
290
275
len += closing_tag_len;
@@ -318,40 +303,36 @@ void ConvertAnsiToPango(TagStack* stack, const char *input, char *output) {
318
303
q += stack->CopyClosingTag (q);
319
304
stack->Clear ();
320
305
} else {
321
- const char *opening_tag = GetOpeningTag (code);
322
- int opening_tag_len = strlen (opening_tag);
323
- memcpy (q, opening_tag, opening_tag_len);
324
- q += opening_tag_len;
306
+ const pango_tag opening_tag = GetOpeningTag (code);
307
+ memcpy (q, opening_tag.str , opening_tag.len );
308
+ q += opening_tag.len ;
325
309
stack->Push (code);
326
310
}
327
311
if (c == ' m' )
328
312
break ;
329
313
}
330
314
}
315
+ continue ;
331
316
} else if (*p == ' &' ) {
332
- p++;
333
317
memcpy (q, " &" , 5 );
334
318
q += 5 ;
335
319
} else if (*p == ' <' ) {
336
- p++;
337
320
memcpy (q, " <" , 4 );
338
321
q += 4 ;
339
322
} else if (*p == ' >' ) {
340
- p++;
341
323
memcpy (q, " >" , 4 );
342
324
q += 4 ;
343
325
} else if (*p == ' \' ' ) {
344
- p++;
345
326
memcpy (q, " '" , 6 );
346
327
q += 6 ;
347
328
} else if (*p == ' "' ) {
348
- p++;
349
329
memcpy (q, " "" , 6 );
350
330
q += 6 ;
351
331
} else {
352
332
// Copy regular characters
353
- *q++ = *p++ ;
333
+ *q++ = *p;
354
334
}
335
+ p++;
355
336
}
356
337
357
338
// Add closing tags
0 commit comments