diff options
Diffstat (limited to 'format.c')
-rw-r--r-- | format.c | 151 |
1 files changed, 151 insertions, 0 deletions
@@ -26,10 +26,12 @@ */ +#include <ctype.h> #include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <stdlib.h> +#include <string.h> #include "nvidia-installer.h" #include "format.h" @@ -174,3 +176,152 @@ static void vformat(FILE *stream, const int wb, nv_free_text_rows(t); } /* vformat() */ + + + +/* + * nv_format_text_rows() - this function breaks the given string str + * into some number of rows, where each row is not longer than the + * specified width. + * + * If prefix is non-NULL, the first line is prepended with the prefix, + * and subsequent lines are indented to line up with the prefix. + * + * If word_boundary is TRUE, then attempt to only break lines on + * boundaries between words. + * + * XXX Note that we don't use nvalloc() or any of the other wrapper + * functions from here, so that this function doesn't require any + * non-c library symbols (so that it can be called from dlopen()'ed + * user interfaces. + */ + +TextRows *nv_format_text_rows(const char *prefix, const char *str, + int width, int word_boundary) +{ + int len, prefix_len, z, w, i; + char *line, *buf, *local_prefix, *a, *b, *c; + TextRows *t; + + /* initialize the TextRows structure */ + + t = (TextRows *) malloc(sizeof(TextRows)); + t->t = NULL; + t->n = 0; + t->m = 0; + + if (!str) return t; + + buf = strdup(str); + + z = strlen(buf); /* length of entire string */ + a = buf; /* pointer to the start of the string */ + + /* initialize the prefix fields */ + + if (prefix) { + prefix_len = strlen(prefix); + local_prefix = nvstrdup(prefix); + } else { + prefix_len = 0; + local_prefix = NULL; + } + + /* adjust the max width for any prefix */ + + w = width - prefix_len; + + do { + /* + * if the string will fit on one line, point b to the end of the + * string + */ + + if (z < w) b = a + z; + + /* + * if the string won't fit on one line, move b to where the + * end of the line should be, and then move b back until we + * find a space; if we don't find a space before we back b all + * the way up to a, just assign b to where the line should end. + */ + + else { + b = a + w; + + if (word_boundary) { + while ((b >= a) && (!isspace(*b))) b--; + if (b <= a) b = a + w; + } + } + + /* look for any newline inbetween a and b, and move b to it */ + + for (c = a; c < b; c++) if (*c == '\n') { b = c; break; } + + /* + * copy the string that starts at a and ends at b, prepending + * with a prefix, if present + */ + + len = b-a; + len += prefix_len; + line = (char *) malloc(len+1); + if (local_prefix) strncpy(line, local_prefix, prefix_len); + strncpy(line + prefix_len, a, len - prefix_len); + line[len] = '\0'; + + /* append the new line to the array of text rows */ + + t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1)); + t->t[t->n] = line; + t->n++; + + if (t->m < len) t->m = len; + + /* + * adjust the length of the string and move the pointer to the + * beginning of the new line + */ + + z -= (b - a + 1); + a = b + 1; + + /* move to the first non whitespace character (excluding newlines) */ + + if (word_boundary && isspace(*b)) { + while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--; + } else { + if (!isspace(*b)) z++, a--; + } + + if (local_prefix) { + for (i = 0; i < prefix_len; i++) local_prefix[i] = ' '; + } + + } while (z > 0); + + if (local_prefix) free(local_prefix); + free(buf); + + return t; + +} /* nv_format_text_rows() */ + + + +/* + * nv_free_text_rows() - free the TextRows data structure allocated by + * nv_format_text_rows() + */ + +void nv_free_text_rows(TextRows *t) +{ + int i; + + if (!t) return; + for (i = 0; i < t->n; i++) free(t->t[i]); + if (t->t) free(t->t); + free(t); + +} /* nv_free_text_rows() */ |