2 * $Id: columns.c,v 1.10 2011/10/20 20:53:55 tom Exp $
4 * columns.c -- implements column-alignment
6 * Copyright 2008-2010,2011 Thomas E. Dickey
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License, version 2.1
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to
19 * Free Software Foundation, Inc.
20 * 51 Franklin St., Fifth Floor
21 * Boston, MA 02110, USA.
26 #define each(row, data) \
27 row = 0, data = target; \
29 ++row, data = next_row(data, per_row)
32 column_separator(void)
36 if ((result
= dialog_vars
.column_separator
) != 0) {
44 next_row(char **target
, int per_row
)
46 char *result
= (char *) target
;
48 return (char **) (void *) result
;
52 next_col(char *source
, unsigned offset
)
54 char *mark
= column_separator();
55 char *result
= source
+ offset
;
57 result
+= strlen(mark
);
58 return strstr(result
, mark
);
62 * Parse the source string, storing the offsets and widths of each column in
63 * the corresponding arrays. Return the number of columns.
66 split_row(char *source
, unsigned *offsets
, unsigned *widths
)
68 int mark
= (int) strlen(column_separator());
75 offset
= (unsigned) (mark
+ next
- source
);
76 widths
[result
- 1] = offset
- offsets
[result
- 1] - (unsigned) mark
;
78 offsets
[result
] = offset
;
80 } while ((next
= next_col(source
, offset
)) != 0);
82 offset
= (unsigned) strlen(source
);
83 widths
[result
- 1] = offset
- offsets
[result
- 1];
89 * The caller passes a pointer to a struct or array containing pointers
90 * to strings that we may want to copy and reformat according to the column
94 dlg_align_columns(char **target
, int per_row
, int num_rows
)
98 if (column_separator()) {
100 unsigned numcols
= 1;
108 /* first allocate arrays for workspace */
109 for (each(row
, value
)) {
110 size_t len
= strlen(*value
);
115 widths
= dlg_calloc(unsigned, maxcols
);
116 offsets
= dlg_calloc(unsigned, maxcols
);
117 maxwidth
= dlg_calloc(unsigned, maxcols
);
119 assert_ptr(widths
, "dlg_align_columns");
120 assert_ptr(offsets
, "dlg_align_columns");
121 assert_ptr(maxwidth
, "dlg_align_columns");
123 /* now, determine the number of columns and the column-widths */
124 for (each(row
, value
)) {
125 unsigned cols
= split_row(*value
, offsets
, widths
);
128 for (n
= 0; n
< cols
; ++n
) {
129 if (maxwidth
[n
] < widths
[n
])
130 maxwidth
[n
] = widths
[n
];
133 realwidth
= numcols
- 1;
134 for (n
= 0; n
< numcols
; ++n
) {
135 realwidth
+= maxwidth
[n
];
138 /* finally, construct reformatted strings */
139 for (each(row
, value
)) {
140 unsigned cols
= split_row(*value
, offsets
, widths
);
142 char *text
= dlg_malloc(char, realwidth
+ 1);
144 assert_ptr(text
, "dlg_align_columns");
146 memset(text
, ' ', (size_t) realwidth
);
147 for (n
= 0; n
< cols
; ++n
) {
148 memcpy(text
+ offset
, *value
+ offsets
[n
], (size_t) widths
[n
]);
149 offset
+= maxwidth
[n
] + 1;
162 * Free temporary storage used while making column-aligned data.
165 dlg_free_columns(char **target
, int per_row
, int num_rows
)
170 if (column_separator()) {
171 for (each(row
, value
)) {