summaryrefslogtreecommitdiff
path: root/format.c
diff options
context:
space:
mode:
Diffstat (limited to 'format.c')
-rw-r--r--format.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/format.c b/format.c
index 72f05aa..f9fe88f 100644
--- a/format.c
+++ b/format.c
@@ -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() */