summaryrefslogtreecommitdiff
path: root/Src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c
index 271c800fd..7409dc876 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -4964,6 +4964,108 @@ metacharlenconv(const char *x, int *c)
/**/
#endif /* MULTIBYTE_SUPPORT */
+/*
+ * Expand tabs to given width, with given starting position on line.
+ * len is length of unmetafied string in bytes.
+ * Output to fout.
+ * Return the end position on the line, i.e. if this is 0 modulo width
+ * the next character is aligned with a tab stop.
+ *
+ * If all is set, all tabs are expanded, else only leading tabs.
+ */
+
+/**/
+mod_export int
+zexpandtabs(const char *s, int len, int width, int startpos, FILE *fout,
+ int all)
+{
+ int at_start = 1;
+
+#ifdef MULTIBYTE_SUPPORT
+ mbstate_t mbs;
+ size_t ret;
+ wchar_t wc;
+
+ memset(&mbs, 0, sizeof(mbs));
+#endif
+
+ while (len) {
+ if (*s == '\t') {
+ if (all || at_start) {
+ s++;
+ len--;
+ if (width <= 0 || !(startpos % width)) {
+ /* always output at least one space */
+ fputc(' ', fout);
+ startpos++;
+ }
+ if (width <= 0)
+ continue; /* paranoia */
+ while (startpos % width) {
+ fputc(' ', fout);
+ startpos++;
+ }
+ } else {
+ /*
+ * Leave tab alone.
+ * Guess width to apply... we might get this wrong.
+ * This is only needed if there's a following string
+ * that needs tabs expanding, which is unusual.
+ */
+ startpos += width - startpos % width;
+ s++;
+ len--;
+ fputc('\t', fout);
+ }
+ continue;
+ } else if (*s == '\n' || *s == '\r') {
+ fputc(*s, fout);
+ s++;
+ len--;
+ startpos = 0;
+ at_start = 1;
+ continue;
+ }
+
+ at_start = 0;
+#ifdef MULTIBYTE_SUPPORT
+ if (isset(MULTIBYTE)) {
+ const char *sstart = s;
+ ret = mbrtowc(&wc, s, len, &mbs);
+ if (ret == MB_INVALID) {
+ /* Assume single character per character */
+ memset(&mbs, 0, sizeof(mbs));
+ s++;
+ len--;
+ } else if (ret == MB_INCOMPLETE) {
+ /* incomplete at end --- assume likewise, best we've got */
+ s++;
+ len--;
+ } else {
+ s += ret;
+ len -= (int)ret;
+ }
+ if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
+ startpos++;
+ } else {
+ int wcw = WCWIDTH(wc);
+ if (wcw > 0) /* paranoia */
+ startpos += wcw;
+ }
+ fwrite(sstart, s - sstart, 1, fout);
+
+ continue;
+ }
+#endif /* MULTIBYTE_SUPPORT */
+ fputc(*s, fout);
+ s++;
+ len--;
+ startpos++;
+ }
+
+ return startpos;
+}
+
/* check for special characters in the string */
/**/