~ubuntu-branches/ubuntu/breezy/gettext/breezy

« back to all changes in this revision

Viewing changes to src/message.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2002-04-10 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20020410131742-npf89tsaygdolprj
Tags: upstream-0.10.40
ImportĀ upstreamĀ versionĀ 0.10.40

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GNU gettext - internationalization aids
 
2
   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
 
3
 
 
4
   This file was written by Peter Miller <millerp@canb.auug.org.au>
 
5
 
 
6
This program is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; either version 2, or (at your option)
 
9
any later version.
 
10
 
 
11
This program is distributed in the hope that it will be useful,
 
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
GNU General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with this program; if not, write to the Free Software
 
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
# include <config.h>
 
22
#endif
 
23
 
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
 
 
27
#include "fstrcmp.h"
 
28
#include "message.h"
 
29
#include "system.h"
 
30
 
 
31
 
 
32
/* Prototypes for local functions.  */
 
33
static message_ty *message_list_search_fuzzy_inner PARAMS ((
 
34
       message_list_ty *__mlp, const char *__msgid, double *__best_weight_p));
 
35
 
 
36
 
 
37
 
 
38
enum is_c_format
 
39
parse_c_format_description_string (s)
 
40
     const char *s;
 
41
{
 
42
  if (strstr (s, "no-c-format") != NULL)
 
43
    return no;
 
44
  else if (strstr (s, "impossible-c-format") != NULL)
 
45
    return impossible;
 
46
  else if (strstr (s, "possible-c-format") != NULL)
 
47
    return possible;
 
48
  else if (strstr (s, "c-format") != NULL)
 
49
    return yes;
 
50
  return undecided;
 
51
}
 
52
 
 
53
 
 
54
int
 
55
possible_c_format_p (is_c_format)
 
56
     enum is_c_format is_c_format;
 
57
{
 
58
  return is_c_format == possible || is_c_format == yes;
 
59
}
 
60
 
 
61
 
 
62
enum is_c_format
 
63
parse_c_width_description_string (s)
 
64
     const char *s;
 
65
{
 
66
  if (strstr (s, "no-wrap") != NULL)
 
67
    return no;
 
68
  else if (strstr (s, "wrap") != NULL)
 
69
    return yes;
 
70
  return undecided;
 
71
}
 
72
 
 
73
 
 
74
message_ty *
 
75
message_alloc (msgid, msgid_plural)
 
76
     char *msgid;
 
77
     const char *msgid_plural;
 
78
{
 
79
  message_ty *mp;
 
80
 
 
81
  mp = xmalloc (sizeof (message_ty));
 
82
  mp->msgid = msgid;
 
83
  mp->msgid_plural = (msgid_plural != NULL ? xstrdup (msgid_plural) : NULL);
 
84
  mp->comment = NULL;
 
85
  mp->comment_dot = NULL;
 
86
  mp->filepos_count = 0;
 
87
  mp->filepos = NULL;
 
88
  mp->variant_count = 0;
 
89
  mp->variant = NULL;
 
90
  mp->used = 0;
 
91
  mp->obsolete = 0;
 
92
  mp->is_fuzzy = 0;
 
93
  mp->is_c_format = undecided;
 
94
  mp->do_wrap = undecided;
 
95
  return mp;
 
96
}
 
97
 
 
98
 
 
99
void
 
100
message_free (mp)
 
101
     message_ty *mp;
 
102
{
 
103
  size_t j;
 
104
 
 
105
  if (mp->comment != NULL)
 
106
    string_list_free (mp->comment);
 
107
  if (mp->comment_dot != NULL)
 
108
    string_list_free (mp->comment_dot);
 
109
  free ((char *) mp->msgid);
 
110
  if (mp->msgid_plural != NULL)
 
111
    free ((char *) mp->msgid_plural);
 
112
  for (j = 0; j < mp->variant_count; ++j)
 
113
    free ((char *) mp->variant[j].msgstr);
 
114
  if (mp->variant != NULL)
 
115
    free (mp->variant);
 
116
  for (j = 0; j < mp->filepos_count; ++j)
 
117
    free ((char *) mp->filepos[j].file_name);
 
118
  if (mp->filepos != NULL)
 
119
    free (mp->filepos);
 
120
  free (mp);
 
121
}
 
122
 
 
123
 
 
124
message_variant_ty *
 
125
message_variant_search (mp, domain)
 
126
     message_ty *mp;
 
127
     const char *domain;
 
128
{
 
129
  size_t j;
 
130
  message_variant_ty *mvp;
 
131
 
 
132
  for (j = 0; j < mp->variant_count; ++j)
 
133
    {
 
134
      mvp = &mp->variant[j];
 
135
      if (0 == strcmp (domain, mvp->domain))
 
136
        return mvp;
 
137
    }
 
138
  return 0;
 
139
}
 
140
 
 
141
 
 
142
void
 
143
message_variant_append (mp, domain, msgstr, msgstr_len, pp)
 
144
     message_ty *mp;
 
145
     const char *domain;
 
146
     const char *msgstr;
 
147
     size_t msgstr_len;
 
148
     const lex_pos_ty *pp;
 
149
{
 
150
  size_t nbytes;
 
151
  message_variant_ty *mvp;
 
152
 
 
153
  nbytes = (mp->variant_count + 1) * sizeof (mp->variant[0]);
 
154
  mp->variant = xrealloc (mp->variant, nbytes);
 
155
  mvp = &mp->variant[mp->variant_count++];
 
156
  mvp->domain = domain;
 
157
  mvp->msgstr = msgstr;
 
158
  mvp->msgstr_len = msgstr_len;
 
159
  mvp->pos = *pp;
 
160
}
 
161
 
 
162
 
 
163
void
 
164
message_comment_append (mp, s)
 
165
     message_ty *mp;
 
166
     const char *s;
 
167
{
 
168
  if (mp->comment == NULL)
 
169
    mp->comment = string_list_alloc ();
 
170
  string_list_append (mp->comment, s);
 
171
}
 
172
 
 
173
 
 
174
void
 
175
message_comment_dot_append (mp, s)
 
176
     message_ty *mp;
 
177
     const char *s;
 
178
{
 
179
  if (mp->comment_dot == NULL)
 
180
    mp->comment_dot = string_list_alloc ();
 
181
  string_list_append (mp->comment_dot, s);
 
182
}
 
183
 
 
184
 
 
185
message_ty *
 
186
message_copy (mp)
 
187
     message_ty *mp;
 
188
{
 
189
  message_ty *result;
 
190
  size_t j;
 
191
 
 
192
  result = message_alloc (xstrdup (mp->msgid), mp->msgid_plural);
 
193
 
 
194
  for (j = 0; j < mp->variant_count; ++j)
 
195
    {
 
196
      message_variant_ty *mvp = &mp->variant[j];
 
197
      message_variant_append (result, mvp->domain, mvp->msgstr, mvp->msgstr_len,
 
198
                              &mvp->pos);
 
199
    }
 
200
  if (mp->comment)
 
201
    {
 
202
      for (j = 0; j < mp->comment->nitems; ++j)
 
203
        message_comment_append (result, mp->comment->item[j]);
 
204
    }
 
205
  if (mp->comment_dot)
 
206
    {
 
207
      for (j = 0; j < mp->comment_dot->nitems; ++j)
 
208
        message_comment_dot_append (result, mp->comment_dot->item[j]);
 
209
    }
 
210
  result->is_fuzzy = mp->is_fuzzy;
 
211
  result->is_c_format = mp->is_c_format;
 
212
  result->do_wrap = mp->do_wrap;
 
213
  for (j = 0; j < mp->filepos_count; ++j)
 
214
    {
 
215
      lex_pos_ty *pp = &mp->filepos[j];
 
216
      message_comment_filepos (result, pp->file_name, pp->line_number);
 
217
    }
 
218
  return result;
 
219
}
 
220
 
 
221
 
 
222
message_ty *
 
223
message_merge (def, ref)
 
224
     message_ty *def;
 
225
     message_ty *ref;
 
226
{
 
227
  message_ty *result;
 
228
  const char *pot_date_ptr = NULL;
 
229
  size_t pot_date_len = 0;
 
230
  size_t j;
 
231
 
 
232
  /* Take the msgid from the reference.  When fuzzy matches are made,
 
233
     the definition will not be unique, but the reference will be -
 
234
     usually because it has a typo.  */
 
235
  result = message_alloc (xstrdup (ref->msgid), ref->msgid_plural);
 
236
 
 
237
  /* If msgid is the header entry (i.e., "") we find the
 
238
     POT-Creation-Date line in the reference.  */
 
239
  if (ref->msgid[0] == '\0')
 
240
    {
 
241
      pot_date_ptr = strstr (ref->variant[0].msgstr, "POT-Creation-Date:");
 
242
      if (pot_date_ptr != NULL)
 
243
        {
 
244
          const char *endp;
 
245
 
 
246
          pot_date_ptr += sizeof ("POT-Creation-Date:") - 1;
 
247
 
 
248
          endp = strchr (pot_date_ptr, '\n');
 
249
          if (endp == NULL)
 
250
            {
 
251
              char *extended;
 
252
              endp = strchr (pot_date_ptr, '\0');
 
253
              pot_date_len = (endp - pot_date_ptr) + 1;
 
254
              extended = (char *) alloca (pot_date_len + 1);
 
255
              stpcpy (stpcpy (extended, pot_date_ptr), "\n");
 
256
              pot_date_ptr = extended;
 
257
            }
 
258
          else
 
259
            pot_date_len = (endp - pot_date_ptr) + 1;
 
260
 
 
261
          if (pot_date_len == 0)
 
262
            pot_date_ptr = NULL;
 
263
        }
 
264
    }
 
265
 
 
266
  /* Take the variant list from the definition.  The msgstr of the
 
267
     refences will be empty, as they were generated by xgettext.  If
 
268
     we currently process the header entry we have to merge the msgstr
 
269
     by using the POT-Creation-Date field from the .pot file.  */
 
270
  for (j = 0; j < def->variant_count; ++j)
 
271
    {
 
272
      message_variant_ty *mvp = &def->variant[j];
 
273
 
 
274
      if (ref->msgid[0] == '\0')
 
275
        {
 
276
          /* Oh, oh.  The header entry and we have something to fill in.  */
 
277
          static const struct
 
278
          {
 
279
            const char *name;
 
280
            size_t len;
 
281
          } known_fields[] =
 
282
          {
 
283
            { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 },
 
284
#define PROJECT_ID      0
 
285
            { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 },
 
286
#define POT_CREATION    1
 
287
            { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 },
 
288
#define PO_REVISION     2
 
289
            { "Last-Translator:", sizeof ("Last-Translator:") - 1 },
 
290
#define LAST_TRANSLATOR 3
 
291
            { "Language-Team:", sizeof ("Language-Team:") - 1 },
 
292
#define LANGUAGE_TEAM   4
 
293
            { "MIME-Version:", sizeof ("MIME-Version:") - 1 },
 
294
#define MIME_VERSION    5
 
295
            { "Content-Type:", sizeof ("Content-Type:") - 1 },
 
296
#define CONTENT_TYPE    6
 
297
            { "Content-Transfer-Encoding:",
 
298
              sizeof ("Content-Transfer-Encoding:") - 1 }
 
299
#define CONTENT_TRANSFER 7
 
300
          };
 
301
#define UNKNOWN 8
 
302
          struct
 
303
          {
 
304
            const char *string;
 
305
            size_t len;
 
306
          } header_fields[UNKNOWN + 1];
 
307
          const char *cp;
 
308
          char *newp;
 
309
          size_t len, cnt;
 
310
 
 
311
          /* Clear all fields.  */
 
312
          memset (header_fields, '\0', sizeof (header_fields));
 
313
 
 
314
          cp = mvp->msgstr;
 
315
          while (*cp != '\0')
 
316
            {
 
317
              const char *endp = strchr (cp, '\n');
 
318
              int terminated = endp != NULL;
 
319
 
 
320
              if (!terminated)
 
321
                {
 
322
                  char *copy;
 
323
                  endp = strchr (cp, '\0');
 
324
 
 
325
                  len = endp - cp + 1;
 
326
 
 
327
                  copy = (char *) alloca (len + 1);
 
328
                  stpcpy (stpcpy (copy, cp), "\n");
 
329
                  cp = copy;
 
330
                }
 
331
              else
 
332
                {
 
333
                  len = (endp - cp) + 1;
 
334
                  ++endp;
 
335
                }
 
336
 
 
337
              /* Compare with any of the known fields.  */
 
338
              for (cnt = 0;
 
339
                   cnt < sizeof (known_fields) / sizeof (known_fields[0]);
 
340
                   ++cnt)
 
341
                if (strncasecmp (cp, known_fields[cnt].name,
 
342
                                 known_fields[cnt].len) == 0)
 
343
                  break;
 
344
 
 
345
              if (cnt < sizeof (known_fields) / sizeof (known_fields[0]))
 
346
                {
 
347
                  header_fields[cnt].string = &cp[known_fields[cnt].len];
 
348
                  header_fields[cnt].len = len - known_fields[cnt].len;
 
349
                }
 
350
              else
 
351
                {
 
352
                  /* It's an unknown field.  Append content to what is
 
353
                     already known.  */
 
354
                  char *extended = (char *) alloca (header_fields[UNKNOWN].len
 
355
                                                    + len + 1);
 
356
                  memcpy (extended, header_fields[UNKNOWN].string,
 
357
                          header_fields[UNKNOWN].len);
 
358
                  memcpy (&extended[header_fields[UNKNOWN].len], cp, len);
 
359
                  extended[header_fields[UNKNOWN].len + len] = '\0';
 
360
                  header_fields[UNKNOWN].string = extended;
 
361
                  header_fields[UNKNOWN].len += len;
 
362
                }
 
363
 
 
364
              cp = endp;
 
365
            }
 
366
 
 
367
          if (pot_date_ptr != NULL)
 
368
            {
 
369
              header_fields[POT_CREATION].string = pot_date_ptr;
 
370
              header_fields[POT_CREATION].len = pot_date_len;
 
371
            }
 
372
 
 
373
          /* Concatenate all the various fields.  */
 
374
          len = 0;
 
375
          for (cnt = 0; cnt < UNKNOWN; ++cnt)
 
376
            if (header_fields[cnt].string != NULL)
 
377
              len += known_fields[cnt].len + header_fields[cnt].len;
 
378
          len += header_fields[UNKNOWN].len;
 
379
 
 
380
          cp = newp = (char *) xmalloc (len + 1);
 
381
          newp[len] = '\0';
 
382
 
 
383
#define IF_FILLED(idx)                                                        \
 
384
          if (header_fields[idx].string)                                      \
 
385
            newp = stpncpy (stpcpy (newp, known_fields[idx].name),            \
 
386
                            header_fields[idx].string, header_fields[idx].len)
 
387
 
 
388
          IF_FILLED (PROJECT_ID);
 
389
          IF_FILLED (POT_CREATION);
 
390
          IF_FILLED (PO_REVISION);
 
391
          IF_FILLED (LAST_TRANSLATOR);
 
392
          IF_FILLED (LANGUAGE_TEAM);
 
393
          IF_FILLED (MIME_VERSION);
 
394
          IF_FILLED (CONTENT_TYPE);
 
395
          IF_FILLED (CONTENT_TRANSFER);
 
396
          if (header_fields[UNKNOWN].string != NULL)
 
397
            stpcpy (newp, header_fields[UNKNOWN].string);
 
398
 
 
399
          message_variant_append (result, mvp->domain, cp, strlen (cp) + 1,
 
400
                                  &mvp->pos);
 
401
        }
 
402
      else
 
403
        message_variant_append (result, mvp->domain, mvp->msgstr,
 
404
                                mvp->msgstr_len, &mvp->pos);
 
405
    }
 
406
 
 
407
  /* Take the comments from the definition file.  There will be none at
 
408
     all in the reference file, as it was generated by xgettext.  */
 
409
  if (def->comment)
 
410
    for (j = 0; j < def->comment->nitems; ++j)
 
411
      message_comment_append (result, def->comment->item[j]);
 
412
 
 
413
  /* Take the dot comments from the reference file, as they are
 
414
     generated by xgettext.  Any in the definition file are old ones
 
415
     collected by previous runs of xgettext and msgmerge.  */
 
416
  if (ref->comment_dot)
 
417
    for (j = 0; j < ref->comment_dot->nitems; ++j)
 
418
      message_comment_dot_append (result, ref->comment_dot->item[j]);
 
419
 
 
420
  /* The flags are mixed in a special way.  Some informations come
 
421
     from the reference message (such as format/no-format), others
 
422
     come from the definition file (fuzzy or not).  */
 
423
  result->is_fuzzy = def->is_fuzzy;
 
424
  result->is_c_format = ref->is_c_format;
 
425
  result->do_wrap = ref->do_wrap;
 
426
 
 
427
  /* Take the file position comments from the reference file, as they
 
428
     are generated by xgettext.  Any in the definition file are old ones
 
429
     collected by previous runs of xgettext and msgmerge.  */
 
430
  for (j = 0; j < ref->filepos_count; ++j)
 
431
    {
 
432
      lex_pos_ty *pp = &ref->filepos[j];
 
433
      message_comment_filepos (result, pp->file_name, pp->line_number);
 
434
    }
 
435
 
 
436
  /* All done, return the merged message to the caller.  */
 
437
  return result;
 
438
}
 
439
 
 
440
 
 
441
void
 
442
message_comment_filepos (mp, name, line)
 
443
     message_ty *mp;
 
444
     const char *name;
 
445
     size_t line;
 
446
{
 
447
  size_t nbytes;
 
448
  lex_pos_ty *pp;
 
449
  int min, max;
 
450
  int j;
 
451
 
 
452
  /* See if we have this position already.  They are kept in sorted
 
453
     order, so use a binary chop.  */
 
454
  /* FIXME: use bsearch */
 
455
  min = 0;
 
456
  max = (int) mp->filepos_count - 1;
 
457
  while (min <= max)
 
458
    {
 
459
      int mid;
 
460
      int cmp;
 
461
 
 
462
      mid = (min + max) / 2;
 
463
      pp = &mp->filepos[mid];
 
464
      cmp = strcmp (pp->file_name, name);
 
465
      if (cmp == 0)
 
466
        cmp = (int) pp->line_number - line;
 
467
      if (cmp == 0)
 
468
        return;
 
469
      if (cmp < 0)
 
470
        min = mid + 1;
 
471
      else
 
472
        max = mid - 1;
 
473
    }
 
474
 
 
475
  /* Extend the list so that we can add an position to it.  */
 
476
  nbytes = (mp->filepos_count + 1) * sizeof (mp->filepos[0]);
 
477
  mp->filepos = xrealloc (mp->filepos, nbytes);
 
478
 
 
479
  /* Shuffle the rest of the list up one, so that we can insert the
 
480
     position at ``min''.  */
 
481
  /* FIXME: use memmove */
 
482
  for (j = mp->filepos_count; j > min; --j)
 
483
    mp->filepos[j] = mp->filepos[j - 1];
 
484
  mp->filepos_count++;
 
485
 
 
486
  /* Insert the postion into the empty slot.  */
 
487
  pp = &mp->filepos[min];
 
488
  pp->file_name = xstrdup (name);
 
489
  pp->line_number = line;
 
490
}
 
491
 
 
492
 
 
493
message_list_ty *
 
494
message_list_alloc ()
 
495
{
 
496
  message_list_ty *mlp;
 
497
 
 
498
  mlp = xmalloc (sizeof (message_list_ty));
 
499
  mlp->nitems = 0;
 
500
  mlp->nitems_max = 0;
 
501
  mlp->item = 0;
 
502
  return mlp;
 
503
}
 
504
 
 
505
 
 
506
void
 
507
message_list_append (mlp, mp)
 
508
     message_list_ty *mlp;
 
509
     message_ty *mp;
 
510
{
 
511
  if (mlp->nitems >= mlp->nitems_max)
 
512
    {
 
513
      size_t nbytes;
 
514
 
 
515
      mlp->nitems_max = mlp->nitems_max * 2 + 4;
 
516
      nbytes = mlp->nitems_max * sizeof (message_ty *);
 
517
      mlp->item = xrealloc (mlp->item, nbytes);
 
518
    }
 
519
  mlp->item[mlp->nitems++] = mp;
 
520
}
 
521
 
 
522
 
 
523
void
 
524
message_list_delete_nth (mlp, n)
 
525
     message_list_ty *mlp;
 
526
     size_t n;
 
527
{
 
528
  size_t j;
 
529
 
 
530
  if (n >= mlp->nitems)
 
531
    return;
 
532
  message_free (mlp->item[n]);
 
533
  for (j = n + 1; j < mlp->nitems; ++j)
 
534
    mlp->item[j - 1] = mlp->item[j];
 
535
  mlp->nitems--;
 
536
}
 
537
 
 
538
 
 
539
message_ty *
 
540
message_list_search (mlp, msgid)
 
541
     message_list_ty *mlp;
 
542
     const char *msgid;
 
543
{
 
544
  size_t j;
 
545
 
 
546
  for (j = 0; j < mlp->nitems; ++j)
 
547
    {
 
548
      message_ty *mp;
 
549
 
 
550
      mp = mlp->item[j];
 
551
      if (0 == strcmp (msgid, mp->msgid))
 
552
        return mp;
 
553
    }
 
554
  return 0;
 
555
}
 
556
 
 
557
 
 
558
static message_ty *
 
559
message_list_search_fuzzy_inner (mlp, msgid, best_weight_p)
 
560
     message_list_ty *mlp;
 
561
     const char *msgid;
 
562
     double *best_weight_p;
 
563
{
 
564
  size_t j;
 
565
  message_ty *best_mp;
 
566
 
 
567
  best_mp = NULL;
 
568
  for (j = 0; j < mlp->nitems; ++j)
 
569
    {
 
570
      size_t k;
 
571
      double weight;
 
572
      message_ty *mp;
 
573
 
 
574
      mp = mlp->item[j];
 
575
 
 
576
      for (k = 0; k < mp->variant_count; ++k)
 
577
        if (mp->variant[k].msgstr != NULL && mp->variant[k].msgstr[0] != '\0')
 
578
          break;
 
579
      if (k >= mp->variant_count)
 
580
        continue;
 
581
 
 
582
      weight = fstrcmp (msgid, mp->msgid);
 
583
      if (weight > *best_weight_p)
 
584
        {
 
585
          *best_weight_p = weight;
 
586
          best_mp = mp;
 
587
        }
 
588
    }
 
589
  return best_mp;
 
590
}
 
591
 
 
592
 
 
593
message_ty *
 
594
message_list_search_fuzzy (mlp, msgid)
 
595
     message_list_ty *mlp;
 
596
     const char *msgid;
 
597
{
 
598
  double best_weight;
 
599
 
 
600
  best_weight = 0.6;
 
601
  return message_list_search_fuzzy_inner (mlp, msgid, &best_weight);
 
602
}
 
603
 
 
604
 
 
605
void
 
606
message_list_free (mlp)
 
607
     message_list_ty *mlp;
 
608
{
 
609
  size_t j;
 
610
 
 
611
  for (j = 0; j < mlp->nitems; ++j)
 
612
    message_free (mlp->item[j]);
 
613
  if (mlp->item)
 
614
    free (mlp->item);
 
615
  free (mlp);
 
616
}
 
617
 
 
618
 
 
619
message_list_list_ty *
 
620
message_list_list_alloc ()
 
621
{
 
622
  message_list_list_ty *mllp;
 
623
 
 
624
  mllp = xmalloc (sizeof (message_list_list_ty));
 
625
  mllp->nitems = 0;
 
626
  mllp->nitems_max = 0;
 
627
  mllp->item = 0;
 
628
  return mllp;
 
629
}
 
630
 
 
631
 
 
632
void
 
633
message_list_list_append (mllp, mlp)
 
634
     message_list_list_ty *mllp;
 
635
     message_list_ty *mlp;
 
636
{
 
637
  if (mllp->nitems >= mllp->nitems_max)
 
638
    {
 
639
      size_t nbytes;
 
640
 
 
641
      mllp->nitems_max = mllp->nitems_max * 2 + 4;
 
642
      nbytes = mllp->nitems_max * sizeof (message_list_ty *);
 
643
      mllp->item = xrealloc (mllp->item, nbytes);
 
644
    }
 
645
  mllp->item[mllp->nitems++] = mlp;
 
646
}
 
647
 
 
648
 
 
649
void
 
650
message_list_list_append_list (mllp, mllp2)
 
651
     message_list_list_ty *mllp;
 
652
     message_list_list_ty *mllp2;
 
653
{
 
654
  size_t j;
 
655
 
 
656
  for (j = 0; j < mllp2->nitems; ++j)
 
657
    message_list_list_append (mllp, mllp2->item[j]);
 
658
}
 
659
 
 
660
 
 
661
message_ty *
 
662
message_list_list_search (mllp, msgid)
 
663
     message_list_list_ty *mllp;
 
664
     const char *msgid;
 
665
{
 
666
  size_t j;
 
667
 
 
668
  for (j = 0; j < mllp->nitems; ++j)
 
669
    {
 
670
      message_list_ty *mlp;
 
671
      message_ty *mp;
 
672
 
 
673
      mlp = mllp->item[j];
 
674
      mp = message_list_search (mlp, msgid);
 
675
      if (mp)
 
676
        return mp;
 
677
    }
 
678
  return 0;
 
679
}
 
680
 
 
681
 
 
682
message_ty *
 
683
message_list_list_search_fuzzy (mllp, msgid)
 
684
     message_list_list_ty *mllp;
 
685
     const char *msgid;
 
686
{
 
687
  size_t j;
 
688
  double best_weight;
 
689
  message_ty *best_mp;
 
690
 
 
691
  best_weight = 0.6;
 
692
  best_mp = NULL;
 
693
  for (j = 0; j < mllp->nitems; ++j)
 
694
    {
 
695
      message_list_ty *mlp;
 
696
      message_ty *mp;
 
697
 
 
698
      mlp = mllp->item[j];
 
699
      mp = message_list_search_fuzzy_inner (mlp, msgid, &best_weight);
 
700
      if (mp)
 
701
        best_mp = mp;
 
702
    }
 
703
  return best_mp;
 
704
}
 
705
 
 
706
 
 
707
void
 
708
message_list_list_free (mllp)
 
709
     message_list_list_ty *mllp;
 
710
{
 
711
  size_t j;
 
712
 
 
713
  for (j = 0; j < mllp->nitems; ++j)
 
714
    message_list_free (mllp->item[j]);
 
715
  if (mllp->item)
 
716
    free (mllp->item);
 
717
  free (mllp);
 
718
}