home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 November / PCONLINE_11_99.ISO / filesbbs / OS2 / APCHSSL2.ZIP / OS2HTTPD / public / cgi-bin / gif_text.cmd < prev    next >
Encoding:
Text File  |  1998-12-12  |  76.9 KB  |  2,423 lines

  1. /* 04 dec 1997.   SRE-http utility and generic CGI-BIN script:
  2. GIF_TEXT: create a gif file containing a message, using an
  3.           "alphabyte" collection of character files.
  4.  
  5. This program will work as a:
  6.  1)"native" SRE-http add-on,
  7.  2) as a generic CGI-BIN script
  8.  3) a stand/alone program
  9. ...it will automatically detect how it's being called.
  10.  
  11. NOTE: You MUST set the GIF_DIR_ROOT parameter below (other parameters are
  12.       optional).
  13.  
  14. ************************************************************************/
  15.  
  16. signal on error name wow1 ; signal on syntax name wow1 ;
  17.  
  18.  
  19. /******************************************************
  20.   ***********BEGIN USER CHANGABLE PARAMETERS ******************************
  21.   ***********BEGIN USER CHANGABLE PARAMETERS ******************************
  22.   ***********BEGIN USER CHANGABLE PARAMETERS ******************************/
  23.  
  24. /*-                   --------------------
  25.                     User changeable parameters
  26.  
  27. The user changeable parameters are:
  28.  
  29. GIF_DIR_ROOT : The "root" directory of the "alphabytes".
  30.  
  31.          !!!!  YOU MUST SET GIF_DIR_ROOT WHEN YOU INSTALL GIF_TEXT  !!!!!
  32.                 All the other parameters can be left unchanged with
  33.                 minimal deteriment, but GIF_TEXT will not work
  34.                 if GIF_DIR_ROOT is not properly set.
  35.  
  36. SEND_PIECES: Try to send early versions of the image, as they become available
  37. DEFAULT_FONT : The default "alphabyte font" (actually, it's directory)
  38. FONT_NAME : Name (prefix) used to match characters to .GIF files
  39. FONT_INDEX : Index file with "alphabyte specific" configuration information
  40. CACHE_SIZE : The maximum number of images to "cache"
  41. CACHE_DURATION : Maximum duration of cached images
  42. HEIGHT : Default height of the created image
  43. WIDTH : Default width of the created image
  44. X_FRAME: Width of frame, in pixels (left and right)
  45. Y_FRAME: Height of frame, in pixels (top and bottom)
  46. TIME_FMT : Default format to use when display current time
  47. DATE_FMT : Default format to use when displaying current date
  48. DEF_BACKCOLOR= Default backcolor
  49. DEF_TEXTCOLOR= Default textcolor (used when no character .GIF file is available)
  50. DEF_TRANSPARENT = Default transparent color index
  51. DEF_TEXTSIZE = Default size of default text characters
  52.  
  53. *  You MUST set the GIF_DIR_ROOT parameter
  54. *  The SEND_PIECES parameter is useful if you are using SRE-http, and 
  55.     large/complicated images are likely
  56.     to be created (which may require the client to wait a minute or more). 
  57. *  You should, but do not need to, set the TIME_FMT, DATE_FMT, and FONT_DIR
  58.    parameters.
  59. *  You should probably set HEIGHT=0 and WIDTH=0.
  60. *  You should probably set FONT_NAME=' ' and FONT_INDEX=' '
  61. *  The DEF_BACKCOLOR, and DEF_TEXTCOLOR are usually
  62.    overridden by "alphabyte" specific values,so you probably
  63.    don't need to worry about them.
  64. *  The DEF_TEXTSIZE is  rarely used (only if there are NO matching characters)!
  65. *  The DEF_TRANSPARENT should almost always equal 0
  66.  
  67. *  CACHE_SIZE=100 and CACHE_DURATION=1 are reasonable values; but if you
  68.    want to avoid clutter, set CACHE_SIZE=0 (in which case, the 
  69.    CACHE option is ignored)
  70.  
  71.  
  72.                                 -----------------
  73. -*/
  74. /*  !!!! You MUST set the GIF_DIR_ROOT parameter !!!! */
  75. /* The "base directory" of the alphabytes (the collection of character gifs) */
  76. /* if no drive is specified, the default drive (i.e.; the goserve working
  77. directory) will be used */
  78. gif_dir_root='\os2httpd\alphabyt'
  79.  
  80. /* Attempt to send "pieces" (actually, less detailed versions) of the image as it becomes
  81.    available (only works with browsers that recognize connection:keep-alive). 
  82.    1=yes, 0=no
  83.    Send_pieces will ONLY work if GIF_TEXT is called as an SRE-http addon*/
  84. send_pieces=1
  85.  
  86.  
  87. /* Default font directory (relative to gif_dir_root) */
  88. DEFAULT_FONT='enviro'
  89.  
  90. /* default font name.If ' ', use "font_dir own name". This should NOT
  91.    include directory information */
  92. font_name=' '
  93.  
  94. /* default "index file" (in font_dir) -- contains alphabyte specific
  95.    configuration information. If ' ', usein font_name.ind.
  96.    This should NOT contain subdirectory information. */
  97. font_index=' '
  98.  
  99. /* the maximum number of images to cache. 0 means "disable caching of images"*/
  100. cache_size=100
  101.  
  102. /* the maximum lifespan of an image cache file. 0 means "disable caching".
  103.    (measured in days, no fractions allowed). */
  104. cache_duration=1
  105.  
  106. /* default height in pixels (0= as big as needed) */
  107. height=0
  108. /* default width in pixels (0=as big as needed) */
  109. width=0
  110.  
  111. /* default size of frame, left and right */
  112. x_frame=0
  113.  
  114. /* default size of frame, top and bottom */
  115. y_frame=0
  116.  
  117. /* time format (using REXX TIME('x') syntax); eg; N= 15:32:01*/
  118. time_fmt='N'
  119. /*date format (using REXX DATE('x') syntax ); eg; N=16 Jun 1997 */
  120. date_fmt='N'
  121.  
  122. /* Set the default RGB intensities for the background (color table #0)
  123.    Use a 6-hex-character (00 to ff); with 000000=black and ffffff=white.
  124.    This may be overridden by the font-index file, or by an option  */
  125. def_backcolor=b0b0b0
  126.  
  127.  
  128. /* set values to use for characters when a .gif file can not be found 
  129.    This may be overridden by the font-index file, or by an option */
  130. def_textcolor=ffffff
  131.  
  132. /* size of text, in pixel, if NO gifs found */
  133. def_text_size =15
  134.  
  135. /* set the "transparent color index" -- use a value between 0 and 255.
  136.   If you do NOT want a transparent color index, use -1. */
  137. def_transparent=0
  138.  
  139. /* verbose level (only used if called as cgi-bin script:
  140.   0=none, 1=minimal, 2=more
  141.  If called as SRE-http addon, then SRE-http's VERBOSE variable is used */
  142. def_verbose=2
  143.  
  144. /* background scaling: 1 for yes, 0 for use tiles */
  145. back_scale=0
  146.  
  147.  
  148. /********** END of USER CHANGABLE PARAMETERS *********/
  149. /********** END of USER CHANGABLE PARAMETERS *********/
  150. /********** END of USER CHANGABLE PARAMETERS *********/
  151.  
  152. foo=rxfuncquery('rxgdloadfuncs')
  153. if foo=1 then do
  154.   Call RxFuncAdd 'RxgdLoadFuncs', 'RXGDUTIL', 'RxgdLoadFuncs'
  155.   Call RxgdLoadFuncs
  156. end
  157. /* Load up advanced REXX functions */
  158. foo=rxfuncquery('sysloadfuncs')
  159. if foo=1 then do
  160.   call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  161.   call SysLoadFuncs
  162. end
  163. if datatype(CACHE_SIZE)<>'NUM'  then cache_size=0
  164. if datatype(CACHE_DURATION)<>'NUM'  then cache_size=0
  165. if datatype(DEF_VERBOSE)<>'NUM'  then def_verbose=1
  166. if datatype(back_scale)<>'NUM'  then back_scale=0
  167.  
  168. if cache_size<1  then cache_size=0
  169. if cache_duration<1 then cache_size=0
  170.  
  171. sqs.!got=rxfuncquery('SQRT')  /* is there a sqrt function available */
  172.  
  173. send_delay=12           /* time to wait before SENDing a piece */
  174.  
  175. if filespec('D',gif_dir_root)=' ' then do
  176.      oof=directory()
  177.      arf=filespec('d',oof)
  178.      gif_dir_root=arf||gif_dir_root
  179. end  /* Do */
  180. if gif_dir_root=' ' then
  181.     gif_dir_root=strip(basedir,'t','\')||'\alphabyt'
  182.  
  183. gif_dir_root=strip(gif_dir_root,'t','\')||'\'
  184.  
  185. parse arg  ddir, tempfile, reqstrg,list,verb ,uri,user, ,
  186.           basedir ,workdir,privset,enmadd,transaction,verbose, ,
  187.          servername,host_nickname,homedir
  188.  
  189. a_box=d2c(254)
  190. if verbose="" then verbose=def_verbose
  191.  
  192. /* check for CGI-BIN call */
  193. is_cgi=0
  194. if verb="" then do    /* is it cgi-bin? */
  195.    method = value("REQUEST_METHOD",,'os2environment')
  196.    if method="" then do
  197.        list=ask_values()
  198.        if list="" then exit
  199.        is_cgi=2         /* signals "stand alone */
  200.        verbose=2
  201.    end /* do */
  202.    else do
  203.       is_cgi=1
  204.       if method='GET' then do
  205.           list=value("QUERY_STRING",,'os2environment')
  206.       end
  207.       else do
  208.          tlen = value("CONTENT_LENGTH",,'os2environment')
  209.          list=charin(,,tlen)
  210.       end /* do */
  211.       verbose=def_verbose
  212.    end
  213. end
  214.  
  215. if is_cgi=0 then do
  216.   if  verb="GET" then    parse var uri . '?' list   /* if srefilter addon, get purer version of request string */
  217. end
  218.  
  219. aa=sysfiletree(gif_dir_root||'*.*','arf','b')
  220. if arf.0=0 then do
  221.    call gpmprintf(" GIF_TEXT: GIF_DIR_ROOT is empty or missing: "gif_dir_root)
  222.    if is_cgi=1 then
  223.         return
  224.    return 0
  225. end /* do */
  226.  
  227.  
  228. /*  request options understood:
  229.    FONT_DIR, SEND, FONT_NAME, FONT_INDEX, TIME_FMT, DATE_FMT, BACKCOLOR,
  230.    TEXTCOLOR, TRANSPARENT, WIDTH, HEIGHT, LITERAL,X_FRAME,y_FRAME 
  231.     X_SCALES Y_SCALES V_ALIGN LINE_JA
  232.     SLIDE SLIDE_VERT SLIDE_HORIZ SLIDE_THRESH SLIDE_PROB
  233.     SLIDE_COORD SLIDE_SIZE SLIDE_RED SLIDE_GREEN SLIDE_BLUE SPECIAL
  234.  */
  235.  
  236. /* set to blank means "use font_index value if none specified in request */
  237. send_bim=0
  238. back_file=' ' ; text=' '
  239. amessage=' ' ; cache_file=' ';  do_cache=0
  240. backcolor=' ' ; textcolor=' ' ; transparent=""
  241. fontdir=default_font; fontname=font_name ; fontindex=font_index
  242. many_type=0 ; many_type_max=0
  243. x_scales="" ;y_scales="" ; y_valign="" ; slide="" ;  slide_vert="" ; 
  244. slide_thresh=' ' ; slide_horiz=''
  245. slide_red="" ; slide_green="" ;slide_blue=""
  246. slide_size=""
  247. slide_coord=""
  248. slide_xcoord="" ; slide_ycoord="" ; slide_prob=''
  249. special=''
  250. linealign='L'
  251.  
  252. /* pull options from request */
  253. literal=0 ;
  254.  do until list=""                /* get user input */
  255.    parse var list a1 '&' list
  256.    parse var a1 a1a '=' a1b0
  257.    a1a=translate(strip(a1a))
  258.    a1b1=packur2(a1b0)
  259.    a1b=strip(translate(a1b1))
  260.    select
  261.       when a1a="FONT_DIR" | a1a="FONT" then do
  262.           if a1b<>' ' then fontdir=a1b
  263.       end  /* Do */
  264.       when a1a="FONT_NAME" | a1a="NAME" then do
  265.            if a1b<>' ' then fontname=a1b
  266.       end
  267.       when a1a="FONT_INDEX" | a1a="INDEX" then do
  268.             if a1b<>' ' then fontindex=a1b
  269.       end  /* Do */
  270.       when abbrev(a1a,'TIME')=1 then time_fmt=a1b
  271.       when abbrev(a1a,'CACHE')=1 then do
  272.                 cache_file=strip(a1b)
  273.                 do_cache=1
  274.                 if a1a='CACHE2' then do_cache=2
  275.       end  /* Do */
  276.       when abbrev(a1a,'DATE')=1 then date_fmt=a1b
  277.       when abbrev(a1a,"TEXTC")=1 then textcolor=a1b
  278.       when abbrev(a1a,"BACKG")+abbrev(a1a,"BACKC")>0 then backcolor=a1b
  279.       when abbrev(a1a,"TRANS")=1 then do
  280.          if datatype(a1b)='NUM' then transparent=a1b
  281.       end
  282.       when a1a="WIDTH" | a1a="W" then width=a1b
  283.       when abbrev(a1a,'SPECIAL')=1 then special=special' 'a1b
  284.       when a1a="SEND" then send_pieces=a1b
  285.       when abbrev(a1a,'MANY_')=1 then do
  286.           if datatype(a1b)='NUM' then
  287.                many_type_max=a1b
  288.           else
  289.                many_type=wordpos(translate(a1b),'CYCLE FIT END RANDOM')
  290.       end /* do */
  291.       when abbrev(a1a,"X_F")=1 then do
  292.            if datatype(a1b)='NUM' then x_frame=a1b
  293.       end
  294.       when abbrev(a1a,"Y_F")=1 then 
  295.           if datatype(a1b)='NUM' then y_Frame=a1b
  296.  
  297.       when a1a="HEIGHT" | a1a="H" then height=a1b
  298.       when abbrev(a1a,"LIT")=1 then literal=a1b
  299.       when a1a="BACK" | a1a="BACK_FILE" then back_file=a1b
  300.       when a1a="BACK_SCALE" | a1a="BKSC" then back_scale=wordpos(translate(a1b),'Y YES 1')
  301.       when abbrev(a1a,'X_SC')+abbrev(a1a,'XSCA')>0 then x_scales=a1b
  302.       when abbrev(a1a,'Y_SC')+abbrev(a1a,'YSCA')>0 then y_scales=a1b
  303.       when abbrev(a1a,'VALI')+abbrev(a1a,'V_ALI') + abbrev(a1a,'Y_VAL')+ abbrev(a1a,'YVAL')>0 then y_valign=a1b
  304.       when abbrev(a1a,'SLIDE_H')=1  then slide_horiz=a1b
  305.       when abbrev(a1a,'SLIDE_T')=1  then slide_thresh=a1b
  306.       when abbrev(a1a,'SLIDE_V')=1  then slide_vert=a1b
  307.       when abbrev(a1a,'SLIDE_F')=1 | a1a='SLIDE'  then  do
  308.           ee=translate(a1b,'\','/')
  309.           ee=strip(a1b,'l','\')
  310.           slide=gif_dir_root||ee
  311.       end
  312.       when abbrev(a1a,'SLIDE_S')=1  then do
  313.           if datatype(a1b)='NUM'  then slide_size=a1b
  314.       end  /* Do */
  315.       when abbrev(a1a,'SLIDE_C')=1  then slide_coord=a1b
  316.       when abbrev(a1a,'JUST')=1 | abbrev(a1a,'LINE_J')=1 then line_just=translate(left(a1b,1))
  317.       when abbrev(a1a,'SLIDE_R')=1  then slide_red=a1b
  318.       when abbrev(a1a,'SLIDE_G')=1  then slide_green=a1b
  319.       when abbrev(a1a,'SLIDE_B')=1  then slide_blue=a1b
  320.       when abbrev(a1a,'SLIDE_P')=1  then slide_prob=a1b
  321.  
  322.       when a1a="MESSAGE" | a1a="TEXT" then do
  323.          a1b0=strip(a1b0,,'"')
  324.          amessage=packur2(a1b0)
  325.       end
  326.       otherwise nop
  327.    end  /* select */
  328. end /* do */
  329. if amessage="" then amessage=' '
  330.  
  331. if verbose>1 then call gpmprintf(' GIF_TEXT font= ' fontdir ', message: 'amessage)
  332.  
  333. /* if send_pieces, then see if the browser supports multi part documents (connection:keep-alive) */
  334. if is_cgi=0 & wordPos(translate(send_pieces),'Y YES 1')>0 then do
  335.     a=translate(strip(reqfield('Connection')))
  336.     a2=translate(strip(reqfield('PROXY-Connection')))
  337.     if a<>'KEEP-ALIVE' & a<>'MAINTAIN' , 
  338.        & a2<>'KEEP-ALIVE' & a2<>'MAINTAIN' then do
  339.          send_pieces=0            /* browser does NOT support connection:keep-alive */
  340.          nsent=0
  341.     end                
  342.     else do
  343.         send_pieces=1   /*  it does */
  344.     end /* do */
  345. end
  346. else  do
  347.    send_pieces=0      /* send_Pieces ONLY works as SRE-http addon */
  348. end  /* Do */
  349.  
  350. call fix_defaults               /* set some default parameters */
  351.  
  352. call fix_options                /* using font_index and request stuff, set options */
  353.  
  354. call fix_message                /* fix up message (special code replacmenet */
  355.  
  356. call check_ndims
  357.  
  358. /* DONE WITH INITIALIZATIONS  ----------------------- */
  359.  
  360. /* for each charater in message, get it's gif file (if avaiable), it's
  361.    size, and it's scale factors */
  362. len0 = Length(amessage)          /* amessage is message, after $t, etc modifications */
  363. xmess=0; ymess=0 ; cfound=0
  364. ysize_tot=0 ; xsize_tot=0
  365. l=0; newls=''
  366. do l0 = 1 to len0
  367.  
  368.    achar = substr(amessage,l0,1)
  369.    ichar=c2d(achar)
  370.    if ichar=10 then do          /* newline */
  371.        newls=newls' 'l   /* record position, and drop character */
  372.        iterate
  373.    end /* do */
  374.  
  375.    if ichar=6 then do           /* font switch -- use carefully */
  376.        parse var user_fonts fontname user_fonts
  377.        switchl.l=fontname
  378.        fontindex='';fontdir=fontname 
  379.        call fix_defaults 1              /* set some default parameters */
  380.        call fix_options
  381.        call check_ndims
  382.        iterate
  383.    end /* do */
  384.  
  385.    l=l+1
  386.    switchl.l=''
  387.  
  388.    cls.l=' '              /* the l'th characters GIF file. ''=n.a. */
  389.    cls.!xscale.l=get_user_scale(l,len0,x_scales) /* char specific width scale factor */
  390.    cls.!yscale.l=get_user_scale(l,len0,y_scales) /* char specific height scale factor */
  391.    cls.!xsize.l=0                       /* char width (0=n.a. */
  392.    cls.!ysize.l=0                       /* char height (0=n.a. */
  393.    cls.!char.l=achar
  394.  
  395. /* note: xscale and yscale are image independent (uses character position in
  396.   the message, and the user_scale parameter) */
  397.  
  398.    select
  399.       when ichar=1 | ichar=2 then do    /* am or pm character */
  400.           achar='PM' ; if ichar=1 then achar='AM'
  401.           cl=get_gifname(achar,gif_dir,fontname)  /* may use UC for LC, etc. */
  402.           if cl=' ' then iterate
  403.       end  /* Do */
  404.       when ichar=254 then do            /* filled box characher */
  405.           cls.l=achar 
  406.           iterate
  407.       end /* do */
  408.       when ichar>139 then do            /* special $x character */
  409.          ichar0=ichar-140
  410.          if symbol('FONT_IND.!chars.'||ichar0)<>'VAR' then iterate /* error, skip*/
  411.          cl=gif_dir||font_ind.!chars.ichar0
  412.          if stream(cl,'c','query exists')=' ' then iterate
  413.       end  /* Do */
  414.       otherwise do             /* normal character -- check for file */
  415.          if achar=' ' then iterate
  416.          cl=get_gifname(achar,gif_dir,fontname)
  417.          if cl=' ' then iterate
  418.       end
  419.    end
  420. /* double check -- is it a gif file? */
  421.    im = RxgdImageCreateFromGIF(cl)
  422.    IF (im = 1 | im=0) THEN do
  423.       IF VERBOSE>0 then call gpmprintf("GIF_TEXT bad GIF file: " cl' 'im)
  424.       iterate
  425.    end
  426.  
  427.    cls.l=cl             /* use the CL gif file for this l'th character */
  428.  
  429.    cfound=cfound+1
  430.  
  431.    cls.!xsize.l=RxgdImageSX(im)
  432.    cls.!ysize.l=RxgdImageSY(im)
  433.  
  434.    xsize_tot=xsize_tot+cls.!xsize.l
  435.    ysize_tot=ysize_tot+cls.!ysize.l
  436.  
  437.    Call RxgdImageDestroy im
  438. end
  439.  
  440. len=l   
  441.  
  442. /* Now, use CLS. and newls to determine HEIGHT AND WIDTH OF MESSAGE */
  443. xmess=X_FRAME*2 ; ymess=Y_FRAME*2 ; yf2=ymess  /* frames are absolute sizes */
  444.  
  445. do mm=1 to len          /* note: n.a. characters do not contribute to these calcluations */
  446.     xmess=xmess+trunc(cls.!xsize.mm*cls.!xscale.mm)
  447.     if trunc(yf2+(cls.!yscale.mm*cls.!ysize.mm))>ymess then 
  448.           ymess=yf2+trunc(cls.!yscale.mm*cls.!ysize.mm)
  449. end /* do */
  450.  
  451. /* adjust for spaces and missing chars (assuming 1 line of text)*/
  452. select
  453.   when cfound=0 then do                 /* no characters found */
  454.      ysize0=def_text_size ; xsize0=def_text_size
  455.      IF FONT_IND.!ndims>0 then DO               /* not generic default, use complete font info */
  456.          xSIZE0=FONT_ind.!WCHAR-(font_ind.!leftoffset+font_ind.!rightoffset)  /*correct for discarded offsets */
  457.          Ysize0=FONT_IND.!HCHAR-(font_ind.!topoffset+font_ind.!bottomoffset)
  458.      END
  459.      do mmm=1 to len            /* fill in CLS. (sort of a stupid approach) */
  460.         cls.!xsize.mmm=xsize0
  461.         cls.!ysize.mmm=ysize0
  462.         xmess=xmess+(xsize0*cls.!xscale.mmm)
  463.         ymess=max(ymess,yf2+trunc(ysize0*cls.!yscale.mmm))
  464.      end /* do */
  465.   end  /* Do */
  466.  
  467.   when len=found then nop               /* all characters found */
  468.  
  469.   otherwise do                          /* some characters found */
  470.      xavgsize=trunc(xsize_tot/cfound)    /* average size of found characters */
  471.      yavgsize=trunc(ysize_tot/cfound)
  472.      do mmm=1 to len              /* set values for n.a. characters */
  473.         if (cls.mmm<>'' & cls.mmm<>a_box)  then iterate   /* got values, so skip */
  474.         xmess=xmess+(xavgsize*cls.!xscale.mmm)
  475.         cls.!xsize.mmm=xavgsize
  476.         cls.!ysize.mmm=yavgsize
  477.      end /* do */
  478.   end   /* otherwise */
  479.  
  480. end  /* adjusting size for spaces etc. */
  481.  
  482.  
  483. numlines=1 
  484. /* if multiple lines, refigure xmess and ymess; using cls. info */
  485. if newls<>'' then do
  486.    j1=1 ; ymess=0 ; xmess=0 ; numlines=words(newls)+1
  487.    ymess.0=0
  488.    do mm1=1 to numlines         /*recomputing mess with and height */
  489.       xmess.mm1=0 ;ymess.mm1=0
  490.       if mm1=numlines then
  491.          j2=len
  492.       else
  493.          j2=strip(word(newls,mm1))
  494.       do wr=j1 to j2
  495.          xmess.mm1=xmess.mm1+trunc(cls.!xsize.wr*cls.!xscale.wr)
  496.          if trunc(cls.!yscale.wr*cls.!ysize.wr)>ymess.mm1 then 
  497.              ymess.mm1=trunc(cls.!yscale.wr*cls.!ysize.wr)
  498.       end
  499.       xmess=max(xmess,xmess.mm1)
  500.       ymess=ymess+ymess.mm1+2  /* 2 pixel high line sepeartor */
  501.       j1=j2+1
  502.    end
  503.    ymess.0=ymess
  504.    ymess=ymess+yf2            /* character heights + frame */
  505.    xmess.0=xmess
  506.    xmess=xmess+(2*x_Frame)
  507. end /* do */
  508.  
  509.         
  510.  
  511. /* we now know the total image size (xmess and ymess), and the
  512. size/scale/file for each character in the message (cls.) */
  513.  
  514. /* determine whole  image scale factors, if any */
  515. width_fact=1
  516. height_fact=1
  517. if datatype(width)='NUM' then do   
  518.   if width>0 then do 
  519.       width_fact=(width-(2*x_Frame))/(xmess-(2*X_FRAME))   /* will force xmess into frame corrected width */
  520.       xmess=width
  521.   end  /* Do */
  522. end  /* Do */
  523. if datatype(height)='NUM' then do
  524.   if height>0 then do 
  525.      height_fact=(height-yf2)/(ymess-yf2)
  526.      ymess=height
  527.   end  /* Do */
  528. end 
  529.  
  530. y_useable=ymess-(2*y_frame)  /* height that can be written to */
  531. /* xmess and ymess are the width/height of message (either determined
  532. from message+FRAME, or preset. Width_fact and height_fact will force actual
  533. characters to fit into this rectangle */
  534.  
  535. /* create a message buffer of required, or desired, size */
  536.    messim=rxgdimagecreate(xmess,ymess)
  537.    if messim=1 | messim=0 then do
  538.       if verbose>0 then  call gpmprintf(" could not create new message buffer ")
  539.       if is_cgi=0 then do
  540.          'NODATA'
  541.          return '400 0'
  542.       end
  543.       else do
  544.            return 
  545.       end /* do */
  546.    end  /* Do */
  547.    if slide<>' ' | slide_size>0 then do                /* if color slide, use seperate back file */
  548.          messim_b=rxgdimagecreate(xmess,ymess)
  549.          if messim_b=1 | messim_b=0 then slide=' '
  550.    end
  551.  
  552. /* set background, default text, and transparent colors */
  553.    oy=rxgdimagecolorallocate(messim,red_back,green_back,blue_back)
  554.    if slide<>' ' | slide_size>0 then  oy=rxgdimagecolorallocate(messim_b,red_back,green_back,blue_back)
  555.  
  556.    if transparent >-1  then do
  557.        call rxgdimagecolortransparent messim,transparent
  558.        if slide_size>0 | slide<>' ' then call rxgdimagecolortransparent messim_b,transparent
  559.    end
  560.  
  561. /* fill in the background ? */
  562.  
  563. back_file=strip(translate(back_file,'\','/'),,'\')
  564. bkf0=back_file
  565. bf2=back_file
  566. if back_file<>' ' then back_file=stream(gif_dir_root||back_file,'c','query exists')
  567. if back_file="" & bf2<>"" & pos(".gif",bf2)=0 then
  568.    back_file=stream(gif_dir_root||bF2||'.gif','c','query exists')
  569.  
  570. mmb=messim 
  571. if slide_size>0 | slide<>' ' then mmb=messim_b   /* where to write background */
  572.  
  573. if back_file<>' ' then do
  574.    imb = RxgdImageCreateFromGIF(back_file)
  575.    IF (imb = 1 | imb=0) THEN do
  576.       IF VERBOSE>0 then call gpmprintf("GIF_TEXT bad background GIF file: " back_file' 'imb)
  577.       back_file=' '  
  578.    end
  579.    else do              /* write scaled, or tiled/portion */
  580.        if back_scale>0 then do     /* scale image to fit into box */
  581.           srcw=RxgdImageSX(imb)
  582.           srch=RxgdImageSY(imb)
  583.           foo=rxgdimagecopyresized(mmb,imb,0,0,0,0,xmess,ymess,srcw,srch)
  584.        end  /* Do */
  585.        else do
  586.           new1=rxgdimagesettile(mmb,imb)
  587.           h1=trunc(xmess/2)+1  ; w1=trunc(ymess/2)+1
  588.           fpp=rxgdimagefill(mmb,h1,w1,new1)  /* fill with multi-pixel color */
  589.        end  /* Do */
  590.    end  /* Do */
  591.    oy=rxgdimagecolorstotal(mmb) 
  592.    if verbose>1 then call gpmprintf(' GIF_TEXT: # of colors in background ('bkf0') = ' oy)
  593. end
  594.  
  595. /* background is done; should it be sent as a preliminary version? */
  596. if send_pieces=1 then do
  597.    oof=img_to_var(mmb,tempfile,1)   /* copy image handle to var; signal errdone if problem */
  598.    fexp=value(enmadd||'FIX_EXPIRE',,'os2environment')
  599.    foo=sref_multi_send(oof,'image/gif','S',,verbose,fexp)
  600.    if foo<0  then signal errdone
  601.    send_bim=rxgdimagecreatefromgif(tempfile)
  602.    foo=sysfiledelete(tempfile)
  603.    nsent=1
  604.   if verbose>1 then call gpmprintf(' GIF_TEXT: SENDing background ')
  605. end /* do */
  606.  
  607. /* Now copy the appripriate alphabet gifs to the message buffer */
  608.  
  609. nowx=x_frame ; online=1
  610. nowy=0
  611. if numlines>1 then do
  612.  if line_just='C' | line_just='R' then do       /* center align */
  613.     f1=(xmess.0-xmess.online)/xmess.0 /* diff twixt max width as fraction */  
  614.     gg=1   
  615.     if line_just='C' then gg=2
  616.     f2=f1*xmess/gg                /* scaled back to actual width */
  617.     nowx=nowx+trunc(f2)
  618.  end /* do */
  619. end                     /* 1st of numlines x correction */
  620.  
  621. do l=1 to len                   /* for each character in "corrected" message */
  622.   if numlines>1 then do
  623.     isl=l-1
  624.     army=wordpos(isl,newls) 
  625.     if army>0 then do           /* new lines, set x and y "line start */
  626.        online=online+1
  627.        nowx=x_frame
  628.        if line_just='C' | line_just='R' then do       /* center align */
  629.           f1=(xmess.0-xmess.online)/xmess.0 /* diff twixt max width as fraction */  
  630.           gg=1   
  631.           if line_just='C' then gg=2
  632.           f2=f1*xmess/gg                /* scaled back to actual width */
  633.           nowx=nowx+trunc(f2)
  634.        end /* do */
  635.        ol1=online-1
  636.        nowy=nowy+trunc((ymess.ol1/ymess.0)*y_useable)
  637.     end /* do */
  638.   end
  639.   achar=cls.!char.l ; fromdef=0  /* fromdef: 0=own.gif, 1=complete font, 2= generic */
  640.   uul=l-1
  641.   if switchl.uul<>' ' & uul>0 then do  
  642.        fontname=switchl.uul
  643.        fontindex='';fontdir=fontname 
  644.        call fix_defaults 1              /* set some default parameters */
  645.        call fix_options
  646.        call check_ndims
  647.    end
  648.  
  649.   if achar=' '  then do          /* a space: skip pixels in image  */
  650.       nowx=nowx+trunc(width_fact*cls.!xscale.l*cls.!xsize.l)
  651.       iterate
  652.   end
  653.  
  654.   if achar=a_box then do                        /* filled box,  treat as a special "default" character */
  655.       im=rxgdimagecreate(16,16)
  656.       oy=rxgdimagecolorallocate(im,red_back,green_back,blue_back)
  657.       text_color=rxgdimagecolorallocate(im,red_text,green_text,blue_text)
  658.       foo=rxgdimagefilledrectangle(im,0,0,15,15,1)
  659.       xsize=16 ; ysize=16
  660.       fromdef=2
  661.       xsc1=cls.!xsize.l/xsize
  662.       ysc1=cls.!ysize.l/ysize
  663.       cls.!xscale.l=cls.!xscale.l*xsc1
  664.       cls.!yscale.l=cls.!yscale.l*ysc1
  665.       cls.!xsize.l=xsize
  666.       cls.!ysize.l=ysize
  667.   end
  668.  
  669.   else do                       /* a character */
  670.      cl=cls.l
  671.      if cl=' ' then     /* n.a. character */
  672.          im=1               /* signal "n.a." .gif file */
  673.      else
  674.         im = RxgdImageCreateFromGIF(cl)
  675.   end
  676.  
  677.   ichar=c2d(achar)              /* might be speial character */
  678.  
  679. /*  if no such file, use generic or complete font */
  680.   select
  681.  
  682.      when im<=1 & (ichar<10 | ichar>139) & (ichar<>254) then do   /* missing special charcter == use space character */
  683.         nowx=trunc(width_fact*cls.!xscale.l*cls.!xsize.l)+nowx
  684.         iterate
  685.      end  /* Do */
  686.  
  687.      when im <= 1  THEN   do       /* missing, use generic or DEFAULT font */
  688.         uul=l-1
  689.    
  690.         im=get_default_char(achar,l,len,many_type_max)   /* alphabyte specific default? */
  691.  
  692.         if im<>1 then do    /* got an image containing the font */
  693.           if  verbose>1 then call gpmprintf(' GIF_TEXT: using alphabyte specific default for character ' achar)
  694.           xsize=RxgdImageSX(im)      /* complete font (useable) size */
  695.           ysize=RxgdImageSY(im)  
  696.           fromdef=1
  697.         end
  698.  
  699.         else do         /* no complete font -- use generic default */
  700.           if  verbose>1 then call gpmprintf(' GIF_TEXT: using default for character ' achar)
  701.           im=rxgdimagecreate(16,16)
  702.           oy=rxgdimagecolorallocate(im,red_back,green_back,blue_back)
  703.           text_color=rxgdimagecolorallocate(im,red_text,green_text,blue_text)
  704.           foo=rxgdimagestring(im,'G',0,0,achar,text_color)
  705.           xsize=16 ; ysize=16
  706.           fromdef=2
  707.         end
  708.  
  709. /* scale must scale xsize,ysize to presumed size (cls.!xsize,!ysize);
  710.   and still include character specific scale */
  711.         xsc1=cls.!xsize.l/xsize
  712.         ysc1=cls.!ysize.l/ysize
  713.         cls.!xscale.l=cls.!xscale.l*xsc1
  714.         cls.!yscale.l=cls.!yscale.l*ysc1
  715.         cls.!xsize.l=xsize
  716.         cls.!ysize.l=ysize
  717.      end
  718.  
  719.      otherwise  do               /* use matching .gif file */
  720.         xsize=cls.!xsize.l
  721.         ysize=cls.!ysize.l
  722.         fromdef=0
  723.      end
  724.  
  725.   end           /* select */
  726.  
  727. /* copy to message buffer. Rxgd will take care of color table matching, etc */
  728.  
  729. /* fix background & transparency */
  730.   foo=0
  731.   if back_File<>' '& fromdef>0  & transparent>-1 then do
  732.     tt=transparent
  733.     if font_ind.!isbw=0 then do
  734.        tt=rxgdimagecolorclosest(im,dim_r,dim_g,dim_b)
  735.     end
  736.     call rxgdimagecolortransparent im,tt
  737.     foo=tt
  738.   end
  739.   else do
  740.    if back_file<>' ' then foo=rxgdimagegettransparent(im)
  741.   end
  742.   if foo=-1 & back_file<>" " & fromdef=0 then do   /* try to fix transparency */
  743.      call rxgdimagecolortransparent im,font_ind.!transparent
  744.   end
  745.  
  746.  
  747. /* now, write possibly scaled image to messim.  There are two scales:
  748.   character specific scale: a combo of the "generic/default to average"
  749.                             and the "user-specified character specific scale"
  750.   whole message scale: fit message to specified message width/height
  751.   and ... adjust vert and horiz for line and line alignment 
  752. */
  753.  
  754.   wfact=width_fact*cls.!xscale.l
  755.   hfact=height_fact*cls.!yscale.l
  756.   xsize=cls.!xsize.l ; ysize=cls.!ysize.l
  757.   yff=y_frame
  758.   ish=y_useable
  759.   if numlines>1 then ish=trunc((ymess.online/ymess.0)*y_useable)
  760.  
  761.   if wfact=1 &hfact=1 then do
  762.       select
  763.          when y_valign='B' then do
  764.               yff=yff+(ish-ysize)
  765.          end  /* Do */
  766.          when y_valign='M' then do
  767.               yff=y_frame+((ish-ysize)/2)
  768.          end  /* Do */
  769.          otherwise nop
  770.       end  /* select */
  771.       foo=rxgdimagecopy(messim,im,nowx,nowy+yff,0,0,xsize,ysize)
  772.       nowx=nowx+xsize
  773.   end
  774.   else do   /* scale it */
  775.       dxsize=trunc(xsize*wfact)
  776.       dysize=trunc(ysize*hfact)
  777.       ish=y_useable
  778.       if numlines>1 then ish=trunc((ymess.online/ymess.0)*y_useable)
  779.       select
  780.          when   y_valign='T' then yff=y_frame
  781.          when y_valign='B' then do
  782.               yff=y_frame+(ish-dysize)
  783.          end  /* Do */
  784.          when y_valign='M' then do
  785.               yff=y_frame+((ish-dysize)/2)
  786.          end  /* Do */
  787.          otherwise yff=y_frame
  788.       end  /* select */
  789.       foo=rxgdimagecopyresized(messim,im,nowx,nowy+yff,0,0, ,
  790.                                dxsize,dysize,xsize,ysize)
  791.       nowx=nowx+dxsize
  792.   end  /* Do */
  793.  
  794.   Call RxgdImageDestroy im
  795.  
  796. end             /* l'th character of message */
  797.  
  798. /* if slide used, slideify messim, and then copyit to messim_b */
  799.  
  800. /* message is done; should it be sent as a secondary version? */
  801. if send_pieces=1 & (slide<>"" | slide_size>0) then do
  802.    foo=rxgdimagecopy(send_bim,messim,0,0,0,0,xmess,ymess) 
  803.    oof=img_to_var(send_bim,tempfile)
  804.    foo=sref_multi_send(oof,'image/gif','M')
  805.    if foo<0 then signal errdone
  806.    nsent=2
  807.    if verbose>1 then call gpmprintf(' GIF_TEXT: SENDing message text ')
  808. end /* do */
  809.  
  810. /* get first row of slide, and fix up color table */
  811. if slide<>' ' then do              /* read slide from file */
  812.    slim=rxgdimagecreatefromgif(slide)
  813.    if (slim=0 | slim=1 )  then do
  814.           slide=''              /* no slide avaialble */
  815.           if verbose>1 then 
  816.              call gpmprintf(' No Slide file available ')
  817.    end  /* Do */
  818. end  /* Do */
  819.  
  820. if slide="" & slide_size>0 then do   /* make your own slide */
  821.    slidect.0=slide_size ; slide.0=slide_size
  822.    do mm=1 to slide_size
  823.       mm0=mm-1
  824.       slidect.!r.mm0=map255(get_user_scale(mm,slide_size,slide_red))
  825.       slidect.!g.mm0=map255(get_user_scale(mm,slide_size,slide_green))
  826.       slidect.!b.mm0=map255(get_user_scale(mm,slide_size,slide_blue))
  827.       slide.mm=mm-1
  828.    end /* do */
  829.    slide_vert='N'       /* force it to be "one row" color slide */
  830.    foo=grab_slide(0,slide_horiz,xmess,1,ymess,,slide_xcoord,slide_ycoord)
  831. end
  832.  
  833. /* valid color slide .gif file, so get the slide */
  834. if slide<>' ' | slide_size>0 then do
  835.  
  836.    if slide<>' ' then do   /* get slide just once */
  837.        foo=grab_slide(slim,slide_horiz,xmess,0,ymess,,slide_xcoord,slide_ycoord)
  838.        foo=rxgdimagecolorstotal(slim)
  839.  
  840. /* read the color slide's color table,*/
  841.        foo=rxgdimagegetcolortable(slim,'tt')
  842.        r='R'; g='G'; b='B'
  843.        slidect.0=tt.0
  844.        do il=0 to slidect.0-1
  845.           slidect.!r.il=tt.r.il
  846.           slidect.!g.il=tt.g.il
  847.           slidect.!b.il=tt.b.il
  848.        end
  849.     end
  850.  
  851. /* if slide_size>0, then we use slidect that was created above */
  852.  
  853. /* get color table of messim (if slide_thresh_type<>'P') */
  854.    if slide_thresh_type<>'P' then do
  855.       foo=rxgdimagegetcolortable(messim,'tt')
  856.       r='R'; g='G'; b='B'
  857.       messct.0=tt.0
  858.       do il=0 to messct.0-1
  859.         messct.!r.il=tt.r.il
  860.         messct.!g.il=tt.g.il
  861.         messct.!b.il=tt.b.il
  862.       end
  863.    end /* do */
  864.  
  865.    foo=add_slide_ct(messim)             /* add/remapslide colors to message image */
  866.    if slide_xcoord<>'' & slide_Ycoord<>'' then do
  867.        ixcoord=slide_xcoord*xmess ; iycoord=slide_ycoord*ymess
  868.    end
  869.    nchanges=0
  870.    if slide_prob="" then do
  871.        ixcoord=0 ; iycoord=ny
  872.    end /* do */
  873.  
  874. /* Get each row of message image, check and (possibly) convert each pixel to slide colors */
  875.    hey=time('r')                /* timer used for SEND */
  876.  
  877.    nofinal=0            /* a special effect -- causes a left side shadow */
  878.    if send_pieces=1 & wordpos('NOFINAL',translate(special))>0 then nofinal=1
  879.    do ny=0 to ymess-1           /* for each row of message image */
  880.      if slide_coord="" then do
  881.          ixcoord=0 ; iycoord=ny
  882.      end /* do */
  883.      if verbose>1 & ny//25=1 &send_pieces<>1 then call gpmprintf(" GIF_TEXT: Transforming message row " ny ' of ' ymess)
  884.      if slide_vert<>'N' then do
  885.         foo=grab_slide(slim,slide_horiz,xmess,ny,ymess,slide_vert)      /* get slide for this rowl */
  886.      end  /* Do */
  887.      foo=rxgdimagegetrowpixels(messim,ny,pxels)
  888.      do nx=1 to xmess
  889.        apix=pxels.nx
  890.        if slide_thresh="P1" & apix=0 then iterate  /* the most common case */
  891.        doit=do_change(apix,slide_thresh_type,slide_thresh_val,nx,xmess)
  892.        if doit=1 then do
  893.            if (slide_xcoord="" | slide_ycoord="") & slide_prob="" then do
  894.                itmp=slide.nx
  895.            end
  896.            else do
  897.                nnx=max(1,trunc(figdist(nx,ny,ixcoord,iycoord)))
  898.                doit=do_change(1,'P',1,nnx,slide.0,slide_prob,1)  /* check probability */
  899.                if doit=0 then iterate 
  900.                itmp=slide.nnx
  901.            end /* do */
  902.            apix=slidect.!alt.itmp ; nchanges=nchanges+1
  903.         end  /* Do */
  904.         pxels.nx=apix
  905.      end
  906.      drop pxels.0
  907.  
  908.       styled  = RxgdImageSetStyle(messim, pxels, xmess)         /* write transformed row back to */
  909.       rc = RxgdImageLine(messim, 0,ny,xmess-1,ny,styled)        /*  the message image */
  910.  
  911.      if send_pieces=1 then do            /* SEND what ya got? */
  912.            hey2=time('e')
  913.            if hey2>send_delay | (nofinal=1 & ny=ymess-1) then do
  914.                 foo=rxgdimagecopy(send_bim,messim,0,0,0,0,xmess,ymess) 
  915.                 oof=img_to_var(send_bim,tempfile)
  916.                 foo=sref_multi_send(oof,'image/gif','M')
  917.                 if foo<0 then signal errdone
  918.                 nsent=nsent+1
  919.                 if verbose>1 then call gpmprintf(' GIF_TEXT: SENDing transformed message text ' ny ' of 'ymess)
  920.                 hey=time('r')
  921.            end /* do */
  922.      end /* do */
  923.  
  924.    end              /* transforming row ny */
  925.    if  nofinal=1 then
  926.       foo=rxgdimagecopy(messim_b,send_bim,0,0,0,0,xmess,ymess)  /* final copy */
  927.    else
  928.       foo=rxgdimagecopy(messim_b,messim,0,0,0,0,xmess,ymess)  /* final copy */
  929.    mmb=messim_b
  930.  
  931. end  /* Do */
  932.  
  933. else do
  934.     mmb=messim
  935. end
  936.  
  937. /* copy buffer to a file, and clean up */
  938. if do_cache=0 then do
  939.   gif_file=gif_dir_root||"MES?????.GIF"
  940.   gfile=systempfilename(gif_file)
  941. end
  942. else do
  943.    gfile=gif_dir_root||cache_file
  944. end
  945.  
  946. foo=rxgdimagegif(mmb,gfile)
  947.  
  948. foo= RxgdImageDestroy(messim)
  949. if slide<>' ' then foo= RxgdImageDestroy(messim_b)
  950. do mm1=1 to font_ind.!ndims
  951.   jdim=dim.mm1
  952.   foo= RxgdImageDestroy(jdim)
  953. end /* do */
  954.  
  955. if send_bim<>0 then foo=rxgdimagedestroy(send_bim)
  956. if back_file<>' ' then  foo=rxgdimagedestroy(imb)
  957. if slide<>' ' then foo=rxgdimagedestroy(slim)
  958. IF VERBOSE>1 then CALL GPMPRINTF(' GIF_TEXT: completed image of size ' xmess ' x ' ymess )
  959.  
  960. shipit: nop             /* jump here if cache entry found */
  961.  
  962. if is_cgi=0 then do             /* srefilte addon */
  963.   signal on failure name nocon
  964.   if send_pieces=1 then do            /* final send? */
  965.       oof=charin(gfile,1,chars(gfile))
  966.       foof=stream(gfile,'c','close')
  967.       foo=sref_multi_send(oof,'image/gif','E')
  968.       ieek=stream(gfile,'c','query size')
  969.       if do_cache=0 then   foo=sysfiledelete(gfile)
  970.       if foo<0  then signal errdone
  971.       nsent=3
  972.       return 200' 'ieek
  973.   end /* do */
  974. /* else, use 'FILE  */
  975.   if do_cache=0 then do
  976.      return 'FILE ERASE TYPE image/gif name ' gfile     /* let sre deal with reply */
  977.    end
  978.    else do
  979.      return 'FILE  TYPE image/gif NOCACHE name ' gfile
  980.    end
  981.    oof=stream(gfile,'c','query size')
  982.   return '200 '||oof
  983. end
  984. if is_cgi=1 then do             /* cgi-bin */
  985.   Say "Content-type: image/gif"
  986.   Say
  987.   ki=chars(gfile); foo=stream(gfile,'c','close')
  988.   foo=charin(gfile,1,ki) 
  989.   foo2=stream(gfile,'c','close')
  990.   call charout,foo
  991.   if result<>0 then 
  992.      call gpmprintf(" GIF_TEXT CGI-BIN error: not all of file written: "||foo3)
  993.   if do_cache=0 then  foo=sysfiledelete(gfile)
  994.   return 
  995. end /* do */
  996.  
  997. if is_cgi=2  then do            /* stand alone */
  998.   foo2=stream(gfile2,'c','close')
  999.   ki=stream(gfile,'c','query size')
  1000.   foo=charin(gfile,1,ki) 
  1001.   aa=charout(gfile2,foo,1)
  1002.   IF AA>0 then 
  1003.       SAY " Problem writing to outfile: " gfile2
  1004.   else
  1005.      say gfile2 " created (length = " ||stream(gfile2,'c','query size')
  1006.   foo=stream(gfile2,'c','close')
  1007.   foo=stream(gfile,'c','close')
  1008.  
  1009.   foo=sysfiledelete(gfile)
  1010.  
  1011.    exit
  1012. end  /* Do */
  1013.  
  1014.  
  1015. errdone:
  1016. if is_cgi=1 then do
  1017.   Say "Content-type: text/plain"
  1018.   Say
  1019.   say "GIF_TEXT error at line  " sigl " (RC=" rc
  1020.   return 
  1021. end /* do */
  1022.  
  1023. say "GIF_TEXT error at line  " sigl " (RC=" rc
  1024. if is_cgi=0 then do
  1025.    'NODATA'
  1026.    return  '400 0'
  1027. end
  1028. exit
  1029.  
  1030. /***********/
  1031. check_ndims:
  1032. /* check on default font info */
  1033. font_ind.!ndims=0
  1034. if font_ind.!defgifs<>' ' then do
  1035.    do wiww=1 to words(font_ind.!defgifs)
  1036.  
  1037.       adefgif=strip(word(font_ind.!defgifs,wiww))
  1038.       bdefgif=gif_dir||adefgif
  1039.  
  1040.       dim= RxgdImageCreateFromGIF(bdefgif)
  1041.       if dim=1 | dim=0 then do
  1042.            CALL gpmprintf(' GIF_TEXT: missing alphabyte specific default:'adefgif)
  1043.            iterate
  1044.       end
  1045.       ndims=ndims+1
  1046.       att=transparent ; if att<0 then att=0
  1047.       dim.ndims=dim
  1048.       dim.ndims.!name=adefgif
  1049.       if ndims=1 then do
  1050.          dim_r=rxgdimagered(dim,att)
  1051.          dim_g=rxgdimagegreen(dim,att)
  1052.          dim_b=rxgdimageblue(dim,att)
  1053.       end
  1054.  
  1055.   end  /* Do */
  1056.   font_ind.!ndims=ndims
  1057. end  /* Do */
  1058. return 1
  1059.  
  1060. /******************/
  1061. /* copy an image to a variable (copy of what would be in .gif file */
  1062. img_to_var:procedure expose tempfile is_cgi
  1063. parse arg im,afile,keepit
  1064. if afile=""  then afile=tempfile
  1065. foo1=rxgdimagegif(im,afile)
  1066. oof=charin(afile,1,chars(afile))
  1067. if oof="" then signal errdone           /* empty -- must be aproblem */
  1068. foo=stream(afile,'c','close')
  1069. if keepit<>1 then foo=sysfiledelete(afile)
  1070. return oof
  1071.  
  1072.  
  1073. /**************************************************/
  1074. /* set/cleanup DEFAULT parametrs */
  1075. fix_defaults:
  1076. parse arg nocheck
  1077.  
  1078. red_text=200 ;green_text=200 ; blue_text=200
  1079. red_back=255 ; green_back=255 ; blue_back=255
  1080.  
  1081. def_transparent=check_byte(def_transparent,-1)
  1082. def_text_size=check_byte(def_text_size,15)
  1083. if fontname=0 then fontname=' '
  1084. if fontindex=0 then fontindex=' '
  1085. if back_file=0 then back_File=' '
  1086.  
  1087. gif_dir=gif_dir_root||strip(fontdir,,'\')||'\'
  1088.  
  1089. /* check the cache? */
  1090. if nocheck<>1 then do
  1091.   if do_cache=1 then
  1092.     if pos('$D',translate(amessage))+pos('$T',translate(amessage))>0 then do_cache=0
  1093.   if cache_size=0 then do_cache=0
  1094.  
  1095.   /* use a cached file? */
  1096.   foo=do_from_cache(cache_file)
  1097.   if foo=1 then signal shipit
  1098. end
  1099. oof=translate(fontdir,'  ','\/')
  1100. if fontname=' ' then fontname=strip(word(oof,words(oof)))
  1101. if fontindex=' ' then fontindex=fontname||'.IND'
  1102. fontindex=gif_dir||fontindex
  1103. dim=0 ; ndims=0;font_ind.!defgifs=' '
  1104. dim_r=0;  dim_g=0 ; dim_b=0
  1105. return 1
  1106.  
  1107.  
  1108.  
  1109. /***************************/
  1110. /* set options, using font_index and request stuff */
  1111. fix_options:
  1112. /* get font index, and possibly  text and back colors and default-font info */
  1113. inind=READ_FONT_INDEX(fontindex)  /* read in font index, and back and text color_index*/
  1114. if textcolor="" then textcolor=font_ind.!textcolor
  1115. if backcolor="" then backcolor=font_ind.!backcolor
  1116. vvs=get_from_hex(textcolor)
  1117. if vvs<>' ' then do
  1118.    parse var vvs red_text green_text blue_text
  1119. end  
  1120. vvs=get_from_hex(backcolor)
  1121. if vvs<>' ' then do
  1122.    parse var vvs red_back green_back blue_back
  1123. end  /* Do */
  1124. /* many_defaults from options ? */
  1125. if many_type>0 then font_ind.!manytype=many_type
  1126.  
  1127. /* if no x_scales or y_scales in request, use .IND file (if exists) */
  1128. if x_scales<>"" then font_ind.!x_user_scale=x_scales
  1129. if y_scales<>"" then font_ind.!y_user_scale=y_scales
  1130. x_SCALES=FIX_SCALE(FONT_IND.!X_USER_SCALE)
  1131. Y_SCALES=FIX_SCALE(FONT_IND.!Y_USER_SCALE)
  1132.  
  1133. if y_valign="" then y_valign=font_ind.!y_valign
  1134. y_valign=translate(y_valign)
  1135. select
  1136.   when abbrev(y_valign,'B')=1 then y_valign='B'
  1137.   when abbrev(y_valign,'T')=1 then y_valign='T'
  1138.   when abbrev(y_valign,'M')+abbrev(y_valign,'C')>0 then y_valign='M'
  1139.   otherwise y_valign='T'
  1140. end
  1141.  
  1142. if slide_vert="" then slide_vert=font_ind.!slide_vert
  1143. /* slide_vert= Tile, Fit, None */
  1144. slide_vert=left(strip(translate(slide_vert)),1)
  1145. if pos(slide_vert,'TFN')=0 then slide_vert='N'  /* use 1 slide is default */
  1146.  
  1147. if slide_horiz="" then slide_horiz=font_ind.!slide_horiz
  1148. slide_horiz=left(strip(translate(slide_horiz)),1)
  1149. /* slide_horiz types: Tile. Resize */
  1150.  
  1151. if slide="" then slide=font_ind.!slide
  1152. if slide<>'' then do
  1153.    stmp=slide
  1154.    slide=stream(slide,'c','query exists')
  1155.    if  slide=' ' & pos('.',stmp)=0 then do  /* try adding .gif to end */
  1156.        slide=stream(stmp||'.gif','c','query exists')
  1157.    end  /* Do */
  1158. end  /* Do */
  1159.  
  1160. if slide_thresh="" then slide_thresh=font_ind.!slide_thresh
  1161. slide_thresh=translate(strip(slide_thresh))
  1162. slide_thresh_type=left(slide_thresh,1)
  1163. slide_thresh_val=substr(slide_thresh,2)
  1164. slide_thresh_val=strip(translate(slide_thresh_val,' ','+:'))  /* might be list of values */
  1165.  
  1166. if slide_size="" then  slide_size=font_ind.!slide_size
  1167. if slide_size<>0 then do
  1168.   if slide_green="" then  slide_green=font_ind.!slide_gre en
  1169.   if slide_red="" then  slide_red=font_ind.!slide_red
  1170.   if slide_blue="" then  slide_blue=font_ind.!slide_blue
  1171.   slide_green=fix_scale(slide_green)
  1172.   slide_red=fix_scale(slide_red)
  1173.   slide_blue=fix_scale(slide_blue)
  1174. end
  1175.  
  1176. if slide_prob="" then slide_prob=font_ind.!slide_prob
  1177. slide_prob=fix_scale(slide_prob)
  1178.  
  1179. if slide_coord="" then slide_coord=fonT_ind.!slide_coord
  1180. slide_coord=fix_scale(slide_coord)  
  1181. parse var slide_coord tx ty
  1182. if datatype(tx)='NUM' & datatype(ty)='NUM' then do
  1183.         slide_xcoord=tx
  1184.         slide_ycoord=ty
  1185. end /* do */
  1186. if pos(slide_thresh_type,'PCB')=0  then do
  1187.      slide=''
  1188.      call gpmprintf(' Error specifying slide_thresh:'slide_thresh)
  1189. end  /* Do */
  1190. do ll=1 to words(slide_thresh_val)
  1191.   if datatype(strip(word(slide_thresh_val,ll)))<>'NUM' then do
  1192.      slide=''                                                        
  1193.      call gpmprintf(' Error specifying slide_thresh:'slide_thresh)   
  1194.   end
  1195. end
  1196.  
  1197. if verbose >1 & slide<>' ' then  do
  1198.   call gpmprintf(" GIF_TEXT: Using color slide " slide)
  1199. end
  1200. else do
  1201.   if verbose >1 & slide_size>0  then call gpmprintf(" GIF_TEXT: Using generated color slide, #colors=" slide_size)
  1202. end
  1203.  
  1204. /* what's the "transparent" color table entry */
  1205. if transparent='' then    /* not specified in request */
  1206.     transparent=font_ind.!transparent
  1207. if transparent>255 | transparent <-1 then transparent=def_transparent /* is it copecetic? */
  1208.  
  1209. return 1
  1210.  
  1211.  
  1212. /**************************************/
  1213. /* fix up message */
  1214. /* convert $x into time, date, etc. */
  1215. fix_message:
  1216. user_fonts=''
  1217. goof='00'x
  1218. aa=translate(amessage,goof,'0d0a09'x)
  1219. aaa=''
  1220. do until aa=""
  1221.    parse var aa a1 (goof) aa
  1222.    aaa=aaa||a1
  1223. end /* do */
  1224. amessage=aaa
  1225. if literal<>1  & pos('$',amessage)<>0 then do
  1226. /* parse amessage, converting $x into appropriate stuff. Note that $$ (or $$$..)
  1227.    is interpreted at $ (or $$...) */
  1228.   newmess=""
  1229.   do until amessage=""
  1230.        parse var amessage m1 '$' m2
  1231.        newmess=newmess||m1
  1232.        if m2="" then leave
  1233.        if abbrev(m2,'$')=1 then do  /* strip out $ and display */
  1234.           amessage=strip(m2,'l','$')
  1235.           idls=length(m2)-length(amessage)
  1236.           newmess=newmess||copies('$',idls)
  1237.           iterate
  1238.        end  
  1239.        akey=translate(left(m2,1))
  1240.        select
  1241.           when  akey='T' then newmess=newmess||get_time(time_fmt)
  1242.           when  akey='D' then newmess=newmess||get_date(date_fmt)
  1243.           when  akey='S' then newmess=newmess||'SERVERNAME'
  1244.           when pos(akey,'1234567890')>0 then do
  1245.              rval=akey
  1246.              akey2=translate(substr(m2,2,1))
  1247.              if pos(akey2,'1234567890')>0 then do
  1248.                  rval=(rval*10)+akey2
  1249.                  amessage=substr(m2,2)
  1250.              end
  1251.              newmess=newmess||d2c(rval+140) /* if val>139, then it's a special */
  1252.              iterate
  1253.           end
  1254.           when akey='B' then  newmess=newmess||d2c(254) /* 254 is "filled box " */
  1255.           when akey='N' then  newmess=newmess||d2c(10)  /* line break */
  1256.           when akey='F' then do
  1257.                parse var amessage . '(' newfont ')' amessage
  1258.                user_fonts=user_fonts||' 'newfont
  1259.                newmess=newmess||d2c(6)          /* 6 signals "font switch */
  1260.                iterate
  1261.           end /* do */
  1262.           otherwise nop
  1263.        end
  1264.        amessage=substr(m2,2)
  1265.   end /* do */
  1266.   amessage=newmess
  1267. end  /* interpret $x */
  1268. return 1
  1269.  
  1270. /***********************************/
  1271. /* map a 0.. 1 to 0..255 */
  1272. map255:procedure
  1273. parse arg a1
  1274. return trunc(max(min(a1*255,255),0))
  1275.  
  1276. /***********************************/
  1277. /* change this pixel ? */
  1278. do_change:procedure expose messct. is_cgi
  1279. parse arg apix,atype,aval0,jjx,xlen,slide_prob,useaval,jjy
  1280. if useaval=1 then
  1281.   aval=aval0
  1282. else
  1283.   aval=get_user_scale(jjx,xlen,aval0) /* pixel specific threshold */
  1284.  
  1285. aprob=get_user_scale(jjx,xlen,slide_prob)   /* probability of using scale: 1- always use,0-use original value*/
  1286. if aprob<1 then do
  1287.    arf=random()/999
  1288.    if arf>aprob then return 0           /* retain with current value */
  1289. end /* do */
  1290.  
  1291. if atype='P' then do
  1292.    if apix >= aval then return 1
  1293.    return 0
  1294. end  /* Do */
  1295. r=messct.!r.apix
  1296. b=messct.!b.apix
  1297. g=messct.!g.apix
  1298. if atype='C' then do            /* if brightest color is over threshold */
  1299.     if max(r,b,g)>=aval then return 1
  1300.     return 0
  1301. end  /* Do */
  1302. if atype='B' then do            /* if average brightness over threshold */
  1303.      if (r+b+g)/3 >= aval then return 1
  1304.      return 0
  1305. end  /* Do */
  1306. return 0                /* shoud never get here */
  1307.  
  1308.  
  1309. /***************/
  1310. /* process from a cached file 
  1311.   return 1 if "used a cache file"; 0 if not. 
  1312.   Also, set do_cache=0 if a problem arises */
  1313.  
  1314. do_from_cache:procedure expose gif_dir_root verbose do_cache cache_duration is_cgi
  1315. parse arg cache_file
  1316. if do_cache=0 then return 0
  1317.  
  1318. if do_cache>0 then do
  1319.    do_cache=1
  1320.    cache_file=gif_dir_root||cache_file
  1321.    gfile=cache_file
  1322.  
  1323.    eek=sysfiletree(cache_file,afile,'FT')
  1324.    if afile.0>0 then do         /* match -- check duration */
  1325.         parse var afile.1 dd .
  1326.         mkdate=space(translate(left(afile.1,8),' ','/'),0)
  1327.         nowdate=space(translate(date('o'),' ','/'),0)
  1328.         if abs(nowdate-mkdate) <= cache_duration then do
  1329.           if verbose>1 then call gpmprintf(' GIF_TEXT: using cached image file: ' cache_file)
  1330.           return 1
  1331.        end
  1332.        if verbose>1  then call gpmprintf('GIF_TEXT: Rewriting cached image file: ' cache_file)
  1333.        return 0
  1334.    end  /* Do */
  1335.    else do              /* no match -- is there room? */
  1336.       foo=sysfiletree(gif_dir_root||'*.*','eek','FO')
  1337.       if eek.0 > cache_size then do 
  1338.          do_cache=0     /* suppress cache! */
  1339.          if verbose>1 then call gpmprintf(' GIF_TEXT: cache_size exceeded, can not cache image file: ' cache_file)
  1340.       end  /* Do */
  1341.       else do
  1342.           if verbose>1 then call gpmprintf(' GIF_TEXT: creating cached image file: ' cache_file)
  1343.       end /* do */
  1344.    end
  1345. end
  1346. return 0
  1347.  
  1348.  
  1349.  
  1350. /***********************************/
  1351. /* get the slide file stuff 
  1352. ATYPE has 3 values:
  1353.   T= repeat slide
  1354.   F= fit (internally repeat)
  1355. */
  1356. grab_slide:procedure expose slide. verbose slidect.   is_cgi sqs.
  1357. parse upper arg sim,atype,mx,ajy,my,stype,sxc,syc
  1358. if sim<>0 then do
  1359.   foo=rxgdimagecolorstotal(sim)
  1360.   jx=rxgdimagesx(sim)
  1361.   jy=rxgdimagesy(sim)
  1362. end
  1363. else do
  1364.    jy=1
  1365.    jx=slide.0
  1366. end /* do */
  1367. jy0=jy
  1368. /* which row to read from ? */
  1369. if jy>1 & ( stype="F" | stype="T" ) then do  /* multi row style -- use my ajy row */
  1370.     select
  1371.      when ajy=0 then jy=0
  1372.      when ajy=my then jy=jy-1
  1373.      when jy>my | stype='F' then do
  1374.        tt=ajy/my
  1375.        jy=trunc(tt*(jy-1))
  1376.      end
  1377.      when stype='T' then do
  1378.         jy=trunc(ajy//(jy-1))
  1379.      end  /* Do */
  1380.      otherwise jy=1
  1381.    end
  1382. end  /* Do */
  1383. else do
  1384.    if jy>1 then 
  1385.        jy=trunc(1+(jy/3))
  1386.    else
  1387.      jy=0
  1388. end
  1389.  
  1390. /* if sxc and syc specified, then measrue distance from there (rather then just using
  1391.     column #. This means computing max distance from sxc,syc */
  1392. if datatype(sxc)='NUM' & datatype(syc)='NUM' then do    /* use distance, not colunm */
  1393.     ixc=1+((mx-1)*sxc);   ixc= max(min(ixc,mx),1)
  1394.     iyc=1+((my-1)*syc) ;  iyc= max(min(iyc,my),1)
  1395.     d1=figdist(ixc,iyc,1,1)
  1396.     d2=figdist(ixc,iyc,mx,1)
  1397.     d3=figdist(ixc,iyc,mx,my)
  1398.     d4=figdist(ixc,iyc,1,my)
  1399.     mx=trunc(max(d1,d2,d3,d4))   /* new "max distance from slide */
  1400.     if verbose>1 then call gpmprintf(' GIF_TEXT: Max distance from slide_coord='mx)
  1401. end
  1402.  
  1403. if verbose>1 & ajy//25=1 then 
  1404.    call gpmprintf(" GIF_TEXT: Getting color slide from row:" jy ' of ' jy0)
  1405.  
  1406. drop aslide.
  1407. if sim<>0 then do               /* using slide form file */
  1408.   foo=rxgdimagegetrowpixels(sim,jy,aslide)
  1409. end
  1410. else do                         /* using user set slide */
  1411.   do mm=0 to slide.0
  1412.      aslide.mm=slide.mm        
  1413.   end /* do */
  1414. end
  1415.  
  1416. /* we now have base slide (from file or from use set); now expand/shrink to fit mx */
  1417. slide.0=mx
  1418. /* if slide > mx, then pick from slide */
  1419. if jx>mx & atype<>'T' then do
  1420.    slide.1=aslide.1 
  1421.    slide.mx=aslide.jx 
  1422.  
  1423.    do ll=2 to mx-1
  1424.        tt=(ll-1)/(mx-1)
  1425.        itt=1+trunc(tt*(jx-1))
  1426.        slide.ll=aslide.itt 
  1427.    end /* do */
  1428.    return 1
  1429. end  /* Do */
  1430.  
  1431. /* slide < mx, need to expand it */
  1432. if atype='T' then do            /* tile it, both cases (jx> or < mx)  */
  1433.     ii=0
  1434.     do mm=1 to mx
  1435.        ii=ii+1
  1436.        if ii>jx then ii=1
  1437.        slide.mm=aslide.ii 
  1438.     end /* do */
  1439.     return 1
  1440. end  /* Do */
  1441.  
  1442. /* fit (internal repeat */
  1443.    slide.1=aslide.1 
  1444.    slide.mx=aslide.jx 
  1445.    do ll=2 to mx-1
  1446.        tt=(ll-1)/(mx-1)
  1447.        itt=1+trunc(tt*(jx-1))
  1448.        slide.ll=aslide.itt 
  1449.    end /* do */
  1450.    return 1
  1451.  
  1452. /***********/
  1453. /* squared distance */
  1454. figdist:procedure expose sqs.
  1455. parse arg ax,ay,cx,cy
  1456. dx=ax-cx ; dy=ay-cy 
  1457. AAS=( (dx*dx)+(dy*dy))
  1458.  
  1459. IF sqs.!got<>0 THEN DO      /* YUCK, USE A NUMERIC SEARCH */
  1460.     AAS2=SQRT2(AAS)
  1461. end /* do */
  1462. ELSE DO
  1463.    AAS2=SQRT(AAS)
  1464. END
  1465. RETURN AAS2
  1466.  
  1467. /********************/
  1468. /*  a square root finder */
  1469. sqrt2:procedure
  1470. parse arg aval
  1471.  
  1472. if aval<=1 then return aval  
  1473.  
  1474. /* do a binary search */
  1475.  
  1476. i1=1 ;i11=1;
  1477. i3=100 ; i33=10000
  1478. do until i33>aval | i3=10000000
  1479.   i3=i3*5
  1480.   i33=i3*i3
  1481. end /* do */
  1482. i2=i3/2 ; i22=i2*i2
  1483.  
  1484. do forever
  1485. if aval=i22 then return i2  /* an exact match */
  1486. oldi2=i2
  1487. if aval <i22 then do
  1488.    i3=i2; i33=i22
  1489.    i2=i1+((i3-i1)/2) ; i22=i2*i2
  1490. end
  1491. else do
  1492.    i1=i2 ; i11=i22 ;
  1493.    i2=i1+((i3-i1)/2) ; i22=i2*i2
  1494. end /* do */
  1495. if abs(oldi2-i2)<0.01 then return i2
  1496. end
  1497.  
  1498.  
  1499. /***********************************/
  1500. /* add slide's color table to messim */
  1501. add_slide_ct:procedure expose slidect. verbose is_cgi
  1502. parse arg mim
  1503. ist=rxgdimagegettransparent(mim)
  1504. usepre=0
  1505. do jj=0 to slidect.0-1
  1506.    r=slidect.!r.jj ; g=slidect.!g.jj ; b=slidect.!b.jj
  1507.    oo=rxgdimagecolorexact(mim,r,g,b)  /* check if color already exists */
  1508.    if oo=-1 | oo=ist then do             /*no exact match, or match transparent  */
  1509.       aa=rxgdimagecolorallocate(mim,r,g,b)  /* add this color */
  1510.       if aa>-1  then do          /* success */
  1511.            slidect.!alt.jj=aa
  1512.       end  /* Do */
  1513.       else do           /* no more colors, use closest */
  1514.          slidect.!alt.jj=rxgdimagecolorclosest(mim,r,g,b)
  1515.          usepre=usepre+1
  1516.       end
  1517.    end  /* Do */
  1518.    else do
  1519.        slidect.!alt.jj=oo              /* use prexisting color */
  1520.    end
  1521. end /* do */
  1522. if usepre>0 & verbose>1  then call gpmprintf(' GIF_TEXT: too many colors, had to share for 'usepre)
  1523.  
  1524. return 1
  1525.  
  1526.  
  1527.  
  1528.  
  1529. /***********************************/
  1530.  
  1531. /* determine a user scale, given ith of Ilen position, and 
  1532.    list of "user_scales". We assume user_scales is a space delimited list
  1533.   of numbers, with 1="use current size", >1 means larger, <1 means smaller */
  1534.  
  1535. get_user_scale:procedure expose is_cgi
  1536. parse arg ith,ilen,user_scales
  1537. if user_scales="" then return 1
  1538.  
  1539. igoo=words(user_scales)
  1540.  
  1541. if ith=1 then return word(user_scales,1)
  1542.  
  1543. if ith=ilen then return word(user_scales,igoo)
  1544.  
  1545. /* middle characters*/
  1546. frac=(ith-1)/(ilen-1)    /* where in scale list is it */
  1547. spot=1+ ((igoo-1)*frac)
  1548. ifrac=trunc(spot)
  1549. afrac=spot-ifrac
  1550.  
  1551. if afrac=0 then return word(user_scales,ifrac)
  1552.  
  1553. ii=ifrac+1
  1554. a1=word(user_scales,ii)
  1555. a2=word(user_scales,ifrac)
  1556.  
  1557. diff=a1-a2
  1558. return (a2+(diff*afrac))
  1559.  
  1560.  
  1561. /***********************************/
  1562. /* get the gif name, using several naming tricks */
  1563. get_gifname:procedure expose font_ind. is_cgi
  1564.  
  1565. parse arg achar,gif_dir,fontname
  1566.  
  1567. if length(achar)>1 then achar=translate(achar)
  1568. /* check index first */
  1569. do iu=1 to font_ind.0
  1570.    if font_ind.iu=achar then do 
  1571.         cl=gif_dir||font_ind.iu.!file
  1572.         if stream(cl,'c','query exists')<>' ' then  return cl
  1573.         leave
  1574.    end  /* Do */
  1575. end /* do */
  1576. if length(achar)>1 then return ' '  /* special character not found */
  1577.  
  1578.  
  1579. /* is it a valid file name (i.e.; don't look for *.gif*/
  1580. if pos(translate(achar),'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$%#&@!~-&^')=0 then RETURN ' '
  1581.  
  1582. /* it is lowerr case: look for xlc.gif? */
  1583.  
  1584. if translate(achar)<>achar then do
  1585.    cl=gif_dir||achar||'lc.gif'
  1586.    if stream(cl,'c','query exists')<>' ' then  return cl
  1587.    cl=gif_dir||fontname||achar||'lc.gif'
  1588.    if stream(cl,'c','query exists')<>' ' then  return cl
  1589.    cl=gif_dir||fontname||'-'||achar||'lc.gif'
  1590.    if stream(cl,'c','query exists')<>' ' then  return cl
  1591.  
  1592. end  /* Do */
  1593.  
  1594. /* try generic name: look for x.gif? */
  1595. cl=gif_dir||achar||'.gif'
  1596. if stream(cl,'c','query exists')<>' ' then  return cl
  1597. cl=gif_dir||fontname||achar||'.gif'
  1598. if stream(cl,'c','query exists')<>' ' then  return cl
  1599. cl=gif_dir||fontname||'-'||achar||'.gif'
  1600. if stream(cl,'c','query exists')<>' ' then  return cl
  1601. cl=gif_dir||achar||fontname||'.gif'
  1602. if stream(cl,'c','query exists')<>' ' then  return cl
  1603.  
  1604. return ' '
  1605.  
  1606.  
  1607.  
  1608. /******/
  1609. /* check for valid 0-255 value, set to def if not */
  1610. check_byte:procedure
  1611. parse arg aval,adef
  1612. if adef=' ' then adef=0
  1613. if datatype(aval)<>'NUM' then return adef
  1614. if aval<0 | aval>255  then return adef
  1615. return aval
  1616.  
  1617.  
  1618.  
  1619. /*******/
  1620. /* read a font index file into font_ind. */
  1621. read_font_index:procedure expose font_ind.  gif_dir  def_transparent def_textcolor def_backcolor is_cgi
  1622. parse arg afile
  1623.  
  1624. defgifs=' '; xoffset=0 ; yoffset=0 ; inrow=16 ; hchar=47  ; wchar=35 ;isbw=1
  1625. charset=' !"'||"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
  1626. leftoffset=0;rightoffset=0;topoffset=0;bottomoffset=0
  1627. transparent="" ; manytype=1
  1628. x_user_scales='' ; y_user_scales="" ;y_valign=' ' ;slide='' ;  slide_horiz=''
  1629. slide_thresh='P1' ; slide_vert=''
  1630. slide_size=""  ; textcolor="" ; backcolor="" ; slide_prob=''
  1631.  
  1632. font_ind.0=0
  1633. font_ind.!defgifs=defgifs
  1634. font_ind.!xoffset=xoffset
  1635. font_ind.!yoffset=yoffset
  1636. font_ind.!topoffset=topoffset
  1637. font_ind.!bottomoffset=bottomoffset
  1638. font_ind.!rightoffset=rightoffset
  1639. font_ind.!leftoffset=leftoffset
  1640. font_ind.!inrow=inrow
  1641. font_ind.!hchar=hchar
  1642. font_ind.!wchar=wchar
  1643. font_ind.!isbw=isbw
  1644. font_ind.!charset=charset
  1645. font_ind.!manytype=1
  1646. font_ind.!x_user_scales=''
  1647. font_ind.!y_user_scales=''
  1648. font_ind.!y_valign=''
  1649. font_ind.!slide=''
  1650. font_ind.!slide_horiz=''
  1651. font_ind.!slide_vert=''
  1652. font_ind.!slide_thresh=''
  1653. font_ind.!transparent=def_transparent
  1654. font_ind.!textcolor=def_textcolor
  1655. font_ind.!backcolor=def_backcolor
  1656. font_ind.!slide_size=0
  1657. font_ind.!slide_coord=''
  1658. font_ind.!slide_blue=''
  1659. font_ind.!slide_red=''
  1660. font_ind.!slide_green=''
  1661. font_ind.!slide_prob=""
  1662.  
  1663. if afile=' ' then return 0
  1664. ii=0
  1665. if stream(afile,'c','query exists')=' ' then return 0
  1666. do until lines(afile)=0
  1667.   ii=ii+1
  1668.   tmp.ii=linein(afile)
  1669. end
  1670. tmp.0=ii
  1671. foo=stream(afile,'c','close')
  1672.  
  1673. iin=0
  1674. do mm=1 to tmp.0
  1675.    aline=strip(tmp.mm)
  1676.    if aline=' ' then iterate
  1677.    if abbrev(aline,'**')=1 then iterate  /* comment */
  1678.    athing=' '
  1679.    if pos('=',aline)<>0 then do
  1680.        parse var aline athing '=' stuff ; athing=strip(translate(athing))
  1681.    end  /* Do */
  1682.    select
  1683.      when abbrev(athing,'DEFAUL')>0 then  defgifs=defgifs||' '||strip(stuff)
  1684.      when athing='DEF_OFFSET' then do
  1685.              stuff=translate(stuff,' ',',')
  1686.              parse var stuff a1 a2
  1687.              if datatype(a1)='NUM'  then xoffset=a1
  1688.              if datatype(a2)='NUM'  then yoffset=a2
  1689.      end
  1690.      when abbrev(athing,'DEF_CHAR_OF')+abbrev(athing,'DEFCHAROF')>0 then do
  1691.              stuff=translate(stuff,' ',',')            
  1692.              parse var stuff a1 a2 a3 a4                    
  1693.              if datatype(a1)='NUM'  then leftoffset=a1    
  1694.              if datatype(a2)='NUM'  then topoffset=a2    
  1695.              if datatype(a3)='NUM'  then rightoffset=a3    
  1696.              if datatype(a4)='NUM'  then bottomoffset=a4    
  1697.      end  /* Do */
  1698.      when abbrev(athing,'DEF_TR')+abbrev(athing,'TRAN')>0 then do
  1699.            if datatype(stuff)='NUM'  then transparent=stuff
  1700.      end
  1701.  
  1702.      when abbrev(athing,'DEF_TEXTC')+abbrev(athing,'TEXT')>0 then do
  1703.         if verify(stuff,'0123456789ABCDEFabcdef#')=0 then  textcolor=stuff
  1704.      end
  1705.  
  1706.      when abbrev(athing,'DEF_BACKC')+abbrev(athing,'BACK')>0 then do
  1707.         if verify(stuff,'0123456789ABCDEFabcdef#')=0 then  backcolor=stuff
  1708.      end
  1709.  
  1710.      when athing='DEF_CHARSIZE' then do
  1711.              stuff=translate(stuff,' ',',')
  1712.              parse var stuff a1 a2
  1713.              if datatype(a1)='NUM'  then wchar=a1
  1714.              if datatype(a2)='NUM'  then hchar=a2
  1715.      end  /* Do */
  1716.      when athing='DEF_CHARS' then charset=stuff
  1717.      when athing='DEF_BW' then isbw=pos(strip(translate(stuff)),'Y YES 1')
  1718.      when abbrev(athing,"MANY_DEF")+abbrev(athing,'MANYDEF')>0 then do
  1719.        manytype=wordpos(translate(stuff),'CYCLE FIT END RANDOM ')
  1720.        if manytype=0 then manytype=1
  1721.      end
  1722.      when athing='DEF_INROW' then
  1723.               if datatype(strip(stuff))='NUM' then inrow=strip(stuff)
  1724.      when athing='CHAR' then do
  1725.       parse var stuff aval afile
  1726.       if datatype(aval)<>'NUM' then iterate /* error- ignoe */
  1727.       if aval<0  | aval>99 then iterate /* out of range, ignore */
  1728.       aval=strip(aval,'l','0')
  1729.       font_ind.!chars.aval=strip(afile)
  1730.       iterate
  1731.      end
  1732.      when abbrev(athing,"X_SC")+abbrev(athing,'XSC')>0 then
  1733.         x_user_scales=stuff
  1734.      when abbrev(athing,"Y_SC")+abbrev(athing,'YSC')>0 then
  1735.         y_user_scales=stuff
  1736.      when abbrev(athing,'VAL')+abbrev(athing,'Y_VAL')>0 then
  1737.         y_valign=stuff
  1738.      when abbrev(athing,'SLIDE_H')>0 then
  1739.         slide_horiz=packur2(stuff)
  1740.      when abbrev(athing,'SLIDE_V')>0 then
  1741.         slide_vert=packur2(stuff)
  1742.      when abbrev(athing,'SLIDE_T')>0 then
  1743.         slide_thresh=packur2(stuff)
  1744.      when abbrev(athing,'SLIDE_F')>0 | athing='SLIDE' then do
  1745.         slide=packur2(stuff)
  1746.         if pos(':',slide)+pos('\',slide)=0 then
  1747.            slide=gif_dir||slide
  1748.      end
  1749.      when abbrev(athing,'SLIDE_R')>0 then
  1750.         slide_red=packur2(stuff)
  1751.      when abbrev(athing,'SLIDE_G')>0 then
  1752.         slide_green=packur2(stuff)
  1753.      when abbrev(athing,'SLIDE_B')>0 then
  1754.         slide_blue=packur2(stuff)
  1755.      when abbrev(athing,'SLIDE_C')>0 then
  1756.         slide_coord=packur2(stuff)
  1757.      when abbrev(athing,'SLIDE_P')>0 then
  1758.         slide_prob=packur2(stuff)
  1759.      when abbrev(athing,'SLIDE_S')>0 then do
  1760.          tt=packur2(stuff)
  1761.          if datatype(tt)='NUM' then slide_size=tt
  1762.      end  /* Do */
  1763.  
  1764.      otherwise do               /* it's a charater to file map */
  1765.         parse var tmp.mm achar afile
  1766.         if length(achar)>1 then achar=translate(achar)
  1767.         iin=iin+1
  1768.         font_ind.iin=strip(achar)   ; font_ind.iin.!file=strip(afile)
  1769.      end
  1770.    end
  1771. end /* do */
  1772.  
  1773.  
  1774.  
  1775. if isbw>0 then isbw=1
  1776. font_ind.!defgifs=defgifs
  1777. font_ind.!xoffset=xoffset
  1778. font_ind.!yoffset=yoffset
  1779.  
  1780. font_ind.!topoffset=topoffset
  1781. font_ind.!bottomoffset=bottomoffset
  1782. font_ind.!rightoffset=rightoffset
  1783. font_ind.!leftoffset=leftoffset
  1784.  
  1785. font_ind.!inrow=inrow
  1786. font_ind.!hchar=hchar
  1787. font_ind.!wchar=wchar
  1788. font_ind.!isbw=isbw
  1789. font_ind.!charset=charset
  1790. font_ind.!transparent=transparent 
  1791. font_ind.!manytype=manytype
  1792. font_ind.!x_user_scale=x_user_scales
  1793. font_ind.!y_user_scale=y_user_scales
  1794. font_ind.!y_valign=y_valign
  1795. font_ind.!slide=slide
  1796. font_ind.!slide_horiz=slide_horiz
  1797. font_ind.!slide_thresh=slide_thresh
  1798. font_ind.!slide_vert=slide_vert
  1799. font_ind.!textcolor=textcolor
  1800. font_ind.!backcolor=backcolor
  1801.  
  1802. font_ind.!slide_size=slide_size
  1803. font_ind.!slide_red=slide_red
  1804. font_ind.!slide_green=slide_green
  1805. font_ind.!slide_blue=slide_blue
  1806. font_ind.!slide_coord=slide_coord
  1807. font_ind.!slide_prob=slide_prob
  1808.  
  1809. font_ind.0=iin
  1810.  
  1811. return iin
  1812.  
  1813. /**********/
  1814. /* fIX A user scale entry */
  1815. fix_scale:procedure
  1816. parse arg ascale
  1817. if ascale=0 then return 1
  1818. ascale=translate(ascale,' ','+')
  1819. tt=''
  1820. do mm=1 to words(ascale)
  1821.    av=strip(word(ascale,mm))
  1822.    if datatype(av)<>'NUM' then  iterate
  1823.    tt=tt' 'av
  1824. end  /* Do */
  1825.  
  1826. return tt
  1827.  
  1828.  
  1829.  
  1830. /**************************/
  1831. /* convert ff21b3 "hex" color code to decimal r g b values
  1832.   If bad value, return ' /' */
  1833. get_from_hex:procedure
  1834. parse arg hval
  1835.  
  1836. hval=strip(strip(hval),,'"')
  1837. hval=strip(hval,,'#')
  1838. select 
  1839.   when length(hval)<>6 then return ' '
  1840.   when verify(translate(hval),'0123456789ABCDEF')>0 then return ' '
  1841.   otherwise do
  1842.     a1=left(hval,2)
  1843.     a2=substr(hval,3,2)
  1844.     a3=substr(hval,5,2)
  1845.     r=x2d(a1)
  1846.     g=x2d(a2)
  1847.     b=x2d(a3)
  1848.   end
  1849. end /* do */
  1850. return r ' ' g ' ' b
  1851.  
  1852.  
  1853. /********************/
  1854. /* return time, using REXX time_fmt. Also, special code: 1 - C without am or pm */
  1855. get_time:procedure
  1856. parse arg tfmt
  1857.  
  1858. if pos(tfmt,'CHLMNS1')=0 then tfmt='N'
  1859. if tfmt='1' then do
  1860.   aa=time('C')
  1861.   a2=translate(right(aa,2))
  1862.   oof=2
  1863.   if a2="AM" then oof=1         /* reserved special character: 1=am, 2=pm */
  1864.   return left(aa,length(aa)-2)||d2c(oof)
  1865. end
  1866. return time(tfmt)
  1867.  
  1868. /********************/
  1869. /* return time, using REXX time_fmt */
  1870. get_date:procedure
  1871. parse arg tfmt
  1872.  
  1873. if pos(tfmt,'BDELMNOSUW')=0 then tfmt='N'
  1874.  
  1875. return date(tfmt)
  1876.  
  1877.  
  1878. /************************************************/
  1879. /* procedure from TEST-CGI.CMD by  Frankie Fan <kfan@netcom.com>  7/11/94 */
  1880. DecodeKeyVal: procedure
  1881.   parse arg Code
  1882.   Text=''
  1883.   Code=translate(Code, ' ', '+')
  1884.   rest='%'
  1885.   do while (rest\='')
  1886.      Parse var Code T '%' rest
  1887.      Text=Text || T
  1888.      if (rest\='' ) then
  1889.       do
  1890.         ch = left( rest,2)
  1891.         if verify(ch,'01234567890ABCDEF')=0 then
  1892.            c=X2C(ch)
  1893.         else
  1894.            c=ch
  1895.         Text=Text || c
  1896.         Code=substr( rest, 3)
  1897.       end
  1898.   end
  1899.   return Text
  1900.  
  1901.  
  1902. /*********/
  1903. packur2:procedure expose is_cgi
  1904. parse arg a1b0
  1905.  
  1906. if is_cgi=0 then
  1907.    return packur(translate(a1b0,' ','+'))
  1908. else
  1909.    return decodekeyval(translate(a1b0,' ','+'))
  1910.  
  1911. /************/
  1912. wow1:
  1913. call gpmprintf(" GIF_TEXT error at line "sigl)
  1914.       if is_cgi=0 then do
  1915.          'NODATA'
  1916.          exit '400 0'
  1917.       end
  1918.       else do
  1919.            exit 
  1920.       end /* do */
  1921.  
  1922.  
  1923. /***********************/
  1924. /* see if an alphabyte specific default is available */
  1925. get_default_char:procedure expose font_ind. verbose dim. red_back green_back blue_back ,
  1926.                         red_text green_text blue_text is_cgi
  1927. parse arg achar,ithchar,mlen,manymax
  1928.  
  1929. if font_ind.!ndims=0 then return 1
  1930. ikk=1
  1931. nfonts=font_ind.!ndims
  1932. if manymax>0 & manymax<nfonts then nfonts=manymax
  1933. if nfonts>1 then do
  1934.   select
  1935.      when font_ind.!manytype=1 then do  /* cycle */
  1936.        ikk=ithchar//nfonts
  1937.        if ikk=0 then ikk=nfonts
  1938.      end
  1939.      when font_ind.!manytype=3 then do   /* end */
  1940.         ikk=min(nfonts,ithchar)
  1941.      end  /* Do */
  1942.      when font_ind.!manytype=4 then do  /* random */
  1943.         ikk=random(1,nfonts)
  1944.      end
  1945.      otherwise    do      /* fit */
  1946.         ikk=1+trunc(nfonts*ithchar/(mlen+0.1))
  1947.      end
  1948.   end
  1949. end
  1950. ic=pos(achar,font_ind.!charset)
  1951. if ic=0 then do
  1952.   achar=translate(achar)
  1953.   ic=pos(achar,font_ind.!charset)
  1954. end
  1955. if ic=0 then return 1
  1956.  
  1957. /* for each character in the charset ... */
  1958. /* determine x offset: */
  1959.    irow=1+((ic-0.1)%font_ind.!inrow)
  1960.    icol=ic-((irow-1)*font_ind.!inrow)
  1961.  
  1962. /* upper left is 0,0 */
  1963.    xat=font_ind.!xoffset + ((icol-1)*font_ind.!wchar)+font_ind.!leftoffset
  1964.    yat=font_ind.!yoffset+ ((irow-1)*font_ind.!hchar)+font_ind.!topoffset
  1965.    jx=font_ind.!wchar-(font_ind.!leftoffset+font_ind.!rightoffset)
  1966.    jy=font_ind.!hchar-(font_ind.!bottomoffset+font_ind.!topoffset)
  1967.    cim=rxgdimagecreate(jx,jy)
  1968.    if font_ind.!isbw=0 then do  /* use colors as is, but include back text colors */
  1969.       oy1=rxgdimagecolorallocate(cim,red_back,green_back,blue_back)
  1970.       oy2=rxgdimagecolorallocate(cim,red_text,green_text,blue_text)
  1971.    end
  1972.  
  1973.    tdim=dim.ikk         /* use the ikk (of possible many_defaults) complete font */
  1974.  
  1975.    foo=rxgdimagecopy(cim,tdim,0,0,xat,yat,jx,jy)
  1976.    if font_ind.!isbw=1 then do   /* convert b/w to back/text colors */
  1977. ww=rxgdimagegettransparent(cim)
  1978.       foo=rxgdimagecolordeallocate(cim,0)
  1979.       oy1=rxgdimagecolorallocate(cim,red_back,green_back,blue_back)
  1980.       foo=rxgdimagecolordeallocate(cim,1)
  1981.       oy2=rxgdimagecolorallocate(cim,red_text,green_text,blue_text)
  1982.    end
  1983.  
  1984.    return cim
  1985.  
  1986.  
  1987. /*********************************/
  1988. /* return r g b of aim at ctable ival */
  1989. three_color:procedure
  1990. parse arg aim,ctable
  1991. r=rxgdimagered(aim,ctable)
  1992. g=rxgdimagegreen(aim,ctable)
  1993. b=rxgdimageblue(aim,ctable)
  1994. return r g b
  1995.  
  1996. /*********************************/
  1997. /* stand alone mode -- build the "list " */
  1998. ask_values:procedure expose gfile2 gif_dir_root
  1999.  
  2000. SIGNAL OFF  ERROR ; SIGNAL OFF SYNTAX
  2001. SIGNAL ON ERROR NAME ASKV 
  2002.  SIGNAL ON SYNTAX NAME ASKV 
  2003.  
  2004. ansion=checkansi()
  2005. if ansion=1 then do
  2006.   aesc='1B'x
  2007.   cy_ye=aesc||'[37;46;m'
  2008.   normal=aesc||'[0;m'
  2009.   bold=aesc||'[1;m'
  2010.   re_wh=aesc||'[31;47;m'
  2011.   reverse=aesc||'[7;m'
  2012. end
  2013. else do
  2014.   say " Warning: Could not detect ANSI....  output will look ugly ! "
  2015.   cy_ye="" ; normal="" ; bold="" ;re_wh="" ;
  2016.   reverse=""
  2017. end  /* Do */
  2018.  
  2019. cls
  2020. say  " " ; say
  2021.  
  2022. call lineout, bold cy_ye
  2023. call lineout, "This is the GIF_TEXT text-to-gif utility: stand alone mode "
  2024. call lineout, normal
  2025.  
  2026.  
  2027. say " Although designed primarily as a WWW script, you can use GIF_TEXT "
  2028. say " to create .GIF files in a stand-alone mode."
  2029. say
  2030. say "      "||cy_ye||"GIF_TEXT does not have graphics display capability    " normal
  2031. say "      "||cy_ye||" ... you'll have to read the files it creates with a  " normal
  2032. say "      "||cy_ye||"     graphics viewer (you can often use your browser)." normal
  2033. say "  "
  2034.  
  2035. if yesno(" Are you ready to continue ")=1 then
  2036.  nop
  2037. else do
  2038.  say " See you later?.. "
  2039.  exit
  2040. end
  2041.  
  2042. /* try reading in prior answers file */
  2043. priora=""
  2044. if stream('GIF_TEXT.ANS','c','query exists')<>"" then do
  2045. say 
  2046.    say bold ' ... reading prior options from GIF_TEXT.ANS'  normal
  2047.    priora=charin('GIF_TEXT.ANS',1,chars('GIF_TEXT.ANS'))
  2048.    foo=stream('GIF_TEXT.ANS','c','close')
  2049. end /* do */
  2050. def.!font="?"; def.!backgrnd="?";def.!colorslide='?'
  2051. def.!width=0 ; def.!height=0
  2052. def.!moreopts='?'
  2053. def.!message='hello'
  2054. def.!outgfile='foo.gif'
  2055. asep='|^&^|'
  2056.  
  2057. do until priora=""
  2058.    parse var priora a1 '|^&^|' priora
  2059.    parse var a1 a1a '=' a1b
  2060.    a2='!'||strip(translate(a1a))
  2061.    def.a2=a1b
  2062. end /* do */
  2063.  
  2064. say
  2065. say " We recommend reading the documentation (GIF_TEXT.DOC) before running "
  2066. say " running this program.  On the other hand, you can always learn by "
  2067. say " making mistakes .... "
  2068. say
  2069. whatfont:
  2070. call charout , "What "reverse "alphabyte font "normal" do you want to use (?=list,ENTER="def.!font"):"
  2071. pull font
  2072. if font=""  then font=def.!font
  2073.  
  2074. if font="?" then do
  2075.    say 
  2076.     say reverse ' List of alphabytes & fonts ' normal
  2077.     do while queued()>0
  2078.         pull .
  2079.     end /* do */
  2080.     oog=sysfiletree(gif_dir_root'*.*',qlist,'DO')
  2081.     foo=show_dir_queue(1)
  2082.     signal whatfont
  2083. end  /* Do */
  2084. if pos('\',whatfont)+pos(':',font)<>1  then do
  2085.      yoob=gif_dir_root||font
  2086.      wow=sysfiletree(yoob'\*.*',geeks)
  2087.      if geeks.0=0  then do
  2088.              say bold " ** Could not find directory for: " normal font
  2089.              signal whatfont
  2090.      end /* do */
  2091. end /* do */
  2092.  
  2093.  
  2094. say
  2095. getbACK:
  2096. call charout , bold"Background file (0=None, ?=list, Enter="def.!backgrnd"):" normal
  2097. pull backgrnd
  2098. if backgrnd='' then backgrnd=def.!backgrnd
  2099. if backgrnd="?" then do
  2100.     say 
  2101.     say reverse ' List of background files in: ' normal bold gif_dir_root'BACKS' normal
  2102.     do while queued()>0
  2103.         pull .
  2104.     end /* do */
  2105.     '@DIR /b  '||gif_dir_root||'BACKS\*.gif | rxqueue'
  2106.     foo=show_dir_queue('.GIF')
  2107.     signal getback
  2108. end
  2109. if pos('\',backgrnd)+pos(':',backgrnd)=0  & backgrnd<>0 then do
  2110.   backgrnd='BACKS\'||backgrnd
  2111.   if stream(gif_dir_root||backgrnd||'.gif','c','query exists')='' then do
  2112.       say " Could not find background file: " backgrnd
  2113.       signal getback
  2114.   end /* do */
  2115. end
  2116.  
  2117. say
  2118. getslide:
  2119. colorslide=0
  2120. call charout , bold"Color slide (0=None, ?=list, ENTER="def.!colorslide"):" normal
  2121. pull colorslide
  2122. if colorslide=''  then colorslide=def.!colorslide
  2123. if colorslide="?" then do
  2124.     say 
  2125.     say reverse ' List of color slides files in: ' normal bold gif_dir_root'SLIDES' normal
  2126.     do while queued()>0
  2127.         pull .
  2128.     end /* do */
  2129.     '@DIR /b  '||gif_dir_root||'SLIDES\*.gif | rxqueue'
  2130.     foo=show_dir_queue('.GIF')
  2131.     signal getslide
  2132. end
  2133. if pos('\',colorslide)+pos(':',colorslide)=0  & colorslide<>0 then do
  2134.   colorslide='slides\'||colorslide
  2135.   if stream(gif_dir_root||colorslide||'.gif','c','query exists')='' then do
  2136.       say " Could not find color slide file: " colorslide
  2137.       signal getslide
  2138.   end /* do */
  2139. end
  2140.  
  2141.  
  2142. say
  2143. getht:
  2144. call charout , bold"Height (in pixels), 0=automatic, ENTER="def.!height": "normal
  2145. pull height
  2146. if height="" then height=def.!height
  2147. if datatype(height)<>'NUM' then signal getht
  2148.  
  2149. getwt:
  2150. call charout , bold "Width (in pixels), 0=automatic ENTER="def.!width": "normal
  2151. pull width
  2152. if width="" then width=def.!width
  2153. if datatype(width)<>'NUM' then signal getwt
  2154.  
  2155.  
  2156. amess:
  2157. Say
  2158. Say bold "Enter your message " normal" ($d=date, $t=time, $n=newline, $f(fontname)=font switch "
  2159. say bold "   (ENTER=" normal reverse Def.!message normal bold ")" normal
  2160. call charout ,bold "The message:"normal
  2161. parse pull adesc
  2162. if adesc='' then adesc=def.!Message
  2163. adesc=a_replacestrg(adesc,'&','%26;','ALL')
  2164. message=translate(adesc,'+',' ')
  2165.  
  2166. get_opts:
  2167. say
  2168. say "Additional options (0=none,? for help, * xx = add xx to prior options "
  2169. say" ENTER=prior options=" bold def.!moreopts  normal
  2170. call charout, bold " ? " normal
  2171. pull moreopts
  2172. if moreopts='' then moreopts=def.!Moreopts
  2173.  
  2174. moreopts=a_replacestrg(moreopts,'*',def.!Moreopts,'ALL')
  2175. if strip(moreopts)=0 then moreopts=''
  2176. if moreopts<>'?' then say " Using options: " moreopts
  2177.  
  2178. if moreopts='?' then do
  2179.  call show_other_opts
  2180.  signal get_opts
  2181. end
  2182. moreopts=translate(moreopts,'&',' ')
  2183.  
  2184. /* now make a list */
  2185.  
  2186. list="font="||font||'&text='||message||'&height='||height||'&width='||width
  2187. list=list||'&back='||backgrnd||'&slide='||colorslide
  2188. if moreopts<>'' then list=list||'&'||moreopts
  2189.  
  2190. getgfile2:
  2191. Say
  2192. call charout,bold"Enter output file name (ENTER="def.!outgfile"):"normal
  2193. pull gfile2
  2194. if gfile2="" then gfile2=def.!outgfile
  2195. if gfile2="" then signal getgfile2
  2196. gfile0=stream(gfile2,'c','query exists')
  2197. if gfile0<>"" then do
  2198.     call charout,Gfile0 ' exists. Overwrite (Y/N)'
  2199.     pull anans
  2200.     if abbrev(strip(anans),'Y')<>1 then signal getgfile2
  2201. end /* do */
  2202. outgfile=gfile2
  2203.  
  2204. say
  2205. say " saving answers to GIF_TEXT.ANS "
  2206.  
  2207.  
  2208.  
  2209. aa='WIDTH='width||asep||'HEIGHT='height||asep||'FONT='font||asep
  2210. aa=aa||'BACKGRND='backgrnd||asep||'COLORSLIDE='colorslide||asep
  2211. aa=aa||'OUTGFILE='outgfile||asep||'MOREOPTS='Moreopts||asep
  2212. aa=aa||'MESSAGE='message||asep
  2213. foo=charout('GIF_TEXT.ANS',aa,1)
  2214. foo=stream('GIF_TEXT.ANS','c','close')
  2215.  
  2216. say " creating the image ..... "
  2217. return list  /* gfile2 is exposed */
  2218.  
  2219.  
  2220. ASKV:
  2221. SAY "Sorry, you made a goof.  Try again " sigl
  2222. exit
  2223.  
  2224.  
  2225. /*********/
  2226. show_other_opts:
  2227. say 
  2228. say ' More commonly used options. p=parameter, n=0..9, nnn=0..255, vv=0.0 ... 1.0 '
  2229. say '   TIME_FMT: Time format. timefmt=p ; p=LNHSCM1 '
  2230. say '   DATE_FMT: Date format. datefmt=p ; p=NDEMBOSUW' 
  2231. say ' BACK_SCALE: background display. back_scale=0/1 ; 1=scale, 0=tile '
  2232. say '        X_F: Size of frame (left and right), in pixels. x_f=n '
  2233. say '        Y_F: Size of frame (top and bottom), in pixels. y_f=n '
  2234. say '      X_SCA: Width scales:  X_SCA=vv+vv+vv (vv<1 = shrink, vv>1 enlarge'
  2235. say '      Y_SCA: Height scales: Y_SCA=vv+vv+vv'
  2236. say '      Y_VAL: Type of vertical alignment: Y_VAL=p ; p=TMB '
  2237. say '     LINE_J: Horizontal justifications (multi-line messages only)'
  2238. say ' These SLIDE_x options are only used when a color slide is specified'
  2239. say '    SLIDE_T: Threshold rules & parameter for color slides: slide_t=pnnn, p=PBC'
  2240. say '    SLIDE_V: Vertical mapping rule for color slides : T(ile),F(it),N(one)'
  2241. say '    SLIDE_H: Horizontal mapping rule for color slides (T(ile),F(it)'
  2242. say '    SLIDE_C: Center coordinates for color slide: slide_c=vv+vv'
  2243. say '   SLIDE_SI: Size of "user specified color slide" (# colors): slide_si=n'
  2244. say '   SLIDE_RE: Red color parameters for created slide: slide_red=vv+vv+vv"'
  2245. say '   SLIDE_GR: Green color parameters for created slide: slide_gr=vv+vv+vv "'
  2246. say '   SLIDE_BL: Blue color parameters for created slide: slide_bl=vv+vv+vv'
  2247. say '   SLIDE_PR: Probability parameters for using slide value: slide_pr=vv+vv+vv'
  2248. say ' Example: time_fmt=N  Y_SCA=0.5+1.2+2 x_F=2 y_f=2'
  2249. return 1
  2250.  
  2251.  
  2252. /*********/
  2253. /* show stuff in queue as a list */
  2254. show_dir_queue:procedure expose qlist.
  2255. parse arg lookfor
  2256.     ibs=0 ;mxlen=0
  2257.     if lookfor<>1 then
  2258.        nq=queued()
  2259.      else
  2260.         nq=qlist.0
  2261.     do ii=1 to nq
  2262.        if lookfor=1 then do
  2263.           aa=qlist.ii
  2264.           ii2=lastpos('\',aa) ; anam=substr(aa,ii2+1)
  2265.        end /* do */
  2266.        else do
  2267.           pull aa
  2268.           if pos(lookfor,aa)=0 then iterate
  2269.           parse var aa anam (lookfor) .
  2270.           if strip(anam)='.' | strip(anam)='..' then iterate
  2271.        end
  2272.        ibs=ibs+1
  2273.        blist.ibs=anam
  2274.        mxlen=max(length(anam),mxlen)
  2275.     end /* do */
  2276. arf=""
  2277. do il=1 to ibs
  2278.    anam=blist.il
  2279.    arf=arf||left(anam,mxlen+2)
  2280.    if length(arf)+mxlen+2>75  then do
  2281.         say arf
  2282.         arf=""
  2283.    end /* do */
  2284. end /* do */
  2285. if length(arf)>1 then say arf
  2286. say
  2287. return 1
  2288.  
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  /* ------------------------------------------------------------------ */
  2295.  /* function: Check if ANSI is activated                               */
  2296.  /*                                                                    */
  2297.  /* call:     CheckAnsi                                                */
  2298.  /*                                                                    */
  2299.  /* where:    -                                                        */
  2300.  /*                                                                    */
  2301.  /* returns:  1 - ANSI support detected                                */
  2302.  /*           0 - no ANSI support available                            */
  2303.  /*          -1 - error detecting ansi                                 */
  2304.  /*                                                                    */
  2305.  /* note:     Tested with the German and the US version of OS/2 3.0    */
  2306.  /*                                                                    */
  2307.  /*                                                                    */
  2308.  CheckAnsi: PROCEDURE
  2309.    thisRC = -1
  2310.  
  2311.    trace off
  2312.                          /* install a local error handler              */
  2313.    SIGNAL ON ERROR Name InitAnsiEnd
  2314.  
  2315.    "@ANSI 2>NUL | rxqueue 2>NUL"
  2316.  
  2317.    thisRC = 0
  2318.  
  2319.    do while queued() <> 0
  2320.      queueLine = lineIN( "QUEUE:" )
  2321.      if pos( " on.", queueLine ) <> 0 | ,                       /* USA */
  2322.         pos( " (ON).", queueLine ) <> 0 then                    /* GER */
  2323.        thisRC = 1
  2324.    end /* do while queued() <> 0 */
  2325.  
  2326.  InitAnsiEnd:
  2327.  signal off error
  2328.  RETURN thisRC
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335. a_replacestrg:
  2336.  
  2337. exactmatch=0
  2338. backward=0 ; doall=0
  2339.  
  2340. parse arg astring ,  target   , putme , type , exactmatch
  2341.  
  2342. type = translate(type)
  2343. if type="BACKWARD" then backward="YES"
  2344. if type="ALL" then doall="YES"
  2345.  
  2346. iat=1
  2347. joelen=length(target)
  2348. joelen2=length(putme)
  2349.  
  2350. doagain:                /* here if doall=yes */
  2351.  if exactmatch="YES" then do
  2352.     if   backward="YES" then
  2353.         joe= lastpos(target,astring)
  2354.     else
  2355.         joe= pos(target,astring,iat)
  2356.  end
  2357.  else do
  2358.    if   backward="YES" then
  2359.         joe= lastpos(translate(target),translate(astring))
  2360.     else
  2361.         joe= pos(translate(target),translate(astring),iat)
  2362.  end
  2363.  if joe=0 then
  2364.          return astring
  2365.  
  2366.  astring=delstr(astring,joe,joelen)
  2367.  if putme<>' ' then
  2368.     astring=insert(putme,astring,joe-1)
  2369.  
  2370.  if doall="YES" then do
  2371.      iat=joe+joelen2
  2372.      signal doagain
  2373.  end
  2374. /* else, all done */
  2375.  return astring
  2376.  
  2377.  
  2378.  
  2379.  
  2380. /* -------------------- */
  2381. /* get a yes or no , return 1 if yes */
  2382. yesno:procedure expose normal reverse bold
  2383. parse arg fooa , allopt,altans
  2384. if altans<>" " & words(altans)>1 then do
  2385.    w1=strip(word(altans,1))
  2386.    w2=strip(word(altans,2))
  2387.    a1=left(w1,1) ; a2=left(w2,1)
  2388.    a1a=substr(w1,2) ; a2a=substr(w2,2)
  2389. end
  2390. else do
  2391.     a1='Y' ; a1a='es'
  2392.     a2='N' ; a2a='o'
  2393. end  /* Do */
  2394. ayn='  '||bold||a1||normal||a1a||'\'||bold||a2||normal||a2a
  2395. if allopt=1 then  ayn=ayn||'\'||bold||'A'||normal||'ll'
  2396.  
  2397. do forever
  2398.  foo1=normal||reverse||fooa||normal||ayn
  2399.  call charout,  foo1 normal ':'
  2400.  pull anans
  2401.  if abbrev(anans,a1)=1 then return 1
  2402.  if abbrev(anans,a2)=1 then return 0
  2403.  if allopt=1 & abbrev(anans,'A')=1 then return 2
  2404. end
  2405.  
  2406. nocon:
  2407. if rc=-7 then return 0
  2408. exit 0
  2409.  
  2410. gpmprintf:procedure expose is_cgi
  2411. parse arg a1
  2412.  
  2413. if is_cgi=2 then do
  2414.   say a1
  2415.   return 1
  2416. end
  2417.  
  2418. if rxfuncquery('pmprintf')=0 then
  2419.     call pmprintf(a1)
  2420. return 0
  2421.  
  2422.  
  2423.