home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / ANSIFUN.ZIP / ANSIFUN.CMD
OS/2 REXX Batch file  |  1990-09-18  |  17KB  |  523 lines

  1. /************************************************************************
  2.  *
  3.  *  AnsiFun      Fun with ANSI escape sequences and REXX.
  4.  *
  5.  *  Programmer:  Michael J Antonio (MikeA) 713221.1742@CompuServe.com
  6.  * 
  7.  *  A series of general routines for manipulating the OS/2
  8.  *  screen by means of ANSI graphics.  The user must have 
  9.  *  set ANSI ON for this program to work.
  10.  *
  11.  *  This program also shows some interesting features of the REXX
  12.  *  language, and its usefulness in the OS/2 environment.
  13.  *
  14.  *  Feel free to use this program and share it with your friends.
  15.  *  If you do any wholesale copying of this code, just mention 
  16.  *  my name in the comments.
  17.  *
  18.  ***********************************************************************/
  19. "@"ECHO OFF
  20. 'ANSI ON | RXQUEUE'
  21. 'RXQUEUE /clear'
  22. /* TRACE A;  /* TRACE R; */ TRACE I */
  23. PARSE ARG length height border
  24.  
  25.    border = strip(border)
  26.    IF border = "" THEN 
  27.       border = 22
  28.  
  29.    Ansi. = "";   Box.  = ""
  30.  
  31.    CALL SetAnsi; CALL SetBox
  32.  
  33.    rc=AnsiSay(Ansi.UnWrap)
  34.  
  35.    /* Blank out the screen */
  36.    rc=AnsiSay(Ansi.plain || Ansi.cls)
  37.    rc=MoveCursor(3,3)
  38.  
  39.    /* There is rather a long pause before the box is drawn. */
  40.    rc=Write("Loading program - please wait...")
  41.  
  42.    /* Draw a box */
  43.    IF \datatype(length, "W") | length = 0 THEN
  44.       length = 75
  45.    IF \datatype(height, "W") | height = 0 THEN
  46.       height = 20
  47.    
  48.    /* Buffer the box to Ansi.string, write it when it is done */
  49.    Ansi.buf = 'on'
  50.    rc=DrawBox(1, 1, length, height, border, Ansi.bblack||Ansi.fred, Ansi.bcyan||Ansi.fblue, ' ') 
  51.    CALL FlushBuf
  52.  
  53.    /* Ego boost time (as if I need it) */
  54.    rc=MoveCursor(length-35,height+1)
  55.    rc=Write("Ansifun. (C) 1990, Michael Antonio.")
  56.    rc=MoveCursor(3,3)
  57.    rc=Write("Some fun stuff you can do with ANSI and REXX!")
  58.    CALL Wait 1
  59.  
  60.  
  61.    /* Show off screen I/O stuff. */
  62.    rc=MoveCursor(3,5)
  63.    rc=AnsiSay(Ansi.plain||Ansi.bold||Ansi.fblue)
  64.    rc=Write("Enter your name here:")
  65.    foo = GetInfo(25, 5, 25)
  66.    
  67.    rc=MoveCursor(3,7)
  68.    rc=AnsiSay(Ansi.plain||Ansi.fmagenta||Ansi.bblack)
  69.    rc=Write("Hello ")
  70.    rc=AnsiSay(Ansi.blink)
  71.    rc=Write(strip(foo))
  72.    rc=AnsiSay(Ansi.plain||Ansi.fmagenta||Ansi.bblack)
  73.    rc=AnsiSay(", and welcome to the world of ANSI!")
  74.    CALL Wait 1
  75.  
  76.    /* Mindless fun */
  77.    rc=MoveCursor(3, 9)
  78.    rc=AnsiSay(Ansi.plain || Ansi.fred ||Ansi.bold)
  79.    rc=Write("This is the world of ANSI"copies( " ", 9)"!")
  80.    rc=MoveCursor("<14")
  81.    CALL Wait 1
  82.    rc=AnsiSay(Ansi.bgreen || Ansi.fmagenta || Ansi.blink)
  83.    rc=Write("Extended Ansi")
  84.    rc=AnsiSay(Ansi.plain)
  85.    rc=MoveCursor("-11")
  86.  
  87.    /* Show off relative line drawing. */
  88.    rc=DrawBox(3,12,12,3,Box.shadow,,1,'03'x)
  89.    CALL Wait .5
  90.    rc=DrawBox(3,12,12,3,12,Ansi.fmagenta)
  91.    CALL Wait .5
  92.    rc=DrawBox(3,12,12,3,21,Ansi.fgreen)
  93.    rc=AnsiSay(Ansi.plain||Ansi.bblue||Ansi.fyellow)
  94.    rc=DrawLine(40,15,"-3","-")
  95.    rc=DrawLine(40,13,"+3","+")
  96.    rc=DrawLine(39,14,"<7","<")
  97.    rc=DrawLine(41,14,"7",">")
  98.    rc=DrawLine(40,14,">1","*",Ansi.blink||Ansi.rev)
  99.  
  100.    /* Get the cursor out of the way */
  101.    rc=MoveCursor(1, 23)
  102.    CALL Wait 2
  103. EXIT
  104.  
  105. /************************************************************************
  106.  *
  107.  * GetInfo:  Prompts the user for information and returns the user
  108.  *           input to the caller.  Prompt is done at screen position
  109.  *           (oCol, oRow) and the prompt goes for a length of (length)
  110.  *
  111.  *           Unfortunatly, there is nothing to prevent the user from 
  112.  *           typing beyond the end of field.
  113.  *
  114.  ***********************************************************************/
  115. GetInfo: PROCEDURE EXPOSE Ansi.
  116.    PARSE ARG oCol, oRow, length
  117.    rc=DrawLine(oCol, oRow, length,' ',Ansi.plain)
  118.    rc = MoveCursor("<"||length)
  119.    input = linein()
  120. RETURN substr(input,1,length,' ')
  121.  
  122. /************************************************************************
  123.  *
  124.  *  DrawBox: Draws a box to the screen at position (top, left) of 
  125.  *           dimensions (length x height).
  126.  *
  127.  *           A box type may be specified.  If (boxType) is a 2 digit 
  128.  *           numeric, then the values in the stem variable (Box.boxType) 
  129.  *           are used.  If boxType is a single character, then that
  130.  *           character is used when drawing the box.
  131.  *
  132.  *           Unless (borderColor) is specified, the current color is
  133.  *           used to draw the box.  A (fillColor) can also be specified,
  134.  *           or 1 to use the current color.  Otherwise, the inside of
  135.  *           the box is not erased.  A (fillChar) may be specified,
  136.  *           but " " is used as the default.
  137.  *
  138.  *           Some characters are pre-defined in the (Box.) stem
  139.  *           variable.
  140.  *
  141.  ***********************************************************************/
  142. DrawBox: PROCEDURE EXPOSE Ansi. Box.
  143.    PARSE ARG oCol,oRow,length,height,boxType,borderColor,fillColor,fillChar
  144.  
  145.    /* Check parameters */
  146.    IF \datatype(height, "W") THEN RETURN 1
  147.    IF \datatype(length, "W") THEN RETURN 1
  148.    IF \datatype(oCol, "W")   THEN oCol = 1
  149.    IF \datatype(oRow, "W")   THEN oRow = 1
  150.  
  151.    /* Set rectangle of box */
  152.    oCol   = MAX(oCol, 1)
  153.    oRow   = MAX(oRow,1)
  154.    height = MAX(height,1)
  155.    length = MAX(length,1)
  156.  
  157.    /* Position Cursor */
  158.    rc=MoveCursor(oCol, oRow)
  159.  
  160.    /* Set box type */
  161.    IF boxType = "" THEN
  162.       c = 22
  163.    ELSE IF length(strip(boxType)) = 2 & datatype(boxType, "W") THEN
  164.       c = boxType
  165.    ELSE
  166.       DO
  167.       c = substr(strip(boxType),1,1)
  168.       CALL SetBStem c
  169.       END
  170.  
  171.    /* Set border color */
  172.    IF borderColor <> "" THEN
  173.       rc=AnsiSay(borderColor)
  174.  
  175.    /* Draw box top */
  176.    rc=Write(Box.c.UpLc || copies(Box.c.HSide, Length) || Box.c.UpRc)
  177.  
  178.    /* Draw box side */
  179.    DO Height
  180.       rc=MoveCursor("-1", "<"||(Length+2))
  181.       rc=Write(Box.c.VSide)
  182.       rc=MoveCursor(">"||Length)
  183.       rc=Write(Box.c.VSide)
  184.    END
  185.  
  186.    /* Draw box Bottom */
  187.    rc=MoveCursor("-1", "<"||(Length+2))
  188.    rc=Write(Box.c.LoLc || copies(Box.c.HSide, Length) || Box.c.LoRc)
  189.  
  190.    /* If a fill color was specified, fill the box */
  191.    IF fillColor <> "" THEN
  192.       DO
  193.       IF fillColor = 1 THEN
  194.          fillColor = borderColor
  195.  
  196.       IF fillChar <> "" THEN
  197.          fChar = substr(strip(fillChar),1,1)
  198.       ELSE
  199.          fChar = " "
  200.  
  201.       rc=AnsiSay(fillColor)
  202.       rc=MoveCursor("+"||Height, "<"||(Length+1))
  203.          DO i = 1 TO height
  204.          rc=Write(copies(fChar, Length))
  205.          rc=MoveCursor("-1", "<"||Length)
  206.          END
  207.       END
  208.  
  209. RETURN rc
  210.  
  211. /*************************************************************************
  212.  *
  213.  *  DrawLine:  Draws a line to the screen at position (oRow, oCol) for
  214.  *             a length of (length).  It draws in the direction 
  215.  *             indicated by (+-<>) (up, down, left, right).  Direction
  216.  *             should be the first charactor of (length). Right is the
  217.  *             assumed direction of the line.
  218.  *
  219.  ************************************************************************/
  220. DrawLine: PROCEDURE EXPOSE Ansi.
  221.    PARSE ARG oCol, oRow, length, lChar, lColor
  222.  
  223.    IF datatype(oRow, "W") & datatype(oCol, "W") THEN
  224.       rc=MoveCursor(oCol, oRow)
  225.  
  226.    length = strip(length)
  227.    way = substr(length,1,1)
  228.    amount = substr(length,2)
  229.  
  230.    IF Pos(way, Ansi.userTable) = 0 THEN
  231.       DO
  232.       amount = way||amount
  233.       way = ">"
  234.       END
  235.  
  236.    IF lChar = "" THEN
  237.       lChar = " "
  238.    ELSE
  239.       lChar = substr(strip(lChar),1,1)
  240.  
  241.    IF lColor <> "" THEN
  242.       rc=AnsiSay(lColor)
  243.  
  244.    IF way = ">" THEN
  245.       rc=Write(copies(lChar, amount))
  246.    IF way = "<" THEN
  247.       DO amount
  248.       rc=Write(lChar)
  249.       rc=MoveCursor("<2")
  250.       END
  251.  
  252.    IF way = "-" | way = "+" THEN
  253.       DO amount
  254.       rc=Write(lChar)
  255.       rc=MoveCursor("<1",way"1")
  256.       END
  257.       
  258. RETURN rc
  259.  
  260. /*************************************************************************
  261.  *
  262.  *  MoveCursor:  Moves the cursor around the terminal screen.
  263.  *               MoveCursor accepts:
  264.  *
  265.  *               1) Two arguments, designating a colunm and row
  266.  *
  267.  *               2) A variable number of numeric arguments
  268.  *                  preceded by one of '+-<>' where:
  269.  *                     +n : Move cursor up    n lines.
  270.  *                     -n : Move cursor down  n lines.
  271.  *                     <n : Move cursor left  n columns.
  272.  *                     >n : Move cursor right n columns.
  273.  *
  274.  *               Note: If all cursor movement is done with MoveCursor,
  275.  *               then MoveCursor will update Ansi.cRow and Ansi.cCol
  276.  *               and not allow you to write outside the screen.
  277.  *
  278.  ************************************************************************/
  279. MoveCursor: PROCEDURE EXPOSE Ansi.  
  280.    PARSE UPPER ARG oCol, oRow
  281.  
  282.    oCol=strip(oCol)
  283.    oRow=strip(oRow)
  284.  
  285.    /* Initialize return code */
  286.    retCd=0
  287.  
  288.    /* Absolute move */
  289.    IF Pos(SubStr(oCol,1,1), Ansi.userTable) = 0 THEN
  290.       DO
  291.       IF  \datatype(oCol,"W") | \datatype(oRow,"W") THEN
  292.          RETURN
  293.       Ansi.col = MIN(oCol, Ansi.cols)
  294.       Ansi.row = MIN(oRow, Ansi.rows)
  295.       rc=AnsiSay(Ansi.esc || Ansi.row";"Ansi.col"f")
  296.       RETURN \((oCol=Ansi.col) & (oRow=Ansi.row))
  297.       END
  298.    ELSE
  299.       moves = oCol","oRow
  300.  
  301.    /* Relative move(s) */
  302.    DO UNTIL moves = ""
  303.       PARSE VAR moves move "," moves
  304.       move = strip(move)
  305.       way = substr(move,1,1)
  306.       amount = substr(move,2)
  307.  
  308.       IF \datatype(amount, "W") THEN ITERATE
  309.  
  310.       SELECT
  311.          WHEN way = "+" THEN
  312.             DO
  313.             IF Ansi.row-amount < 0 THEN
  314.                amount = Ansi.row
  315.             Ansi.row = Ansi.row - amount
  316.             END
  317.          WHEN way = "-" THEN 
  318.             DO
  319.             IF Ansi.row+amount > Ansi.rows THEN
  320.                amount = (Ansi.row+amount) - (Ansi.rows+1)
  321.             Ansi.row = MAX(Ansi.row + amount,1)
  322.             END
  323.          WHEN way = "<" THEN
  324.             DO
  325.             IF Ansi.col-amount < 0 THEN
  326.                amount = Ansi.col
  327.             Ansi.col = MAX(Ansi.col - amount,1)
  328.             END
  329.          WHEN way = ">" THEN 
  330.             DO
  331.             IF Ansi.col+amount > Ansi.cols THEN
  332.                amount = (Ansi.col+amount) - (Ansi.cols+1)
  333.             Ansi.col = Ansi.col + amount
  334.             END
  335.          OTHERWISE ITERATE
  336.       END
  337.  
  338.       IF amount = 0 THEN
  339.          ITERATE
  340.  
  341.       theWay = translate(way, Ansi.moveTable, Ansi.userTable)
  342.       rc=AnsiSay(Ansi.esc || amount || theWay)
  343.    END /* End DO UNTIL moves = "" */
  344.  
  345. RETURN retCd
  346.  
  347. /*************************************************************************
  348.  *
  349.  *  AnsiSay:  Writes Ansi screen attributes to the screen
  350.  *            so that it can be modified easily.  If Ansi.cls is
  351.  *            written, then Ansi.row and Ansi.col are set to 1.
  352.  *
  353.  *            If Ansi.buf = 'on', then the output is sent to a buffer.
  354.  *
  355.  ************************************************************************/
  356. AnsiSay: PROCEDURE EXPOSE Ansi.
  357.    PARSE ARG attribs
  358.    IF pos(Ansi.cls, attribs) <> 0 THEN
  359.       DO
  360.       Ansi.row=1; Ansi.col=1
  361.       END
  362.    IF Ansi.buf = 'on' THEN
  363.       Ansi.string = Ansi.string || attribs
  364.    ELSE
  365.       rc = charout(, attribs)
  366. RETURN 0
  367.  
  368. /*************************************************************************
  369.  *
  370.  *  Write:  Writes a string to the screen. Returns number of chars 
  371.  *          written.
  372.  *
  373.  *          If Ansi.buf = 'on', then the output is sent to a buffer.
  374.  *
  375.  ************************************************************************/
  376. Write: PROCEDURE EXPOSE Ansi.
  377.    PARSE ARG oStr
  378.    Ansi.col = Ansi.col + length(oStr)
  379.    IF Ansi.col > Ansi.cols THEN
  380.       DO
  381.       amt=length(oStr)-(Ansi.col-Ansi.cols)
  382.       oStr = substr(oStr,1,amt)
  383.       Ansi.col = Ansi.cols
  384.       END
  385.    IF Ansi.buf = 'on' THEN
  386.       Ansi.string = Ansi.string || oStr
  387.    ELSE
  388.       rc = charout(, oStr)
  389. RETURN rc
  390.  
  391. /*************************************************************************
  392.  *
  393.  *  FlushBuf:  Flushes the Ansi.string buffer to the screen.
  394.  *
  395.  ************************************************************************/
  396. FlushBuf: PROCEDURE EXPOSE Ansi.
  397.    rc=charout(,Ansi.string)
  398.    Ansi.string=""
  399.    Ansi.buf = ''
  400. RETURN
  401.  
  402. /*************************************************************************
  403.  *
  404.  *  Wait:  Pauses for (delay) seconds.
  405.  *
  406.  ************************************************************************/
  407. Wait: PROCEDURE
  408.    PARSE ARG delay
  409.    
  410.    IF \datatype(delay, "N") THEN
  411.       delay = 1
  412.    CALL Time("R")
  413.    DO WHILE Time("E") < delay
  414.       NOP
  415.    END
  416. RETURN
  417.  
  418. /*************************************************************************
  419.  *
  420.  *  SetAnsi:  Puts the ANSI escape codes and a few usefull constants
  421.  *            in the Ansi. stem variable
  422.  *
  423.  ************************************************************************/
  424. SetAnsi: PROCEDURE EXPOSE Ansi.  
  425.    escCd = '1B'x || "["
  426.  
  427.    /** Constants **/
  428.    Ansi.esc = escCd
  429.  
  430.    /* Row and column variables */
  431.    Ansi.rows=25; Ansi.cols=80
  432.    Ansi.row=1;  Ansi.col=1
  433.  
  434.    /* Move charactos - Up, Down, Left, Right */
  435.    Ansi.moveTable = "ABDC"
  436.    Ansi.userTable = '+-<>'
  437.  
  438.    /** Escape codes : NS = Not Supported under OS/2 **/
  439.  
  440.    Ansi.cls    = escCd || "2J"  /* Clears the screen */
  441.    Ansi.erase  = escCd || "K"   /* Erase to End-Of-Line */
  442.  
  443.    /** Screen Attributes:  Used with ScrAttr */
  444.  
  445.    /* Styles */
  446.    Ansi.plain  = escCd || "0m"  /* All attributes off */
  447.    Ansi.bold   = escCd || "1m"  /* Bold type */
  448.    Ansi.faint  = escCd || "2m"  /* Faint type -NS */
  449.    Ansi.italic = escCd || "3m"  /* Italic type */
  450.    Ansi.blink  = escCd || "5m"  /* Blink type */
  451.    Ansi.rblink = escCd || "6m"  /* Rapid-Blink type - NS */
  452.    Ansi.rev    = escCd || "7m"  /* Reverse video */
  453.    Ansi.hidden = escCd || "8m"  /* Concealed type */
  454.    Ansi.subscr = escCd || "48m" /* Subscript */
  455.    Ansi.supscr = escCd || "49m" /* Superscript */
  456.  
  457.    /* Colors, (b)ackground and (f)oreground */
  458.    Ansi.bblack   = escCd || "30m"; Ansi.fblack   = escCd || "40m"
  459.    Ansi.bred     = escCd || "31m"; Ansi.fred     = escCd || "41m"
  460.    Ansi.bgreen   = escCd || "32m"; Ansi.fgreen   = escCd || "42m"
  461.    Ansi.byellow  = escCd || "33m"; Ansi.fyellow  = escCd || "43m"
  462.    Ansi.bblue    = escCd || "34m"; Ansi.fblue    = escCd || "44m"
  463.    Ansi.bmagneta = escCd || "35m"; Ansi.fmagenta = escCd || "45m"
  464.    Ansi.bcyan    = escCd || "36m"; Ansi.fcyan    = escCd || "46m"
  465.    
  466.    /* Screen modes 40x25 = 40 X 25, B = Black and White.  C = Color */
  467.    Ansi.40x25B   = escCd || "=0h"; Ansi.40x25C   = escCd || "=1h"
  468.    Ansi.80x25B   = escCd || "=2h"; Ansi.80x25C   = escCd || "=3h"
  469.    Ansi.320x200B = escCd || "=4h"
  470.    Ansi.640x200B = escCd || "=5h"; Ansi.640x200C = escCd || "=6h"
  471.    Ansi.Wrap     = escCd || "=7h"; Ansi.UnWrap   = escCd || "=7I"
  472. RETURN
  473.  
  474. /*************************************************************************
  475.  *
  476.  *  SetBox:  Sets up borders for the different kinds of boxes DrawBox
  477.  *           can draw.
  478.  *
  479.  ************************************************************************/
  480. SetBox: PROCEDURE EXPOSE Box.
  481.  
  482.    Box.space   = ' '
  483.    Box.LShadow = 'B0'x
  484.    Box.Shadow  = 'B1'x
  485.    Box.DShadow = 'B2'x
  486.  
  487.    /* Single border */
  488.    Box.11.UpLc  = 'DA'x; Box.11.LoLc  = 'C0'x
  489.    Box.11.UpRc  = 'BF'x; Box.11.LoRc  = 'D9'x
  490.    Box.11.HSide = 'C4'x; Box.11.VSide = 'B3'x
  491.  
  492.    /* Double border */
  493.    Box.22.UpLc  = 'C9'x; Box.22.LoLc  = 'C8'x
  494.    Box.22.UpRc  = 'BB'x; Box.22.LoRc  = 'BC'x
  495.    Box.22.HSide = 'CD'x; Box.22.VSide = 'BA'x
  496.  
  497.    /* Single top+bot, double sides */
  498.    Box.12.UpLc  = 'D6'x;Box.12.LoLc  = 'D3'x
  499.    Box.12.UpRc  = 'B7'x;Box.12.LoRc  = 'BD'x
  500.    Box.12.HSide = 'C4'x;Box.12.VSide = 'BA'x
  501.  
  502.    /* Double top+bot, single sides */
  503.    Box.21.UpLc  = 'D5'x;Box.21.LoLc  = 'D4'x
  504.    Box.21.UpRc  = 'B8'x;Box.21.LoRc  = 'BE'x
  505.    Box.21.HSide = 'CD'x;Box.21.VSide = 'B3'x
  506.  
  507. RETURN
  508.  
  509. /*************************************************************************
  510.  *
  511.  *  SetBStem:  Sets up border to draw the user defined charactor.
  512.  *
  513.  ************************************************************************/
  514. SetBStem: PROCEDURE EXPOSE Box.
  515.    PARSE ARG char
  516.  
  517.    Box.char.UpLc  = char;Box.char.LoLc  = char
  518.    Box.char.UpRc  = char;Box.char.LoRc  = char
  519.    Box.char.HSide = char;Box.char.VSide = char
  520.  
  521. RETURN
  522. /* END */
  523.