~ubuntu-branches/ubuntu/quantal/openmotif/quantal

« back to all changes in this revision

Viewing changes to lib/Xm/XmStringFunc.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bauer
  • Date: 2010-06-23 12:12:31 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100623121231-u89gxdp51sg9wjj2
Tags: 2.3.0-1
* New Maintainer (Closes: #379258) 
* Acknowledge NMU changes
* New upstream release (Closes: #494375)
* Get rid of security patches as they are already part of new upstream
  release (00-xpmvuln.openmotif.patch, 342092-CVE-2005-3964.patch)
* Bump Standards to 3.8.4
* Added {misc:Depends} to make the package lintian cleaner
* Fix weak-library-dev-dependency by adding ${binary:Version}) for the
  -dev Package of openmotif
* Let package depend on autotools-dev to use newer autotools-helper-files
* Work around an autoconf-bug (Gentoo-Bug #1475)
* Added Client-side anti-aliased fonts support via XFT
* Added UTF-8 and UTF8_STRING atom support
* Ability to show text and pixmaps in Label, LabelGadget and all
  derived widgets
* Support of PNG/JPEG image formats in the same way as XPM is supported
* Increase FILE_OFFSET_BITS to 64 to show files >2GB in file-selector
  Idea taken from Magne Oestlyngen (Closes: #288537)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * @OPENGROUP_COPYRIGHT@
 
3
 * COPYRIGHT NOTICE
 
4
 * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 
5
 * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 
6
 * ALL RIGHTS RESERVED (MOTIF).  See the file named COPYRIGHT.MOTIF for
 
7
 * the full copyright text.
 
8
 * 
 
9
 * This software is subject to an open license. It may only be
 
10
 * used on, with or for operating systems which are themselves open
 
11
 * source systems. You must contact The Open Group for a license
 
12
 * allowing distribution and sublicensing of this software on, with,
 
13
 * or for operating systems which are not Open Source programs.
 
14
 * 
 
15
 * See http://www.opengroup.org/openmotif/license for full
 
16
 * details of the license agreement. Any use, reproduction, or
 
17
 * distribution of the program constitutes recipient's acceptance of
 
18
 * this agreement.
 
19
 * 
 
20
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 
21
 * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
22
 * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 
23
 * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 
24
 * OR FITNESS FOR A PARTICULAR PURPOSE
 
25
 * 
 
26
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 
27
 * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 
28
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 
30
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
32
 * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 
33
 * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 
34
 * POSSIBILITY OF SUCH DAMAGES.
 
35
 * 
 
36
 */
 
37
/*
 
38
 * HISTORY
 
39
 */
 
40
#ifdef HAVE_CONFIG_H
 
41
#include <config.h>
 
42
#endif
 
43
 
 
44
 
 
45
#ifdef REV_INFO
 
46
#ifndef lint
 
47
static char rcsid[] = "$TOG: XmStringFunc.c /main/9 1999/10/14 11:20:50 mgreess $"
 
48
#endif
 
49
#endif
 
50
 
 
51
#include <Xm/XmosP.h>
 
52
 
 
53
#include "XmI.h"
 
54
#include "XmStringI.h"
 
55
#include "XmRenderTI.h"
 
56
#include "XmTabListI.h"
 
57
 
 
58
/********    Static Function Declarations    ********/
 
59
 
 
60
static void new_line(_XmString string) ;
 
61
 
 
62
/********    End Static Function Declarations    ********/
 
63
 
 
64
 
 
65
XmStringComponentType
 
66
XmStringPeekNextTriple(XmStringContext context)
 
67
{
 
68
  unsigned int len;
 
69
  XtPointer    val;
 
70
 
 
71
  return XmeStringGetComponent((_XmStringContext) context, False, False, &len, &val);
 
72
}
 
73
 
 
74
Boolean 
 
75
XmStringHasSubstring(
 
76
        XmString string,
 
77
        XmString substring )
 
78
{
 
79
  _XmStringContextRec stack_context;
 
80
  char               *text;
 
81
  char               *subtext;
 
82
  short               char_count;
 
83
  short               subchar_count;
 
84
  Boolean             found;
 
85
  int                 i, j, max;
 
86
  _XmStringEntry      line, *entry, seg;
 
87
  XmStringComponentType type;
 
88
  unsigned int        len;
 
89
  XtPointer           val;
 
90
    
 
91
  _XmProcessLock();
 
92
  if ((string == NULL) || (substring == NULL) || (XmStringEmpty(substring))) {
 
93
    _XmProcessUnlock();
 
94
    return (FALSE);
 
95
  }
 
96
 
 
97
  /*
 
98
   * The substring must be a one line/one segment string.
 
99
   */
 
100
  
 
101
  if (_XmStrEntryCountGet(substring) != 1) {
 
102
    _XmProcessUnlock();
 
103
    return (FALSE);
 
104
  }
 
105
 
 
106
  if (((entry = _XmStrEntryGet(substring)) != NULL) && 
 
107
      _XmEntrySegmentCountGet(entry[0]) > 1) {
 
108
    _XmProcessUnlock();
 
109
    return (FALSE);
 
110
  }
 
111
 
 
112
  /*
 
113
   * Get the text out of the substring.
 
114
   */
 
115
 
 
116
  if (_XmStrOptimized(substring))
 
117
    {
 
118
      subchar_count = (short)_XmStrByteCount(substring);
 
119
      subtext = (char *)_XmStrText(substring);
 
120
    }
 
121
  else if (_XmStrMultiple(substring))
 
122
    {
 
123
      line = entry[0];
 
124
      
 
125
      if (_XmEntryMultiple(line))
 
126
        {
 
127
          seg = (_XmStringEntry)_XmEntrySegmentGet(line)[0];
 
128
          
 
129
          subchar_count = (short)_XmEntryByteCountGet(seg);
 
130
          subtext = (char*) _XmEntryTextGet(seg);
 
131
        }
 
132
      else
 
133
        {
 
134
          subchar_count = (short)_XmEntryByteCountGet(line);
 
135
          subtext = (char*) _XmEntryTextGet(line);
 
136
        }
 
137
    }
 
138
  else {                  /* Oops, some weird string! */
 
139
    _XmProcessUnlock();
 
140
    return (FALSE);
 
141
  }
 
142
  
 
143
    
 
144
  if ((subchar_count == 0) || (subtext == NULL)) {
 
145
    _XmProcessUnlock();
 
146
    return (FALSE);
 
147
  }
 
148
 
 
149
  /** Find a text component that matches. **/
 
150
  if (string) {
 
151
    _XmStringContextReInit(&stack_context, string);
 
152
    while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
 
153
                                         &len, &val)) != 
 
154
           XmSTRING_COMPONENT_END)
 
155
      {
 
156
        switch(type) 
 
157
          {
 
158
          case XmSTRING_COMPONENT_TEXT:
 
159
          case XmSTRING_COMPONENT_LOCALE_TEXT:
 
160
          case XmSTRING_COMPONENT_WIDECHAR_TEXT:
 
161
 
 
162
            char_count = len;
 
163
            text = (char *)val;
 
164
              
 
165
            if (char_count >= subchar_count) {
 
166
              max = char_count - subchar_count;
 
167
              for (i = 0; i <= max; i++) {
 
168
                found = TRUE;
 
169
              
 
170
                for (j = 0; j < subchar_count; j++) {
 
171
                  if (text[i+j] != subtext[j])  {
 
172
                    found = FALSE;
 
173
                    break;
 
174
                  }
 
175
                }
 
176
                if (found) {
 
177
                  _XmStringContextFree(&stack_context);
 
178
                  _XmProcessUnlock();
 
179
                  return(TRUE);
 
180
                }
 
181
              }
 
182
            }
 
183
            break;
 
184
          default:
 
185
            break;
 
186
          }
 
187
      }
 
188
    _XmStringContextFree(&stack_context);
 
189
  }
 
190
  _XmProcessUnlock();
 
191
  return (FALSE);
 
192
}
 
193
 
 
194
XmStringTable
 
195
XmStringTableParseStringArray(XtPointer   *strings,
 
196
                              Cardinal     count,
 
197
                              XmStringTag  tag, 
 
198
                              XmTextType   type, 
 
199
                              XmParseTable parse, 
 
200
                              Cardinal     parse_count,
 
201
                              XtPointer    call_data)
 
202
{
 
203
  int   i;
 
204
  XmStringTable strs;
 
205
 
 
206
  _XmProcessLock();
 
207
  if ((strings == NULL) || (count == 0)) {
 
208
    _XmProcessUnlock();
 
209
    return(NULL);
 
210
  }
 
211
  
 
212
  strs = (XmStringTable)XtMalloc(count * sizeof(XmString));
 
213
  
 
214
  for (i = 0; i < count; i++)
 
215
    {
 
216
      strs[i] = XmStringParseText(strings[i], NULL, tag, type, 
 
217
                                  parse, parse_count, call_data);
 
218
    }
 
219
 
 
220
  _XmProcessUnlock();
 
221
  return(strs);
 
222
}
 
223
 
 
224
XtPointer *
 
225
XmStringTableUnparse(XmStringTable     table,
 
226
                     Cardinal          count,
 
227
                     XmStringTag       tag, 
 
228
                     XmTextType        tag_type, 
 
229
                     XmTextType        output_type, 
 
230
                     XmParseTable      parse, 
 
231
                     Cardinal          parse_count, 
 
232
                     XmParseModel      parse_model)
 
233
{
 
234
  XtPointer     *strs;
 
235
  int           i;
 
236
  
 
237
  _XmProcessLock();
 
238
  if ((table == NULL) || (count == 0)) {
 
239
    _XmProcessUnlock();
 
240
    return(NULL);
 
241
  }
 
242
  
 
243
  strs = (XtPointer *)XtMalloc(count * sizeof(XtPointer));
 
244
  
 
245
  for (i = 0; i < count; i++)
 
246
    strs[i] = XmStringUnparse(table[i], tag, tag_type, output_type,
 
247
                              parse, parse_count, parse_model);
 
248
  _XmProcessUnlock();
 
249
  return(strs);
 
250
}
 
251
 
 
252
XmString
 
253
XmStringTableToXmString(XmStringTable  table,
 
254
                        Cardinal       count,
 
255
                        XmString       break_comp)
 
256
{
 
257
  /* Note: this is a very expensive way to do this.  Fix for Beta */
 
258
  int           i;
 
259
  XmString      str = NULL, tmp1, tmp2;
 
260
 
 
261
  _XmProcessLock();
 
262
  tmp1 = NULL;
 
263
 
 
264
  for (i = 0; i < count; i++)
 
265
    {
 
266
      tmp2 = XmStringConcatAndFree(tmp1, XmStringCopy(table[i]));
 
267
      str = XmStringConcatAndFree(tmp2, XmStringCopy(break_comp));
 
268
 
 
269
      tmp1 = str;
 
270
    }
 
271
  
 
272
  _XmProcessUnlock();
 
273
  return(str);
 
274
}
 
275
 
 
276
XmString
 
277
XmStringPutRendition(XmString string,
 
278
                     XmStringTag rendition)
 
279
{
 
280
  /* Quick and dirty.  Fix for beta! */
 
281
  XmString      str, tmp1, tmp2;
 
282
  
 
283
  tmp1 = XmStringComponentCreate(XmSTRING_COMPONENT_RENDITION_BEGIN,
 
284
                                 strlen(rendition), (XtPointer)rendition);
 
285
  tmp2 = XmStringConcatAndFree(tmp1, XmStringCopy(string));
 
286
 
 
287
  tmp1 = XmStringComponentCreate(XmSTRING_COMPONENT_RENDITION_END,
 
288
                                 strlen(rendition), (XtPointer)rendition);
 
289
  str = XmStringConcatAndFree(tmp2, tmp1);
 
290
  
 
291
  return(str);
 
292
}
 
293
 
 
294
void 
 
295
XmParseMappingGetValues(XmParseMapping mapping,
 
296
                        ArgList        arg_list,
 
297
                        Cardinal       arg_count)
 
298
{
 
299
  register Cardinal i;
 
300
  register String arg_name;
 
301
 
 
302
  _XmProcessLock();
 
303
  /* Do a little error checking. */
 
304
  if (mapping == NULL) {
 
305
    _XmProcessUnlock();
 
306
    return;
 
307
  }
 
308
 
 
309
  /* Modify the specified values. */
 
310
  for (i = 0; i < arg_count; i++)
 
311
    {
 
312
      arg_name = arg_list[i].name;
 
313
 
 
314
      if ((arg_name == XmNpattern) ||
 
315
          (strcmp(arg_name, XmNpattern) == 0))
 
316
        *((XtPointer*)arg_list[i].value) = mapping->pattern;
 
317
      else if ((arg_name == XmNpatternType) ||
 
318
               (strcmp(arg_name, XmNpatternType) == 0))
 
319
        *((XmTextType*)arg_list[i].value) = mapping->pattern_type;
 
320
      else if ((arg_name == XmNsubstitute) ||
 
321
               (strcmp(arg_name, XmNsubstitute) == 0))
 
322
        *((XmString*)arg_list[i].value) = XmStringCopy(mapping->substitute);
 
323
      else if ((arg_name == XmNinvokeParseProc) ||
 
324
               (strcmp(arg_name, XmNinvokeParseProc) == 0))
 
325
        *((XmParseProc*)arg_list[i].value) = mapping->parse_proc;
 
326
      else if ((arg_name == XmNclientData) ||
 
327
               (strcmp(arg_name, XmNclientData) == 0))
 
328
        *((XtPointer*)arg_list[i].value) = mapping->client_data;
 
329
      else if ((arg_name == XmNincludeStatus) ||
 
330
               (strcmp(arg_name, XmNincludeStatus) == 0))
 
331
        *((XmIncludeStatus*)arg_list[i].value) = mapping->include_status;
 
332
    }
 
333
  _XmProcessUnlock();
 
334
}
 
335
 
 
336
void 
 
337
XmParseMappingFree(XmParseMapping mapping)
 
338
{
 
339
  _XmProcessLock();
 
340
  if (mapping != NULL)
 
341
    {
 
342
      /* Free copied data. */
 
343
      XmStringFree(mapping->substitute);
 
344
 
 
345
      /* Free the record. */
 
346
      XtFree((char*) mapping);
 
347
    }
 
348
  _XmProcessUnlock();
 
349
}
 
350
 
 
351
void 
 
352
XmParseTableFree(XmParseTable parse_table,
 
353
                 Cardinal     parse_count)
 
354
{
 
355
  /* Free each entry in the table. */
 
356
  Cardinal i;
 
357
 
 
358
  _XmProcessLock();
 
359
  for (i = 0; i < parse_count; i++)
 
360
    XmParseMappingFree(parse_table[i]);
 
361
 
 
362
  /* Free the table itself. */
 
363
  XtFree((char*) parse_table);
 
364
  _XmProcessUnlock();
 
365
}
 
366
 
 
367
/*
 
368
 * XmeGetNextCharacter: An XmParseProc to consume the triggering
 
369
 *      character and insert the following character.
 
370
 */
 
371
/*ARGSUSED*/
 
372
XmIncludeStatus
 
373
XmeGetNextCharacter(XtPointer     *in_out, 
 
374
                    XtPointer      text_end,
 
375
                    XmTextType     type, 
 
376
                    XmStringTag    tag, 
 
377
                    XmParseMapping entry, /* unused */
 
378
                    int            pattern_length,
 
379
                    XmString      *str_include,
 
380
                    XtPointer      call_data) /* unused */
 
381
{
 
382
  char* ptr = (char*) *in_out;
 
383
  int len = 0;
 
384
  XmStringComponentType comp_type;
 
385
  assert(in_out != NULL);
 
386
 
 
387
  _XmProcessLock();
 
388
  /* Initialize the out parameters */
 
389
  *str_include = NULL;
 
390
 
 
391
  /* Consume the triggering characters. */
 
392
  ptr += pattern_length;
 
393
 
 
394
  /* Select the component type. */
 
395
  switch (type)
 
396
    {
 
397
    case XmCHARSET_TEXT:
 
398
      if ((tag != NULL) && (strcmp(XmFONTLIST_DEFAULT_TAG, tag) == 0))
 
399
        comp_type = XmSTRING_COMPONENT_LOCALE_TEXT;
 
400
      else
 
401
        comp_type = XmSTRING_COMPONENT_TEXT;
 
402
      if ((text_end == NULL) || (ptr < (char*) text_end))
 
403
#ifndef NO_MULTIBYTE
 
404
        len = mblen(ptr, MB_CUR_MAX);
 
405
#else
 
406
        len = *ptr ? 1 : 0;
 
407
#endif
 
408
      break;
 
409
 
 
410
    case XmMULTIBYTE_TEXT:
 
411
      /* In Motif 2.0 dynamic switching of locales isn't supported. */
 
412
      comp_type = XmSTRING_COMPONENT_LOCALE_TEXT;
 
413
      if ((text_end == NULL) || (ptr < (char*) text_end))
 
414
#ifndef NO_MULTIBYTE
 
415
        len = mblen(ptr, MB_CUR_MAX);
 
416
#else
 
417
        len = *ptr ? 1 : 0;
 
418
#endif
 
419
      break;
 
420
 
 
421
    case XmWIDECHAR_TEXT:
 
422
      comp_type = XmSTRING_COMPONENT_WIDECHAR_TEXT;
 
423
      if ((text_end == NULL) || (ptr < (char*) text_end))
 
424
        len = sizeof(wchar_t);
 
425
      break;
 
426
 
 
427
    default:
 
428
      comp_type = XmSTRING_COMPONENT_UNKNOWN;
 
429
      break;
 
430
    }
 
431
 
 
432
  /* Quit if mblen() failed or if type was unrecognized. */
 
433
  if ((len <= 0) || (comp_type == XmSTRING_COMPONENT_UNKNOWN))
 
434
    {
 
435
      *in_out = (XtPointer) ptr;
 
436
      _XmProcessUnlock();
 
437
      return XmINSERT;
 
438
    }
 
439
 
 
440
  /* Create a component containing the next character. */
 
441
  *str_include = XmStringComponentCreate(comp_type, len, ptr);
 
442
  ptr += len;
 
443
  *in_out = (XtPointer) ptr;
 
444
  
 
445
  _XmProcessUnlock();
 
446
  return XmINSERT;
 
447
}
 
448
 
 
449
static void 
 
450
new_line(
 
451
        _XmString string )
 
452
{
 
453
    int lc = _XmStrEntryCount(string);
 
454
    _XmStringEntry line;
 
455
    
 
456
    _XmStrImplicitLine(string) = TRUE;
 
457
 
 
458
    _XmStrEntry(string) = (_XmStringEntry *) 
 
459
      XtRealloc((char *) _XmStrEntry(string), 
 
460
                sizeof(_XmStringEntry) * (lc + 1));
 
461
    
 
462
    _XmEntryCreate(line, XmSTRING_ENTRY_ARRAY);
 
463
    _XmStrEntry(string)[lc] = line;
 
464
 
 
465
    _XmEntrySegmentCount(line) = 0;
 
466
    _XmEntrySegment(line) = NULL;
 
467
 
 
468
    _XmStrEntryCount(string)++;
 
469
}
 
470
 
 
471
static XmString
 
472
MakeStrFromSeg(XmStringContext start)
 
473
{
 
474
  _XmStringEntry        *line;
 
475
  _XmStringEntry        *segs, seg;
 
476
  _XmString             str;
 
477
  
 
478
  if (_XmStrContOpt(start)) {
 
479
    _XmStrContError(start) = TRUE;
 
480
    return(XmStringCopy(_XmStrContString(start)));
 
481
  } else {
 
482
    /* get segment */
 
483
    line = _XmStrEntry(_XmStrContString(start));
 
484
    
 
485
    /* Create XmString structure */
 
486
    _XmStrCreate(str, XmSTRING_MULTIPLE_ENTRY, 0);
 
487
    
 
488
    if (_XmEntryMultiple(line[_XmStrContCurrLine(start)])) {
 
489
      segs = (_XmStringEntry*)_XmEntrySegment(line[_XmStrContCurrLine(start)]);
 
490
      
 
491
      new_line(str);
 
492
    
 
493
      if (_XmStrContCurrSeg(start) < _XmEntrySegmentCount(line)) {
 
494
        seg = segs[_XmStrContCurrSeg(start)];
 
495
        
 
496
        _XmStringSegmentNew(str, 0, seg, True);
 
497
        
 
498
        _XmStrContCurrSeg(start)++;
 
499
        
 
500
        _XmStrContDir(start)     = _XmEntryDirectionGet(seg);
 
501
        _XmStrContTag(start)     = _XmEntryTag(seg);
 
502
        _XmStrContTagType(start) = (XmTextType) _XmEntryTextTypeGet(seg);
 
503
      } else {
 
504
        new_line(str);
 
505
        _XmStrContCurrSeg(start) = 0;
 
506
        _XmStrContCurrLine(start)++;
 
507
      }
 
508
    } else {
 
509
      seg = line[_XmStrContCurrLine(start)];
 
510
      _XmStringSegmentNew(str, 0, seg, True);
 
511
      
 
512
      _XmStrContCurrSeg(start) = 0;
 
513
      _XmStrContCurrLine(start)++;
 
514
      
 
515
      _XmStrContDir(start)     = _XmEntryDirectionGet(seg);
 
516
      _XmStrContTag(start)     = _XmEntryTag(seg);
 
517
      _XmStrContTagType(start) = (XmTextType) _XmEntryTextTypeGet(seg);
 
518
    }
 
519
    _XmStrContState(start)   = PUSH_STATE;
 
520
  }
 
521
  return(str);
 
522
}
 
523
 
 
524
static Boolean
 
525
LastSeg(XmStringContext start)
 
526
{
 
527
  _XmStringEntry        *line;
 
528
  
 
529
  if (_XmStrContOpt(start)) 
 
530
    {
 
531
      return(TRUE);
 
532
    } else {
 
533
      line = _XmStrEntry(_XmStrContString(start));
 
534
    
 
535
      if (_XmEntryMultiple(line[_XmStrContCurrLine(start)]))
 
536
        return(_XmStrContCurrSeg(start) == _XmEntrySegmentCount(line));
 
537
      else return(TRUE);
 
538
    }
 
539
}
 
540
 
 
541
static Boolean
 
542
ContextsMatch(XmStringContext a,
 
543
              XmStringContext b)
 
544
{
 
545
  if ((_XmStrContCurrLine(a) == _XmStrContCurrLine(b)) &&
 
546
      (_XmStrContCurrSeg(a) == _XmStrContCurrSeg(b)) &&
 
547
      (_XmStrContState(a) == _XmStrContState(b)))
 
548
 
 
549
    if (((_XmStrContState(a) == BEGIN_REND_STATE) ||
 
550
        (_XmStrContState(a) == END_REND_STATE)))
 
551
 
 
552
      if (_XmStrContRendIndex(a) == _XmStrContRendIndex(b))
 
553
        return(TRUE);
 
554
      else return(FALSE);
 
555
 
 
556
    else return(TRUE);
 
557
 
 
558
  else return(FALSE);
 
559
}
 
560
 
 
561
static XmString
 
562
MakeStr(XmStringContext start,
 
563
        XmStringContext end)
 
564
{
 
565
  /* This is quick and dirty, need to be smarter about it before Beta. */
 
566
  XmStringComponentType type;
 
567
  unsigned int          len;
 
568
  XtPointer             val;
 
569
  XmString              str;
 
570
  
 
571
 
 
572
  /* Next component over start until at segment break */
 
573
  str = NULL;
 
574
  
 
575
  while (_XmStrContState(start) != PUSH_STATE)
 
576
    {
 
577
      type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val);
 
578
 
 
579
      if (ContextsMatch(start, end)) return(str);
 
580
 
 
581
      str = XmStringConcatAndFree(str,
 
582
                                  XmStringComponentCreate(type, len, val));
 
583
    }
 
584
       
 
585
  /* Next segment over start incrementing until one segment before context */
 
586
  while ((_XmStrContCurrLine(start) < (_XmStrContCurrLine(end) - 1)) ||
 
587
         ((_XmStrContCurrLine(start) == _XmStrContCurrLine(end)) &&
 
588
          (_XmStrContCurrSeg(start) < _XmStrContCurrSeg(end))) ||
 
589
         !LastSeg(start))
 
590
    {
 
591
      str = XmStringConcatAndFree(str, MakeStrFromSeg(start));
 
592
    }
 
593
 
 
594
  /* Next component over start until it matches context */
 
595
  type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val);
 
596
  while (!ContextsMatch(start, end))
 
597
    {
 
598
      str = XmStringConcatAndFree(str, XmStringComponentCreate(type, len, val));
 
599
      type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val);
 
600
  }
 
601
    
 
602
  return(str);
 
603
}
 
604
 
 
605
Cardinal
 
606
XmStringToXmStringTable(XmString string, 
 
607
                        XmString break_component,
 
608
                        XmStringTable *table)
 
609
{
 
610
  /* Note: this is a very expensive way to do this.  Fix for Beta */
 
611
  _XmStringContextRec   stack_context, stack_start;
 
612
  XmStringComponentType type, b_type;
 
613
  unsigned int          len, b_len;
 
614
  XtPointer             val, b_val;
 
615
  int                   i, count;
 
616
  
 
617
  _XmProcessLock();
 
618
  /* Get triple for first component of break_component */
 
619
  if (break_component)
 
620
    {
 
621
      _XmStringContextReInit(&stack_context, break_component);
 
622
      b_type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
 
623
                                     &b_len, &b_val);
 
624
      _XmStringContextFree(&stack_context);
 
625
    }
 
626
  else
 
627
    /* Nothing to match against.  Return complete string. */
 
628
    {
 
629
      if (table != NULL)
 
630
        {
 
631
          *table = (XmStringTable)XtMalloc(sizeof(XmString));
 
632
          *table[0] = XmStringCopy(string);
 
633
        }
 
634
      _XmProcessUnlock();
 
635
      return(1);
 
636
    }
 
637
 
 
638
  /* Get context */
 
639
  if (!string)
 
640
    {
 
641
      if (table != NULL) *table = NULL;
 
642
      _XmProcessUnlock();
 
643
      return(0);
 
644
    }
 
645
  _XmStringContextReInit(&stack_context, string);
 
646
  
 
647
  /* Count number of entries for table */
 
648
  count = 0;
 
649
  while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
 
650
                                       &len, &val)) != 
 
651
         XmSTRING_COMPONENT_END)
 
652
    {
 
653
      if ((type == b_type) && (len == b_len) &&
 
654
          (memcmp(val, b_val, len) == 0))
 
655
        count++;
 
656
    }
 
657
 
 
658
  /* Allocate table and insert new strings */
 
659
  if (table != NULL)
 
660
    {
 
661
      *table = (XmStringTable)XtMalloc(count * sizeof(XmString));
 
662
      
 
663
      _XmStringContextReInit(&stack_context, string);
 
664
      _XmStringContextReInit(&stack_start, string);
 
665
      
 
666
      i = 0;
 
667
      
 
668
      while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
 
669
                                           &len, &val)) != 
 
670
             XmSTRING_COMPONENT_END)
 
671
        {
 
672
          if ((type == b_type) && (len == b_len) &&
 
673
              (memcmp(val, b_val, len) == 0))
 
674
            {
 
675
              /* make XmString from start to end */
 
676
              (*table)[i] = MakeStr(&stack_start, &stack_context);
 
677
              i++;
 
678
            }
 
679
        } 
 
680
 
 
681
      _XmStringContextFree(&stack_start);
 
682
    }
 
683
  _XmStringContextFree(&stack_context);
 
684
 
 
685
  _XmProcessUnlock();
 
686
  return(count);
 
687
}
 
688
 
 
689
 
 
690
 
 
691
XmTabList
 
692
XmStringTableProposeTablist(XmStringTable strings,
 
693
                            Cardinal num_strings,
 
694
                            Widget widget,
 
695
                            float pad_value,
 
696
                            XmOffsetModel offset_model)
 
697
{
 
698
  int                   i, j;
 
699
  _XmStringContextRec   stack_ctx;
 
700
  XmTabList             tl;
 
701
  XmTab                 tab, prev, start;
 
702
  float                 width, val;
 
703
  unsigned char         units;
 
704
  Arg                   args[1];
 
705
  int                   n;
 
706
  _XmRenditionRec       scratch;
 
707
  XmRendition           rend;
 
708
  _XmRendition          tmp;
 
709
  XmRenderTable         rt;
 
710
  NextTabResult         ret_val;
 
711
  
 
712
  _XmProcessLock();
 
713
  if ((strings == NULL) || (num_strings == 0)) {
 
714
    _XmProcessUnlock();
 
715
    return ((XmTabList)NULL);
 
716
  }
 
717
  
 
718
  bzero((char*) &scratch, sizeof(_XmRenditionRec));
 
719
  tmp = &scratch;
 
720
  rend = &tmp;
 
721
  
 
722
  _XmRendDisplay(rend) = XtDisplayOfObject(widget);
 
723
 
 
724
  n = 0;
 
725
  XtSetArg(args[n], XmNrenderTable, &rt); n++;
 
726
  XtGetValues(widget, args, n);
 
727
 
 
728
  /* Work around weird bug with XtGetValues. */
 
729
  n = 0;
 
730
  XtSetArg(args[n], XmNunitType, &units); n++;
 
731
  XtGetValues(widget, args, n);
 
732
 
 
733
  if (rt == NULL) rt = XmeGetDefaultRenderTable(widget, XmTEXT_FONTLIST);
 
734
 
 
735
  tab = XmTabCreate(0.0, units, offset_model, XmALIGNMENT_BEGINNING, ".");
 
736
 
 
737
  tl = XmTabListInsertTabs(NULL, &tab, 1, 0);
 
738
  
 
739
  XmTabFree(tab);
 
740
  
 
741
  for (i = 0; i < num_strings; i++)
 
742
    {
 
743
      if (!strings[i])
 
744
        {
 
745
          /* Clean up */
 
746
          XmTabListFree(tl);
 
747
          _XmProcessUnlock();
 
748
          return((XmTabList)NULL);
 
749
        }
 
750
      _XmStringContextReInit(&stack_ctx, strings[i]);      
 
751
 
 
752
      tab = _XmTabLStart(tl);
 
753
      val = 0.0;
 
754
      
 
755
      /* Scan str for tabs, update tl if necessary. */
 
756
      j = 0;
 
757
      
 
758
      while ((ret_val = _XmStringGetNextTabWidth(&stack_ctx, widget, units, 
 
759
                                                 rt, &width, &rend)) != 
 
760
             XmTAB_EOS)
 
761
        {
 
762
          if (ret_val == XmTAB_NEWLINE) 
 
763
            {
 
764
              tab = _XmTabLStart(tl);
 
765
              j = 0;
 
766
              continue;
 
767
            }
 
768
          
 
769
          val = width + pad_value;
 
770
          
 
771
          if (j >= _XmTabLCount(tl))
 
772
            /* Need to add a tab */
 
773
            {
 
774
              tab = XmTabCreate(0.0, units, offset_model,
 
775
                                XmALIGNMENT_BEGINNING, ".");
 
776
              start = _XmTabLStart(tl);
 
777
              prev = _XmTabPrev(start);
 
778
              
 
779
              _XmTabNext(prev) = tab;
 
780
              _XmTabPrev(tab) = prev;
 
781
              _XmTabNext(tab) = start;
 
782
              _XmTabPrev(start) = tab;
 
783
              _XmTabLCount(tl)++;
 
784
            }
 
785
          else if (j > 0)
 
786
            {
 
787
              tab = _XmTabNext(tab);
 
788
            }
 
789
 
 
790
          if (val > _XmTabValue(tab)) XmTabSetValue(tab, val);
 
791
          else val = _XmTabValue(tab);
 
792
          j++;
 
793
        }
 
794
      
 
795
      _XmStringContextFree(&stack_ctx);
 
796
    }
 
797
  
 
798
  if (offset_model == XmABSOLUTE)
 
799
    {
 
800
      start = _XmTabLStart(tl);
 
801
      val = _XmTabValue(start);
 
802
      
 
803
      for (tab = _XmTabNext(start); tab != start; tab = _XmTabNext(tab))
 
804
        {
 
805
          val += _XmTabValue(tab);
 
806
          XmTabSetValue(tab, val);
 
807
        }
 
808
    }
 
809
  
 
810
  _XmProcessUnlock();
 
811
  return(tl);
 
812
}
 
813
 
 
814
/*
 
815
 * Helper function for XmTabList.c
 
816
 * This routine performs successive reads on an XmStringContext
 
817
 * and returns the width (in units of XmNunitType of widget) of
 
818
 * the text segments between the previous and next tab or end of line.  
 
819
 * It uses the XmNrenderTable from widget to calculate the width.  It 
 
820
 * returns XmTAB_EOS if the end of the string has been reached, XmTAB_NEWLINE
 
821
 * if the end of line is reached and XmTAB_NEXT if a tab is encountered.
 
822
 */
 
823
NextTabResult
 
824
_XmStringGetNextTabWidth(XmStringContext ctx,
 
825
                         Widget widget,
 
826
                         unsigned char units,
 
827
                         XmRenderTable rt,
 
828
                         float *width,
 
829
                         XmRendition *rend)
 
830
{
 
831
  float         divisor;
 
832
  int           toType;                   /*  passed to XmConvertUnits */
 
833
  Dimension     w_sum, w_cur;
 
834
  
 
835
  if (_XmStrContError(ctx))
 
836
    {
 
837
      *width = 0.0;
 
838
      return(XmTAB_EOS);
 
839
    }
 
840
  
 
841
  w_sum = 0;
 
842
  *width = 0.0;
 
843
 
 
844
  /* Big units need to be converted to small ones. */
 
845
  toType = _XmConvertFactor(units, &divisor);
 
846
      
 
847
  /* Calculate the width to the next tab. */
 
848
  if (_XmStrContOpt(ctx))
 
849
    {
 
850
      _XmStrContError(ctx) = True;
 
851
      return(XmTAB_EOS);
 
852
    } 
 
853
  else 
 
854
    {
 
855
      _XmString                 str = _XmStrContString(ctx);
 
856
      _XmStringEntry            line;
 
857
      int                       line_count;
 
858
      _XmStringEntry            seg;
 
859
      int                       seg_count;
 
860
      _XmStringArraySegRec      array_seg;
 
861
      
 
862
      line_count = _XmStrLineCountGet(str);
 
863
      
 
864
      /* Keep checking lines and segments until we run out or hit a tab. */
 
865
      if (_XmStrContCurrLine(ctx) < line_count) 
 
866
        {
 
867
          if (_XmStrImplicitLine(str))
 
868
            {
 
869
              line = _XmStrEntry(str)[_XmStrContCurrLine(ctx)];
 
870
            }
 
871
          else
 
872
            {
 
873
              _XmEntryType(&array_seg) = XmSTRING_ENTRY_ARRAY;
 
874
              _XmEntrySegmentCount(&array_seg) = _XmStrEntryCount(str);
 
875
              _XmEntrySegment(&array_seg) = (_XmStringNREntry *)_XmStrEntry(str);
 
876
              line = (_XmStringEntry)&array_seg;
 
877
            }
 
878
      
 
879
          if (_XmEntryMultiple(line)) 
 
880
            seg_count = _XmEntrySegmentCount(line);
 
881
          else 
 
882
            seg_count = 1;
 
883
 
 
884
          if (seg_count == 0) {
 
885
            /* Empty line. */
 
886
            _XmStrContCurrLine(ctx)++;
 
887
            *width = 0.0;
 
888
            return(XmTAB_NEWLINE);
 
889
          }
 
890
 
 
891
          while (_XmStrContCurrSeg(ctx) < seg_count)
 
892
            {
 
893
              if (_XmEntryMultiple(line)) 
 
894
                seg = (_XmStringEntry)_XmEntrySegment(line)[_XmStrContCurrSeg(ctx)];
 
895
              else
 
896
                seg = line;
 
897
 
 
898
              w_cur = 0;
 
899
        
 
900
              if (_XmStrContTabCount(ctx) < _XmEntryTabsGet(seg)) {
 
901
                _XmStrContTabCount(ctx)++;
 
902
                *width = (XmConvertUnits(widget, XmHORIZONTAL,
 
903
                                         XmPIXELS, w_sum, toType) / divisor);
 
904
                return(XmTAB_NEXT);
 
905
              }
 
906
 
 
907
              (void)_XmStringSegmentExtents(seg, rt, rend, NULL,
 
908
                                            &w_cur, NULL, NULL, NULL);
 
909
              w_sum += w_cur;
 
910
        
 
911
              _XmStrContCurrSeg(ctx)++;
 
912
              _XmStrContTabCount(ctx) = 0;
 
913
            }
 
914
 
 
915
          _XmStrContCurrLine(ctx)++;
 
916
          _XmStrContCurrSeg(ctx) = 0;
 
917
          _XmStrContTabCount(ctx) = 0;
 
918
          
 
919
          return(XmTAB_NEWLINE);
 
920
        }
 
921
 
 
922
      _XmStrContError(ctx) = True;
 
923
      return(XmTAB_EOS);
 
924
    }
 
925
}
 
926