source: mainline/uspace/lib/fmtutil/fmtutil.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was 1b20da0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on non-empty lines, in certain file types.

Command used: tools/srepl '\([^[:space:]]\)\s\+$' '\1' -- *.c *.h *.py *.sh *.s *.S *.ag

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <io/console.h>
30#include <errno.h>
31#include <fmtutil.h>
32#include <stdlib.h>
33#include <str.h>
34
35typedef struct {
36 align_mode_t alignment;
37 bool newline_always;
38 size_t width;
39} printmode_t;
40
41errno_t print_wrapped_console(const char *str, align_mode_t alignment)
42{
43 console_ctrl_t *console = console_init(stdin, stdout);
44 if (console == NULL) {
45 printf("%s", str);
46 return EOK;
47 }
48 sysarg_t con_rows, con_cols, con_col, con_row;
49 errno_t rc = console_get_size(console, &con_cols, &con_rows);
50 if (rc != EOK) {
51 return rc;
52 }
53 rc = console_get_pos(console, &con_col, &con_row);
54 if (rc != EOK) {
55 return rc;
56 }
57 if (con_col != 0) {
58 printf("\n");
59 }
60 return print_wrapped(str, con_cols, alignment);
61}
62
63/** Line consumer that prints the lines aligned according to spec
64 *
65 **/
66static errno_t print_line(wchar_t *wstr, size_t chars, bool last, void *data)
67{
68 printmode_t *pm = (printmode_t *) data;
69 wchar_t old_char = wstr[chars];
70 wstr[chars] = 0;
71 errno_t rc = print_aligned_w(wstr, pm->width, last, pm->alignment);
72 wstr[chars] = old_char;
73 return rc;
74}
75
76errno_t print_wrapped(const char *str, size_t width, align_mode_t mode)
77{
78 printmode_t pm;
79 pm.alignment = mode;
80 pm.newline_always = false;
81 pm.width = width;
82 wchar_t *wstr = str_to_awstr(str);
83 if (wstr == NULL) {
84 return ENOMEM;
85 }
86 errno_t rc = wrap(wstr, width, print_line, &pm);
87 free(wstr);
88 return rc;
89}
90
91errno_t print_aligned_w(const wchar_t *wstr, size_t width, bool last,
92 align_mode_t mode)
93{
94 size_t i;
95 size_t len = wstr_length(wstr);
96 if (mode == ALIGN_LEFT || (mode == ALIGN_JUSTIFY && last)) {
97 for (i = 0; i < width; i++) {
98 if (i < len)
99 putchar(wstr[i]);
100 else
101 putchar(' ');
102 }
103 }
104 else if (mode == ALIGN_RIGHT) {
105 for (i = 0; i < width; i++) {
106 if (i < width - len)
107 putchar(' ');
108 else
109 putchar(wstr[i- (width - len)]);
110 }
111 }
112 else if (mode == ALIGN_CENTER) {
113 size_t padding = (width - len) / 2;
114 for (i = 0; i < width; i++) {
115 if ((i < padding) || ((i - padding) >= len))
116 putchar(' ');
117 else
118 putchar(wstr[i-padding]);
119 }
120 }
121 else if (mode == ALIGN_JUSTIFY) {
122 size_t words = 0;
123 size_t word_chars = 0;
124 bool space = true;
125 for (i = 0; i < len; i++) {
126 if (space && wstr[i] != ' ') {
127 words++;
128 }
129 space = wstr[i] == ' ';
130 if (!space) word_chars++;
131 }
132 size_t done_words = 0;
133 size_t done_chars = 0;
134 if (words == 0)
135 goto skip_words;
136 size_t excess_spaces = width - word_chars - (words-1);
137 space = true;
138 i = 0;
139 size_t j;
140 while (i < len) {
141 /* Find a word */
142 while (i < len && wstr[i] == ' ') i++;
143 if (i == len) break;
144 if (done_words) {
145 size_t spaces = 1 + (((done_words *
146 excess_spaces) / (words - 1)) -
147 (((done_words - 1) * excess_spaces) /
148 (words - 1)));
149 for (j = 0; j < spaces; j++) {
150 putchar(' ');
151 }
152 done_chars += spaces;
153 }
154 while (i < len && wstr[i] != ' ') {
155 putchar(wstr[i++]);
156 done_chars++;
157 }
158 done_words++;
159 }
160skip_words:
161 while (done_chars < width) {
162 putchar(' ');
163 done_chars++;
164 }
165 }
166 else {
167 return EINVAL;
168 }
169
170 return EOK;
171}
172errno_t print_aligned(const char *str, size_t width, bool last, align_mode_t mode)
173{
174 wchar_t *wstr = str_to_awstr(str);
175 if (wstr == NULL) {
176 return ENOMEM;
177 }
178 errno_t rc = print_aligned_w(wstr, width, last, mode);
179 free(wstr);
180 return rc;
181}
182
183errno_t wrap(wchar_t *wstr, size_t width, line_consumer_fn consumer, void *data)
184{
185 size_t word_start = 0;
186 size_t last_word_end = 0;
187 size_t line_start = 0;
188 size_t line_len = 0;
189 size_t pos = 0;
190
191 /*
192 * Invariants:
193 * * line_len = last_word_end - line_start
194 * * line_start <= last_word_end <= word_start <= pos
195 */
196
197 while (wstr[pos] != 0) {
198 /* Skip spaces and process newlines */
199 while (wstr[pos] == ' ' || wstr[pos] == '\n') {
200 if (wstr[pos] == '\n') {
201 consumer(wstr + line_start, line_len, true,
202 data);
203 last_word_end = line_start = pos + 1;
204 line_len = 0;
205 }
206 pos++;
207 }
208 word_start = pos;
209 /* Find end of word */
210 while (wstr[pos] != 0 && wstr[pos] != ' ' &&
211 wstr[pos] != '\n')
212 pos++;
213 bool last = wstr[pos] == 0;
214 /* Check if the line still fits width */
215 if (pos - line_start > width) {
216 if (line_len > 0)
217 consumer(wstr + line_start, line_len, last,
218 data);
219 line_start = last_word_end = word_start;
220 line_len = 0;
221 }
222 /* Check if we need to force wrap of long word*/
223 if (pos - word_start > width) {
224 consumer(wstr + word_start, width, last, data);
225 pos = line_start = last_word_end = word_start + width;
226 line_len = 0;
227 }
228 last_word_end = pos;
229 line_len = last_word_end - line_start;
230 }
231 /* Here we have less than width chars starting from line_start.
232 * Moreover, the last portion does not contain spaces or newlines
233 */
234 if (pos - line_start > 0)
235 consumer(wstr + line_start, pos - line_start, true, data);
236
237 return EOK;
238}
239
Note: See TracBrowser for help on using the repository browser.