Index: trunk/Ohana/src/libkapa/Makefile
===================================================================
--- trunk/Ohana/src/libkapa/Makefile	(revision 41318)
+++ trunk/Ohana/src/libkapa/Makefile	(revision 41319)
@@ -42,4 +42,5 @@
 $(SRC)/RotFont.$(ARCH).o        \
 $(SRC)/DrawRotString.$(ARCH).o  \
+$(SRC)/PDFRotFont.$(ARCH).o	\
 $(SRC)/PSRotFont.$(ARCH).o
 
Index: trunk/Ohana/src/libkapa/include/kapa.h
===================================================================
--- trunk/Ohana/src/libkapa/include/kapa.h	(revision 41318)
+++ trunk/Ohana/src/libkapa/include/kapa.h	(revision 41319)
@@ -222,4 +222,5 @@
 int KapaPNG (int fd, const char *filename);
 int KapaPPM (int fd, const char *filename);
+int KapaPDF (int fd, const char *filename, int scaleMode, int pageMode, char *pagename);
 
 /* KiiCursor.c */
@@ -291,9 +292,9 @@
 int DrawRotTextInit (Display *display, Window window, GC gc, unsigned long fore, unsigned long back);
 
+/* PDFRotFont.c */
+void PDFRotText (IOBuffer *buffer, int x, int y, char *string, int pos, double angle);
 
 /* PSRotFont.c */
 void PSRotText PROTO((FILE *f, int x, int y, char *string, int pos, double angle));
-void PSDumpRotSegment PROTO((FILE *f, char *segment, int *Nseg));
-void PSSetFont PROTO((FILE *f, char *name, int size));
 int PSRotStrlen PROTO((char *c));
 
Index: trunk/Ohana/src/libkapa/src/DrawRotString.c
===================================================================
--- trunk/Ohana/src/libkapa/src/DrawRotString.c	(revision 41318)
+++ trunk/Ohana/src/libkapa/src/DrawRotString.c	(revision 41319)
@@ -77,8 +77,12 @@
 
   YoffBase = Yoff;
+  int Ydelta = 0;
   /* draw characters one-by-one */
+
+  // successive subscripts / superscripts drop the line by
+  // same amount each time, but size remains 0.8
+  // sub followed by sup, or vice versa, should clear and do basic sup/sub
+
   unsigned int i;
-  // unsigned char *tmpstring = (unsigned char *) string;
-
   for (i = 0; i < strlen(string); i++) {
     // N = (unsigned int)(tmpstring[i]);
@@ -98,4 +102,7 @@
 	SetRotFont (currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
+
+	if (Ydelta > 0) { Ydelta = 0; Yoff = YoffBase; }
+	Ydelta --;
 	Yoff -= 0.5*currentscale*dY;
 	continue;
@@ -105,4 +112,7 @@
 	SetRotFont (currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
+
+	if (Ydelta < 0) { Ydelta = 0; Yoff = YoffBase; }
+	Ydelta ++;
 	Yoff += 0.5*currentscale*dY;
 	continue;
@@ -113,4 +123,5 @@
 	currentfont = GetRotFontData (&currentscale);
 	Yoff = YoffBase;
+	Ydelta = 0;
 	continue;
       }
Index: trunk/Ohana/src/libkapa/src/KapaColors.c
===================================================================
--- trunk/Ohana/src/libkapa/src/KapaColors.c	(revision 41318)
+++ trunk/Ohana/src/libkapa/src/KapaColors.c	(revision 41319)
@@ -4,28 +4,28 @@
 
 static char KAPA_COLORS[N_KAPA_COLORS][3][16] = {
-{"black",    	 "black",    	 "0.00 0.00 0.00"}, 
-{"white",    	 "white",    	 "1.00 1.00 1.00"}, 
-{"red",      	 "red",      	 "1.00 0.00 0.00"}, 
-{"pink",     	 "pink",     	 "1.00 0.75 0.80"}, 
-{"orange",   	 "orange",   	 "1.00 0.65 0.00"}, 
-{"yellow",   	 "yellow",   	 "1.00 1.00 0.00"}, 
-{"wheat",    	 "wheat",    	 "0.96 0.87 0.70"}, 
-{"gold",     	 "gold",     	 "1.00 0.84 0.00"}, 
-{"green",    	 "green",    	 "0.00 1.00 0.00"}, 
-{"darkgreen",	 "darkgreen",	 "0.00 0.40 0.00"}, 
-{"darkblue",     "darkblue", 	 "0.50 0.50 1.00"}, 
-{"blue",     	 "blue",     	 "0.00 0.00 1.00"}, 
-{"skyblue",  	 "skyblue",  	 "0.53 0.81 0.92"}, 
-{"indigo",   	 "mediumpurple", "0.57 0.44 0.86"}, 
-{"violet",   	 "darkviolet", 	 "0.58 0.00 0.88"},
-{"blue10",     	 "rgb:00/00/33", "0.00 0.00 0.20"}, 
-{"blue20",     	 "rgb:00/00/66", "0.00 0.00 0.40"}, 
-{"blue30",     	 "rgb:00/00/99", "0.00 0.00 0.60"}, 
-{"blue40",     	 "rgb:00/00/cc", "0.00 0.00 0.80"}, 
-{"blue50",     	 "rgb:00/00/ff", "0.00 0.00 1.00"}, 
-{"blue60",     	 "rgb:33/33/ff", "0.20 0.20 1.00"}, 
-{"blue70",     	 "rgb:66/66/ff", "0.40 0.40 1.00"}, 
-{"blue80",     	 "rgb:99/99/ff", "0.60 0.60 1.00"}, 
-{"blue90",     	 "rgb:cc/cc/ff", "0.80 0.80 1.00"}, 
+{"black",    	 "black",    	         "0.00 0.00 0.00"}, 
+{"white",    	 "white",    	         "1.00 1.00 1.00"}, 
+{"red",      	 "red",      	         "1.00 0.00 0.00"}, 
+{"pink",     	 "pink",     	         "1.00 0.75 0.80"}, 
+{"orange",   	 "orange",   	         "1.00 0.65 0.00"}, 
+{"yellow",   	 "yellow",   	         "1.00 1.00 0.00"}, 
+{"wheat",    	 "wheat",    	         "0.96 0.87 0.70"}, 
+{"gold",     	 "gold",     	         "1.00 0.84 0.00"}, 
+{"green",    	 "green",    	         "0.00 1.00 0.00"}, 
+{"darkgreen",	 "darkgreen",	         "0.00 0.40 0.00"}, 
+{"darkblue",     "darkblue", 	         "0.50 0.50 1.00"}, 
+{"blue",     	 "blue",     	         "0.00 0.00 1.00"}, 
+{"skyblue",  	 "skyblue",  	         "0.53 0.81 0.92"}, 
+{"indigo",   	 "mediumpurple",         "0.57 0.44 0.86"}, 
+{"violet",   	 "darkviolet", 	         "0.58 0.00 0.88"},
+{"blue10",     	 "rgb:00/00/33",         "0.00 0.00 0.20"}, 
+{"blue20",     	 "rgb:00/00/66",         "0.00 0.00 0.40"}, 
+{"blue30",     	 "rgb:00/00/99",         "0.00 0.00 0.60"}, 
+{"blue40",     	 "rgb:00/00/cc",         "0.00 0.00 0.80"}, 
+{"blue50",     	 "rgb:00/00/ff",         "0.00 0.00 1.00"}, 
+{"blue60",     	 "rgb:33/33/ff",         "0.20 0.20 1.00"}, 
+{"blue70",     	 "rgb:66/66/ff",         "0.40 0.40 1.00"}, 
+{"blue80",     	 "rgb:99/99/ff",         "0.60 0.60 1.00"}, 
+{"blue90",     	 "rgb:cc/cc/ff",         "0.80 0.80 1.00"}, 
 {"red10",     	 "rgb:33/00/00",     	 "0.20 0.00 0.00"}, 
 {"red20",     	 "rgb:66/00/00",     	 "0.40 0.00 0.00"}, 
@@ -37,13 +37,13 @@
 {"red80",     	 "rgb:ff/99/99",     	 "1.00 0.60 0.60"}, 
 {"red90",     	 "rgb:ff/cc/cc",     	 "1.00 0.80 0.80"}, 
-{"grey10",   	 "grey10",   	 "0.10 0.10 0.10"},
-{"grey20",   	 "grey20",   	 "0.20 0.20 0.20"},
-{"grey30",   	 "grey30",   	 "0.30 0.30 0.30"},
-{"grey40",   	 "grey40",   	 "0.40 0.40 0.40"},
-{"grey50",   	 "grey50",   	 "0.50 0.50 0.50"},
-{"grey60",   	 "grey60",   	 "0.60 0.60 0.60"},
-{"grey70",   	 "grey70",   	 "0.70 0.70 0.70"},
-{"grey80",   	 "grey80",   	 "0.80 0.80 0.80"},
-{"grey90",   	 "grey90",   	 "0.90 0.90 0.90"}};
+{"grey10",   	 "grey10",   	         "0.10 0.10 0.10"},
+{"grey20",   	 "grey20",   	         "0.20 0.20 0.20"},
+{"grey30",   	 "grey30",   	         "0.30 0.30 0.30"},
+{"grey40",   	 "grey40",   	         "0.40 0.40 0.40"},
+{"grey50",   	 "grey50",   	         "0.50 0.50 0.50"},
+{"grey60",   	 "grey60",   	         "0.60 0.60 0.60"},
+{"grey70",   	 "grey70",   	         "0.70 0.70 0.70"},
+{"grey80",   	 "grey80",   	         "0.80 0.80 0.80"},
+{"grey90",   	 "grey90",   	         "0.90 0.90 0.90"}};
 
 int KapaColorByName (char *name) {
@@ -70,9 +70,11 @@
 
 char *KapaColorRGBString (int N) {
-  return (KAPA_COLORS[N][2]);
+  int Nused = MAX (0, MIN (N_KAPA_COLORS, N));
+  return (KAPA_COLORS[Nused][2]);
 }
 
 char *KapaColorName (int N) {
-  return (KAPA_COLORS[N][0]);
+  int Nused = MAX (0, MIN (N_KAPA_COLORS, N));
+  return (KAPA_COLORS[Nused][0]);
 }
 
Index: trunk/Ohana/src/libkapa/src/KiiConvert.c
===================================================================
--- trunk/Ohana/src/libkapa/src/KiiConvert.c	(revision 41318)
+++ trunk/Ohana/src/libkapa/src/KiiConvert.c	(revision 41319)
@@ -32,2 +32,10 @@
   return (TRUE);
 }
+
+int KapaPDF (int fd, const char *filename, int scaleMode, int pageMode, char *pagename) {
+
+  KiiSendCommand (fd, 4, "PDFT");
+  KiiSendMessage (fd, "%s %s %d %d", filename, pagename, scaleMode, pageMode);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
Index: trunk/Ohana/src/libkapa/src/PDFRotFont.c
===================================================================
--- trunk/Ohana/src/libkapa/src/PDFRotFont.c	(revision 41319)
+++ trunk/Ohana/src/libkapa/src/PDFRotFont.c	(revision 41319)
@@ -0,0 +1,184 @@
+# include <kapa_internal.h>
+# define NROTCHARS 256
+
+// local functions
+void PDF_DumpRotSegment (IOBuffer *buffer, char *segment, int *Nseg);
+void PDF_SetFont (IOBuffer *buffer, char *name, int size);
+
+/* writes commands to print string at location and angle using currently set font and size */
+void PDFRotText (IOBuffer *buffer, int x, int y, char *string, int pos, double angle) {
+
+  char *segment, basename[64], *currentname;
+  int N, code, protect;
+  int dX, dY, Xoff, Yoff, X, Y, Nseg, NSEG;
+  double cs, sn, currentscale;
+  int basesize, currentsize;
+  RotFont *currentfont;
+  
+  currentname = GetRotFont (&currentsize);
+  currentfont = GetRotFontData (&currentscale);
+  strcpy (basename, currentname);
+  basesize = currentsize;
+
+  /* strip off leading WHITESPACE */
+  stripwhite (string);
+  if (*string == 0) return;
+  
+  /* compute string length */
+  dX = PSRotStrlen (string); // common function for PDF & PS
+  dY = currentfont[65].ascent;
+  int dP = ceil(0.25 * dY);
+  
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+    case 0: Xoff =  -dX-dP; Yoff = -(dY+dP); break;
+    case 1: Xoff = -0.5*dX; Yoff = -(dY+dP); break;
+    case 2: Xoff =      dP; Yoff = -(dY+dP); break;
+    case 3: Xoff =  -dX-dP; Yoff = -0.5*dY; break;
+    case 4: Xoff = -0.5*dX; Yoff = -0.5*dY; break;
+    case 5: Xoff =      dP; Yoff = -0.5*dY; break;
+    case 6: Xoff =  -dX-dP; Yoff = dP; break;
+    case 7: Xoff = -0.5*dX; Yoff = dP; break;
+    case 8: Xoff =      dP; Yoff = dP; break;
+  }
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  X = x + Xoff*cs + Yoff*sn;
+  Y = y - Xoff*sn + Yoff*cs;
+
+  PDF_SetFont (buffer, currentname, currentsize);
+
+  if (fabs(angle) < 0.001) {
+    PrintIOBuffer (buffer, " %d %d m\n", X, Y);
+  } else {
+    PrintIOBuffer (buffer, " 0 0 m q\n");
+    PrintIOBuffer (buffer, " %5.3f %5.3f %5.3f %5.3f %d %d cm\n", cs, -sn, sn, cs, X, Y);
+  }
+
+  Nseg = 0;
+  NSEG = strlen(string) + 2;
+  ALLOCATE (segment, char, NSEG);
+  bzero (segment, NSEG);
+
+  code = FALSE;
+  protect = FALSE;
+
+  int YoffBase = 0;
+  /* accumulate string segments with common state */
+
+  unsigned int i;
+  for (i = 0; i < strlen (string); i++) {
+    N = (int)(string[i]);
+    if ((N < 0) || (N >= NROTCHARS)) continue;
+
+    if (N == 39) { // single-quote
+      protect = protect ? FALSE : TRUE;
+    } 
+
+    // XXX I need to track the number of sub and super symbols
+    // normal resets to the raw text
+    // each sub or super scripts font and drops font
+
+    /* check for special characters */
+    if (!code && !protect) {
+      /* subscript character (_) */
+      if (N == 94) {
+	PDF_DumpRotSegment (buffer, segment, &Nseg);
+	PDF_SetFont (buffer, currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	if (YoffBase > 0) YoffBase = 0;
+	YoffBase --;
+	PrintIOBuffer (buffer, "%d Ts\n", -5*YoffBase);
+	continue;
+      }
+      /* superscript character (^) */
+      if (N == 95) { 
+	PDF_DumpRotSegment (buffer, segment, &Nseg);
+	PDF_SetFont (buffer, currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	if (YoffBase < 0) YoffBase = 0;
+	YoffBase ++;
+	PrintIOBuffer (buffer, "%d Ts\n", -5*YoffBase);
+	continue;
+      }
+      /* end super/sub script (|) */
+      if (N == 124) {
+	PDF_DumpRotSegment (buffer, segment, &Nseg);
+	PDF_SetFont (buffer, currentname, basesize);
+	currentfont = GetRotFontData (&currentscale);
+
+	YoffBase = 0;
+	PrintIOBuffer (buffer, "0 Ts\n");
+	continue;
+      }
+      /* escape char (\) */
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      /* begin paren (insert \) */
+      if (N == 40) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* end paren (insert \) */
+      if (N == 41) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* font change character (&) */
+      if (N == 38) {
+	PDF_DumpRotSegment (buffer, segment, &Nseg);
+	if (string[i+1] == 'h') {
+	  PDF_SetFont (buffer, "helvetica", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 't') {
+	  PDF_SetFont (buffer, "times", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 'c') {
+	  PDF_SetFont (buffer, "courier", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 's') {
+	  PDF_SetFont (buffer, "symbol", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    segment[Nseg] = N;
+    Nseg ++;
+    CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+  }
+  PDF_DumpRotSegment (buffer, segment, &Nseg);
+
+  if (fabs(angle) >= 0.001) {
+    PrintIOBuffer (buffer, " Q\n");
+  }
+
+  free (segment);
+  PDF_SetFont (buffer, basename, basesize);
+}
+
+void PDF_DumpRotSegment (IOBuffer *buffer, char *segment, int *Nseg) {
+  segment[*Nseg] = 0;
+  PrintIOBuffer (buffer, "(%s) Tj\n", segment);
+  bzero (segment, *Nseg);
+  *Nseg = 0;
+}
+
+void PDF_SetFont (IOBuffer *buffer, char *name, int size) {
+  if (!strcmp (name, "times"))     PrintIOBuffer (buffer, "/Ft %d Tf\n", size);
+  if (!strcmp (name, "helvetica")) PrintIOBuffer (buffer, "/Fh %d Tf\n", size);
+  if (!strcmp (name, "courier"))   PrintIOBuffer (buffer, "/Fc %d Tf\n", size);
+  if (!strcmp (name, "symbol"))    PrintIOBuffer (buffer, "/Fs %d Tf\n", size);
+}
Index: trunk/Ohana/src/libkapa/src/PSRotFont.c
===================================================================
--- trunk/Ohana/src/libkapa/src/PSRotFont.c	(revision 41318)
+++ trunk/Ohana/src/libkapa/src/PSRotFont.c	(revision 41319)
@@ -1,4 +1,8 @@
 # include <kapa_internal.h>
 # define NROTCHARS 256
+
+// local functions:
+void PSDumpRotSegment (FILE *f, char *segment, int *Nseg);
+void PSSetFont (FILE *f, char *name, int size);
 
 /* writes commands to print string at location and angle using
Index: trunk/Ohana/src/libkapa/src/bDrawRotFont.c
===================================================================
--- trunk/Ohana/src/libkapa/src/bDrawRotFont.c	(revision 41318)
+++ trunk/Ohana/src/libkapa/src/bDrawRotFont.c	(revision 41319)
@@ -57,5 +57,10 @@
 
   YoffBase = Yoff;
+  int Ydelta = 0;
   /* draw characters one-by-one */
+
+  // successive subscripts / superscripts drop the line by
+  // same amount each time, but size remains 0.8
+  // sub followed by sup, or vice versa, should clear and do basic sup/sub
 
   unsigned int i;
@@ -73,5 +78,8 @@
 	SetRotFont (currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
-	Yoff -= 0.5*currentscale*dY;
+
+	if (Ydelta > 0) { Ydelta = 0; Yoff = YoffBase; }
+	Ydelta --;
+	Yoff -= 0.75*currentscale*dY;
 	continue;
       }
@@ -79,5 +87,8 @@
 	SetRotFont (currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
-	Yoff += 0.5*currentscale*dY;
+
+	if (Ydelta < 0) { Ydelta = 0; Yoff = YoffBase; }
+	Ydelta ++;
+	Yoff += 0.75*currentscale*dY;
 	continue;
       }
@@ -86,4 +97,5 @@
 	currentfont = GetRotFontData (&currentscale);
 	Yoff = YoffBase;
+	Ydelta = 0;
 	continue;
       }
