center() can have multi-character fills and different left and right fills
authorAri Johnson <ari@cobramush.org>
Tue, 20 Feb 2007 22:00:50 +0000 (22:00 +0000)
committerAri Johnson <ari@cobramush.org>
Tue, 20 Feb 2007 22:00:50 +0000 (22:00 +0000)
game/txt/hlp/cobra_func.hlp
hdrs/externs.h
src/function.c
src/funstr.c
src/strutil.c

index 40f8bec2d6a4f46459ab50e99db7191f424b3f39..68ca47bc89fa644d82570f0ee26be04f1fa82b5a 100644 (file)
 
   See also: floor(), bound(), round(), trunc()
 & CENTER()
-  center(<string>,<width>[,<fill>])
+  center(<string>,<width>[,<fill>[,<rightfill>]])
+
   This function will center <string> within a field <width> characters wide,
-  using <fill> characters for padding on either end of the string for
-  centering. If <fill> is not specified, a space will be used.
+  using the <fill> string for padding on the left side of the string,
+  and <rightfill> for padding on the right side. <rightfill> defaults
+  to the mirror-image of <fill> if not specified. <fill> defaults to
+  a space if neither <fill> nor <rightfill> are specified. 
+
+  If <string> divides <width> into uneven portions, the left side
+  will be one character shorter than the right side.
+
   Example:
     > say center(X,5,-)
     You say, "--X--"
-    > say center(.NEAT.,15)
-    You say, "    .NEAT.      "
+    > say center(X,5,-=)
+    You say, "-=X=-"
+    > say center(.NEAT.,15,-,=)
+    You say, "----.NEAT.====="
+    > say center(hello,16,12345)
+    You say, "12345hello543215"
 
 & CHECKPASS()
   checkpass(<player>,<string>)
index c8b535ff26e1d5de4d99473a0eadceea2e3e5f07..d7567e6b761d13eab6ce804ad976ba7fd3470b48 100644 (file)
@@ -451,6 +451,7 @@ strdup(const char *s)
 
 
     extern ansi_string *parse_ansi_string(const char *src) __attribute_malloc__;
+    extern void flip_ansi_string(ansi_string *as);
     extern void free_ansi_string(ansi_string *as);
     extern void populate_codes(ansi_string *as);
     extern void depopulate_codes(ansi_string *as);
index 3eef453f2ca94e232450c121b17ec0860afd10d3..a8fde26c0efd7a20f993eb4ec4362f1e165fd3cb 100644 (file)
@@ -312,7 +312,7 @@ FUNTAB flist[] = {
   {"CTITLE", fun_ctitle, 2, 2, FN_REG},
   {"CWHO", fun_cwho, 1, 1, FN_REG},
 #endif /* CHAT_SYSTEM */
-  {"CENTER", fun_center, 2, 3, FN_REG},
+  {"CENTER", fun_center, 2, 4, FN_REG},
   {"CHILDREN", fun_lsearch, 1, 1, FN_REG},
   {"CHR", fun_chr, 1, 1, FN_REG},
   {"CHECKPASS", fun_checkpass, 2, 2, FN_REG | FN_DIRECTOR},
index 250c78bd5551654bc0fb961828fd75094df44892..0d254921b6c1565ba431c2f171e2ed07dff5c97c 100644 (file)
@@ -606,25 +606,9 @@ FUNCTION(fun_strcat)
 FUNCTION(fun_flip)
 {
   ansi_string *as;
-  int p, n;
-
   as = parse_ansi_string(args[0]);
-  populate_codes(as);
-
-  for (p = 0, n = as->len - 1; p < n; p++, n--) {
-    char *tcode;
-    char t;
-
-    tcode = as->codes[p];
-    t = as->text[p];
-    as->codes[p] = as->codes[n];
-    as->text[p] = as->text[n];
-    as->codes[n] = tcode;
-    as->text[n] = t;
-  }
-
+  flip_ansi_string(as);
   safe_ansi_string(as, 0, as->len, buff, bp);
-
   free_ansi_string(as);
 }
 
@@ -931,10 +915,11 @@ FUNCTION(fun_rjust)
 /* ARGSUSED */
 FUNCTION(fun_center)
 {
-  /* pads a string with leading blanks (or other fill character) */
-
-  size_t width, len, lsp, rsp;
-  char sep;
+  /* pads a string with leading blanks (or other fill string) */
+  size_t width, len, lsp, rsp, filllen;
+  int fillq, fillr, i;
+  char fillstr[BUFFER_LEN], *fp;
+  ansi_string *as;
 
   if (!is_uinteger(args[1])) {
     safe_str(T(e_uint), buff, bp);
@@ -946,20 +931,60 @@ FUNCTION(fun_center)
     safe_strl(args[0], arglens[0], buff, bp);
     return;
   }
-  rsp = width - len;
-  lsp = rsp / 2;
-  rsp -= lsp;
+  lsp = rsp = (width - len) / 2;
+  rsp += (width - len) % 2;
   if (lsp >= BUFFER_LEN)
-    lsp = BUFFER_LEN - 1;
-  if (rsp >= BUFFER_LEN)
-    rsp = BUFFER_LEN - 1;
+    lsp = rsp = BUFFER_LEN - 1;
 
-  if (!delim_check(buff, bp, nargs, args, 3, &sep))
+  if (!args[2] || !*args[2]) {
+    /* Fast case for default fill with spaces */
+    safe_fill(' ', lsp, buff, bp);
+    safe_strl(args[0], arglens[0], buff, bp);
+    safe_fill(' ', rsp, buff, bp);
     return;
+  }
 
-  safe_fill(sep, lsp, buff, bp);
+  /* args[2] contains the possibly ansi, multi-char fill string */
+  filllen = ansi_strlen(args[2]);
+  as = parse_ansi_string(args[2]);
+  fillq = lsp / filllen;
+  fillr = lsp % filllen;
+  fp = fillstr;
+  for (i = 0; i < fillq; i++)
+    safe_ansi_string(as, 0, as->len, fillstr, &fp);
+  safe_ansi_string(as, 0, fillr, fillstr, &fp);
+  *fp = '\0';
+  free_ansi_string(as);
+  safe_str(fillstr, buff, bp);
   safe_strl(args[0], arglens[0], buff, bp);
-  safe_fill(sep, rsp, buff, bp);
+  /* If we have args[3], that's the right-side fill string */
+  if (nargs > 3) {
+    if (args[3] && *args[3]) {
+      filllen = ansi_strlen(args[3]);
+      as = parse_ansi_string(args[3]);
+      fillq = rsp / filllen;
+      fillr = rsp % filllen;
+      fp = fillstr;
+      for (i = 0; i < fillq; i++)
+      safe_ansi_string(as, 0, as->len, fillstr, &fp);
+      safe_ansi_string(as, 0, fillr, fillstr, &fp);
+      *fp = '\0';
+      free_ansi_string(as);
+      safe_str(fillstr, buff, bp);
+    } else {
+      /* Null args[3], fill right side with spaces */
+      safe_fill(' ', rsp, buff, bp);
+    }
+    return;
+  }
+  /* No args[3], so we flip args[2] */
+  as = parse_ansi_string(fillstr);
+  flip_ansi_string(as);
+  safe_ansi_string(as, 0, as->len, buff, bp);
+  /* Is there an extra char left over we need to pad with? */
+  if (rsp > lsp)
+    safe_ansi_string(as, 0, 1, buff, bp);
+  free_ansi_string(as);
 }
 
 /* ARGSUSED */
index 2d6e6051945dca65e150f3f08164556251fb3e23..4eaa680d5b3f92fd4b54fd3bafe4ecd7cf03ebbe 100644 (file)
@@ -1626,6 +1626,31 @@ depopulate_codes(ansi_string *as)
   }
 }
 
+/** Reverse an ansi string, preserving its ansification.
+ * This function destructively modifies the ansi_string passed.
+ * \param as pointer to an ansi string.
+ */
+void
+flip_ansi_string(ansi_string *as)
+{
+  int p, n;
+
+  populate_codes(as);
+
+  for (p = 0, n = as->len - 1; p < n; p++, n--) {
+    char *tcode;
+    char t;
+
+    tcode = as->codes[p];
+    t = as->text[p];
+    as->codes[p] = as->codes[n];
+    as->text[p] = as->text[n];
+    as->codes[n] = tcode;
+    as->text[n] = t;
+  }
+}
+
+
 static int is_ansi_code(const char *s);
 static int is_start_html_code(const char *s) __attribute__ ((__unused__));
 static int is_end_html_code(const char *s);