Index: ChangeLog
===================================================================
--- ChangeLog	(revision 10b866d633f70e1c8778b601ad1cc1b6596e8563)
+++ ChangeLog	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -34,4 +34,19 @@
 		of a zephyr being composed:  C-c it and restart it 
 		and then M-p to get the aborted composition back.
+	Added owl::send_zwrite(command, message) to the perl glue
+	        to allow for the direct sending of multi-line messages.
+		For example:  owl::send_zwrite("-c foo -i bar", "hello"); 
+	Reverted attempted fix for the pagedown problem
+	        which just made things worse.
+	Changed owl_fmtext_print_plain to return an alloc'd string to 
+	        avoid buffer overrun risks.
+	Added owl::ztext_stylestrip("...") function to perlglue 
+	         which returns the ztext with formatting stripped out.
+	Added colorztext variable which can be used to disable @color()
+	         strings arriving in messages after it is set.
+		 (Currently, changing its value won't reformat messages).
+	Outgoing zephyr logging now obeys the logpath variable.
+	The '~' character in logpath and classlogpath now gets
+	         replaced with the user's home directory.
 	
 1.2.1-pre-1
@@ -84,5 +99,5 @@
 		color messages matching the current one green.
 	
-1.2.0-pre-erikdevel-17
+1.2.0-pre-1
 	Integrated change to fix problem with popup blinking on new zephyrs.
 	C-l and resizes will now refresh an open viewwin (eg, help).
@@ -94,6 +109,4 @@
 	        and to not mess up spaces.  exec also returns a string
 		of the output now.
-	
-1.2.0-pre-erikdevel-16
 	Integrated changes from 1.1.3, and added docs for "zlocate -d"
 		and new show commands.
@@ -101,12 +114,7 @@
 	Fix a bug in readconfig caught by efence (where we'd try to read before 
 	        the beginning of a string if it was empty).
-	
-1.1.2-erikdevel-15
         The perl command doesn't do makemsg directly, but instead
 	     returns the string and it will get printed if it 
 	     was run interactively.
-
-1.1.2-erikdevel-14
-	*** NOTE: I probably missed some things here...
 	New framework for command handling.
 	New framework for keymap handling.
Index: fmtext.c
===================================================================
--- fmtext.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ fmtext.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -180,5 +180,7 @@
 	/* if it's a color read the color, set the current color and
            continue */
-      } else if (!strcasecmp(buff, "@color") && owl_global_get_hascolors(&g)) {
+      } else if (!strcasecmp(buff, "@color") 
+		 && owl_global_get_hascolors(&g)
+		 && owl_global_is_colorztext(&g)) {
 	owl_free(buff);
 	txtptr+=7;
@@ -325,6 +327,20 @@
 
 
-void owl_fmtext_print_plain(owl_fmtext *f, char *buff) {
-  strcpy(buff, f->textbuff);
+/* caller is responsible for freeing */
+char *owl_fmtext_print_plain(owl_fmtext *f) {
+  return owl_strdup(f->textbuff);
+}
+
+/* strips formatting from ztext and returns the unformatted text. 
+ * caller is responsible for freeing. */
+char *owl_fmtext_ztext_stylestrip(char *zt) {
+  owl_fmtext fm;
+  char *plaintext;
+
+  owl_fmtext_init_null(&fm);
+  owl_fmtext_append_ztext(&fm, zt);
+  plaintext = owl_fmtext_print_plain(&fm);
+  owl_fmtext_free(&fm);
+  return(plaintext);
 }
 
Index: global.c
===================================================================
--- global.c	(revision 10b866d633f70e1c8778b601ad1cc1b6596e8563)
+++ global.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -18,5 +18,4 @@
   struct hostent *hent;
   char hostname[MAXHOSTNAMELEN];
-  char buff[MAXPATHLEN];
 
   gethostname(hostname, MAXHOSTNAMELEN);
@@ -78,9 +77,4 @@
   /* TODO: come back later and check passwd file first */
   strcpy(g->homedir, getenv("HOME"));
-  sprintf(buff, "%s/zlog/people/", owl_global_get_homedir(g));
-  owl_global_set_logpath(g, buff);
-  sprintf(buff, "%s/zlog/class/", owl_global_get_homedir(g));
-  owl_global_set_classlogpath(g, buff);
-  
 
   owl_messagelist_create(&(g->msglist));
Index: logging.c
===================================================================
--- logging.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ logging.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -9,5 +9,5 @@
 void owl_log_outgoing(char *to, char *text) {
   FILE *file;
-  char filename[MAXPATHLEN];
+  char filename[MAXPATHLEN], *logpath;
   char *tobuff, *ptr;
 
@@ -21,8 +21,13 @@
   }
 
-  sprintf(filename, "%s/zlog/people/%s", owl_global_get_homedir(&g), tobuff);
+  /* expand ~ in path names */
+  logpath = owl_util_substitute(owl_global_get_logpath(&g), "~", 
+				owl_global_get_homedir(&g));
+
+  snprintf(filename, MAXPATHLEN, "%s/%s", logpath, tobuff);
   file=fopen(filename, "a");
   if (!file) {
     owl_function_makemsg("Unable to open file for outgoing logging");
+    owl_free(logpath);
     return;
   }
@@ -33,5 +38,6 @@
   fclose(file);
 
-  sprintf(filename, "%s/zlog/people/all", owl_global_get_homedir(&g));
+  snprintf(filename, MAXPATHLEN, "%s/all", logpath);
+  owl_free(logpath);
   file=fopen(filename, "a");
   if (!file) {
@@ -50,5 +56,5 @@
 void owl_log_incoming(owl_message *m) {
   FILE *file, *allfile;
-  char filename[MAXPATHLEN], allfilename[MAXPATHLEN];
+  char filename[MAXPATHLEN], allfilename[MAXPATHLEN], *logpath;
   char *frombuff, *ptr, *from, *buff, *tmp;
   int len, ch, i, personal;
@@ -86,5 +92,5 @@
 
   for (i=0; i<len; i++) {
-    if (frombuff[i]<'!' || frombuff[i]>'~') from="weird";
+    if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";
   }
 
@@ -95,11 +101,18 @@
   }
 
-  /* create the filename */
+  /* create the filename (expanding ~ in path names) */
   if (personal) {
-    sprintf(filename, "%s/%s", owl_global_get_logpath(&g), from);
-    sprintf(allfilename, "%s/all", owl_global_get_logpath(&g));
+    logpath = owl_util_substitute(owl_global_get_logpath(&g), "~", 
+				  owl_global_get_homedir(&g));
+    snprintf(filename, MAXPATHLEN, "%s/%s", logpath, from);
+    snprintf(allfilename, MAXPATHLEN, "%s/all", logpath);
+
   } else {
-    sprintf(filename, "%s/%s", owl_global_get_classlogpath(&g), from);
+    logpath = owl_util_substitute(owl_global_get_classlogpath(&g), "~", 
+				owl_global_get_homedir(&g));
+
+    snprintf(filename, MAXPATHLEN, "%s/%s", logpath, from);
   }
+  owl_free(logpath);
   
   file=fopen(filename, "a");
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision 83a9b639a179e54f4a8db0a8abd1570885ad42b6)
+++ perlglue.xs	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -6,6 +6,8 @@
 
 /* Yeah, we should just include owl.h, but curses and perl don't play nice. */
-extern char *owl_function_command(char *cmd);
-extern void owl_free(void *x);
+extern char *owl_function_command(char *);
+extern void owl_free(void *);
+extern int owl_zwrite_create_and_send_from_line(char *, char *);
+extern char *owl_fmtext_ztext_stylestrip(char *);
 
 MODULE = owl		PACKAGE = owl		
@@ -24,2 +26,24 @@
 		if (rv) owl_free(rv);
 
+void
+send_zwrite(cmd,msg)
+	char *cmd
+	char *msg
+	PREINIT:
+		int i;
+	CODE:
+		i = owl_zwrite_create_and_send_from_line(cmd, msg);
+
+char *
+ztext_stylestrip(ztext)
+	char *ztext
+	PREINIT:
+		char *rv = NULL;
+	CODE:
+		rv = owl_fmtext_ztext_stylestrip(ztext);
+		RETVAL = rv;
+	OUTPUT:
+		RETVAL
+	CLEANUP:
+		if (rv) owl_free(rv);
+
Index: tester.c
===================================================================
--- tester.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ tester.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -30,5 +30,5 @@
   screeninit();
 
-  owl_editwin_init(&e, stdscr, LINES, COLS, OWL_EDITWIN_STYLE_MULTILINE);
+  owl_editwin_init(&e, stdscr, LINES, COLS, OWL_EDITWIN_STYLE_MULTILINE, NULL);
   /* owl_editwin_set_locktext(&e, "Here is some locktext:\n");*/
   doupdate();
@@ -137,4 +137,5 @@
   int numfailures=0;
   if (argc==2 && 0==strcmp(argv[1],"reg")) {
+    numfailures += owl_util_regtest();
     numfailures += owl_dict_regtest();
     numfailures += owl_variable_regtest();
Index: util.c
===================================================================
--- util.c	(revision 10b866d633f70e1c8778b601ad1cc1b6596e8563)
+++ util.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -148,5 +148,5 @@
 
 /* skips n tokens and returns where that would be.
- * TODO: handle quotes. */
+ * TODO: handle quotes more sanely. */
 char *skiptokens(char *buff, int n) {
   int inquotes=0;
@@ -154,5 +154,5 @@
       while (*buff == ' ') buff++;
       while (*buff && (inquotes || *buff != ' ')) { 
-	if (*buff == '"') inquotes=!inquotes;
+	if (*buff == '"' || *buff == '\'') inquotes=!inquotes;
 	buff++;
       }
@@ -386,4 +386,35 @@
 }
 
+/* Caller must free returned string.
+ * Returns a string with any occurances of 'from' replaced with 'to'.
+ * Does not currently handle backslash quoting, but may in the future.
+ */
+char *owl_util_substitute(char *in, char *from, char *to) {
+  char *out;
+  int   outlen, tolen, fromlen, inpos=0, outpos=0;
+
+  if (!*from) return owl_strdup(in);
+
+  outlen = strlen(in)+1;
+  tolen  = strlen(to);
+  fromlen  = strlen(from);
+  out = malloc(outlen);
+
+  while (in[inpos]) {
+    if (!strncmp(in+inpos, from, fromlen)) {
+      outlen += tolen;
+      out = owl_realloc(out, outlen);
+      strcpy(out+outpos, to);
+      inpos += fromlen;
+      outpos += tolen;
+    } else {
+      out[outpos] = in[inpos];
+      inpos++; outpos++;
+    }
+  }
+  out[outpos] = '\0';
+  return(out);
+}
+
 
 int owl_util_string_to_color(char *color) {
@@ -422,2 +453,37 @@
   return("Unknown color");
 }
+
+
+/**************************************************************************/
+/************************* REGRESSION TESTS *******************************/
+/**************************************************************************/
+
+#ifdef OWL_INCLUDE_REG_TESTS
+
+#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
+
+int owl_util_regtest(void) {
+  int numfailed=0;
+
+  printf("BEGIN testing owl_util\n");
+
+  FAIL_UNLESS("owl_util_substitute 1",
+	      !strcmp("foo", owl_util_substitute("foo", "", "Y")));
+  FAIL_UNLESS("owl_util_substitute 2",
+	      !strcmp("fYZYZ", owl_util_substitute("foo", "o", "YZ")));
+  FAIL_UNLESS("owl_util_substitute 3",
+	      !strcmp("foo", owl_util_substitute("fYZYZ", "YZ", "o")));
+  FAIL_UNLESS("owl_util_substitute 4",
+	      !strcmp("/u/foo/meep", owl_util_substitute("~/meep", "~", "/u/foo")));
+
+  FAIL_UNLESS("skiptokens 1", 
+	      !strcmp("bar quux", skiptokens("foo bar quux", 1)));
+  FAIL_UNLESS("skiptokens 2", 
+	      !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
+
+  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
+  printf("END testing owl_util (%d failures)\n", numfailed);
+  return(numfailed);
+}
+
+#endif /* OWL_INCLUDE_REG_TESTS */
Index: variable.c
===================================================================
--- variable.c	(revision 217a43edbf201d330595640b4d5c648d09e4b753)
+++ variable.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -7,4 +7,6 @@
 
 static const char fileIdent[] = "$Id$";
+
+static int in_regtest = 0;
 
 #define OWLVAR_BOOL(name,default,docstring) \
@@ -85,4 +87,7 @@
 	       "turn class logging on or off" ),
 
+  OWLVAR_BOOL( "colorztext" /* %OwlVarStub */, 1,
+	       "allow @color() in zephyrs to change color" ),
+
   OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
 		    "don't send zephyrs on C-d (or disable if in the middle of the message if set to 'middle')", "off,middle,on",
@@ -193,4 +198,7 @@
  * any user setting of this */
 int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval) {
+
+  if (in_regtest) return owl_variable_int_set_default(v, newval);
+
   if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
     if (*(int*)newval == 2) {
@@ -675,4 +683,6 @@
   char buf[1024];
 
+  in_regtest = 1;
+
   printf("BEGIN testing owl_variable\n");
   FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
Index: zwrite.c
===================================================================
--- zwrite.c	(revision 1c6c4d32e1e8e1d158e1586d924d0c440edc8a8b)
+++ zwrite.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
@@ -36,6 +36,8 @@
   }
   myargc=argc;
-  myargc--;
-  myargv++;
+  if (myargc && *(myargv[0])!='-') {
+    myargc--;
+    myargv++;
+  }
   while (myargc) {
     if (!strcmp(myargv[0], "-c")) {
