home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / shwini32.zip / boxedit.cmd next >
OS/2 REXX Batch file  |  1992-06-01  |  23KB  |  744 lines

  1. /*
  2. program: boxedit.cmd
  3. type:    REXXSAA-OS/2, OS/2 2.0
  4. purpose: allow for editing text in a box
  5. version: 1.04
  6. date:    1992-06-01
  7.  
  8. author:  Rony G. Flatscher
  9.          RONY@AWIWUW11.BITNET
  10.          rony@wu-wien.ac.at
  11.  
  12. usage:   BOXEDIT(first_row first_col last_row last_col style [, [initial_text] [,[A|H] [, prompt] ]] )
  13. returns: edited text
  14.  
  15. argument 1: rectangular dimensions plus optional style
  16.             ... first_row = 0-based, first_col = 0-based
  17.             style ... "", 1, 2, 3
  18.  
  19. argument 2: initial text (optional)
  20.  
  21. arbument 3: optional type of text
  22.             A ... ASCII-Text (default)
  23.             H ... hexadecimal Text
  24.  
  25. argument 4: prompt to be displayed (optional)
  26.  
  27. Following key-combinations can be used while editing:
  28.  
  29.         ESC             ... abort editing, return unchanged text
  30.         F10             ... save edited text, return it
  31.  
  32.         ENTER           ... get to beginning of next line
  33.  
  34.         TAB             ... advance cursor 8 characters
  35.         BACK-TAB        ... move cursor 8 characters backward
  36.  
  37.         CTRL-RIGHT      ... move cursor to beginning of next word
  38.         CTRL-LEFT       ... move cursor to beginning of present/previous word
  39.  
  40.         END             ... move cursor to last column of current line
  41.         HOME            ... move cursor to first column of current line
  42.  
  43.         CTRL-END        ... move cursor to last line, last column of box
  44.         CTRL-HOME       ... move cursor to first line, first column of box
  45.  
  46.         CTRL-ENTER      ... insert blank line, move current line down
  47.         CTRL-BACKSPACE  ... delete current line
  48.  
  49. All rights reserved, copyrighted 1992, no guarantee that it works without
  50. errors, etc. etc.
  51.  
  52. donated to the public domain granted that you are not charging anything (money
  53. etc.) for it and derivates based upon it, as you did not write it,
  54. etc. if that holds you may bundle it with commercial programs too
  55.  
  56. you may freely distribute this program, granted that no changes are made
  57. to it
  58.  
  59. Please, if you find an error, post me a message describing it, I will
  60. try to fix and rerelease it to the net.
  61.  
  62. */
  63.  
  64.  
  65. PARSE SOURCE  . invocation .
  66.  
  67. IF invocation <> "FUNCTION" THEN SIGNAL usage
  68.  
  69. PARSE VALUE ARG(1) WITH first_row first_col last_row last_col style
  70.  
  71. CALL ON HALT
  72.  
  73.  
  74. type = TRANSLATE(ARG(3))        /* translate into uppercase */
  75.  
  76. IF TRANSLATE(SUBSTR(ARG(3),1,1)) = "H" THEN type = "H"  /* hex-edit */
  77. ELSE type = "A"                                         /* ASCII-edit */
  78.  
  79. /* check whether RxFuncs are loaded, if not, load them */
  80. IF RxFuncQuery('SysLoadFuncs') THEN
  81. DO
  82.     /* load the load-function */
  83.     CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'       
  84.  
  85.     /* load the Sys* utilities */
  86.     CALL SysLoadFuncs                                                 
  87. END
  88.  
  89. /* save screen-area context */
  90. PARSE VALUE SysTextScreenSize() WITH row columns
  91. PARSE VALUE SysCurPos() WITH cursor_row cursor_col
  92.  
  93. save_screen = SysTextScreenRead(first_row, 0, (last_row - first_row + 1) * (columns + 1))
  94.  
  95. IF type = "H" THEN top_line = "Hex-edit [0-9,A-F]"
  96. ELSE top_line = "ASCII-edit"
  97.  
  98. IF ARG(4) <> "" THEN            /* was a prompt supplied ? */
  99. DO
  100.    top_line = ARG(4) "(" || top_line || ")"
  101. END
  102.  
  103. bottom_line = "<F10:save> <Esc:abort>"
  104. client_area = draw_box(ARG(1), top_line, bottom_line)   /* draw frame */
  105.  
  106. CALL write_box client_area ARG(2)                       /* fill box with text */
  107.  
  108. /* position cursor one character after the last letter */
  109. PARSE VAR client_area startRow startColumn endRow endColumn
  110.  
  111. textLength = LENGTH(ARG(2))
  112. charsPerLine = endColumn - startColumn + 1
  113. posColumn = startColumn + textLength // charsPerLine 
  114. posRow = startRow + textLength % charsPerLine
  115.  
  116. IF posColumn > endColumn THEN
  117. DO
  118.    posColumn = startColumn
  119.    posRow = posRow + 1
  120. END
  121.  
  122. IF posRow > endRow THEN posRow = startRow
  123.  
  124. CALL SysCurPos posRow, posColumn       /* position cursor right after last character */
  125.  
  126.  
  127. tmp = edit_box(client_area)            /* edit text */
  128.  
  129. IF tmp = "SAVE" THEN res = read_box(client_area) /* read new text */
  130.                 ELSE res = ARG(2)                /* leave text unchanged */
  131.  
  132. /* restore screen-area context */
  133. CALL SysCurState "off"                 /* turn cursor off */
  134. CALL SysCurPos first_row, 0            /* place cursor    */
  135. CALL CHAROUT , save_screen             /* restore screen  */
  136. CALL SysCurPos cursor_row, cursor_col  /* restore cursor  */
  137. CALL SysCurState "on"                  /* turn cursor on  */
  138.  
  139. RETURN res
  140.  
  141.  
  142.  
  143. /*****************************************************************/
  144.  
  145. HALT:
  146. /* 
  147.    Say "stop? (y/n) "
  148.    key = SysGetKey("noecho")
  149.    IF TRANSLATE(key) = "Y" THEN EXIT
  150.    key = "3"x 
  151. */
  152.    RETURN
  153.  
  154.  
  155.  
  156. /* define a square on a text-screen to edit */
  157. EDIT_BOX: PROCEDURE EXPOSE type
  158.    PARSE ARG first_row first_col last_row last_col
  159.    PARSE VALUE SysCurPos() WITH act_row act_col
  160.  
  161.    DO FOREVER
  162.  
  163.       key = SysGetKey("noecho")
  164.       d2ckey = C2D(key)
  165.  
  166.       SELECT
  167.          WHEN d2ckey = 13 THEN      /* Carriage-return was pressed */
  168.             DO
  169.                d2ckey = 224         /* fake lead-in */
  170.                d2ckey2 = 999        /* "impossible" char-value */
  171.             END
  172.  
  173.          WHEN d2ckey = 8 THEN       /* Backspace pressed */
  174.             DO
  175.                CALL edit_box_text ARG(1) "BACKUP"
  176.                PARSE VALUE SysCurPos() WITH act_row act_col
  177.                ITERATE
  178.             END
  179.  
  180.          WHEN d2ckey = 9 THEN       /* TAB pressed */
  181.             DO
  182.                CALL edit_box_text ARG(1) "TAB"
  183.                PARSE VALUE SysCurPos() WITH act_row act_col
  184.                ITERATE
  185.             END
  186.  
  187.          WHEN d2ckey = 10 THEN      /* CTRL-Enter pressed = insertline */
  188.             DO
  189.                CALL edit_box_text ARG(1) "INSERTLINE"
  190.                ITERATE
  191.             END
  192.  
  193.  
  194.          WHEN d2ckey = 27 THEN      /* ESCape was pressed, abort */
  195.             RETURN "ESCAPE"
  196.  
  197.          WHEN d2ckey = 127 THEN     /* CTRL-Backspace pressed = deleteline */
  198.             DO
  199.                CALL edit_box_text ARG(1) "DELETELINE"
  200.                ITERATE
  201.             END
  202.  
  203.          WHEN d2ckey = 224 | d2ckey = 0 THEN   /* escape-sequence in hand ? */
  204.             DO
  205.                key2 = SysGetKey("noecho")       /* get next code */
  206.                d2ckey2 = C2D(key2)
  207.  
  208.                IF d2ckey = 224 THEN
  209.                   SELECT
  210.                      WHEN d2ckey2 = 82  THEN    /* insert pressed */
  211.                      DO
  212.                         CALL edit_box_text ARG(1) "INSERT"
  213.                         ITERATE
  214.                      END
  215.  
  216.                      WHEN d2ckey2 = 83 THEN /* delete pressed */
  217.                      DO
  218.                         CALL edit_box_text ARG(1) "DELETE"
  219.                         ITERATE
  220.                      END
  221.  
  222.                      WHEN d2ckey2 = 116 THEN /* CTRL-right pressed */
  223.                      DO
  224.                         CALL edit_box_text ARG(1) "CTRL-RIGHT"
  225.                         PARSE VALUE SysCurPos() WITH act_row act_col
  226.                         ITERATE
  227.                      END
  228.  
  229.                      WHEN d2ckey2 = 115 THEN /* CTRL-left pressed */
  230.                      DO
  231.                         CALL edit_box_text ARG(1) "CTRL-LEFT"
  232.                         PARSE VALUE SysCurPos() WITH act_row act_col
  233.                         ITERATE
  234.                      END
  235.  
  236.                      WHEN d2ckey2 = 119 THEN /* CTRL-HOME (STRG-POS1) pressed move to first row, column */
  237.                      DO
  238.                         act_row = first_row
  239.                         act_col = first_col
  240.                         CALL SysCurPos act_row, act_col
  241.                         ITERATE
  242.                      END
  243.  
  244.                      WHEN d2ckey2 = 71 THEN /* HOME (POS1) pressed move to first column */
  245.                      DO
  246.                         act_col = first_col
  247.                         CALL SysCurPos act_row, act_col
  248.                         ITERATE
  249.                      END
  250.  
  251.                      WHEN d2ckey2 = 117 THEN /* CTRL-END (STRG-ENDE) pressed move to last row, column */
  252.                      DO
  253.                         act_row = last_row
  254.                         act_col = last_col
  255.                         CALL SysCurPos act_row, act_col
  256.                         ITERATE
  257.                      END
  258.  
  259.                      WHEN d2ckey2 = 79 THEN /* END (ENDE) pressed move to last column */
  260.                      DO
  261.                         act_col = last_col
  262.                         CALL SysCurPos act_row, act_col
  263.                         ITERATE
  264.                      END
  265.  
  266.  
  267.                      OTHERWISE NOP
  268.                   END
  269.             END
  270.  
  271.          OTHERWISE   /* regular key pressed */
  272.             DO
  273.                IF type = "H" THEN
  274.                DO
  275.                   key = TRANSLATE(key)
  276.                   IF POS(key, "0123456789ABCDEF") = 0 THEN
  277.                   DO
  278.                      CALL BEEP 440, 100
  279.                      ITERATE
  280.                   END
  281.                END
  282.  
  283.                CALL CHAROUT , key      /* echo key to screen */
  284.                /* fake a right-key-press */
  285.                d2ckey  = 224
  286.                d2ckey2 = 77
  287.             END
  288.       END
  289.  
  290.       IF d2ckey = 224 THEN            /* cursor-pad-key pressed */
  291.       DO
  292.          SELECT
  293.             WHEN d2ckey2 = 999 THEN    /* enter was pressed, get to beginning of next line */
  294.                DO
  295.                   act_row = act_row + 1
  296.                   act_col = first_col
  297.                END
  298.  
  299.             WHEN d2ckey2 = 72 THEN     /* upper-arrow pressed */
  300.                act_row = act_row - 1
  301.  
  302.             WHEN d2ckey2 = 80 THEN     /* down-arrow pressed */
  303.                act_row = act_row + 1
  304.  
  305.             WHEN d2ckey2 = 75 THEN     /* left-arrow pressed */
  306.                act_col = act_col - 1
  307.  
  308.             WHEN d2ckey2 = 77 THEN     /* right-arrow pressed */
  309.                act_col = act_col + 1
  310.  
  311.             OTHERWISE CALL BEEP 440, 100
  312.          END
  313.  
  314.  
  315.          IF act_col < first_col THEN   /* check whether valid ranges */
  316.          DO
  317.             act_col = last_col
  318.             act_row = act_row - 1
  319.          END
  320.  
  321.          IF act_col > last_col THEN
  322.          DO
  323.             act_col = first_col
  324.             act_row = act_row + 1
  325.          END
  326.  
  327.          IF act_row < first_row THEN
  328.          DO
  329.             act_row = last_row
  330.          END
  331.  
  332.          IF act_row > last_row THEN
  333.          DO
  334.             act_row = first_row
  335.          END
  336.  
  337.       END
  338.       ELSE     /* lead-in is 0 */
  339.       DO
  340.          SELECT
  341.             WHEN d2ckey2 = 15 THEN       /* BACK-TAB pressed */
  342.                DO
  343.                   CALL edit_box_text ARG(1) "BACK-TAB"
  344.                   PARSE VALUE SysCurPos() WITH act_row act_col
  345.                   ITERATE
  346.                END
  347.  
  348.             WHEN d2ckey2 = 68 THEN     /* F10 was pressed, save */
  349.             DO
  350.                IF type = "H" THEN       /* check for even numbers of characters and no blanks */
  351.                DO
  352.                   tmp = STRIP(read_box(ARG(1)))
  353.                   IF POS(" ", tmp) > 0 THEN
  354.                   DO
  355.                      CALL error_msg "HEX-string must not contain blanks!"
  356.                      ITERATE
  357.                   END
  358.  
  359.                   IF LENGTH(tmp) // 2 = 1 THEN
  360.                   DO
  361.                      CALL error_msg "HEX-string must consist of even number of characters! ("LENGTH(tmp)" in HEX-string)"
  362.                      ITERATE
  363.                   END
  364.                     
  365.  
  366.  
  367.                END
  368.                RETURN "SAVE"
  369.             END
  370.  
  371.             OTHERWISE                  /* all other keys are ignored */
  372.                CALL BEEP 440, 100
  373.          END
  374.       END
  375.  
  376.       CALL SysCurPos act_row, act_col  /* position cursor on new position */
  377.    END
  378.    RETURN
  379.  
  380.  
  381.  
  382. /* process edit keys DELETE, INSERT, BACKSPACE,
  383.    CTRL-RIGHT, CTRL-LEFT, TAB and BACKTAB in box */
  384.  
  385. EDIT_BOX_TEXT: PROCEDURE EXPOSE type
  386.    PARSE ARG first_row first_col last_row last_col switch
  387.    PARSE VALUE SysCurPos() WITH act_row act_col
  388.  
  389.    delimiters = " !""#$%&'()*+,-./:;<=>@[\]^_`{|}~"
  390.  
  391.    client = first_row first_col last_row last_col
  392.    text = Read_Box(client)
  393.    line_nr = act_row - first_row
  394.    line_length = last_col - first_col + 1
  395.  
  396.    charpos = line_nr * line_length + (act_col - first_col + 1)
  397.  
  398.    SELECT
  399.       WHEN switch = "INSERT" THEN
  400.          DO
  401.             tmp = SUBSTR(text, 1, charpos - 1) || " " || SUBSTR(text, charpos)
  402.          END
  403.  
  404.       WHEN switch = "DELETE" THEN
  405.          DO
  406.             tmp = SUBSTR(text, 1, charpos - 1) || SUBSTR(text, charpos + 1)
  407.          END
  408.  
  409.       WHEN switch = "BACKUP" THEN
  410.          DO
  411.             IF (act_row act_col) = (first_row first_col) THEN
  412.             DO
  413.                CALL BEEP 440,100  /* cannot backspace, if in first position */
  414.                RETURN
  415.             END
  416.             ELSE
  417.             DO
  418.                tmp = SUBSTR(text, 1, charpos - 2) || SUBSTR(text, charpos)
  419.                act_col = act_col - 1
  420.  
  421.                IF act_col < first_col THEN
  422.                DO
  423.                   act_col = last_col
  424.                   act_row = act_row - 1
  425.                   IF act_row < first_row THEN
  426.                      act_row = last_row
  427.                END
  428.             END
  429.          END
  430.  
  431.       WHEN switch = "CTRL-RIGHT" THEN  /* find beginning of NEXT word */
  432.          DO
  433.             /* find first character which appears in delimiters */
  434.             index = VERIFY(text, delimiters, "M", charpos)
  435.  
  436.             IF index = 0 THEN index = 1
  437.  
  438.             index = VERIFY(text, delimiters, , index)
  439.  
  440.             IF index = 0 THEN
  441.             DO
  442.                act_row = first_row
  443.                act_col = first_col
  444.             END
  445.             ELSE
  446.             DO
  447.                index = index - 1
  448.                act_row = first_row + index % line_length
  449.                act_col = first_col + index // line_length
  450.             END
  451.  
  452.             CALL SysCurPos act_row, act_col  /* position cursor */
  453.             RETURN
  454.          END
  455.  
  456.  
  457.       WHEN switch = "CTRL-LEFT" THEN  /* find beginning of PREVIOUS word */
  458.          DO
  459.             IF LENGTH(text) = 0 THEN RETURN
  460.  
  461.             /* if on first, position search from the very last */
  462.             IF (act_row act_col) = (first_row first_col) THEN
  463.                 i = 0
  464.             ELSE     /* only delimiters before this character ? */
  465.             DO i = charpos - 1 TO 1 BY -1
  466.                IF POS(SUBSTR(text, i, 1), delimiters) > 0 THEN ITERATE
  467.                LEAVE
  468.             END
  469.  
  470.             IF i = 0 THEN charpos = LENGTH(text) + 1
  471.  
  472.             index = charpos - 1
  473.             alpha = (POS(SUBSTR(text, (charpos - 1), 1), delimiters) = 0)
  474.  
  475.             IF \alpha THEN    /* non-alpha in hand, search for first alpha */
  476.             DO
  477.                DO i = charpos - 2 TO 1 BY -1
  478.                   IF POS(SUBSTR(text, i, 1), delimiters) > 0 THEN ITERATE
  479.                   index = i
  480.                   LEAVE
  481.                END
  482.             END
  483.  
  484.             alpha_processed = 0
  485.  
  486.             DO i = index TO 1 BY -1 /* search beginning of alpha */
  487.                IF POS(SUBSTR(text, i, 1,), delimiters) = 0 THEN ITERATE
  488.                index = i + 1
  489.                alpha_processed = 1
  490.                LEAVE
  491.             END
  492.  
  493.             IF \alpha_processed THEN index = 1
  494.  
  495.             IF index = 0 THEN
  496.             DO
  497.                act_row = first_row
  498.                act_col = first_col
  499.             END
  500.             ELSE
  501.             DO
  502.                index = index - 1
  503.                act_row = first_row + index % line_length
  504.                act_col = first_col + index // line_length
  505.             END
  506.  
  507.             CALL SysCurPos act_row, act_col  /* position cursor */
  508.             RETURN
  509.          END
  510.  
  511.       WHEN switch = "INSERTLINE" | switch = "DELETELINE" THEN
  512.          DO
  513.             text = read_box(client)   /* read actual text */
  514.  
  515.             line_length = last_col - first_col + 1
  516.             line_nr     = last_row - first_row + 1
  517.             act_line    = act_row  - first_row + 1
  518.  
  519.             IF switch = "INSERTLINE" THEN
  520.             DO
  521.                tmp = SUBSTR(text, 1, (act_line - 1) * line_length) ||,
  522.                      COPIES(" ", line_length) ||,
  523.                      SUBSTR(text, (act_line - 1) * line_length + 1)
  524.  
  525.              END
  526.             ELSE     /* delete present line */
  527.             DO
  528.                IF act_line = 1 THEN
  529.                   tmp = SUBSTR(text, line_length + 1)
  530.                ELSE
  531.                   tmp = SUBSTR(text, 1, (act_line - 1) * line_length) ||,
  532.                         SUBSTR(text, act_line * line_length + 1)
  533.             END
  534.          END
  535.  
  536.       WHEN switch = "TAB" | switch = "BACK-TAB" THEN  /* position according to tab */
  537.          DO
  538.             tabs = 8    /* tab-interval */
  539.             IF switch = "TAB" THEN act_col = act_col + tabs
  540.                               ELSE act_col = act_col - tabs
  541.  
  542.             IF act_col > last_col THEN
  543.             DO
  544.                act_row = act_row + 1
  545.                act_col = first_col + (act_col - last_col) - 1
  546.             END
  547.  
  548.             IF act_col < first_col THEN
  549.             DO
  550.                act_row = act_row - 1
  551.                act_col = last_col + (act_col - first_col) + 1
  552.             END
  553.  
  554.             IF act_row > last_row THEN
  555.                act_row = first_row
  556.  
  557.             IF act_row < first_row THEN
  558.                act_row = last_row
  559.  
  560.  
  561.             CALL SysCurPos act_row, act_col  /* position cursor */
  562.             RETURN
  563.          END
  564.  
  565.  
  566.       OTHERWISE NOP
  567.    END
  568.  
  569.    CALL Write_Box(client tmp)       /* update box */
  570.    CALL SysCurPos act_row, act_col  /* restore cursor */
  571.  
  572.    RETURN
  573.  
  574.  
  575.  
  576.  
  577.  
  578. /* draw a box in the given square, return client-size */
  579. draw_box: PROCEDURE EXPOSE type
  580.    PARSE ARG first_row first_col last_row last_col style
  581.  
  582.    IF style = '' then style = 1   /* define default */
  583.  
  584.    /* text-window dimenstions */
  585.    PARSE VALUE SysTextScreenSize() with sys_row sys_col
  586.    sys_row = sys_row - 1
  587.    sys_col = sys_col - 1
  588.  
  589.  
  590.    /* left-upper-corner, horizontal, right-upper-corner,
  591.       left-lower-corner, vertical, right-lower-corner */
  592.    set.1 = "┌ ─ ┐ └ │ ┘"
  593.    set.2 = "╔ ═ ╗ ╚ ║ ╝"
  594.    set.3 = "+ - + + | +"
  595.  
  596.    inner_width = last_col - first_col - 1
  597.    CALL SysCurState "off"               /* turn cursor off */
  598.  
  599.    /* first line of box */
  600.  
  601.    tmp0 = WORD(set.style, 1) || COPIES(WORD(set.style, 2), inner_width) || WORD(set.style, 3)
  602.    tmp1 = ARG(2)                        /* prompt */
  603.  
  604.    n = TRUNC((LENGTH(tmp0) - LENGTH(tmp1)) / 2) + 1
  605.    IF n < 1 THEN 
  606.       n = 1
  607.  
  608.    tmp0 = OVERLAY(tmp1, tmp0, n)
  609.  
  610.    CALL SysCurPos first_row, first_col
  611.    CALL CHAROUT , tmp0
  612.                   
  613.  
  614.    /* middle lines of box */
  615.    middle_line = WORD(set.style, 5) || ,
  616.                  COPIES(" ", last_col - first_col - 1) || ,
  617.                  WORD(set.style, 5)
  618.    DO i = first_row + 1 TO last_row - 1
  619.       CALL SysCurPos i, first_col
  620.       CALL CHAROUT , middle_line
  621.    END
  622.  
  623.    /* last line of box */
  624.    CALL SysCurPos last_row, first_col
  625.  
  626.    tmp0 = WORD(set.style, 4) || COPIES(WORD(set.style, 2), inner_width) || WORD(set.style, 6)
  627.  
  628.    tmp1 = ARG(3)
  629.  
  630.    n = TRUNC((LENGTH(tmp0) - LENGTH(tmp1)) / 2) + 1
  631.  
  632.    IF n < 1 THEN 
  633.       n = 1
  634.  
  635.    tmp0 = OVERLAY(tmp1, tmp0, n)
  636.    CALL CHAROUT , tmp0
  637.  
  638.  
  639.    CALL SysCurPos first_row + 1, first_col + 1  /* position in client-area */
  640.    CALL SysCurState "on"     /* turn cursor on */
  641.  
  642.    RETURN (first_row + 1) (first_col + 1) (last_row - 1) (last_col - 1)
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649. /* write string into box */
  650. WRITE_BOX: PROCEDURE
  651.    PARSE ARG first_row first_col last_row last_col text
  652.  
  653.    line_length = last_col - first_col + 1
  654.    line_nr     = last_row - first_row + 1
  655.  
  656.    CALL SysCurState "off"     /* turn cursor off */
  657.  
  658.    next_item = 1
  659.    DO i = 0 TO line_nr - 1
  660.       CALL SysCurPos first_row + i, first_col
  661.       CALL CHAROUT , SUBSTR(text, next_item, line_length)
  662.       next_item = next_item + line_length
  663.    END
  664.  
  665.    CALL SysCurState "on"     /* turn cursor on */
  666.    CALL SysCurPos first_row, first_col
  667.  
  668.    RETURN
  669.  
  670.  
  671.  
  672. /* read string from box */
  673. READ_BOX: PROCEDURE
  674.    PARSE ARG first_row first_col last_row last_col .
  675.  
  676.    line_length = last_col - first_col + 1
  677.    line_nr     = last_row - first_row + 1
  678.    tmp = ''
  679.    DO i = 0 TO line_nr - 1
  680.       tmp = tmp || SysTextScreenRead(first_row + i, first_col, line_length)
  681.    END
  682.  
  683.    RETURN tmp
  684.  
  685.  
  686. /* show an error box */
  687. ERROR_MSG: PROCEDURE
  688.    /* save screen-area context */
  689.    nr_lines = 1
  690.  
  691.    CALL SysCurState "off"                               /* turn cursor off */
  692.    PARSE VALUE SysTextScreenSize() WITH row columns     /* get screen dimensions */
  693.    PARSE VALUE SysCurPos() WITH cursor_row cursor_col   /* get current position */
  694.  
  695.    r0 = cursor_row - nr_lines
  696.    IF r0 < 0 THEN
  697.       r0 = 0
  698.  
  699.    /* draw box at center of screen */
  700.    c0 = (columns - LENGTH(ARG(1))) % 2 - 1              /* starting position of window */
  701.    rn = cursor_row + nr_lines
  702.  
  703.    cn = c0 + LENGTH(ARG(1)) + 3                         /* wideness of window */
  704.  
  705.    save_screen = SysTextScreenRead(r0, 0, (rn - r0 + 1) * columns)
  706.  
  707.    client_area = draw_box(r0 c0 rn cn 2, "Error:", "<press any key to continue>")    /* draw frame */
  708.  
  709.    CALL write_box client_area CENTER(ARG(1), cn - (c0 + 2) + 1) /* fill box with text */
  710.  
  711.  
  712.    CALL BEEP 2500, 250
  713.    CALL SysCurState "off"                               /* turn cursor off */
  714.    key = SysGetKey("noecho")
  715.  
  716.  
  717.    /* restore screen-area context */
  718.    CALL SysCurPos r0, 0                                 /* place cursor    */
  719.    CALL CHAROUT , save_screen                           /* restore screen  */
  720.    CALL SysCurPos cursor_row, cursor_col                /* restore cursor  */
  721.    CALL SysCurState "on"                                /* turn cursor on  */
  722.    RETURN
  723.  
  724.  
  725. /* show usage */
  726. USAGE:
  727.    SAY "Function to allow editing text on an ANSI-screen"
  728.    SAY
  729.    SAY " BOXEDIT(first_row first_col last_row last_col [style] [, initial_text][,A|H])"
  730.    SAY " ... first_row = 0, first_col = 0"
  731.    SAY
  732.    SAY " argument 1: rectangular dimensions plus optional [style]"
  733.    SAY "             style ... '', 1, 2, 3"
  734.    SAY 
  735.    SAY " argument 2: initial text (optional)"
  736.    SAY
  737.    SAY " argument 3: optional type of text"
  738.    SAY "             A ... ASCII-Text (default)"
  739.    SAY "             H ... hexadecimal Text"
  740.    SAY
  741.    SAY " argument 4: prompt to be displayed (optional)"
  742.    EXIT
  743.  
  744.