[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
[0325]
[0326]
[0327]
[0328]
[0329]
[0330]
[0331]
[0332]
[0333]
[0334]
[0335]
[0336]
[0337]
[0338]
[0339]
[0340]
[0341]
[0342]
[0343]
[0344]
[0345]
[0346]
[0347]
[0348]
[0349]
[0350]
[0351]
[0352]
[0353]
[0354]
[0355]
[0356]
[0357]
[0358]
[0359]
[0360]
[0361]
[0362]
[0363]
[0364]
[0365]
[0366]
[0367]
[0368]
[0369]
[0370]
[0371]
[0372]
[0373]
[0374]
[0375]
[0376]
[0377]
[0378]
[0379]
[0380]
[0381]
[0382]
[0383]
[0384]
[0385]
[0386]
[0387]
[0388]
[0389]
[0390]
[0391]
[0392]
[0393]
[0394]
[0395]
[0396]
[0397]
[0398]
[0399]
[0400]
[0401]
[0402]
[0403]
[0404]
[0405]
[0406]
[0407]
[0408]
[0409]
[0410]
[0411]
[0412]
[0413]
[0414]
[0415]
[0416]
[0417]
[0418]
[0419]
[0420]
[0421]
[0422]
[0423]
[0424]
[0425]
[0426]
[0427]
[0428]
[0429]
[0430]
[0431]
[0432]
[0433]
[0434]
[0435]
[0436]
[0437]
[0438]
[0439]
[0440]
[0441]
[0442]
[0443]
[0444]
[0445]
[0446]
[0447]
[0448]
[0449]
[0450]
[0451]
[0452]
[0453]
[0454]
[0455]
[0456]
[0457]
[0458]
[0459]
[0460]
[0461]
[0462]
[0463]
[0464]
[0465]
[0466]
[0467]
[0468]
[0469]
[0470]
[0471]
[0472]
[0473]
[0474]
[0475]
[0476]
[0477]
[0478]
[0479]
[0480]
[0481]
[0482]
[0483]
[0484]
[0485]
[0486]
[0487]
[0488]
[0489]
[0490]
[0491]
[0492]
[0493]
[0494]
[0495]
[0496]
[0497]
[0498]
[0499]
[0500]
[0501]
[0502]
[0503]
[0504]
[0505]
[0506]
[0507]
[0508]
[0509]
[0510]
[0511]
[0512]
[0513]
[0514]
[0515]
[0516]
[0517]
[0518]
[0519]
[0520]
[0521]
[0522]
[0523]
[0524]
[0525]
[0526]
[0527]
[0528]
[0529]
[0530]
[0531]
[0532]
[0533]
[0534]
[0535]
[0536]
[0537]
[0538]
[0539]
[0540]
[0541]
[0542]
[0543]
[0544]
[0545]
[0546]
[0547]
[0548]
[0549]
[0550]
[0551]
[0552]
[0553]
[0554]
[0555]
[0556]
[0557]
[0558]
[0559]
[0560]
[0561]
[0562]
[0563]
[0564]
[0565]
[0566]
[0567]
[0568]
[0569]
[0570]
[0571]
[0572]
[0573]
[0574]
[0575]
[0576]
[0577]
[0578]
[0579]
[0580]
[0581]
[0582]
[0583]
[0584]
[0585]
[0586]
[0587]
[0588]
[0589]
[0590]
[0591]
[0592]
[0593]
[0594]
[0595]
[0596]
[0597]
[0598]
[0599]
[0600]
[0601]
[0602]
[0603]
[0604]
[0605]
[0606]
[0607]
[0608]
[0609]
[0610]
[0611]
[0612]
[0613]
[0614]
[0615]
[0616]
[0617]
[0618]
[0619]
[0620]
[0621]
[0622]
[0623]
/*****************************************************************************/
/*
                                   draw.c

Box diagram drawing using a Q&D conversion from ASCII to HTML box characters.

https://en.wikipedia.org/wiki/Box_Drawing_(Unicode_block)

Given a box-like line drawing such as the test one below...

  +---------+                 +---------+
  |         |<-- THIS one --->|         |
  | ONE one |                 | two TWO +---+
  |         |<-- this TWO --->|         |   |
  +--+------+                 +---------+   |
     |   ^                         ^        |
     |   |                         |        |
     |   +-------------------------|--------+
     |                             |
     +-----------------------------+

the code scans the characters, taking into consideration adjacent characters in
all directions, and generates equivalent Unicode HTML entities.  Reserved (to
this module) characters must be escaped using '\'.  The usual '|' wasDOC
behaviour does not apply within |draw|..|!draw|.

Drawing reserved characters; | - + < > ^ # : . * { } \

Immediately following the |draw| directive custom styling may be included.

  |draw|
  <style>
  ...styling...
  </style>
  ...diagram...
  |!draw|

This URL allows ad hoc development outside of a full document.  Must begin with
the string "|draw|".  Otherwise follows the same rules as for in-document
drawings.

   https://the.server.name/cgi-bin/wasdoc/path/to/file.txt?draw


VERSION HISTORY
---------------
24-JAN-2020  MGD  initial
*/
/*****************************************************************************/

#include "wasdoc.h"
#include "cgilib.h"

/* https://unicode-search.net/ */
/* http://www.alanwood.net/unicode/index.html */
#define ARROW_DOWN   "<span class=\"dvflip\">&#x25b2;</span>"
#define ARROW_LEFT   "<span class=\"dnoflip\">&#x25c4;</span>"
#define ARROW_RIGHT  "<span class=\"dhflip\">&#x25c4;</span>"
#define ARROW_UP     "<span class=\"dnoflip\">&#x25b2;</span>"
#define CIRCLE       "&#x25cf;"
#define DOWNLEFT     "&#x2510;"
#define DOWNRIGHT    "&#x250c;"
#define HORIZONTAL   "&#x2500;"
#define HORIZDASH    "&#x254c;"
#define HORIZDOWN    "&#x252c;"
#define HORIZUP      "&#x2534;"
#define HORIZVERT    "&#x253c;"
#define UPLEFT       "&#x2518;"
#define UPRIGHT      "&#x2514;"
#define VERTICAL     "&#x2502;"
#define VERTDASH     "&#x254e;"
#define VERTLEFT     "&#x2524;"
#define VERTRIGHT    "&#x251c;"
#define HUH          "&#x2e2e;"

extern int  dbug, isCgi, isCgiPlus;

extern char  CopyrightDate [],
             DefaultType [],
             SoftwareID [],
             Utility [];

#define ISRES(c) ((c == '-') || (c == '|') || (c == '+') || (c == '<') || \
                  (c == '>') || (c == '^') || (c == '#') || (c == ':') || \
                  (c == '.') || (c == '*') || (c == '\\') || \
                  (c == '{') || (c == '}'))

#define NOTRES(c) (!ISRES(c))

/*****************************************************************************/
/*
Draw the diagram and insert it into the document.
*/

int drawThis (struct wasdoc_st *docptr)
{
   char  ch;
   char  *cptr, *tptr, *tzptr;

   TGET (docptr, tptr);

   if (*tptr == '|') tptr++;
   if (*tptr == '\n') tptr++;
   if (dbug>1) dbugThis (FI_LI, "drawThis() %s", dbugMax(tptr));
   for (cptr = tptr; *cptr; cptr++)
   {
     if (*cptr != '|') continue;
     if (MATCH7 (cptr, "|!draw|")) break;
     /* if suspiciously like a wasDOC heading */
     if (isdigit(cptr[1]) && isalpha(cptr[2])) break;
   }
   if (!MATCH7 (cptr, "|!draw|")) return (EINVAL);
   tzptr = cptr;

   wasDocAsIs (docptr, "\n");

   if (!docptr->drawStyle)
   {
      /* should only need this the once */
      wasDocAsIs (docptr, drawStyle());
      docptr->drawStyle = 1;
   }

   if (tptr < tzptr)
   {
      if (MATCH6(tptr,"<style"))
      {
         cptr = tptr;
         while (tptr < tzptr && !MATCH8(tptr,"</style>")) tptr++;
         if (tptr < tzptr) tptr += 8;
         while (tptr < tzptr && *tptr != '\n') tptr++;
         if (tptr < tzptr) tptr++;
         if (tptr < tzptr)
         {
            ch = *tptr;
            *tptr = '\0';
            if (dbug>1) dbugThis (FI_LI, "prologue %s", dbugMax(cptr));
            wasDocAsIs (docptr, cptr);
            *tptr = ch;
         }
         /* unless an explicit style */
         docptr->drawStyle = 0;
      }
   }
   if (tptr >= tzptr) return (EINVAL);

   if (dbug>1) dbugThis (FI_LI, "diagram %s", dbugMax(tptr));
   cptr = drawDiagram (tptr, tzptr - tptr);
   wasDocAsIs (docptr, cptr);
   free (cptr);

   tzptr += 7;
   TPUT (docptr, tzptr);

   return (0);
}

/*****************************************************************************/
/*
Draw a diagram that is contained in an external file.
*/

void drawAdHoc (char *fname)

{
   int  alen;
   char  *aptr, *cptr, *sptr;

   cptr = drawReadFile (fname);
   if (MATCH4(cptr,"\0\0\0\0") && isalpha(cptr[4]))
   {
      CgiLibResponseHeader (404, "text/plain");
      fputs (cptr+4, stdout);
      fputc ('\n', stdout);
      free (cptr);
      return;
   }

   if (!MATCH6 (cptr, "|draw|"))
   {
      CgiLibResponseHeader (404, "text/plain");
      fputs ("cannot draw from this file\n", stdout);
      free (cptr);
      return;
   }

   aptr = "";
   alen = 0;
   for (cptr += 6; *cptr && isspace(*cptr) && *cptr != '\n'; cptr++);
   if (*cptr == '\n') cptr++;
   if (*cptr)
   {
      if (MATCH6(cptr,"<style"))
      {
         aptr = cptr;
         while (*cptr && !MATCH8(cptr,"</style>")) cptr++;
         if (*cptr) cptr += 8;
         while (*cptr && *cptr != '\n') cptr++;
         if (*cptr) cptr++;
         alen = cptr - aptr;
      }
   }
   for (sptr = cptr; *sptr && !MATCH7(sptr,"|!draw|"); sptr++);
   *sptr = '\0';

   sptr = drawDiagram (cptr, sptr - cptr);

   CgiLibResponseHeader (200, "text/html");
   fprintf (stdout, "%s%*.*s<div class=\"dfont drawing\">%s</div>\n",
            drawStyle(), alen, alen, aptr, sptr);

   free (sptr);
}

/*****************************************************************************/
/*
Return a pointer to the HTML-ised diagram.
*/

char* drawDiagram (char* diagram, int dlength)

{
   int  hsize,
        rescount;
   char  cabove, cbelow, cleft, cright;
   char  *cptr, *dptr, *dzptr, *sptr, *zptr,
         *hiagram;

   if (dlength < 0) dlength = strlen(diagram);
   dzptr = (dptr = diagram) + dlength;

   rescount = 0;
   for (cptr = dptr; *cptr; cptr++)
      if (ISRES(*cptr) || isspace(*cptr)) rescount++;
   hiagram = calloc (1, hsize = (dlength - rescount + (rescount * 8)));
   if (!hiagram) exit (vaxc$errno);
   zptr = (sptr = hiagram) + hsize;

   while (dptr < dzptr)
   {
      while (dptr < dzptr && NOTRES(*dptr) && !isspace(*dptr))
         *sptr++ = *dptr++;
      if (dptr >= dzptr) break;

      if (*dptr == '\n')
      {
         dptr++;
         cptr = "<br>\n";
      }
      else
      if (*dptr == '{')
      {
         /* escaped sequence */
         dptr++;
         while (dptr < dzptr && *dptr != '}' && sptr < zptr)
         {
            if (*dptr == '\\' && *(dptr+1) == '}') dptr++;
            *sptr++ = *dptr++;
         }
         if (dptr < dzptr) dptr++;
      }
      else
      if (isspace(*dptr))
      {
         dptr++;
         cptr = "&nbsp;";
      }
      else
      if (*dptr == '\\')
      {
         dptr++;
         if (*dptr && sptr < zptr) *sptr++ = *dptr++;
         cptr = NULL;
      }
      else
      if (*dptr == '-')
      {
         dptr++;
         cptr = HORIZONTAL;
      }
      else
      if (*dptr == '|')
      {
         dptr++;
         cptr = VERTICAL;
      }
      else
      if (*dptr == ':')
      {
         dptr++;
         cptr = VERTDASH;
      }
      else
      if (*dptr == '.')
      {
         dptr++;
         cptr = HORIZDASH;
      }
      else
      if (*dptr == '<')
      {
         dptr++;
         cptr = ARROW_LEFT;
      }
      else
      if (*dptr == '>')
      {
         dptr++;
         cptr = ARROW_RIGHT;
      }
      else
      if (*dptr == '^')
      {
         dptr++;
         cptr = ARROW_UP;
      }
      else
      if (*dptr == '#')
      {
         dptr++;
         cptr = ARROW_DOWN;
      }
      else
      if (*dptr == '*')
      {
         dptr++;
         cptr = CIRCLE;
      }
      else
      if (*dptr == '+')
      {
         /* now it gets interesting */
         cabove = cbelow = cleft = cright = 0;
         if (dptr > diagram) cleft = *(dptr-1);
         if (dptr < dzptr-1) cright = *(dptr+1);
         cabove = drawCharAbove (diagram, dzptr, dptr);
         cbelow = drawCharBelow (diagram, dzptr, dptr);

         if (cleft == '-' && cright == '-')
         {
            if ((cabove == '|' || cabove == ':' || cabove == '+') &&
                (cbelow == '|' || cbelow == ':' || cbelow == '+'))
               cptr = HORIZVERT;
            else
            if (cabove == '|' || cabove == ':' || cabove == '+')
               cptr = HORIZUP;
            else
            if (cbelow == '|' || cbelow == ':' || cbelow == '+')
               cptr = HORIZDOWN;
            else
               cptr = HUH;
         }
         else
         if (cleft == '-' || cleft == '.')
         {
            if ((cabove == '|' || cabove == ':' || cabove == '+') &&
                (cbelow == '|' || cbelow == ':' || cbelow == '+'))
               cptr = VERTLEFT;
            else
            if (cabove == '|' || cabove == ':' || cabove == '+')
               cptr = UPLEFT;
            else
            if (cbelow == '|' || cbelow == ':' || cbelow == '+')
               cptr = DOWNLEFT;
            else
               cptr = HUH;
         }
         else
         if (cright == '-' || cright == '.')
         {
            if ((cabove == '|' || cabove == ':' || cabove == '+') &&
                (cbelow == '|' || cbelow == ':' || cbelow == '+'))
               cptr = VERTRIGHT;
            else
            if (cabove == '|' || cabove == ':' || cabove == '+')
               cptr = UPRIGHT;
            else
            if (cbelow == '|' || cbelow == ':' || cbelow == '+')
               cptr = DOWNRIGHT;
            else
               cptr = HUH;
         }
         else
            cptr = HUH;
         dptr++;
      }
      else
      {
         if (sptr < zptr) *sptr++ = *dptr;
         dptr++;
      }

      if (cptr) while (*cptr && sptr < zptr) *sptr++ = *cptr++;
   }

   return (hiagram);
}

/*****************************************************************************/
/*
Return the character in the line above.  Go back to the start of the previous
line.  Then count from there to the same location as the supplied character
pointer.  Return that character, or 0 if none above.
*/

char drawCharAbove
(
char *diagram,
char *dzptr,
char *here
)
{
   char  *cptr, *hptr;

   /* back to the end of the previous line */
   for (cptr = here; cptr > diagram && *cptr != '\n'; cptr--);
   if (cptr <= diagram) return (0);
   cptr--;
   /* then to the beginning of that previous line */
   while (cptr > diagram && *cptr != '\n') cptr--;
   if (cptr > diagram) cptr++;
   /* go to the beginning of the current line */
   for (hptr = here; hptr > diagram && *hptr != '\n'; hptr--);
   if (hptr > diagram) hptr++;
   /* then move down the number of chars to |here| */
   while (hptr < here)
   {
      if (*hptr == '{')
      {
         /* escaped sequence */
         while (hptr < dzptr && *hptr != '}' && *hptr != '\n')
         {
            if (*hptr == '\\' && *(hptr+1) == '}') hptr++;
            hptr++;
         }
         if (hptr < dzptr && *hptr == '}') hptr++;
         continue;
      }
      if (*cptr == '{')
      {
         /* escaped sequence */
         while (cptr < dzptr && *cptr != '}' && *cptr != '\n')
         {
            if (*cptr == '\\' && *(cptr+1) == '}') cptr++;
            cptr++;
         }
         if (cptr < dzptr && *cptr == '}') cptr++;
         continue;
      }
      if (*hptr == '\\')
      {
         /* escaped character */
         hptr++;
         if (hptr < dzptr) hptr++;
      }
      else
         hptr++;
      if (*cptr == '\\')
      {
         /* escaped character */
         cptr += 2;
      }
      else
         cptr++;
      /* if previous line has fewer characters then none below */
      if (*cptr == '\n') return (0);
   }
   if (*cptr == '\n') return (0);
   return (*cptr);
}

/*****************************************************************************/
/*
Return the character in the line below.  Go to the start of the next line.
Then count from there to the same location as the supplied character pointer.
Return that character, or 0 if none below.
*/

char drawCharBelow
(
char *diagram,
char *dzptr,
char *here
)
{
   char  *cptr, *hptr;

   /* to the beginning of the next line */
   for (cptr = here; cptr < dzptr && *cptr != '\n'; cptr++);
   if (cptr < dzptr) cptr++;
   if (cptr >= dzptr) return (0);
   /* go to the beginning of the current line */
   for (hptr = here; hptr > diagram && *hptr != '\n'; hptr--);
   if (hptr > diagram) hptr++;
   /* then move down the number of chars to |here| */
   while (hptr < here)
   {
      if (*hptr == '{')
      {
         /* escaped sequence */
         while (hptr < dzptr && *hptr != '}' && *hptr != '\n')
         {
            if (*hptr == '\\' && *(hptr+1) == '}') hptr++;
            hptr++;
         }
         if (hptr < dzptr && *hptr == '}') hptr++;
         continue;
      }
      if (*cptr == '{')
      {
         /* escaped sequence */
         while (cptr < dzptr && *cptr != '}' && *cptr != '\n')
         {
            if (*cptr == '\\' && *(cptr+1) == '}') cptr++;
            cptr++;
         }
         if (cptr < dzptr && *cptr == '}') cptr++;
         continue;
      }
      if (*hptr == '\\')
      {
         /* escaped character */
         hptr++;
         if (hptr < dzptr) hptr++;
      }
      else
         hptr++;
      if (*cptr == '\\')
      {
         /* escaped character */
         cptr++;
         if (cptr < dzptr) cptr++;
      }
      else
         cptr++;
      /* if next line has fewer characters then none below */
      if (cptr >= dzptr || *cptr == '\n') return (0);
   }
   if (*cptr == '\n') return (0);
   return (*cptr);
}

/*****************************************************************************/
/*
Styling for drawing.  The .dnoflip seems necessary to retain comparitive sizes
on some platforms.  A document can change font (and everything else) by
prologue "<style>.drawing { ... }</style>" (though these seem to work well
across many platforms.
*/

char* drawStyle ()

{
   static char styling[] = "\
<style>\n\
.dhflip { display:inline-block;transform:rotate(180deg); }\n\
.dvflip { display:inline-block;transform:rotate(-180deg); }\n\
.dnoflip { display:inline-block;transform:rotate(360deg); }\n\
.dfont { font-family:monospace;font-size:1em;line-height:0.9em;\
line-spacing:0em; }\n\
</style>\n";

   return (styling);
}

/*****************************************************************************/
/*
Read a file external to a WASDOC proper.
Return a string which must bee free()ed.
Error returned as string with two leading and two trailing null characters.
*/

char* drawReadFile (char *fname)

{
   int  bytes, errnum;
   char  *aptr, *cptr, *sptr;
   FILE  *ifptr;
   stat_t  fstatbuf;

   if (ifptr = fopen (fname, "r"))
      fstat (fileno(ifptr), &fstatbuf);

   if (errnum = vaxc$errno)
   {
      bytes = strlen (cptr = strerror(errnum));
      if (!(aptr = calloc (1, bytes+16))) exit (vaxc$errno);
      sprintf (aptr, "%c%c%c%c%s", 0, 0, 0, 0, cptr);
      return (aptr);
   }

   bytes = fstatbuf.st_size + 32;
   aptr = sptr = calloc (1, bytes);
   if (!aptr) exit (vaxc$errno);

   /* read the entire file into memory */
   while (fgets (sptr, bytes-(sptr-aptr), ifptr))
      while (*sptr) sptr++;

   fclose (ifptr);

   return (aptr);
}

/*****************************************************************************/
/*
*/

#if 0
char* drawDebugLine (char *line)

{
   static char  buf [256];
   char  *cptr, *sptr;
   sptr = buf;
   for (cptr = line; *cptr && *cptr != '\n'; *sptr++ = *cptr++);
   *sptr = '\0';
   return (buf);
}
#endif

/*****************************************************************************/