1 /****************************************************************************
2 * Copyright (c) 1999-2009,2010 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Thomas E. Dickey <dickey@clark.net> 1999-on *
31 ****************************************************************************/
34 * align_ttype.c -- functions for TERMTYPE
36 * _nc_align_termtype()
41 #include <curses.priv.h>
45 MODULE_ID("$Id: alloc_ttype.c,v 1.22 2010/12/19 00:24:09 tom Exp $")
49 * Merge the a/b lists into dst. Both a/b are sorted (see _nc_extend_names()),
50 * so we do not have to worry about order dependencies.
53 merge_names(char **dst
, char **a
, int na
, char **b
, int nb
)
56 while (na
> 0 && nb
> 0) {
57 int cmp
= strcmp(*a
, *b
);
64 } else if (cmp
== 0) {
76 DEBUG(4, ("merge_names -> %d", n
));
81 find_name(char **table
, int length
, char *name
)
83 while (length
-- > 0) {
84 if (!strcmp(*table
++, name
)) {
85 DEBUG(4, ("found name '%s'", name
));
89 DEBUG(4, ("did not find name '%s'", name
));
93 #define EXTEND_NUM(num, ext) \
94 to->num = (unsigned short) (to->num + (ext - to->ext))
97 realign_data(TERMTYPE
*to
, char **ext_Names
,
103 int limit
= (to
->ext_Booleans
+ to
->ext_Numbers
+ to
->ext_Strings
);
105 if (to
->ext_Booleans
!= ext_Booleans
) {
106 EXTEND_NUM(num_Booleans
, ext_Booleans
);
107 to
->Booleans
= typeRealloc(NCURSES_SBOOL
, to
->num_Booleans
, to
->Booleans
);
108 for (n
= to
->ext_Booleans
- 1,
109 m
= ext_Booleans
- 1,
110 base
= to
->num_Booleans
- (m
+ 1); m
>= 0; m
--) {
111 if (find_name(to
->ext_Names
, limit
, ext_Names
[m
])) {
112 to
->Booleans
[base
+ m
] = to
->Booleans
[base
+ n
--];
114 to
->Booleans
[base
+ m
] = FALSE
;
117 to
->ext_Booleans
= UShort(ext_Booleans
);
119 if (to
->ext_Numbers
!= ext_Numbers
) {
120 EXTEND_NUM(num_Numbers
, ext_Numbers
);
121 to
->Numbers
= typeRealloc(short, to
->num_Numbers
, to
->Numbers
);
122 for (n
= to
->ext_Numbers
- 1,
124 base
= to
->num_Numbers
- (m
+ 1); m
>= 0; m
--) {
125 if (find_name(to
->ext_Names
, limit
, ext_Names
[m
+ ext_Booleans
])) {
126 to
->Numbers
[base
+ m
] = to
->Numbers
[base
+ n
--];
128 to
->Numbers
[base
+ m
] = ABSENT_NUMERIC
;
131 to
->ext_Numbers
= UShort(ext_Numbers
);
133 if (to
->ext_Strings
!= ext_Strings
) {
134 EXTEND_NUM(num_Strings
, ext_Strings
);
135 to
->Strings
= typeRealloc(char *, to
->num_Strings
, to
->Strings
);
136 for (n
= to
->ext_Strings
- 1,
138 base
= to
->num_Strings
- (m
+ 1); m
>= 0; m
--) {
139 if (find_name(to
->ext_Names
, limit
, ext_Names
[m
+ ext_Booleans
+ ext_Numbers
])) {
140 to
->Strings
[base
+ m
] = to
->Strings
[base
+ n
--];
142 to
->Strings
[base
+ m
] = ABSENT_STRING
;
145 to
->ext_Strings
= UShort(ext_Strings
);
150 * Returns the first index in ext_Names[] for the given token-type
153 _nc_first_ext_name(TERMTYPE
*tp
, int token_type
)
157 switch (token_type
) {
162 first
= tp
->ext_Booleans
;
165 first
= (unsigned) (tp
->ext_Booleans
+ tp
->ext_Numbers
);
175 * Returns the last index in ext_Names[] for the given token-type
178 _nc_last_ext_name(TERMTYPE
*tp
, int token_type
)
182 switch (token_type
) {
184 last
= tp
->ext_Booleans
;
187 last
= (unsigned) (tp
->ext_Booleans
+ tp
->ext_Numbers
);
191 last
= NUM_EXT_NAMES(tp
);
198 * Lookup an entry from extended-names, returning -1 if not found
201 _nc_find_ext_name(TERMTYPE
*tp
, char *name
, int token_type
)
204 unsigned first
= _nc_first_ext_name(tp
, token_type
);
205 unsigned last
= _nc_last_ext_name(tp
, token_type
);
207 for (j
= first
; j
< last
; j
++) {
208 if (!strcmp(name
, tp
->ext_Names
[j
])) {
216 * Translate an index into ext_Names[] into the corresponding index into data
217 * (e.g., Booleans[]).
220 _nc_ext_data_index(TERMTYPE
*tp
, int n
, int token_type
)
222 switch (token_type
) {
224 n
+= (tp
->num_Booleans
- tp
->ext_Booleans
);
227 n
+= (tp
->num_Numbers
- tp
->ext_Numbers
)
228 - (tp
->ext_Booleans
);
232 n
+= (tp
->num_Strings
- tp
->ext_Strings
)
233 - (tp
->ext_Booleans
+ tp
->ext_Numbers
);
239 * Adjust tables to remove (not free) an extended name and its corresponding
243 _nc_del_ext_name(TERMTYPE
*tp
, char *name
, int token_type
)
248 if ((first
= _nc_find_ext_name(tp
, name
, token_type
)) >= 0) {
249 last
= (int) NUM_EXT_NAMES(tp
) - 1;
250 for (j
= first
; j
< last
; j
++) {
251 tp
->ext_Names
[j
] = tp
->ext_Names
[j
+ 1];
253 first
= _nc_ext_data_index(tp
, first
, token_type
);
254 switch (token_type
) {
256 last
= tp
->num_Booleans
- 1;
257 for (j
= first
; j
< last
; j
++)
258 tp
->Booleans
[j
] = tp
->Booleans
[j
+ 1];
263 last
= tp
->num_Numbers
- 1;
264 for (j
= first
; j
< last
; j
++)
265 tp
->Numbers
[j
] = tp
->Numbers
[j
+ 1];
270 last
= tp
->num_Strings
- 1;
271 for (j
= first
; j
< last
; j
++)
272 tp
->Strings
[j
] = tp
->Strings
[j
+ 1];
283 * Adjust tables to insert an extended name, making room for new data. The
284 * index into the corresponding data array is returned.
287 _nc_ins_ext_name(TERMTYPE
*tp
, char *name
, int token_type
)
289 unsigned first
= _nc_first_ext_name(tp
, token_type
);
290 unsigned last
= _nc_last_ext_name(tp
, token_type
);
291 unsigned total
= NUM_EXT_NAMES(tp
) + 1;
294 for (j
= first
; j
< last
; j
++) {
295 int cmp
= strcmp(name
, tp
->ext_Names
[j
]);
297 /* already present */
298 return _nc_ext_data_index(tp
, (int) j
, token_type
);
304 tp
->ext_Names
= typeRealloc(char *, total
, tp
->ext_Names
);
305 for (k
= total
- 1; k
> j
; k
--)
306 tp
->ext_Names
[k
] = tp
->ext_Names
[k
- 1];
307 tp
->ext_Names
[j
] = name
;
308 j
= (unsigned) _nc_ext_data_index(tp
, (int) j
, token_type
);
310 switch (token_type
) {
314 tp
->Booleans
= typeRealloc(NCURSES_SBOOL
, tp
->num_Booleans
, tp
->Booleans
);
315 for (k
= (unsigned) (tp
->num_Booleans
- 1); k
> j
; k
--)
316 tp
->Booleans
[k
] = tp
->Booleans
[k
- 1];
321 tp
->Numbers
= typeRealloc(short, tp
->num_Numbers
, tp
->Numbers
);
322 for (k
= (unsigned) (tp
->num_Numbers
- 1); k
> j
; k
--)
323 tp
->Numbers
[k
] = tp
->Numbers
[k
- 1];
328 tp
->Strings
= typeRealloc(char *, tp
->num_Strings
, tp
->Strings
);
329 for (k
= (unsigned) (tp
->num_Strings
- 1); k
> j
; k
--)
330 tp
->Strings
[k
] = tp
->Strings
[k
- 1];
337 * Look for strings that are marked cancelled, which happen to be the same name
338 * as a boolean or number. We'll get this as a special case when we get a
339 * cancellation of a name that is inherited from another entry.
342 adjust_cancels(TERMTYPE
*to
, TERMTYPE
*from
)
344 int first
= to
->ext_Booleans
+ to
->ext_Numbers
;
345 int last
= first
+ to
->ext_Strings
;
348 for (j
= first
; j
< last
;) {
349 char *name
= to
->ext_Names
[j
];
350 int j_str
= to
->num_Strings
- first
- to
->ext_Strings
;
352 if (to
->Strings
[j
+ j_str
] == CANCELLED_STRING
) {
353 if (_nc_find_ext_name(from
, to
->ext_Names
[j
], BOOLEAN
) >= 0) {
354 if (_nc_del_ext_name(to
, name
, STRING
)
355 || _nc_del_ext_name(to
, name
, NUMBER
)) {
356 k
= _nc_ins_ext_name(to
, name
, BOOLEAN
);
357 to
->Booleans
[k
] = FALSE
;
361 } else if (_nc_find_ext_name(from
, to
->ext_Names
[j
], NUMBER
) >= 0) {
362 if (_nc_del_ext_name(to
, name
, STRING
)
363 || _nc_del_ext_name(to
, name
, BOOLEAN
)) {
364 k
= _nc_ins_ext_name(to
, name
, NUMBER
);
365 to
->Numbers
[k
] = CANCELLED_NUMERIC
;
369 } else if (_nc_find_ext_name(from
, to
->ext_Names
[j
], STRING
) >= 0) {
370 if (_nc_del_ext_name(to
, name
, NUMBER
)
371 || _nc_del_ext_name(to
, name
, BOOLEAN
)) {
372 k
= _nc_ins_ext_name(to
, name
, STRING
);
373 to
->Strings
[k
] = CANCELLED_STRING
;
387 _nc_align_termtype(TERMTYPE
*to
, TERMTYPE
*from
)
389 int na
= (int) NUM_EXT_NAMES(to
);
390 int nb
= (int) NUM_EXT_NAMES(from
);
394 int ext_Booleans
, ext_Numbers
, ext_Strings
;
395 bool used_ext_Names
= FALSE
;
397 DEBUG(2, ("align_termtype to(%d:%s), from(%d:%s)", na
, to
->term_names
,
398 nb
, from
->term_names
));
400 if (na
!= 0 || nb
!= 0) {
401 if ((na
== nb
) /* check if the arrays are equivalent */
402 &&(to
->ext_Booleans
== from
->ext_Booleans
)
403 && (to
->ext_Numbers
== from
->ext_Numbers
)
404 && (to
->ext_Strings
== from
->ext_Strings
)) {
405 for (n
= 0, same
= TRUE
; n
< na
; n
++) {
406 if (strcmp(to
->ext_Names
[n
], from
->ext_Names
[n
])) {
415 * This is where we pay for having a simple extension representation.
416 * Allocate a new ext_Names array and merge the two ext_Names arrays
417 * into it, updating to's counts for booleans, etc. Fortunately we do
418 * this only for the terminfo compiler (tic) and comparer (infocmp).
420 ext_Names
= typeMalloc(char *, (size_t)(na
+ nb
));
422 if (to
->ext_Strings
&& (from
->ext_Booleans
+ from
->ext_Numbers
))
423 adjust_cancels(to
, from
);
425 if (from
->ext_Strings
&& (to
->ext_Booleans
+ to
->ext_Numbers
))
426 adjust_cancels(from
, to
);
428 ext_Booleans
= merge_names(ext_Names
,
433 ext_Numbers
= merge_names(ext_Names
+ ext_Booleans
,
438 + from
->ext_Booleans
,
440 ext_Strings
= merge_names(ext_Names
+ ext_Numbers
+ ext_Booleans
,
450 * Now we must reallocate the Booleans, etc., to allow the data to be
453 if (na
!= (ext_Booleans
+ ext_Numbers
+ ext_Strings
)) {
454 realign_data(to
, ext_Names
, ext_Booleans
, ext_Numbers
, ext_Strings
);
455 FreeIfNeeded(to
->ext_Names
);
456 to
->ext_Names
= ext_Names
;
457 DEBUG(2, ("realigned %d extended names for '%s' (to)",
458 NUM_EXT_NAMES(to
), to
->term_names
));
459 used_ext_Names
= TRUE
;
461 if (nb
!= (ext_Booleans
+ ext_Numbers
+ ext_Strings
)) {
462 nb
= (ext_Booleans
+ ext_Numbers
+ ext_Strings
);
463 realign_data(from
, ext_Names
, ext_Booleans
, ext_Numbers
, ext_Strings
);
464 from
->ext_Names
= typeRealloc(char *, (size_t) nb
, from
->ext_Names
);
465 memcpy(from
->ext_Names
, ext_Names
, sizeof(char *) * (size_t) nb
);
466 DEBUG(2, ("realigned %d extended names for '%s' (from)",
467 NUM_EXT_NAMES(from
), from
->term_names
));
476 _nc_copy_termtype(TERMTYPE
*dst
, TERMTYPE
*src
)
480 *dst
= *src
; /* ...to copy the sizes and string-tables */
481 dst
->Booleans
= typeMalloc(NCURSES_SBOOL
, NUM_BOOLEANS(dst
));
482 dst
->Numbers
= typeMalloc(short, NUM_NUMBERS(dst
));
483 dst
->Strings
= typeMalloc(char *, NUM_STRINGS(dst
));
485 /* FIXME: use memcpy for these and similar loops */
486 for_each_boolean(i
, dst
)
487 dst
->Booleans
[i
] = src
->Booleans
[i
];
488 for_each_number(i
, dst
)
489 dst
->Numbers
[i
] = src
->Numbers
[i
];
490 for_each_string(i
, dst
)
491 dst
->Strings
[i
] = src
->Strings
[i
];
493 /* FIXME: we probably should also copy str_table and ext_str_table,
494 * but tic and infocmp are not written to exploit that (yet).
498 if ((i
= NUM_EXT_NAMES(src
)) != 0) {
499 dst
->ext_Names
= typeMalloc(char *, i
);
500 memcpy(dst
->ext_Names
, src
->ext_Names
, i
* sizeof(char *));