• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

neomutt / neomutt / 12308706524

12 Dec 2024 04:06PM UTC coverage: 49.224% (-0.02%) from 49.243%
12308706524

push

github

flatcap
merge: colour refactoring

 * color: split out qstyle
 * color: move color_is_header()
 * color: factor out sidebar init
 * color: remove expando '%' hack
 * color: move notify parent
 * color: add macro COLOR_QUOTED()
 * color: make NumQuotedColors static
 * color: create a deprecated colours section
 * color: distinguish color_reset/cleanup()

31 of 210 new or added lines in 8 files covered. (14.76%)

2 existing lines in 1 file now uncovered.

8875 of 18030 relevant lines covered (49.22%)

232.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/color/qstyle.c
1
/**
2
 * @file
3
 * Quoted style
4
 *
5
 * @authors
6
 * Copyright (C) 2021-2023 Richard Russon <rich@flatcap.org>
7
 *
8
 * @copyright
9
 * This program is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License as published by the Free Software
11
 * Foundation, either version 2 of the License, or (at your option) any later
12
 * version.
13
 *
14
 * This program is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU General Public License along with
20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22

23
/**
24
 * @page color_qstyle Quoted style
25
 *
26
 * Quoted style
27
 */
28

29
#include "config.h"
30
#include <stdbool.h>
31
#include "mutt/lib.h"
32
#include "qstyle.h"
33
#include "quoted.h"
34

35
/**
36
 * qstyle_free - Free a single QuoteStyle object
37
 * @param ptr QuoteStyle to free
38
 *
39
 * @note Use qstyle_free_tree() to free the entire tree
40
 */
NEW
41
static void qstyle_free(struct QuoteStyle **ptr)
×
42
{
NEW
43
  if (!ptr || !*ptr)
×
44
    return;
45

46
  struct QuoteStyle *qc = *ptr;
NEW
47
  FREE(&qc->prefix);
×
48

NEW
49
  FREE(ptr);
×
50
}
51

52
/**
53
 * qstyle_free_tree - Free an entire tree of QuoteStyle
54
 * @param[out] quote_list Quote list to free
55
 *
56
 * @note Use qstyle_free() to free a single object
57
 */
NEW
58
void qstyle_free_tree(struct QuoteStyle **quote_list)
×
59
{
60
  struct QuoteStyle *next = NULL;
61

NEW
62
  while (*quote_list)
×
63
  {
NEW
64
    if ((*quote_list)->down)
×
NEW
65
      qstyle_free_tree(&((*quote_list)->down));
×
NEW
66
    next = (*quote_list)->next;
×
NEW
67
    qstyle_free(quote_list);
×
NEW
68
    *quote_list = next;
×
69
  }
NEW
70
}
×
71

72
/**
73
 * qstyle_new - Create a new QuoteStyle
74
 * @retval ptr New QuoteStyle
75
 */
76
static struct QuoteStyle *qstyle_new(void)
77
{
NEW
78
  return MUTT_MEM_CALLOC(1, struct QuoteStyle);
×
79
}
80

81
/**
82
 * qstyle_insert - Insert a new quote colour class into a list
83
 * @param[in]     quote_list List of quote colours
84
 * @param[in]     new_class  New quote colour to inset
85
 * @param[in]     index      Index to insert at
86
 * @param[in,out] q_level    Quote level
87
 */
NEW
88
static void qstyle_insert(struct QuoteStyle *quote_list,
×
89
                          struct QuoteStyle *new_class, int index, int *q_level)
90
{
91
  struct QuoteStyle *q_list = quote_list;
NEW
92
  new_class->quote_n = -1;
×
93

NEW
94
  while (q_list)
×
95
  {
NEW
96
    if (q_list->quote_n >= index)
×
97
    {
NEW
98
      q_list->quote_n++;
×
NEW
99
      q_list->attr_color = quoted_colors_get(q_list->quote_n);
×
100
    }
NEW
101
    if (q_list->down)
×
102
    {
103
      q_list = q_list->down;
104
    }
NEW
105
    else if (q_list->next)
×
106
    {
107
      q_list = q_list->next;
108
    }
109
    else
110
    {
NEW
111
      while (!q_list->next)
×
112
      {
NEW
113
        q_list = q_list->up;
×
NEW
114
        if (!q_list)
×
115
          break;
116
      }
NEW
117
      if (q_list)
×
NEW
118
        q_list = q_list->next;
×
119
    }
120
  }
121

NEW
122
  new_class->quote_n = index;
×
NEW
123
  new_class->attr_color = quoted_colors_get(index);
×
NEW
124
  (*q_level)++;
×
NEW
125
}
×
126

127
/**
128
 * qstyle_classify - Find a style for a string
129
 * @param[out] quote_list   List of quote colours
130
 * @param[in]  qptr         String to classify
131
 * @param[in]  length       Length of string
132
 * @param[out] force_redraw Set to true if a screen redraw is needed
133
 * @param[out] q_level      Quoting level
134
 * @retval ptr Quoting style
135
 */
NEW
136
struct QuoteStyle *qstyle_classify(struct QuoteStyle **quote_list, const char *qptr,
×
137
                                   size_t length, bool *force_redraw, int *q_level)
138
{
NEW
139
  struct QuoteStyle *q_list = *quote_list;
×
140
  struct QuoteStyle *qc = NULL, *tmp = NULL, *ptr = NULL, *save = NULL;
141
  const char *tail_qptr = NULL;
142
  size_t offset, tail_lng;
143
  int index = -1;
144

145
  /* classify quoting prefix */
NEW
146
  while (q_list)
×
147
  {
NEW
148
    if (length <= q_list->prefix_len)
×
149
    {
150
      /* case 1: check the top level nodes */
151

NEW
152
      if (mutt_strn_equal(qptr, q_list->prefix, length))
×
153
      {
NEW
154
        if (length == q_list->prefix_len)
×
NEW
155
          return q_list; /* same prefix: return the current class */
×
156

157
        /* found shorter prefix */
NEW
158
        if (tmp)
×
159
        {
160
          /* found another branch for which tmp is a shorter prefix */
161

162
          /* save the next sibling for later */
NEW
163
          save = q_list->next;
×
164

165
          /* unlink q_list from the top level list */
NEW
166
          if (q_list->next)
×
NEW
167
            q_list->next->prev = q_list->prev;
×
NEW
168
          if (q_list->prev)
×
NEW
169
            q_list->prev->next = q_list->next;
×
170

171
          /* at this point, we have a tmp->down; link q_list to it */
NEW
172
          ptr = tmp->down;
×
173
          /* sibling order is important here, q_list should be linked last */
NEW
174
          while (ptr->next)
×
175
            ptr = ptr->next;
NEW
176
          ptr->next = q_list;
×
NEW
177
          q_list->next = NULL;
×
NEW
178
          q_list->prev = ptr;
×
NEW
179
          q_list->up = tmp;
×
180

NEW
181
          index = q_list->quote_n;
×
182

183
          /* next class to test; as above, we shouldn't go down */
184
          q_list = save;
185
        }
186
        else
187
        {
188
          /* add a node above q_list */
189
          tmp = qstyle_new();
NEW
190
          tmp->prefix = mutt_strn_dup(qptr, length);
×
NEW
191
          tmp->prefix_len = length;
×
192

193
          /* replace q_list by tmp in the top level list */
NEW
194
          if (q_list->next)
×
195
          {
NEW
196
            tmp->next = q_list->next;
×
NEW
197
            q_list->next->prev = tmp;
×
198
          }
NEW
199
          if (q_list->prev)
×
200
          {
NEW
201
            tmp->prev = q_list->prev;
×
NEW
202
            q_list->prev->next = tmp;
×
203
          }
204

205
          /* make q_list a child of tmp */
NEW
206
          tmp->down = q_list;
×
NEW
207
          q_list->up = tmp;
×
208

209
          /* q_list has no siblings for now */
NEW
210
          q_list->next = NULL;
×
NEW
211
          q_list->prev = NULL;
×
212

213
          /* update the root if necessary */
NEW
214
          if (q_list == *quote_list)
×
NEW
215
            *quote_list = tmp;
×
216

NEW
217
          index = q_list->quote_n;
×
218

219
          /* tmp should be the return class too */
220
          qc = tmp;
221

222
          /* next class to test; if tmp is a shorter prefix for another
223
           * node, that node can only be in the top level list, so don't
224
           * go down after this point */
NEW
225
          q_list = tmp->next;
×
226
        }
227

228
        /* we found a shorter prefix, so certain quotes have changed classes */
NEW
229
        *force_redraw = true;
×
NEW
230
        continue;
×
231
      }
232
      else
233
      {
234
        /* shorter, but not a substring of the current class: try next */
NEW
235
        q_list = q_list->next;
×
NEW
236
        continue;
×
237
      }
238
    }
239
    else
240
    {
241
      /* case 2: try subclassing the current top level node */
242

243
      /* tmp != NULL means we already found a shorter prefix at case 1 */
NEW
244
      if (!tmp && mutt_strn_equal(qptr, q_list->prefix, q_list->prefix_len))
×
245
      {
246
        /* ok, it's a subclass somewhere on this branch */
247

248
        ptr = q_list;
NEW
249
        offset = q_list->prefix_len;
×
250

NEW
251
        q_list = q_list->down;
×
NEW
252
        tail_lng = length - offset;
×
NEW
253
        tail_qptr = qptr + offset;
×
254

NEW
255
        while (q_list)
×
256
        {
NEW
257
          if (length <= q_list->prefix_len)
×
258
          {
NEW
259
            if (mutt_strn_equal(tail_qptr, (q_list->prefix) + offset, tail_lng))
×
260
            {
261
              /* same prefix: return the current class */
NEW
262
              if (length == q_list->prefix_len)
×
NEW
263
                return q_list;
×
264

265
              /* found shorter common prefix */
NEW
266
              if (!tmp)
×
267
              {
268
                /* add a node above q_list */
269
                tmp = qstyle_new();
NEW
270
                tmp->prefix = mutt_strn_dup(qptr, length);
×
NEW
271
                tmp->prefix_len = length;
×
272

273
                /* replace q_list by tmp */
NEW
274
                if (q_list->next)
×
275
                {
NEW
276
                  tmp->next = q_list->next;
×
NEW
277
                  q_list->next->prev = tmp;
×
278
                }
NEW
279
                if (q_list->prev)
×
280
                {
NEW
281
                  tmp->prev = q_list->prev;
×
NEW
282
                  q_list->prev->next = tmp;
×
283
                }
284

285
                /* make q_list a child of tmp */
NEW
286
                tmp->down = q_list;
×
NEW
287
                tmp->up = q_list->up;
×
NEW
288
                q_list->up = tmp;
×
NEW
289
                if (tmp->up->down == q_list)
×
NEW
290
                  tmp->up->down = tmp;
×
291

292
                /* q_list has no siblings */
NEW
293
                q_list->next = NULL;
×
NEW
294
                q_list->prev = NULL;
×
295

NEW
296
                index = q_list->quote_n;
×
297

298
                /* tmp should be the return class too */
299
                qc = tmp;
300

301
                /* next class to test */
NEW
302
                q_list = tmp->next;
×
303
              }
304
              else
305
              {
306
                /* found another branch for which tmp is a shorter prefix */
307

308
                /* save the next sibling for later */
NEW
309
                save = q_list->next;
×
310

311
                /* unlink q_list from the top level list */
NEW
312
                if (q_list->next)
×
NEW
313
                  q_list->next->prev = q_list->prev;
×
NEW
314
                if (q_list->prev)
×
NEW
315
                  q_list->prev->next = q_list->next;
×
316

317
                /* at this point, we have a tmp->down; link q_list to it */
NEW
318
                ptr = tmp->down;
×
NEW
319
                while (ptr->next)
×
320
                  ptr = ptr->next;
NEW
321
                ptr->next = q_list;
×
NEW
322
                q_list->next = NULL;
×
NEW
323
                q_list->prev = ptr;
×
NEW
324
                q_list->up = tmp;
×
325

NEW
326
                index = q_list->quote_n;
×
327

328
                /* next class to test */
329
                q_list = save;
330
              }
331

332
              /* we found a shorter prefix, so we need a redraw */
NEW
333
              *force_redraw = true;
×
NEW
334
              continue;
×
335
            }
336
            else
337
            {
NEW
338
              q_list = q_list->next;
×
NEW
339
              continue;
×
340
            }
341
          }
342
          else
343
          {
344
            /* longer than the current prefix: try subclassing it */
NEW
345
            if (!tmp && mutt_strn_equal(tail_qptr, (q_list->prefix) + offset,
×
346
                                        q_list->prefix_len - offset))
347
            {
348
              /* still a subclass: go down one level */
349
              ptr = q_list;
NEW
350
              offset = q_list->prefix_len;
×
351

NEW
352
              q_list = q_list->down;
×
NEW
353
              tail_lng = length - offset;
×
NEW
354
              tail_qptr = qptr + offset;
×
355

NEW
356
              continue;
×
357
            }
358
            else
359
            {
360
              /* nope, try the next prefix */
NEW
361
              q_list = q_list->next;
×
NEW
362
              continue;
×
363
            }
364
          }
365
        }
366

367
        /* still not found so far: add it as a sibling to the current node */
NEW
368
        if (!qc)
×
369
        {
370
          tmp = qstyle_new();
NEW
371
          tmp->prefix = mutt_strn_dup(qptr, length);
×
NEW
372
          tmp->prefix_len = length;
×
373

NEW
374
          if (ptr->down)
×
375
          {
NEW
376
            tmp->next = ptr->down;
×
NEW
377
            ptr->down->prev = tmp;
×
378
          }
NEW
379
          ptr->down = tmp;
×
NEW
380
          tmp->up = ptr;
×
381

NEW
382
          tmp->quote_n = (*q_level)++;
×
NEW
383
          tmp->attr_color = quoted_colors_get(tmp->quote_n);
×
384

NEW
385
          return tmp;
×
386
        }
387
        else
388
        {
NEW
389
          if (index != -1)
×
NEW
390
            qstyle_insert(*quote_list, tmp, index, q_level);
×
391

NEW
392
          return qc;
×
393
        }
394
      }
395
      else
396
      {
397
        /* nope, try the next prefix */
NEW
398
        q_list = q_list->next;
×
NEW
399
        continue;
×
400
      }
401
    }
402
  }
403

NEW
404
  if (!qc)
×
405
  {
406
    /* not found so far: add it as a top level class */
407
    qc = qstyle_new();
NEW
408
    qc->prefix = mutt_strn_dup(qptr, length);
×
NEW
409
    qc->prefix_len = length;
×
NEW
410
    qc->quote_n = (*q_level)++;
×
NEW
411
    qc->attr_color = quoted_colors_get(qc->quote_n);
×
412

NEW
413
    if (*quote_list)
×
414
    {
NEW
415
      if ((*quote_list)->next)
×
416
      {
NEW
417
        qc->next = (*quote_list)->next;
×
NEW
418
        qc->next->prev = qc;
×
419
      }
NEW
420
      (*quote_list)->next = qc;
×
NEW
421
      qc->prev = *quote_list;
×
422
    }
423
    else
424
    {
NEW
425
      *quote_list = qc;
×
426
    }
427
  }
428

NEW
429
  if (index != -1)
×
NEW
430
    qstyle_insert(*quote_list, tmp, index, q_level);
×
431

432
  return qc;
433
}
434

435
/**
436
 * qstyle_recurse - Update the quoting styles after colour changes
437
 * @param quote_list Styles to update
438
 * @param num_qlevel Number of quote levels
439
 * @param cur_qlevel Current quote level
440
 */
NEW
441
static void qstyle_recurse(struct QuoteStyle *quote_list, int num_qlevel, int *cur_qlevel)
×
442
{
NEW
443
  if (!quote_list)
×
444
    return;
445

NEW
446
  if (num_qlevel > 0)
×
447
  {
NEW
448
    quote_list->attr_color = quoted_colors_get(*cur_qlevel);
×
NEW
449
    *cur_qlevel = (*cur_qlevel + 1) % num_qlevel;
×
450
  }
451
  else
452
  {
NEW
453
    quote_list->attr_color = NULL;
×
454
  }
455

NEW
456
  qstyle_recurse(quote_list->down, num_qlevel, cur_qlevel);
×
NEW
457
  qstyle_recurse(quote_list->next, num_qlevel, cur_qlevel);
×
458
}
459

460
/**
461
 * qstyle_recolor - Recolour quotes after colour changes
462
 * @param quote_list List of quote colours
463
 */
NEW
464
void qstyle_recolor(struct QuoteStyle *quote_list)
×
465
{
NEW
466
  if (!quote_list)
×
NEW
467
    return;
×
468

NEW
469
  int num = quoted_colors_num_used();
×
NEW
470
  int cur = 0;
×
471

NEW
472
  qstyle_recurse(quote_list, num, &cur);
×
473
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc