]>
Commit | Line | Data |
---|---|---|
3e542c76 KZ |
1 | /* |
2 | * table.c - functions handling the data at the table level | |
3 | * | |
4 | * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com> | |
9fd9b99f | 5 | * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com> |
9e930041 | 6 | * Copyright (C) 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com> |
3e542c76 KZ |
7 | * |
8 | * This file may be redistributed under the terms of the | |
9 | * GNU Lesser General Public License. | |
10 | */ | |
1d90bcb1 OO |
11 | |
12 | /** | |
e2310281 | 13 | * SECTION: table |
1d90bcb1 | 14 | * @title: Table |
2473b711 | 15 | * @short_description: container for rows and columns |
1d90bcb1 | 16 | * |
e2310281 | 17 | * Table data manipulation API. |
1d90bcb1 OO |
18 | */ |
19 | ||
ce44112b | 20 | |
3e542c76 KZ |
21 | #include <stdlib.h> |
22 | #include <unistd.h> | |
23 | #include <string.h> | |
24 | #include <termios.h> | |
25 | #include <ctype.h> | |
26 | ||
27 | #include "nls.h" | |
19055a25 | 28 | #include "ttyutils.h" |
3e542c76 KZ |
29 | #include "smartcolsP.h" |
30 | ||
31 | #ifdef HAVE_WIDECHAR | |
d52f5542 KZ |
32 | #define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char | */ |
33 | #define UTF_VR "\342\224\234" /* U+251C, Vertical and right |- */ | |
34 | #define UTF_H "\342\224\200" /* U+2500, Horizontal - */ | |
35 | #define UTF_UR "\342\224\224" /* U+2514, Up and right '- */ | |
36 | ||
37 | #define UTF_V3 "\342\224\206" /* U+2506 Triple Dash Vertical | */ | |
38 | #define UTF_H3 "\342\224\210" /* U+2504 Triple Dash Horizontal - */ | |
39 | #define UTF_DR "\342\224\214" /* U+250C Down and Right ,- */ | |
40 | #define UTF_DH "\342\224\254" /* U+252C Down and Horizontal |' */ | |
41 | ||
42 | #define UTF_TR "\342\226\266" /* U+25B6 Black Right-Pointing Triangle > */ | |
3e542c76 KZ |
43 | #endif /* !HAVE_WIDECHAR */ |
44 | ||
45 | #define is_last_column(_tb, _cl) \ | |
46 | list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns) | |
47 | ||
48 | ||
37948503 KZ |
49 | static void check_padding_debug(struct libscols_table *tb) |
50 | { | |
51 | const char *str; | |
52 | ||
53 | assert(libsmartcols_debug_mask); /* debug has to be enabled! */ | |
54 | ||
55 | str = getenv("LIBSMARTCOLS_DEBUG_PADDING"); | |
56 | if (!str || (strcmp(str, "on") != 0 && strcmp(str, "1") != 0)) | |
57 | return; | |
58 | ||
59 | DBG(INIT, ul_debugobj(tb, "padding debug: ENABLE")); | |
60 | tb->padding_debug = 1; | |
61 | } | |
62 | ||
1d90bcb1 OO |
63 | /** |
64 | * scols_new_table: | |
3e542c76 | 65 | * |
1d90bcb1 | 66 | * Returns: A newly allocated table. |
3e542c76 | 67 | */ |
0925a9dd | 68 | struct libscols_table *scols_new_table(void) |
3e542c76 KZ |
69 | { |
70 | struct libscols_table *tb; | |
e33b3874 | 71 | int c, l; |
3e542c76 KZ |
72 | |
73 | tb = calloc(1, sizeof(struct libscols_table)); | |
74 | if (!tb) | |
75 | return NULL; | |
76 | ||
3e542c76 | 77 | tb->refcount = 1; |
571441e2 | 78 | tb->out = stdout; |
e33b3874 KZ |
79 | |
80 | get_terminal_dimension(&c, &l); | |
81 | tb->termwidth = c > 0 ? c : 80; | |
82 | tb->termheight = l > 0 ? l : 24; | |
3e542c76 KZ |
83 | |
84 | INIT_LIST_HEAD(&tb->tb_lines); | |
85 | INIT_LIST_HEAD(&tb->tb_columns); | |
d52f5542 | 86 | INIT_LIST_HEAD(&tb->tb_groups); |
3e542c76 | 87 | |
710ed55d | 88 | DBG(TAB, ul_debugobj(tb, "alloc")); |
37948503 KZ |
89 | ON_DBG(INIT, check_padding_debug(tb)); |
90 | ||
1424fe8c | 91 | return tb; |
3e542c76 KZ |
92 | } |
93 | ||
1d90bcb1 OO |
94 | /** |
95 | * scols_ref_table: | |
96 | * @tb: a pointer to a struct libscols_table instance | |
97 | * | |
98 | * Increases the refcount of @tb. | |
99 | */ | |
3e542c76 KZ |
100 | void scols_ref_table(struct libscols_table *tb) |
101 | { | |
102 | if (tb) | |
103 | tb->refcount++; | |
104 | } | |
105 | ||
d52f5542 KZ |
106 | static void scols_table_remove_groups(struct libscols_table *tb) |
107 | { | |
108 | while (!list_empty(&tb->tb_groups)) { | |
109 | struct libscols_group *gr = list_entry(tb->tb_groups.next, | |
110 | struct libscols_group, gr_groups); | |
111 | scols_group_remove_children(gr); | |
112 | scols_group_remove_members(gr); | |
113 | scols_unref_group(gr); | |
114 | } | |
115 | } | |
116 | ||
1d90bcb1 OO |
117 | /** |
118 | * scols_unref_table: | |
119 | * @tb: a pointer to a struct libscols_table instance | |
120 | * | |
3175f035 KZ |
121 | * Decreases the refcount of @tb. When the count falls to zero, the instance |
122 | * is automatically deallocated. | |
1d90bcb1 | 123 | */ |
3e542c76 KZ |
124 | void scols_unref_table(struct libscols_table *tb) |
125 | { | |
126 | if (tb && (--tb->refcount <= 0)) { | |
d52f5542 KZ |
127 | DBG(TAB, ul_debugobj(tb, "dealloc <-")); |
128 | scols_table_remove_groups(tb); | |
3e542c76 KZ |
129 | scols_table_remove_lines(tb); |
130 | scols_table_remove_columns(tb); | |
131 | scols_unref_symbols(tb->symbols); | |
e865838d | 132 | scols_reset_cell(&tb->title); |
d52f5542 | 133 | free(tb->grpset); |
d1b4d14f OO |
134 | free(tb->linesep); |
135 | free(tb->colsep); | |
2a6cfc13 | 136 | free(tb->name); |
3e542c76 | 137 | free(tb); |
d52f5542 KZ |
138 | DBG(TAB, ul_debug("<- done")); |
139 | } | |
140 | } | |
141 | ||
142 | /* Private API */ | |
143 | int scols_table_next_group(struct libscols_table *tb, | |
144 | struct libscols_iter *itr, | |
145 | struct libscols_group **gr) | |
146 | { | |
147 | int rc = 1; | |
148 | ||
149 | if (!tb || !itr || !gr) | |
150 | return -EINVAL; | |
151 | *gr = NULL; | |
152 | ||
153 | if (!itr->head) | |
154 | SCOLS_ITER_INIT(itr, &tb->tb_groups); | |
155 | if (itr->p != itr->head) { | |
156 | SCOLS_ITER_ITERATE(itr, *gr, struct libscols_group, gr_groups); | |
157 | rc = 0; | |
3e542c76 | 158 | } |
d52f5542 KZ |
159 | |
160 | return rc; | |
3e542c76 KZ |
161 | } |
162 | ||
2a6cfc13 KZ |
163 | /** |
164 | * scols_table_set_name: | |
165 | * @tb: a pointer to a struct libscols_table instance | |
618a1d6d | 166 | * @name: a name |
2a6cfc13 KZ |
167 | * |
168 | * The table name is used for example for JSON top level object name. | |
169 | * | |
170 | * Returns: 0, a negative number in case of an error. | |
982034c3 KZ |
171 | * |
172 | * Since: 2.27 | |
2a6cfc13 | 173 | */ |
618a1d6d | 174 | int scols_table_set_name(struct libscols_table *tb, const char *name) |
2a6cfc13 | 175 | { |
618a1d6d | 176 | return strdup_to_struct_member(tb, name, name); |
2a6cfc13 KZ |
177 | } |
178 | ||
96960717 IG |
179 | /** |
180 | * scols_table_get_name: | |
181 | * @tb: a pointer to a struct libscols_table instance | |
182 | * | |
183 | * Returns: The current name setting of the table @tb | |
184 | * | |
185 | * Since: 2.29 | |
186 | */ | |
187 | const char *scols_table_get_name(const struct libscols_table *tb) | |
188 | { | |
189 | return tb->name; | |
190 | } | |
191 | ||
703d0196 IG |
192 | /** |
193 | * scols_table_get_title: | |
194 | * @tb: a pointer to a struct libscols_table instance | |
195 | * | |
a593128f KZ |
196 | * The returned pointer is possible to modify by cell functions. Note that |
197 | * title output alignment on non-tty is hardcoded to 80 output chars. For the | |
198 | * regular terminal it's based on terminal width. | |
199 | * | |
aef70f55 | 200 | * Returns: Title of the table, or NULL in case of blank title. |
703d0196 IG |
201 | * |
202 | * Since: 2.28 | |
203 | */ | |
e865838d | 204 | struct libscols_cell *scols_table_get_title(struct libscols_table *tb) |
703d0196 | 205 | { |
e865838d | 206 | return &tb->title; |
703d0196 IG |
207 | } |
208 | ||
1d90bcb1 OO |
209 | /** |
210 | * scols_table_add_column: | |
211 | * @tb: a pointer to a struct libscols_table instance | |
212 | * @cl: a pointer to a struct libscols_column instance | |
1d90bcb1 | 213 | * |
7ad4b850 KZ |
214 | * Adds @cl to @tb's column list. The column cannot be shared between more |
215 | * tables. | |
1d90bcb1 OO |
216 | * |
217 | * Returns: 0, a negative number in case of an error. | |
218 | */ | |
0925a9dd | 219 | int scols_table_add_column(struct libscols_table *tb, struct libscols_column *cl) |
3e542c76 | 220 | { |
17658145 KZ |
221 | struct libscols_iter itr; |
222 | struct libscols_line *ln; | |
223 | int rc = 0; | |
224 | ||
225 | if (!tb || !cl || cl->table) | |
3e542c76 KZ |
226 | return -EINVAL; |
227 | ||
ebc2397e KZ |
228 | if (!list_empty(&cl->cl_columns)) |
229 | return -EINVAL; | |
230 | ||
0925a9dd KZ |
231 | if (cl->flags & SCOLS_FL_TREE) |
232 | tb->ntreecols++; | |
b72b824d | 233 | |
63c9c05d | 234 | DBG(TAB, ul_debugobj(tb, "add column")); |
3e542c76 KZ |
235 | list_add_tail(&cl->cl_columns, &tb->tb_columns); |
236 | cl->seqnum = tb->ncols++; | |
d10fa7e6 | 237 | cl->table = tb; |
3e542c76 KZ |
238 | scols_ref_column(cl); |
239 | ||
17658145 KZ |
240 | if (list_empty(&tb->tb_lines)) |
241 | return 0; | |
242 | ||
243 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
244 | ||
245 | /* Realloc line cell arrays | |
3e542c76 | 246 | */ |
17658145 KZ |
247 | while (scols_table_next_line(tb, &itr, &ln) == 0) { |
248 | rc = scols_line_alloc_cells(ln, tb->ncols); | |
249 | if (rc) | |
250 | break; | |
251 | } | |
252 | ||
253 | return rc; | |
3e542c76 KZ |
254 | } |
255 | ||
1d90bcb1 OO |
256 | /** |
257 | * scols_table_remove_column: | |
258 | * @tb: a pointer to a struct libscols_table instance | |
259 | * @cl: a pointer to a struct libscols_column instance | |
260 | * | |
261 | * Removes @cl from @tb. | |
262 | * | |
263 | * Returns: 0, a negative number in case of an error. | |
264 | */ | |
3e542c76 KZ |
265 | int scols_table_remove_column(struct libscols_table *tb, |
266 | struct libscols_column *cl) | |
267 | { | |
3e542c76 KZ |
268 | if (!tb || !cl || !list_empty(&tb->tb_lines)) |
269 | return -EINVAL; | |
270 | ||
0925a9dd KZ |
271 | if (cl->flags & SCOLS_FL_TREE) |
272 | tb->ntreecols--; | |
273 | ||
63c9c05d | 274 | DBG(TAB, ul_debugobj(tb, "remove column")); |
3e542c76 KZ |
275 | list_del_init(&cl->cl_columns); |
276 | tb->ncols--; | |
d10fa7e6 | 277 | cl->table = NULL; |
3e542c76 KZ |
278 | scols_unref_column(cl); |
279 | return 0; | |
280 | } | |
281 | ||
1d90bcb1 OO |
282 | /** |
283 | * scols_table_remove_columns: | |
284 | * @tb: a pointer to a struct libscols_table instance | |
285 | * | |
286 | * Removes all of @tb's columns. | |
287 | * | |
288 | * Returns: 0, a negative number in case of an error. | |
289 | */ | |
3e542c76 KZ |
290 | int scols_table_remove_columns(struct libscols_table *tb) |
291 | { | |
3e542c76 KZ |
292 | if (!tb || !list_empty(&tb->tb_lines)) |
293 | return -EINVAL; | |
294 | ||
710ed55d | 295 | DBG(TAB, ul_debugobj(tb, "remove all columns")); |
3e542c76 KZ |
296 | while (!list_empty(&tb->tb_columns)) { |
297 | struct libscols_column *cl = list_entry(tb->tb_columns.next, | |
298 | struct libscols_column, cl_columns); | |
299 | scols_table_remove_column(tb, cl); | |
300 | } | |
301 | return 0; | |
302 | } | |
303 | ||
7bdefc7f KZ |
304 | /** |
305 | * scols_table_move_column: | |
306 | * @tb: table | |
307 | * @pre: column before the column | |
73afd3f8 | 308 | * @cl: column to move |
7bdefc7f | 309 | * |
4ab60277 | 310 | * Move the @cl behind @pre. If the @pre is NULL then the @col is the first |
7bdefc7f KZ |
311 | * column in the table. |
312 | * | |
4ab60277 KZ |
313 | * Since: 2.30 |
314 | * | |
7bdefc7f KZ |
315 | * Returns: 0, a negative number in case of an error. |
316 | */ | |
317 | int scols_table_move_column(struct libscols_table *tb, | |
318 | struct libscols_column *pre, | |
319 | struct libscols_column *cl) | |
320 | { | |
321 | struct list_head *head; | |
322 | struct libscols_iter itr; | |
48645e7b KZ |
323 | struct libscols_column *p; |
324 | struct libscols_line *ln; | |
325 | size_t n = 0, oldseq; | |
326 | ||
327 | if (!tb || !cl) | |
328 | return -EINVAL; | |
329 | ||
330 | if (pre && pre->seqnum + 1 == cl->seqnum) | |
331 | return 0; | |
332 | if (pre == NULL && cl->seqnum == 0) | |
333 | return 0; | |
334 | ||
335 | DBG(TAB, ul_debugobj(tb, "move column %zu behind %zu", | |
336 | cl->seqnum, pre? pre->seqnum : 0)); | |
7bdefc7f KZ |
337 | |
338 | list_del_init(&cl->cl_columns); /* remove from old position */ | |
339 | ||
340 | head = pre ? &pre->cl_columns : &tb->tb_columns; | |
341 | list_add(&cl->cl_columns, head); /* add to the new place */ | |
342 | ||
48645e7b KZ |
343 | oldseq = cl->seqnum; |
344 | ||
7bdefc7f KZ |
345 | /* fix seq. numbers */ |
346 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
48645e7b KZ |
347 | while (scols_table_next_column(tb, &itr, &p) == 0) |
348 | p->seqnum = n++; | |
7bdefc7f | 349 | |
48645e7b KZ |
350 | /* move data in lines */ |
351 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
352 | while (scols_table_next_line(tb, &itr, &ln) == 0) | |
353 | scols_line_move_cells(ln, cl->seqnum, oldseq); | |
7bdefc7f KZ |
354 | return 0; |
355 | } | |
356 | ||
1d90bcb1 OO |
357 | /** |
358 | * scols_table_new_column: | |
3e542c76 KZ |
359 | * @tb: table |
360 | * @name: column header | |
14cd0a67 | 361 | * @whint: column width hint (absolute width: N > 1; relative width: 0 < N < 1) |
1d90bcb1 | 362 | * @flags: flags integer |
3e542c76 KZ |
363 | * |
364 | * This is shortcut for | |
365 | * | |
366 | * cl = scols_new_column(); | |
367 | * scols_column_set_....(cl, ...); | |
368 | * scols_table_add_column(tb, cl); | |
369 | * | |
cbe3e495 | 370 | * The column width is possible to define by: |
3e542c76 | 371 | * |
14cd0a67 | 372 | * @whint: 0 < N < 1 : relative width, percent of terminal width |
3e542c76 | 373 | * |
14cd0a67 | 374 | * @whint: N >= 1 : absolute width, empty column will be truncated to |
cbe3e495 | 375 | * the column header width if no specified STRICTWIDTH flag |
3e542c76 | 376 | * |
cbe3e495 KZ |
377 | * Note that if table has disabled "maxout" flag (disabled by default) than |
378 | * relative width is used as a hint only. It's possible that column will be | |
379 | * narrow if the specified size is too large for column data. | |
3e542c76 | 380 | * |
f6918314 KZ |
381 | * |
382 | * If the width of all columns is greater than terminal width then library | |
383 | * tries to reduce width of the individual columns. It's done in three stages: | |
384 | * | |
385 | * #1 reduce columns with SCOLS_FL_TRUNC flag and with relative width if the | |
386 | * width is greater than width defined by @whint (@whint * terminal_width) | |
387 | * | |
388 | * #2 reduce all columns with SCOLS_FL_TRUNC flag | |
389 | * | |
390 | * #3 reduce all columns with relative width | |
391 | * | |
392 | * The next stage is always used if the previous stage is unsuccessful. Note | |
393 | * that SCOLS_FL_WRAP is interpreted as SCOLS_FL_TRUNC when calculate column | |
394 | * width (if custom wrap function is not specified), but the final text is not | |
395 | * truncated, but wrapped to multi-line cell. | |
396 | * | |
397 | * | |
cbe3e495 KZ |
398 | * The column is necessary to address by sequential number. The first defined |
399 | * column has the colnum = 0. For example: | |
3e542c76 KZ |
400 | * |
401 | * scols_table_new_column(tab, "FOO", 0.5, 0); // colnum = 0 | |
402 | * scols_table_new_column(tab, "BAR", 0.5, 0); // colnum = 1 | |
403 | * . | |
404 | * . | |
405 | * scols_line_get_cell(line, 0); // FOO column | |
406 | * scols_line_get_cell(line, 1); // BAR column | |
407 | * | |
408 | * Returns: newly allocated column | |
409 | */ | |
410 | struct libscols_column *scols_table_new_column(struct libscols_table *tb, | |
411 | const char *name, | |
8b992cb5 OO |
412 | double whint, |
413 | int flags) | |
3e542c76 KZ |
414 | { |
415 | struct libscols_column *cl; | |
416 | struct libscols_cell *hr; | |
417 | ||
3e542c76 KZ |
418 | if (!tb) |
419 | return NULL; | |
710ed55d KZ |
420 | |
421 | DBG(TAB, ul_debugobj(tb, "new column name=%s, whint=%g, flags=%d", | |
422 | name, whint, flags)); | |
3e542c76 KZ |
423 | cl = scols_new_column(); |
424 | if (!cl) | |
425 | return NULL; | |
426 | ||
427 | /* set column name */ | |
428 | hr = scols_column_get_header(cl); | |
429 | if (!hr) | |
430 | goto err; | |
431 | if (scols_cell_set_data(hr, name)) | |
432 | goto err; | |
433 | ||
434 | scols_column_set_whint(cl, whint); | |
8b992cb5 OO |
435 | scols_column_set_flags(cl, flags); |
436 | ||
0925a9dd | 437 | if (scols_table_add_column(tb, cl)) /* this increments column ref-counter */ |
3e542c76 KZ |
438 | goto err; |
439 | ||
440 | scols_unref_column(cl); | |
441 | return cl; | |
442 | err: | |
443 | scols_unref_column(cl); | |
444 | return NULL; | |
445 | } | |
446 | ||
1d90bcb1 OO |
447 | /** |
448 | * scols_table_next_column: | |
449 | * @tb: a pointer to a struct libscols_table instance | |
450 | * @itr: a pointer to a struct libscols_iter instance | |
451 | * @cl: a pointer to a pointer to a struct libscols_column instance | |
452 | * | |
453 | * Returns the next column of @tb via @cl. | |
454 | * | |
455 | * Returns: 0, a negative value in case of an error. | |
456 | */ | |
3e542c76 KZ |
457 | int scols_table_next_column(struct libscols_table *tb, |
458 | struct libscols_iter *itr, | |
459 | struct libscols_column **cl) | |
460 | { | |
461 | int rc = 1; | |
462 | ||
463 | if (!tb || !itr || !cl) | |
464 | return -EINVAL; | |
465 | *cl = NULL; | |
466 | ||
467 | if (!itr->head) | |
468 | SCOLS_ITER_INIT(itr, &tb->tb_columns); | |
469 | if (itr->p != itr->head) { | |
470 | SCOLS_ITER_ITERATE(itr, *cl, struct libscols_column, cl_columns); | |
471 | rc = 0; | |
472 | } | |
473 | ||
474 | return rc; | |
475 | } | |
476 | ||
94dbb322 KZ |
477 | /** |
478 | * scols_table_set_columns_iter: | |
479 | * @tb: tab pointer | |
480 | * @itr: iterator | |
481 | * @cl: tab entry | |
482 | * | |
483 | * Sets @iter to the position of @cl in the file @tb. | |
484 | * | |
485 | * Returns: 0 on success, negative number in case of error. | |
40a48456 KZ |
486 | * |
487 | * Since: 2.35 | |
94dbb322 KZ |
488 | */ |
489 | int scols_table_set_columns_iter( | |
490 | struct libscols_table *tb, | |
491 | struct libscols_iter *itr, | |
492 | struct libscols_column *cl) | |
493 | { | |
494 | if (!tb || !itr || !cl) | |
495 | return -EINVAL; | |
496 | ||
497 | if (cl->table != tb) | |
498 | return -EINVAL; | |
499 | ||
500 | SCOLS_ITER_INIT(itr, &tb->tb_columns); | |
501 | itr->p = &cl->cl_columns; | |
502 | ||
503 | return 0; | |
504 | } | |
505 | ||
1d90bcb1 OO |
506 | /** |
507 | * scols_table_get_ncols: | |
3e542c76 KZ |
508 | * @tb: table |
509 | * | |
f7a9ea28 | 510 | * Returns: the ncols table member. |
3e542c76 | 511 | */ |
f7a9ea28 | 512 | size_t scols_table_get_ncols(const struct libscols_table *tb) |
3e542c76 | 513 | { |
d4275a4b | 514 | return tb->ncols; |
3e542c76 KZ |
515 | } |
516 | ||
e2310281 | 517 | /** |
1d90bcb1 | 518 | * scols_table_get_nlines: |
3e542c76 KZ |
519 | * @tb: table |
520 | * | |
f7a9ea28 | 521 | * Returns: the nlines table member. |
3e542c76 | 522 | */ |
f7a9ea28 | 523 | size_t scols_table_get_nlines(const struct libscols_table *tb) |
3e542c76 | 524 | { |
d4275a4b | 525 | return tb->nlines; |
3e542c76 KZ |
526 | } |
527 | ||
1d90bcb1 OO |
528 | /** |
529 | * scols_table_set_stream: | |
530 | * @tb: table | |
531 | * @stream: output stream | |
532 | * | |
533 | * Sets the output stream for table @tb. | |
534 | * | |
535 | * Returns: 0, a negative number in case of an error. | |
536 | */ | |
571441e2 KZ |
537 | int scols_table_set_stream(struct libscols_table *tb, FILE *stream) |
538 | { | |
539 | assert(tb); | |
540 | if (!tb) | |
541 | return -EINVAL; | |
542 | ||
710ed55d | 543 | DBG(TAB, ul_debugobj(tb, "setting alternative stream")); |
571441e2 KZ |
544 | tb->out = stream; |
545 | return 0; | |
546 | } | |
547 | ||
1d90bcb1 OO |
548 | /** |
549 | * scols_table_get_stream: | |
550 | * @tb: table | |
551 | * | |
552 | * Gets the output stream for table @tb. | |
553 | * | |
554 | * Returns: stream pointer, NULL in case of an error or an unset stream. | |
555 | */ | |
f7a9ea28 | 556 | FILE *scols_table_get_stream(const struct libscols_table *tb) |
571441e2 | 557 | { |
d4275a4b | 558 | return tb->out; |
571441e2 KZ |
559 | } |
560 | ||
1d90bcb1 OO |
561 | /** |
562 | * scols_table_reduce_termwidth: | |
563 | * @tb: table | |
564 | * @reduce: width | |
565 | * | |
19981b07 KZ |
566 | * If necessary then libsmartcols use all terminal width, the @reduce setting |
567 | * provides extra space (for example for borders in ncurses applications). | |
568 | * | |
9e930041 | 569 | * The @reduce must be smaller than terminal width, otherwise it's silently |
19981b07 | 570 | * ignored. The reduction is not applied when STDOUT_FILENO is not terminal. |
1d90bcb1 | 571 | * |
f46a8d7e KZ |
572 | * Note that after output initialization (scols_table_print_* calls) the width |
573 | * will be reduced, this behavior affects subsequenced scols_table_get_termwidth() | |
574 | * calls. | |
575 | * | |
1d90bcb1 OO |
576 | * Returns: 0, a negative value in case of an error. |
577 | */ | |
e906be06 KZ |
578 | int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce) |
579 | { | |
e906be06 KZ |
580 | if (!tb) |
581 | return -EINVAL; | |
582 | ||
710ed55d | 583 | DBG(TAB, ul_debugobj(tb, "reduce terminal width: %zu", reduce)); |
e906be06 KZ |
584 | tb->termreduce = reduce; |
585 | return 0; | |
586 | } | |
587 | ||
1d90bcb1 OO |
588 | /** |
589 | * scols_table_get_column: | |
3e542c76 | 590 | * @tb: table |
1d90bcb1 | 591 | * @n: number of column (0..N) |
3e542c76 KZ |
592 | * |
593 | * Returns: pointer to column or NULL | |
594 | */ | |
595 | struct libscols_column *scols_table_get_column(struct libscols_table *tb, | |
596 | size_t n) | |
597 | { | |
598 | struct libscols_iter itr; | |
599 | struct libscols_column *cl; | |
600 | ||
3e542c76 KZ |
601 | if (!tb) |
602 | return NULL; | |
603 | if (n >= tb->ncols) | |
604 | return NULL; | |
605 | ||
606 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
607 | while (scols_table_next_column(tb, &itr, &cl) == 0) { | |
608 | if (cl->seqnum == n) | |
609 | return cl; | |
610 | } | |
611 | return NULL; | |
612 | } | |
613 | ||
1d90bcb1 OO |
614 | /** |
615 | * scols_table_add_line: | |
616 | * @tb: table | |
617 | * @ln: line | |
618 | * | |
619 | * Note that this function calls scols_line_alloc_cells() if number | |
3e542c76 | 620 | * of the cells in the line is too small for @tb. |
1d90bcb1 OO |
621 | * |
622 | * Returns: 0, a negative value in case of an error. | |
3e542c76 KZ |
623 | */ |
624 | int scols_table_add_line(struct libscols_table *tb, struct libscols_line *ln) | |
625 | { | |
c434b278 | 626 | if (!tb || !ln) |
3e542c76 KZ |
627 | return -EINVAL; |
628 | ||
ebc2397e KZ |
629 | if (!list_empty(&ln->ln_lines)) |
630 | return -EINVAL; | |
631 | ||
3e542c76 KZ |
632 | if (tb->ncols > ln->ncells) { |
633 | int rc = scols_line_alloc_cells(ln, tb->ncols); | |
634 | if (rc) | |
635 | return rc; | |
636 | } | |
637 | ||
63c9c05d | 638 | DBG(TAB, ul_debugobj(tb, "add line")); |
3e542c76 KZ |
639 | list_add_tail(&ln->ln_lines, &tb->tb_lines); |
640 | ln->seqnum = tb->nlines++; | |
641 | scols_ref_line(ln); | |
642 | return 0; | |
643 | } | |
644 | ||
1d90bcb1 OO |
645 | /** |
646 | * scols_table_remove_line: | |
647 | * @tb: table | |
648 | * @ln: line | |
649 | * | |
650 | * Note that this function does not destroy the parent<->child relationship between lines. | |
3e542c76 | 651 | * You have to call scols_line_remove_child() |
1d90bcb1 OO |
652 | * |
653 | * Returns: 0, a negative value in case of an error. | |
3e542c76 KZ |
654 | */ |
655 | int scols_table_remove_line(struct libscols_table *tb, | |
656 | struct libscols_line *ln) | |
657 | { | |
3e542c76 KZ |
658 | if (!tb || !ln) |
659 | return -EINVAL; | |
660 | ||
63c9c05d | 661 | DBG(TAB, ul_debugobj(tb, "remove line")); |
3e542c76 KZ |
662 | list_del_init(&ln->ln_lines); |
663 | tb->nlines--; | |
664 | scols_unref_line(ln); | |
665 | return 0; | |
666 | } | |
667 | ||
1d90bcb1 OO |
668 | /** |
669 | * scols_table_remove_lines: | |
670 | * @tb: table | |
671 | * | |
672 | * This empties the table and also destroys all the parent<->child relationships. | |
673 | */ | |
3e542c76 KZ |
674 | void scols_table_remove_lines(struct libscols_table *tb) |
675 | { | |
3e542c76 KZ |
676 | if (!tb) |
677 | return; | |
678 | ||
710ed55d | 679 | DBG(TAB, ul_debugobj(tb, "remove all lines")); |
3e542c76 KZ |
680 | while (!list_empty(&tb->tb_lines)) { |
681 | struct libscols_line *ln = list_entry(tb->tb_lines.next, | |
682 | struct libscols_line, ln_lines); | |
683 | if (ln->parent) | |
684 | scols_line_remove_child(ln->parent, ln); | |
685 | scols_table_remove_line(tb, ln); | |
686 | } | |
687 | } | |
688 | ||
1d90bcb1 OO |
689 | /** |
690 | * scols_table_next_line: | |
691 | * @tb: a pointer to a struct libscols_table instance | |
692 | * @itr: a pointer to a struct libscols_iter instance | |
693 | * @ln: a pointer to a pointer to a struct libscols_line instance | |
694 | * | |
695 | * Finds the next line and returns a pointer to it via @ln. | |
696 | * | |
697 | * Returns: 0, a negative value in case of an error. | |
698 | */ | |
3e542c76 KZ |
699 | int scols_table_next_line(struct libscols_table *tb, |
700 | struct libscols_iter *itr, | |
701 | struct libscols_line **ln) | |
702 | { | |
703 | int rc = 1; | |
704 | ||
705 | if (!tb || !itr || !ln) | |
706 | return -EINVAL; | |
707 | *ln = NULL; | |
708 | ||
709 | if (!itr->head) | |
710 | SCOLS_ITER_INIT(itr, &tb->tb_lines); | |
711 | if (itr->p != itr->head) { | |
712 | SCOLS_ITER_ITERATE(itr, *ln, struct libscols_line, ln_lines); | |
713 | rc = 0; | |
714 | } | |
715 | ||
716 | return rc; | |
717 | } | |
718 | ||
1d90bcb1 OO |
719 | /** |
720 | * scols_table_new_line: | |
3e542c76 KZ |
721 | * @tb: table |
722 | * @parent: parental line or NULL | |
723 | * | |
724 | * This is shortcut for | |
725 | * | |
1d90bcb1 | 726 | * ln = scols_new_line(); |
3e542c76 | 727 | * scols_table_add_line(tb, ln); |
6e792bb6 OO |
728 | * scols_line_add_child(parent, ln); |
729 | * | |
3e542c76 KZ |
730 | * |
731 | * Returns: newly allocate line | |
732 | */ | |
733 | struct libscols_line *scols_table_new_line(struct libscols_table *tb, | |
734 | struct libscols_line *parent) | |
735 | { | |
736 | struct libscols_line *ln; | |
737 | ||
c434b278 | 738 | if (!tb) |
3e542c76 | 739 | return NULL; |
710ed55d | 740 | |
3e542c76 KZ |
741 | ln = scols_new_line(); |
742 | if (!ln) | |
743 | return NULL; | |
744 | ||
745 | if (scols_table_add_line(tb, ln)) | |
746 | goto err; | |
747 | if (parent) | |
748 | scols_line_add_child(parent, ln); | |
749 | ||
750 | scols_unref_line(ln); /* ref-counter incremented by scols_table_add_line() */ | |
751 | return ln; | |
752 | err: | |
753 | scols_unref_line(ln); | |
754 | return NULL; | |
755 | } | |
756 | ||
1d90bcb1 OO |
757 | /** |
758 | * scols_table_get_line: | |
759 | * @tb: table | |
760 | * @n: column number (0..N) | |
761 | * | |
2a750b4c | 762 | * Returns: a line or NULL |
1d90bcb1 | 763 | */ |
3e542c76 KZ |
764 | struct libscols_line *scols_table_get_line(struct libscols_table *tb, |
765 | size_t n) | |
766 | { | |
767 | struct libscols_iter itr; | |
768 | struct libscols_line *ln; | |
769 | ||
3e542c76 KZ |
770 | if (!tb) |
771 | return NULL; | |
772 | if (n >= tb->nlines) | |
773 | return NULL; | |
774 | ||
775 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
776 | while (scols_table_next_line(tb, &itr, &ln) == 0) { | |
777 | if (ln->seqnum == n) | |
778 | return ln; | |
779 | } | |
780 | return NULL; | |
781 | } | |
782 | ||
1d90bcb1 OO |
783 | /** |
784 | * scols_copy_table: | |
785 | * @tb: table | |
786 | * | |
3e542c76 KZ |
787 | * Creates a new independent table copy, except struct libscols_symbols that |
788 | * are shared between the tables. | |
1d90bcb1 OO |
789 | * |
790 | * Returns: a newly allocated copy of @tb | |
3e542c76 KZ |
791 | */ |
792 | struct libscols_table *scols_copy_table(struct libscols_table *tb) | |
793 | { | |
794 | struct libscols_table *ret; | |
795 | struct libscols_line *ln; | |
796 | struct libscols_column *cl; | |
797 | struct libscols_iter itr; | |
798 | ||
3e542c76 KZ |
799 | if (!tb) |
800 | return NULL; | |
0925a9dd | 801 | ret = scols_new_table(); |
3e542c76 KZ |
802 | if (!ret) |
803 | return NULL; | |
804 | ||
63c9c05d | 805 | DBG(TAB, ul_debugobj(tb, "copy")); |
710ed55d | 806 | |
0925a9dd KZ |
807 | if (tb->symbols) |
808 | scols_table_set_symbols(ret, tb->symbols); | |
809 | ||
3e542c76 KZ |
810 | /* columns */ |
811 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
812 | while (scols_table_next_column(tb, &itr, &cl) == 0) { | |
813 | cl = scols_copy_column(cl); | |
814 | if (!cl) | |
815 | goto err; | |
0925a9dd | 816 | if (scols_table_add_column(ret, cl)) |
3e542c76 KZ |
817 | goto err; |
818 | scols_unref_column(cl); | |
819 | } | |
820 | ||
821 | /* lines */ | |
822 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
823 | while (scols_table_next_line(tb, &itr, &ln) == 0) { | |
824 | struct libscols_line *newln = scols_copy_line(ln); | |
825 | if (!newln) | |
826 | goto err; | |
827 | if (scols_table_add_line(ret, newln)) | |
828 | goto err; | |
829 | if (ln->parent) { | |
830 | struct libscols_line *p = | |
831 | scols_table_get_line(ret, ln->parent->seqnum); | |
832 | if (p) | |
833 | scols_line_add_child(p, newln); | |
834 | } | |
835 | scols_unref_line(newln); | |
836 | } | |
837 | ||
d1b4d14f OO |
838 | /* separators */ |
839 | if (scols_table_set_column_separator(ret, tb->colsep) || | |
840 | scols_table_set_line_separator(ret, tb->linesep)) | |
841 | goto err; | |
842 | ||
3e542c76 KZ |
843 | return ret; |
844 | err: | |
845 | scols_unref_table(ret); | |
846 | return NULL; | |
847 | } | |
848 | ||
63168cf9 KZ |
849 | /** |
850 | * scols_table_set_default_symbols: | |
851 | * @tb: table | |
852 | * | |
853 | * The library check the current environment to select ASCII or UTF8 symbols. | |
854 | * This default behavior could be controlled by scols_table_enable_ascii(). | |
855 | * | |
856 | * Use scols_table_set_symbols() to unset symbols or use your own setting. | |
857 | * | |
858 | * Returns: 0, a negative value in case of an error. | |
3f47320a KZ |
859 | * |
860 | * Since: 2.29 | |
63168cf9 KZ |
861 | */ |
862 | int scols_table_set_default_symbols(struct libscols_table *tb) | |
863 | { | |
864 | struct libscols_symbols *sy; | |
865 | int rc; | |
866 | ||
867 | if (!tb) | |
868 | return -EINVAL; | |
869 | ||
870 | DBG(TAB, ul_debugobj(tb, "setting default symbols")); | |
871 | ||
872 | sy = scols_new_symbols(); | |
873 | if (!sy) | |
874 | return -ENOMEM; | |
875 | ||
876 | #if defined(HAVE_WIDECHAR) | |
877 | if (!scols_table_is_ascii(tb) && | |
878 | !strcmp(nl_langinfo(CODESET), "UTF-8")) { | |
d52f5542 | 879 | /* tree chart */ |
63168cf9 KZ |
880 | scols_symbols_set_branch(sy, UTF_VR UTF_H); |
881 | scols_symbols_set_vertical(sy, UTF_V " "); | |
882 | scols_symbols_set_right(sy, UTF_UR UTF_H); | |
d52f5542 KZ |
883 | /* groups chart */ |
884 | scols_symbols_set_group_horizontal(sy, UTF_H3); | |
885 | scols_symbols_set_group_vertical(sy, UTF_V3); | |
886 | ||
887 | scols_symbols_set_group_first_member(sy, UTF_DR UTF_H3 UTF_TR); | |
888 | scols_symbols_set_group_last_member(sy, UTF_UR UTF_DH UTF_TR); | |
889 | scols_symbols_set_group_middle_member(sy, UTF_VR UTF_H3 UTF_TR); | |
890 | scols_symbols_set_group_last_child(sy, UTF_UR UTF_H3); | |
891 | scols_symbols_set_group_middle_child(sy, UTF_VR UTF_H3); | |
63168cf9 KZ |
892 | } else |
893 | #endif | |
894 | { | |
d52f5542 | 895 | /* tree chart */ |
63168cf9 KZ |
896 | scols_symbols_set_branch(sy, "|-"); |
897 | scols_symbols_set_vertical(sy, "| "); | |
898 | scols_symbols_set_right(sy, "`-"); | |
d52f5542 KZ |
899 | /* groups chart */ |
900 | scols_symbols_set_group_horizontal(sy, "-"); | |
901 | scols_symbols_set_group_vertical(sy, "|"); | |
902 | ||
903 | scols_symbols_set_group_first_member(sy, ",->"); | |
904 | scols_symbols_set_group_last_member(sy, "'->"); | |
905 | scols_symbols_set_group_middle_member(sy, "|->"); | |
906 | scols_symbols_set_group_last_child(sy, "`-"); | |
907 | scols_symbols_set_group_middle_child(sy, "|-"); | |
63168cf9 KZ |
908 | } |
909 | scols_symbols_set_title_padding(sy, " "); | |
910 | scols_symbols_set_cell_padding(sy, " "); | |
911 | ||
912 | rc = scols_table_set_symbols(tb, sy); | |
913 | scols_unref_symbols(sy); | |
914 | return rc; | |
915 | } | |
916 | ||
917 | ||
1d90bcb1 OO |
918 | /** |
919 | * scols_table_set_symbols: | |
920 | * @tb: table | |
0925a9dd KZ |
921 | * @sy: symbols or NULL |
922 | * | |
923 | * Add a reference to @sy from the table. The symbols are used by library to | |
63168cf9 KZ |
924 | * draw tree output. If no symbols are used for the table then library creates |
925 | * default temporary symbols to draw output by scols_table_set_default_symbols(). | |
926 | * | |
12f17a23 | 927 | * If @sy is NULL then remove reference from the currently used symbols. |
1d90bcb1 OO |
928 | * |
929 | * Returns: 0, a negative value in case of an error. | |
930 | */ | |
3e542c76 KZ |
931 | int scols_table_set_symbols(struct libscols_table *tb, |
932 | struct libscols_symbols *sy) | |
933 | { | |
3e542c76 KZ |
934 | if (!tb) |
935 | return -EINVAL; | |
936 | ||
63168cf9 KZ |
937 | /* remove old */ |
938 | if (tb->symbols) { | |
63c9c05d | 939 | DBG(TAB, ul_debugobj(tb, "remove symbols reference")); |
3e542c76 | 940 | scols_unref_symbols(tb->symbols); |
63168cf9 KZ |
941 | tb->symbols = NULL; |
942 | } | |
943 | ||
944 | /* set new */ | |
3e542c76 | 945 | if (sy) { /* ref user defined */ |
63c9c05d | 946 | DBG(TAB, ul_debugobj(tb, "set symbols")); |
3e542c76 KZ |
947 | tb->symbols = sy; |
948 | scols_ref_symbols(sy); | |
3e542c76 | 949 | } |
3e542c76 KZ |
950 | return 0; |
951 | } | |
2a6cfc13 | 952 | |
63168cf9 KZ |
953 | /** |
954 | * scols_table_get_symbols: | |
955 | * @tb: table | |
956 | * | |
957 | * Returns: pointer to symbols table. | |
3f47320a KZ |
958 | * |
959 | * Since: 2.29 | |
63168cf9 KZ |
960 | */ |
961 | struct libscols_symbols *scols_table_get_symbols(const struct libscols_table *tb) | |
962 | { | |
963 | return tb->symbols; | |
964 | } | |
965 | ||
2981e0fd | 966 | /** |
43e06c67 | 967 | * scols_table_enable_nolinesep: |
2981e0fd KZ |
968 | * @tb: table |
969 | * @enable: 1 or 0 | |
970 | * | |
9e930041 | 971 | * Enable/disable line separator printing. This is useful if you want to |
2981e0fd | 972 | * re-printing the same line more than once (e.g. progress bar). Don't use it |
65f3ebc3 | 973 | * if you're not sure. |
2981e0fd | 974 | * |
1e467762 KZ |
975 | * Note that for the last line in the table the separator is disabled at all. |
976 | * The library differentiate between table terminator and line terminator | |
977 | * (although for standard output \n byte is used in both cases). | |
978 | * | |
2981e0fd KZ |
979 | * Returns: 0 on success, negative number in case of an error. |
980 | */ | |
981 | int scols_table_enable_nolinesep(struct libscols_table *tb, int enable) | |
982 | { | |
983 | if (!tb) | |
984 | return -EINVAL; | |
985 | ||
986 | DBG(TAB, ul_debugobj(tb, "nolinesep: %s", enable ? "ENABLE" : "DISABLE")); | |
43e06c67 | 987 | tb->no_linesep = enable ? 1 : 0; |
2981e0fd KZ |
988 | return 0; |
989 | } | |
990 | ||
43e06c67 IG |
991 | /** |
992 | * scols_table_is_nolinesep: | |
993 | * @tb: a pointer to a struct libscols_table instance | |
994 | * | |
995 | * Returns: 1 if line separator printing is disabled. | |
996 | * | |
997 | * Since: 2.29 | |
998 | */ | |
999 | int scols_table_is_nolinesep(const struct libscols_table *tb) | |
1000 | { | |
1001 | return tb->no_linesep; | |
1002 | } | |
1003 | ||
8a38a8d3 OO |
1004 | /** |
1005 | * scols_table_enable_colors: | |
1006 | * @tb: table | |
1007 | * @enable: 1 or 0 | |
1008 | * | |
0925a9dd | 1009 | * Enable/disable colors. |
8a38a8d3 OO |
1010 | * |
1011 | * Returns: 0 on success, negative number in case of an error. | |
1012 | */ | |
1013 | int scols_table_enable_colors(struct libscols_table *tb, int enable) | |
1014 | { | |
8a38a8d3 OO |
1015 | if (!tb) |
1016 | return -EINVAL; | |
710ed55d KZ |
1017 | |
1018 | DBG(TAB, ul_debugobj(tb, "colors: %s", enable ? "ENABLE" : "DISABLE")); | |
8a38a8d3 OO |
1019 | tb->colors_wanted = enable; |
1020 | return 0; | |
1021 | } | |
2a6cfc13 | 1022 | |
8a38a8d3 | 1023 | /** |
0925a9dd | 1024 | * scols_table_enable_raw: |
8a38a8d3 OO |
1025 | * @tb: table |
1026 | * @enable: 1 or 0 | |
1027 | * | |
0925a9dd | 1028 | * Enable/disable raw output format. The parsable output formats |
2a6cfc13 | 1029 | * (export, raw, JSON, ...) are mutually exclusive. |
8a38a8d3 OO |
1030 | * |
1031 | * Returns: 0 on success, negative number in case of an error. | |
1032 | */ | |
0925a9dd | 1033 | int scols_table_enable_raw(struct libscols_table *tb, int enable) |
8a38a8d3 | 1034 | { |
8a38a8d3 OO |
1035 | if (!tb) |
1036 | return -EINVAL; | |
0925a9dd | 1037 | |
710ed55d | 1038 | DBG(TAB, ul_debugobj(tb, "raw: %s", enable ? "ENABLE" : "DISABLE")); |
0925a9dd KZ |
1039 | if (enable) |
1040 | tb->format = SCOLS_FMT_RAW; | |
1041 | else if (tb->format == SCOLS_FMT_RAW) | |
1042 | tb->format = 0; | |
8a38a8d3 OO |
1043 | return 0; |
1044 | } | |
0925a9dd | 1045 | |
2a6cfc13 KZ |
1046 | /** |
1047 | * scols_table_enable_json: | |
1048 | * @tb: table | |
1049 | * @enable: 1 or 0 | |
1050 | * | |
1051 | * Enable/disable JSON output format. The parsable output formats | |
1052 | * (export, raw, JSON, ...) are mutually exclusive. | |
1053 | * | |
1054 | * Returns: 0 on success, negative number in case of an error. | |
982034c3 KZ |
1055 | * |
1056 | * Since: 2.27 | |
2a6cfc13 KZ |
1057 | */ |
1058 | int scols_table_enable_json(struct libscols_table *tb, int enable) | |
1059 | { | |
1060 | if (!tb) | |
1061 | return -EINVAL; | |
1062 | ||
1063 | DBG(TAB, ul_debugobj(tb, "json: %s", enable ? "ENABLE" : "DISABLE")); | |
1064 | if (enable) | |
1065 | tb->format = SCOLS_FMT_JSON; | |
1066 | else if (tb->format == SCOLS_FMT_JSON) | |
1067 | tb->format = 0; | |
1068 | return 0; | |
1069 | } | |
1070 | ||
8a38a8d3 | 1071 | /** |
0925a9dd | 1072 | * scols_table_enable_export: |
8a38a8d3 OO |
1073 | * @tb: table |
1074 | * @enable: 1 or 0 | |
1075 | * | |
0925a9dd KZ |
1076 | * Enable/disable export output format (COLUMNAME="value" ...). |
1077 | * The parsable output formats (export and raw) are mutually exclusive. | |
8a38a8d3 OO |
1078 | * |
1079 | * Returns: 0 on success, negative number in case of an error. | |
1080 | */ | |
0925a9dd | 1081 | int scols_table_enable_export(struct libscols_table *tb, int enable) |
8a38a8d3 | 1082 | { |
8a38a8d3 OO |
1083 | if (!tb) |
1084 | return -EINVAL; | |
710ed55d KZ |
1085 | |
1086 | DBG(TAB, ul_debugobj(tb, "export: %s", enable ? "ENABLE" : "DISABLE")); | |
0925a9dd KZ |
1087 | if (enable) |
1088 | tb->format = SCOLS_FMT_EXPORT; | |
1089 | else if (tb->format == SCOLS_FMT_EXPORT) | |
1090 | tb->format = 0; | |
8a38a8d3 OO |
1091 | return 0; |
1092 | } | |
0925a9dd | 1093 | |
8a38a8d3 | 1094 | /** |
0925a9dd | 1095 | * scols_table_enable_ascii: |
8a38a8d3 OO |
1096 | * @tb: table |
1097 | * @enable: 1 or 0 | |
1098 | * | |
0925a9dd KZ |
1099 | * The ASCII-only output is relevant for tree-like outputs. The library |
1100 | * checks if the current environment is UTF8 compatible by default. This | |
1101 | * function overrides this check and force the library to use ASCII chars | |
1102 | * for the tree. | |
8a38a8d3 | 1103 | * |
0925a9dd KZ |
1104 | * If a custom libcols_symbols are specified (see scols_table_set_symbols() |
1105 | * then ASCII flag setting is ignored. | |
8a38a8d3 OO |
1106 | * |
1107 | * Returns: 0 on success, negative number in case of an error. | |
1108 | */ | |
0925a9dd | 1109 | int scols_table_enable_ascii(struct libscols_table *tb, int enable) |
8a38a8d3 | 1110 | { |
8a38a8d3 OO |
1111 | if (!tb) |
1112 | return -EINVAL; | |
710ed55d KZ |
1113 | |
1114 | DBG(TAB, ul_debugobj(tb, "ascii: %s", enable ? "ENABLE" : "DISABLE")); | |
0925a9dd | 1115 | tb->ascii = enable ? 1 : 0; |
8a38a8d3 OO |
1116 | return 0; |
1117 | } | |
0925a9dd | 1118 | |
8a38a8d3 | 1119 | /** |
0925a9dd | 1120 | * scols_table_enable_noheadings: |
8a38a8d3 OO |
1121 | * @tb: table |
1122 | * @enable: 1 or 0 | |
1123 | * | |
0925a9dd | 1124 | * Enable/disable header line. |
8a38a8d3 OO |
1125 | * |
1126 | * Returns: 0 on success, negative number in case of an error. | |
1127 | */ | |
0925a9dd | 1128 | int scols_table_enable_noheadings(struct libscols_table *tb, int enable) |
8a38a8d3 | 1129 | { |
8a38a8d3 OO |
1130 | if (!tb) |
1131 | return -EINVAL; | |
710ed55d | 1132 | DBG(TAB, ul_debugobj(tb, "noheading: %s", enable ? "ENABLE" : "DISABLE")); |
0925a9dd | 1133 | tb->no_headings = enable ? 1 : 0; |
8a38a8d3 OO |
1134 | return 0; |
1135 | } | |
3e542c76 | 1136 | |
36e07ceb KZ |
1137 | /** |
1138 | * scols_table_enable_header_repeat: | |
1139 | * @tb: table | |
1140 | * @enable: 1 or 0 | |
1141 | * | |
1142 | * Enable/disable header line repeat. The header line is printed only once by | |
1143 | * default. Note that the flag will be silently ignored and disabled if the | |
1144 | * output is not on terminal or output format is JSON, raw, etc. | |
1145 | * | |
1146 | * Returns: 0 on success, negative number in case of an error. | |
1147 | * | |
1148 | * Since: 2.31 | |
1149 | */ | |
1150 | int scols_table_enable_header_repeat(struct libscols_table *tb, int enable) | |
1151 | { | |
1152 | if (!tb) | |
1153 | return -EINVAL; | |
1154 | DBG(TAB, ul_debugobj(tb, "header-repeat: %s", enable ? "ENABLE" : "DISABLE")); | |
1155 | tb->header_repeat = enable ? 1 : 0; | |
1156 | return 0; | |
1157 | } | |
1158 | ||
8a38a8d3 | 1159 | /** |
0925a9dd | 1160 | * scols_table_enable_maxout: |
8a38a8d3 OO |
1161 | * @tb: table |
1162 | * @enable: 1 or 0 | |
1163 | * | |
0925a9dd | 1164 | * The extra space after last column is ignored by default. The output |
94dbb322 KZ |
1165 | * maximization add padding for all columns. |
1166 | * | |
40a48456 | 1167 | * This setting is mutually exclusive to scols_table_enable_minout(). |
8a38a8d3 OO |
1168 | * |
1169 | * Returns: 0 on success, negative number in case of an error. | |
1170 | */ | |
0925a9dd | 1171 | int scols_table_enable_maxout(struct libscols_table *tb, int enable) |
8a38a8d3 | 1172 | { |
94dbb322 | 1173 | if (!tb || tb->minout) |
8a38a8d3 | 1174 | return -EINVAL; |
94dbb322 | 1175 | |
710ed55d | 1176 | DBG(TAB, ul_debugobj(tb, "maxout: %s", enable ? "ENABLE" : "DISABLE")); |
0925a9dd | 1177 | tb->maxout = enable ? 1 : 0; |
8a38a8d3 OO |
1178 | return 0; |
1179 | } | |
0925a9dd | 1180 | |
94dbb322 KZ |
1181 | /** |
1182 | * scols_table_enable_minout: | |
1183 | * @tb: table | |
1184 | * @enable: 1 or 0 | |
1185 | * | |
1186 | * Force library to terminate line after last column with data. The extra | |
1187 | * padding is not added to the empty cells at the end of the line. The default is fill | |
1188 | * tailing empty cells except the last line cell. | |
1189 | * | |
1190 | * This setting is mutually exclusive to cols_table_enable_maxout(). | |
1191 | * | |
1192 | * Returns: 0 on success, negative number in case of an error. | |
40a48456 KZ |
1193 | * |
1194 | * Since: 2.35 | |
94dbb322 KZ |
1195 | */ |
1196 | int scols_table_enable_minout(struct libscols_table *tb, int enable) | |
1197 | { | |
1198 | if (!tb || tb->maxout) | |
1199 | return -EINVAL; | |
1200 | ||
1201 | DBG(TAB, ul_debugobj(tb, "minout: %s", enable ? "ENABLE" : "DISABLE")); | |
1202 | tb->minout = enable ? 1 : 0; | |
1203 | return 0; | |
1204 | } | |
1205 | ||
df73852b KZ |
1206 | /** |
1207 | * scols_table_enable_nowrap: | |
1208 | * @tb: table | |
1209 | * @enable: 1 or 0 | |
1210 | * | |
1211 | * Never continue on next line, remove last column(s) when too large, truncate last column. | |
1212 | * | |
1213 | * Returns: 0 on success, negative number in case of an error. | |
db307d8e IG |
1214 | * |
1215 | * Since: 2.28 | |
df73852b KZ |
1216 | */ |
1217 | int scols_table_enable_nowrap(struct libscols_table *tb, int enable) | |
1218 | { | |
1219 | if (!tb) | |
1220 | return -EINVAL; | |
1221 | DBG(TAB, ul_debugobj(tb, "nowrap: %s", enable ? "ENABLE" : "DISABLE")); | |
1222 | tb->no_wrap = enable ? 1 : 0; | |
1223 | return 0; | |
1224 | } | |
1225 | ||
8427c2ec IG |
1226 | /** |
1227 | * scols_table_is_nowrap: | |
1228 | * @tb: a pointer to a struct libscols_table instance | |
1229 | * | |
1230 | * Returns: 1 if nowrap is enabled. | |
1231 | * | |
1232 | * Since: 2.29 | |
1233 | */ | |
1234 | int scols_table_is_nowrap(const struct libscols_table *tb) | |
1235 | { | |
1236 | return tb->no_wrap; | |
1237 | } | |
1238 | ||
28a3cc83 KZ |
1239 | /** |
1240 | * scols_table_enable_noencoding: | |
1241 | * @tb: table | |
1242 | * @enable: 1 or 0 | |
1243 | * | |
c43874ba | 1244 | * The library encode non-printable and control chars by \xHEX by default. |
28a3cc83 KZ |
1245 | * |
1246 | * Returns: 0 on success, negative number in case of an error. | |
1247 | * | |
1248 | * Since: 2.31 | |
1249 | */ | |
1250 | int scols_table_enable_noencoding(struct libscols_table *tb, int enable) | |
1251 | { | |
1252 | if (!tb) | |
1253 | return -EINVAL; | |
1254 | DBG(TAB, ul_debugobj(tb, "encoding: %s", enable ? "ENABLE" : "DISABLE")); | |
1255 | tb->no_encode = enable ? 1 : 0; | |
1256 | return 0; | |
1257 | } | |
1258 | ||
1259 | /** | |
1260 | * scols_table_is_noencoding: | |
1261 | * @tb: a pointer to a struct libscols_table instance | |
1262 | * | |
1263 | * Returns: 1 if encoding is disabled. | |
1264 | * | |
1265 | * Since: 2.31 | |
1266 | */ | |
1267 | int scols_table_is_noencoding(const struct libscols_table *tb) | |
1268 | { | |
1269 | return tb->no_encode; | |
1270 | } | |
1271 | ||
8a38a8d3 OO |
1272 | /** |
1273 | * scols_table_colors_wanted: | |
1274 | * @tb: table | |
1275 | * | |
0925a9dd | 1276 | * Returns: 1 if colors are enabled. |
8a38a8d3 | 1277 | */ |
f7a9ea28 | 1278 | int scols_table_colors_wanted(const struct libscols_table *tb) |
8a38a8d3 | 1279 | { |
d4275a4b | 1280 | return tb->colors_wanted; |
8a38a8d3 | 1281 | } |
c0070f81 OO |
1282 | |
1283 | /** | |
1284 | * scols_table_is_empty: | |
1285 | * @tb: table | |
1286 | * | |
8427c2ec | 1287 | * Returns: 1 if the table is empty. |
c0070f81 | 1288 | */ |
f7a9ea28 | 1289 | int scols_table_is_empty(const struct libscols_table *tb) |
c0070f81 | 1290 | { |
d4275a4b | 1291 | return !tb->nlines; |
c0070f81 | 1292 | } |
0925a9dd | 1293 | |
8a38a8d3 | 1294 | /** |
0925a9dd | 1295 | * scols_table_is_ascii: |
8a38a8d3 OO |
1296 | * @tb: table |
1297 | * | |
0925a9dd | 1298 | * Returns: 1 if ASCII tree is enabled. |
8a38a8d3 | 1299 | */ |
f7a9ea28 | 1300 | int scols_table_is_ascii(const struct libscols_table *tb) |
8a38a8d3 | 1301 | { |
d4275a4b | 1302 | return tb->ascii; |
8a38a8d3 | 1303 | } |
0925a9dd | 1304 | |
8a38a8d3 | 1305 | /** |
0925a9dd | 1306 | * scols_table_is_noheadings: |
8a38a8d3 OO |
1307 | * @tb: table |
1308 | * | |
0925a9dd | 1309 | * Returns: 1 if header output is disabled. |
8a38a8d3 | 1310 | */ |
f7a9ea28 | 1311 | int scols_table_is_noheadings(const struct libscols_table *tb) |
8a38a8d3 | 1312 | { |
d4275a4b | 1313 | return tb->no_headings; |
8a38a8d3 | 1314 | } |
0925a9dd | 1315 | |
36e07ceb KZ |
1316 | /** |
1317 | * scols_table_is_header_repeat | |
1318 | * @tb: table | |
1319 | * | |
1320 | * Returns: 1 if header repeat is enabled. | |
1321 | * | |
1322 | * Since: 2.31 | |
1323 | */ | |
1324 | int scols_table_is_header_repeat(const struct libscols_table *tb) | |
1325 | { | |
1326 | return tb->header_repeat; | |
1327 | } | |
1328 | ||
8a38a8d3 | 1329 | /** |
0925a9dd | 1330 | * scols_table_is_export: |
8a38a8d3 OO |
1331 | * @tb: table |
1332 | * | |
0925a9dd | 1333 | * Returns: 1 if export output format is enabled. |
8a38a8d3 | 1334 | */ |
f7a9ea28 | 1335 | int scols_table_is_export(const struct libscols_table *tb) |
8a38a8d3 | 1336 | { |
d4275a4b | 1337 | return tb->format == SCOLS_FMT_EXPORT; |
8a38a8d3 | 1338 | } |
0925a9dd | 1339 | |
8a38a8d3 | 1340 | /** |
0925a9dd | 1341 | * scols_table_is_raw: |
8a38a8d3 OO |
1342 | * @tb: table |
1343 | * | |
0925a9dd | 1344 | * Returns: 1 if raw output format is enabled. |
8a38a8d3 | 1345 | */ |
f7a9ea28 | 1346 | int scols_table_is_raw(const struct libscols_table *tb) |
8a38a8d3 | 1347 | { |
d4275a4b | 1348 | return tb->format == SCOLS_FMT_RAW; |
8a38a8d3 | 1349 | } |
0925a9dd | 1350 | |
2a6cfc13 KZ |
1351 | /** |
1352 | * scols_table_is_json: | |
1353 | * @tb: table | |
1354 | * | |
1355 | * Returns: 1 if JSON output format is enabled. | |
982034c3 KZ |
1356 | * |
1357 | * Since: 2.27 | |
2a6cfc13 | 1358 | */ |
f7a9ea28 | 1359 | int scols_table_is_json(const struct libscols_table *tb) |
2a6cfc13 | 1360 | { |
d4275a4b | 1361 | return tb->format == SCOLS_FMT_JSON; |
2a6cfc13 KZ |
1362 | } |
1363 | ||
8a38a8d3 | 1364 | /** |
0925a9dd | 1365 | * scols_table_is_maxout |
8a38a8d3 OO |
1366 | * @tb: table |
1367 | * | |
d4275a4b | 1368 | * Returns: 1 if output maximization is enabled or 0 |
8a38a8d3 | 1369 | */ |
f7a9ea28 | 1370 | int scols_table_is_maxout(const struct libscols_table *tb) |
8a38a8d3 | 1371 | { |
d4275a4b | 1372 | return tb->maxout; |
8a38a8d3 | 1373 | } |
0925a9dd | 1374 | |
94dbb322 KZ |
1375 | /** |
1376 | * scols_table_is_minout | |
1377 | * @tb: table | |
1378 | * | |
1379 | * Returns: 1 if output minimization is enabled or 0 | |
40a48456 KZ |
1380 | * |
1381 | * Since: 2.35 | |
94dbb322 KZ |
1382 | */ |
1383 | int scols_table_is_minout(const struct libscols_table *tb) | |
1384 | { | |
1385 | return tb->minout; | |
1386 | } | |
1387 | ||
8a38a8d3 OO |
1388 | /** |
1389 | * scols_table_is_tree: | |
1390 | * @tb: table | |
1391 | * | |
0925a9dd | 1392 | * Returns: returns 1 tree-like output is expected. |
8a38a8d3 | 1393 | */ |
f7a9ea28 | 1394 | int scols_table_is_tree(const struct libscols_table *tb) |
8a38a8d3 | 1395 | { |
d4275a4b | 1396 | return tb->ntreecols > 0; |
8a38a8d3 | 1397 | } |
d1b4d14f OO |
1398 | |
1399 | /** | |
1400 | * scols_table_set_column_separator: | |
1401 | * @tb: table | |
1402 | * @sep: separator | |
1403 | * | |
1404 | * Sets the column separator of @tb to @sep. | |
d1b4d14f OO |
1405 | * |
1406 | * Returns: 0, a negative value in case of an error. | |
1407 | */ | |
4baab7df | 1408 | int scols_table_set_column_separator(struct libscols_table *tb, const char *sep) |
d1b4d14f | 1409 | { |
8fcdce8f | 1410 | return strdup_to_struct_member(tb, colsep, sep); |
d1b4d14f OO |
1411 | } |
1412 | ||
1413 | /** | |
1414 | * scols_table_set_line_separator: | |
1415 | * @tb: table | |
1416 | * @sep: separator | |
1417 | * | |
1418 | * Sets the line separator of @tb to @sep. | |
1419 | * | |
1420 | * Returns: 0, a negative value in case of an error. | |
1421 | */ | |
4baab7df | 1422 | int scols_table_set_line_separator(struct libscols_table *tb, const char *sep) |
d1b4d14f | 1423 | { |
8fcdce8f | 1424 | return strdup_to_struct_member(tb, linesep, sep); |
d1b4d14f OO |
1425 | } |
1426 | ||
1427 | /** | |
1428 | * scols_table_get_column_separator: | |
1429 | * @tb: table | |
1430 | * | |
1431 | * Returns: @tb column separator, NULL in case of an error | |
1432 | */ | |
f7a9ea28 | 1433 | const char *scols_table_get_column_separator(const struct libscols_table *tb) |
d1b4d14f | 1434 | { |
d1b4d14f OO |
1435 | return tb->colsep; |
1436 | } | |
1437 | ||
1438 | /** | |
1439 | * scols_table_get_line_separator: | |
1440 | * @tb: table | |
1441 | * | |
1442 | * Returns: @tb line separator, NULL in case of an error | |
1443 | */ | |
f7a9ea28 | 1444 | const char *scols_table_get_line_separator(const struct libscols_table *tb) |
d1b4d14f | 1445 | { |
d1b4d14f | 1446 | return tb->linesep; |
d1b4d14f | 1447 | } |
95a528dd KZ |
1448 | /* for lines in the struct libscols_line->ln_lines list */ |
1449 | static int cells_cmp_wrapper_lines(struct list_head *a, struct list_head *b, void *data) | |
57a86f9b KZ |
1450 | { |
1451 | struct libscols_column *cl = (struct libscols_column *) data; | |
1452 | struct libscols_line *ra, *rb; | |
1453 | struct libscols_cell *ca, *cb; | |
1454 | ||
1455 | assert(a); | |
1456 | assert(b); | |
1457 | assert(cl); | |
1458 | ||
1459 | ra = list_entry(a, struct libscols_line, ln_lines); | |
1460 | rb = list_entry(b, struct libscols_line, ln_lines); | |
1461 | ca = scols_line_get_cell(ra, cl->seqnum); | |
1462 | cb = scols_line_get_cell(rb, cl->seqnum); | |
1463 | ||
1464 | return cl->cmpfunc(ca, cb, cl->cmpfunc_data); | |
1465 | } | |
1466 | ||
95a528dd KZ |
1467 | /* for lines in the struct libscols_line->ln_children list */ |
1468 | static int cells_cmp_wrapper_children(struct list_head *a, struct list_head *b, void *data) | |
1469 | { | |
1470 | struct libscols_column *cl = (struct libscols_column *) data; | |
1471 | struct libscols_line *ra, *rb; | |
1472 | struct libscols_cell *ca, *cb; | |
1473 | ||
1474 | assert(a); | |
1475 | assert(b); | |
1476 | assert(cl); | |
1477 | ||
1478 | ra = list_entry(a, struct libscols_line, ln_children); | |
1479 | rb = list_entry(b, struct libscols_line, ln_children); | |
1480 | ca = scols_line_get_cell(ra, cl->seqnum); | |
1481 | cb = scols_line_get_cell(rb, cl->seqnum); | |
1482 | ||
1483 | return cl->cmpfunc(ca, cb, cl->cmpfunc_data); | |
1484 | } | |
1485 | ||
1486 | ||
1487 | static int sort_line_children(struct libscols_line *ln, struct libscols_column *cl) | |
1488 | { | |
1489 | struct list_head *p; | |
1490 | ||
d52f5542 KZ |
1491 | if (!list_empty(&ln->ln_branch)) { |
1492 | list_for_each(p, &ln->ln_branch) { | |
1493 | struct libscols_line *chld = | |
1494 | list_entry(p, struct libscols_line, ln_children); | |
1495 | sort_line_children(chld, cl); | |
1496 | } | |
1497 | ||
1498 | list_sort(&ln->ln_branch, cells_cmp_wrapper_children, cl); | |
1499 | } | |
1500 | ||
1501 | if (is_first_group_member(ln)) { | |
1502 | list_for_each(p, &ln->group->gr_children) { | |
1503 | struct libscols_line *chld = | |
1504 | list_entry(p, struct libscols_line, ln_children); | |
1505 | sort_line_children(chld, cl); | |
1506 | } | |
95a528dd | 1507 | |
d52f5542 | 1508 | list_sort(&ln->group->gr_children, cells_cmp_wrapper_children, cl); |
95a528dd KZ |
1509 | } |
1510 | ||
95a528dd KZ |
1511 | return 0; |
1512 | } | |
1513 | ||
57a86f9b KZ |
1514 | /** |
1515 | * scols_sort_table: | |
1516 | * @tb: table | |
1517 | * @cl: order by this column | |
1518 | * | |
066f46e0 KZ |
1519 | * Orders the table by the column. See also scols_column_set_cmpfunc(). If the |
1520 | * tree output is enabled then children in the tree are recursively sorted too. | |
57a86f9b KZ |
1521 | * |
1522 | * Returns: 0, a negative value in case of an error. | |
1523 | */ | |
1524 | int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl) | |
1525 | { | |
8afabdb1 | 1526 | if (!tb || !cl || !cl->cmpfunc) |
57a86f9b KZ |
1527 | return -EINVAL; |
1528 | ||
710ed55d | 1529 | DBG(TAB, ul_debugobj(tb, "sorting table")); |
95a528dd KZ |
1530 | list_sort(&tb->tb_lines, cells_cmp_wrapper_lines, cl); |
1531 | ||
1532 | if (scols_table_is_tree(tb)) { | |
1533 | struct libscols_line *ln; | |
1534 | struct libscols_iter itr; | |
1535 | ||
1536 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
1537 | while (scols_table_next_line(tb, &itr, &ln) == 0) | |
1538 | sort_line_children(ln, cl); | |
1539 | } | |
1540 | ||
57a86f9b KZ |
1541 | return 0; |
1542 | } | |
19055a25 | 1543 | |
066f46e0 KZ |
1544 | static struct libscols_line *move_line_and_children(struct libscols_line *ln, struct libscols_line *pre) |
1545 | { | |
1546 | if (pre) { | |
1547 | list_del_init(&ln->ln_lines); /* remove from old position */ | |
1548 | list_add(&ln->ln_lines, &pre->ln_lines); /* add to the new place (behind @pre) */ | |
1549 | } | |
1550 | pre = ln; | |
1551 | ||
1552 | if (!list_empty(&ln->ln_branch)) { | |
1553 | struct list_head *p; | |
1554 | ||
1555 | list_for_each(p, &ln->ln_branch) { | |
1556 | struct libscols_line *chld = | |
1557 | list_entry(p, struct libscols_line, ln_children); | |
1558 | pre = move_line_and_children(chld, pre); | |
1559 | } | |
1560 | } | |
1561 | ||
1562 | return pre; | |
1563 | } | |
1564 | ||
1565 | /** | |
1566 | * scols_sort_table_by_tree: | |
1567 | * @tb: table | |
1568 | * | |
c8341f41 KZ |
1569 | * Reorders lines in the table by parent->child relation. Note that order of |
1570 | * the lines in the table is independent on the tree hierarchy. | |
066f46e0 | 1571 | * |
4ab60277 KZ |
1572 | * Since: 2.30 |
1573 | * | |
066f46e0 KZ |
1574 | * Returns: 0, a negative value in case of an error. |
1575 | */ | |
1576 | int scols_sort_table_by_tree(struct libscols_table *tb) | |
1577 | { | |
1578 | struct libscols_line *ln; | |
1579 | struct libscols_iter itr; | |
1580 | ||
1581 | if (!tb) | |
1582 | return -EINVAL; | |
1583 | ||
1584 | DBG(TAB, ul_debugobj(tb, "sorting table by tree")); | |
1585 | ||
1586 | scols_reset_iter(&itr, SCOLS_ITER_FORWARD); | |
1587 | while (scols_table_next_line(tb, &itr, &ln) == 0) { | |
1588 | if (ln->parent) | |
1589 | continue; | |
1590 | ||
1591 | move_line_and_children(ln, NULL); | |
1592 | } | |
1593 | ||
1594 | return 0; | |
1595 | } | |
1596 | ||
1597 | ||
19055a25 KZ |
1598 | /** |
1599 | * scols_table_set_termforce: | |
1600 | * @tb: table | |
1601 | * @force: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO} | |
1602 | * | |
8e7d9d23 | 1603 | * Forces library to use stdout as terminal, non-terminal or use automatic |
19055a25 KZ |
1604 | * detection (default). |
1605 | * | |
1606 | * Returns: 0, a negative value in case of an error. | |
3f47320a KZ |
1607 | * |
1608 | * Since: 2.29 | |
19055a25 KZ |
1609 | */ |
1610 | int scols_table_set_termforce(struct libscols_table *tb, int force) | |
1611 | { | |
1612 | if (!tb) | |
1613 | return -EINVAL; | |
1614 | tb->termforce = force; | |
1615 | return 0; | |
1616 | } | |
1617 | ||
1618 | /** | |
1619 | * scols_table_get_termforce: | |
1620 | * @tb: table | |
1621 | * | |
1622 | * Returns: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO} or a negative value in case of an error. | |
3f47320a KZ |
1623 | * |
1624 | * Since: 2.29 | |
19055a25 | 1625 | */ |
f7a9ea28 | 1626 | int scols_table_get_termforce(const struct libscols_table *tb) |
19055a25 KZ |
1627 | { |
1628 | return tb->termforce; | |
1629 | } | |
1630 | ||
1631 | /** | |
1632 | * scols_table_set_termwidth | |
1633 | * @tb: table | |
1634 | * @width: terminal width | |
1635 | * | |
1636 | * The library automatically detects terminal width or defaults to 80 chars if | |
1637 | * detections is unsuccessful. This function override this behaviour. | |
1638 | * | |
1639 | * Returns: 0, a negative value in case of an error. | |
3f47320a KZ |
1640 | * |
1641 | * Since: 2.29 | |
19055a25 KZ |
1642 | */ |
1643 | int scols_table_set_termwidth(struct libscols_table *tb, size_t width) | |
1644 | { | |
7e2a4ef7 | 1645 | DBG(TAB, ul_debugobj(tb, "set terminatl width: %zu", width)); |
19055a25 KZ |
1646 | tb->termwidth = width; |
1647 | return 0; | |
1648 | } | |
1649 | ||
1650 | /** | |
1651 | * scols_table_get_termwidth | |
1652 | * @tb: table | |
1653 | * | |
e33b3874 | 1654 | * Returns: terminal width. |
19055a25 | 1655 | */ |
e0140aa1 | 1656 | size_t scols_table_get_termwidth(const struct libscols_table *tb) |
19055a25 | 1657 | { |
19055a25 KZ |
1658 | return tb->termwidth; |
1659 | } | |
e33b3874 KZ |
1660 | |
1661 | /** | |
1662 | * scols_table_set_termheight | |
1663 | * @tb: table | |
1664 | * @height: terminal height (number of lines) | |
1665 | * | |
1666 | * The library automatically detects terminal height or defaults to 24 lines if | |
1667 | * detections is unsuccessful. This function override this behaviour. | |
1668 | * | |
1669 | * Returns: 0, a negative value in case of an error. | |
1670 | * | |
1671 | * Since: 2.31 | |
1672 | */ | |
1673 | int scols_table_set_termheight(struct libscols_table *tb, size_t height) | |
1674 | { | |
1675 | DBG(TAB, ul_debugobj(tb, "set terminatl height: %zu", height)); | |
1676 | tb->termheight = height; | |
1677 | return 0; | |
1678 | } | |
1679 | ||
1680 | /** | |
1681 | * scols_table_get_termheight | |
1682 | * @tb: table | |
1683 | * | |
1684 | * Returns: terminal height (number of lines). | |
1685 | * | |
1686 | * Since: 2.31 | |
1687 | */ | |
1688 | size_t scols_table_get_termheight(const struct libscols_table *tb) | |
1689 | { | |
1690 | return tb->termheight; | |
1691 | } |