home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / clarion / clarmemo.zip / MEMOEDIT.CLA < prev    next >
Text File  |  1991-12-30  |  36KB  |  820 lines

  1.           MEMBER()
  2. !═════════════════════════════════════════════════════════════════════════
  3. !
  4. !  'MEMOEDIT.CLA' - Clarion Memo Field Editor
  5. !
  6. !  Revision Number: '1'
  7. !  Revision Date  : '21-Sep-91'
  8. !
  9. !  Copyright : Bobcat Systems (c) 1991
  10. !  Author    : Robert J. Pupazzoni
  11. !           CIS:[70441,204]
  12. !
  13. !  Compiler  : Clarion Professional Developer v.2.1, Batch 2105
  14. !
  15. !  Modified by Bob Gamer DTM Data Services. 12/29/91
  16. !
  17. !  BACKGROUND
  18. !
  19. !    I wrote this because of my frustration with Eckenroed's MEMO3 product.
  20. !    While MEMO3 does what it claims to do, it is quite inflexible and a real
  21. !    memory hog (>30K BIN file).  This was not acceptable for the app I was
  22. !    writing at the time, so MEMOEDIT is my attempt to rectify the situation.
  23. !
  24. !  DESCRIPTION
  25. !
  26. !    This module replaces the standard Clarion memo field editing.  It adds the
  27. !    following features:
  28. !
  29. !       Dynamic word wrapping and paragraph reformatting (optional b.g.)
  30. !
  31. !       Block operations: Copy, Move, Delete
  32. !
  33. !       NOT a LEM - Written entirely in Clarion, so it can be put in an
  34. !     overlay.
  35. !
  36. !       Since it's all in Clarion, you can add as many Hot Keys, features
  37. !     etc. as you want.
  38. !
  39. !
  40. !═════════════════════════════════════════════════════════════════════════
  41.  
  42. !═════════════════════════════════════════════════════════════════════════
  43. !               Edit a memo field
  44. !═════════════════════════════════════════════════════════════════════════
  45. MemoEdit     FUNCTION( xMemo, xLine, ibRow, ibMaxRows, eRow, eColumn )
  46.  
  47.          ! Parameters:
  48. xMemo         EXTERNAL,DIM(1)             ! Memo field
  49. xLine         EXTERNAL                 ! Screen string for edit
  50. ibRow         EXTERNAL                 ! Repeat index for screen
  51. ibMaxRows    BYTE                 ! # of rows on screen
  52. eRow         EXTERNAL                            ! Edit Col Disp (new b.g.)
  53. eColumn      EXTERNAL                            ! Edit Row Disp (new b.g.)
  54.  
  55.          ! Return:
  56. bbModified   BYTE                 ! Modified flag
  57.  
  58.          ! Equates:
  59. eMarkedFG    EQUATE(14)                 ! Foreground for marked text
  60. eMarkedBG    EQUATE(4)                 ! Background for marked text
  61. oHueFG       BYTE                                ! Orig fore hue (new b.g.)
  62. oHueBG       BYTE                                ! Orig back hue (new b.g.)
  63. noReform     BYTE                                ! No Reformat   (new b.g.)
  64. eHelpID         EQUATE('MEMOEDIT')             ! Help screen ID
  65.  
  66.          ! Locals:
  67. tTable         TABLE,PRE(TAB)             ! Edit table
  68.            STRING(255)             !
  69.          .                     !
  70.  
  71. tHold         TABLE,PRE(HLD)             ! Hold area for block ops.
  72.            STRING(255)             !
  73.          .                     !
  74.  
  75. sCursorSize  STRING('<07><06><07><04>')         ! Cursor sizes
  76. aCursorSize  SHORT,DIM(2),OVER(sCursorSize)     !
  77.  
  78. gRegisters   GROUP                 ! CPU Registers
  79. isAX           SHORT                 !
  80. isBX           SHORT                 !
  81. isCX           SHORT                 !
  82. isDX           SHORT                 !
  83. isSI           SHORT                 !
  84. isDI           SHORT                 !
  85. isDS           SHORT                 !
  86. isES           SHORT                 !
  87. ibInt           BYTE                 !
  88. isFlags           SHORT                 !
  89.          .                     !
  90.  
  91. ilMemoRows   SHORT                    ! Total rows in memo field
  92.  
  93. ibRowOfs     BYTE                 ! Screen field row offset
  94. ibColOfs     BYTE                 ! Screen field column offset
  95. ilRowTop     SHORT                 ! Index of top displayed line
  96. ibCol         BYTE                 ! Cursor column
  97.  
  98. ibMaxCols    BYTE                 ! Max. displayable columns
  99. ibWrapCol    BYTE                 ! Column to word-wrap on
  100.  
  101. isKeystroke  SHORT                 ! Last keystroke
  102. bbInsertMode BYTE                 ! Insert mode flag
  103.  
  104. sTemp         STRING(255)             ! Temporary line buffer
  105.  
  106. ilMarkBegRow SHORT                 ! Start row of marked block
  107. ibMarkBegCol BYTE                 ! Start column of marked block
  108. ilMarkEndRow SHORT                 ! End row of marked block
  109. ibMarkEndCol BYTE                 ! End column of marked block
  110. bbMarking    BYTE                 ! Marking mode flag
  111.  
  112. ilAbsTarget  SHORT                 ! Temporaries used in block
  113. ilAbsMrkBeg  SHORT                 ! operations
  114. ilAbsMrkEnd  SHORT                 !
  115. ibHiCol1     BYTE                 ! Hilight column start
  116. ibHiCol2     BYTE                 ! Hilight column end
  117.  
  118. ilTblNdx     SHORT                 ! Edit table index
  119. ilHoldNdx    SHORT                 ! Hold table index
  120. ilMemoNdx    SHORT                 ! Memo array index
  121. ibColNdx     BYTE                 ! Column index
  122. ibLineNdx    BYTE                 ! Line index
  123.  
  124.   CODE
  125.   eRow         = 1                               ! Row Disp (new b.g.)
  126.   eColumn      = 1                               ! Col Disp (new b.g.)
  127.   bbModified   = 0                 ! Clear modified flag
  128.   bbInsertMode = 0                 ! Ins mode OFF (new b.g.)
  129.   ibRow           = 1                 ! Start on first row
  130.   ibCol           = 1                 ! Start in first column
  131.   noReform     = 1                               ! Turn on Reformat bypass
  132.  
  133.   ilMemoRows = MAXIMUM(xMemo[],1)         ! Set row/column values
  134.   ibRowOfs   = ROW(xLine) - 1             !
  135.   ibColOfs   = COL(xLine) - 1             !
  136.   ibMaxCols  = COLS(xLine)             !
  137.   ibWrapCol  = ibMaxCols - 1             !
  138.  
  139.   oHueFG     = FOREHUE(ibRowOfs+1,ibColOfs+1)    ! Orig Fore hue (new b.g.)
  140.   oHueBG     = BACKHUE(ibRowOfs+1,ibColOfs+1)    ! Orig Back hue (new b.g.)
  141.  
  142.   ilMarkBegRow = 0                 ! Reset marked block values
  143.   ibMarkBegCol = 0                 !
  144.   ilMarkEndRow = 0                 !
  145.   ibMarkEndCol = 0                 !
  146.   bbMarking    = 0                 !
  147.  
  148.   HELP(,eHelpID)                 ! Set the help window
  149.  
  150.   DO LoadMemo                     ! Load memo into table
  151.   DO First_Page                     ! Display first page
  152.   DO EditLoop                     ! Edit the memo
  153.   DO SaveMemo                     ! Save table to memo field
  154.  
  155.   HELP(,'')                     ! Deactivate help window
  156.   SETCURSOR                     ! Turn offf cursor
  157.   FREE(tTable)                     ! Clean up
  158.   FREE(tHold)                     !
  159.   SETHUE                                         ! (new b.g.)
  160.   RETURN(bbModified)                 ! Return modified flag
  161.  
  162. !──────────────────────────────────────────────────────────────────────────
  163. EditLoop     ROUTINE      ! Main edit loop
  164. !──────────────────────────────────────────────────────────────────────────
  165.   LOOP                         ! Loop
  166.     SETCURSOR(ibRowOfs+ibRow,ibColOfs+ibCol)     !   Set cursor position
  167.     DO CursorSize                 !   Set cursor size
  168.     ASK                         !   Wait for keystroke
  169.     isKeystroke = KEYCODE()             !   Save it
  170.     CASE isKeystroke                 !   Process action
  171.       OF Esc_Key;    BREAK             !
  172.       OF F1_Key;     HELP             !
  173.  
  174.       OF Left_Key;   DO Move_Left         !   Horizontal movement
  175.       OF Ctrl_Left;  DO MoveW_Left         !
  176.       OF Home_Key;   DO Move_BOL         !
  177.       OF Right_Key;  DO Move_Right         !
  178.       OF Ctrl_Right; DO MoveW_Right         !
  179.       OF End_Key;    DO Move_EOL         !
  180.       OF Tab_Key;    DO Tab_Right         !
  181.  
  182.       OF Up_Key;     DO Move_Up             !   Vertical movement
  183.       OF Down_Key;   DO Move_Down         !
  184.       OF PgUp_Key;   DO Page_Up             !
  185.       OF PgDn_Key;   DO Page_Down         !
  186.       OF Ctrl_PgUp;  DO First_Page         !
  187.       OF Ctrl_PgDn;  DO Last_Page         !
  188.  
  189.       OF Enter_Key;  DO Newline             !   Insertion/deletion
  190.       OF Ins_Key;    DO Toggle_Ins         !
  191.       OF Del_Key;    DO Delete_Char         !
  192.       OF BS_Key;     DO Backspace         !
  193.       OF Ctrl_End;   DO Delete_EOL         !
  194.  
  195.       OF Alt_K;         DO Block_Mark         !   Block operations
  196.       OF Alt_D;         DO Block_Delete         !
  197.       OF Alt_C;         DO Block_Copy         !   (new b.g.)
  198.       OF Alt_M;         DO Block_Move         !
  199.       OF Alt_U;      DO Block_Unmark             !   (new b.g.)
  200.  
  201.       OF Alt_O;         sTemp = '°'         !   Special keys
  202.              Do Insert_Str         !
  203.                          !
  204.       OF F4_Key;     sTemp = FORMAT(TODAY(),@D1) !
  205.              Do Insert_Str         !
  206.  
  207.     ELSE
  208.       IF ALERTED(isKeystroke) THEN BREAK.     !   Return on alerted key
  209.       IF INRANGE(isKeystroke,32,255)         !   Printable character
  210.     DO Insert_Char                 !
  211.       ELSE                     !
  212.     BEEP                     !   Garbage
  213.     . .
  214.     IF bbMarking                 !   If marking a block
  215.       ilMarkEndRow = ilRowTop + ibRow         !     Update block end row
  216.       ibMarkEndCol = ibCol             !     Update block end column
  217.       DO Show_Page                 !     Update marking on screen
  218.   . .                         ! End loop
  219.  
  220.  
  221. !**************************************************************************
  222. !              Horizontal Movement Routines
  223. !**************************************************************************
  224.  
  225. !──────────────────────────────────────────────────────────────────────────
  226. Move_Left    ROUTINE      ! Move cursor left
  227. !──────────────────────────────────────────────────────────────────────────
  228.   IF ibCol > 1                     ! If not at first column
  229.     ibCol -= 1                     !   Move cursor left
  230.     DO SetRowCol                                 !   Row/Col Disp (new b.g.)
  231.   ELSE BEEP                                      ! (new b.g.)
  232.   .                         ! Endif
  233.  
  234. !──────────────────────────────────────────────────────────────────────────
  235. MoveW_Left   ROUTINE      ! Move left one word
  236. !──────────────────────────────────────────────────────────────────────────
  237.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  238.   ibColNdx = ibCol - 1                 ! Set column index
  239.   DO Word_Left                     ! Search left
  240.   ibCol = ibColNdx                 ! Set new cursor postion
  241.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  242.  
  243. !──────────────────────────────────────────────────────────────────────────
  244. Move_BOL     ROUTINE      ! Move to beginning of line
  245. !──────────────────────────────────────────────────────────────────────────
  246.   ibCol = 1                     ! Set to first column
  247.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  248.  
  249. !──────────────────────────────────────────────────────────────────────────
  250. Move_Right   ROUTINE      ! Move cursor right
  251. !──────────────────────────────────────────────────────────────────────────
  252.   IF ibCol < ibMaxCols                 ! If not on last column
  253.     ibCol += 1                     !   Move cursor right
  254.   ELSE BEEP                                      ! (new b.g.)
  255.   .                         ! Endif
  256.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  257.  
  258. !──────────────────────────────────────────────────────────────────────────
  259. MoveW_Right  ROUTINE      ! Move right one word
  260. !──────────────────────────────────────────────────────────────────────────
  261.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  262.   ibColNdx = ibCol                 ! Set column index
  263.   DO Word_Right                     ! Search right
  264.   ibCol = ibColNdx                 ! Set new cursor postion
  265.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  266.  
  267. !──────────────────────────────────────────────────────────────────────────
  268. Move_EOL     ROUTINE
  269. !──────────────────────────────────────────────────────────────────────────
  270.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  271.   ibCol = LEN(CLIP(tTable)) + 1             ! Set cursor to last character
  272.   IF ibCol > ibMaxCols
  273.     ibCol = ibMaxCols
  274.   .
  275.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  276.  
  277. !──────────────────────────────────────────────────────────────────────────
  278. Tab_Right    ROUTINE
  279. !──────────────────────────────────────────────────────────────────────────
  280.   ibCol = 8 * (ibCol/8 + 1)             ! Calculate new tab column
  281.   IF ibCol > ibMaxCols                 ! If past end of screen
  282.     ibCol = ibMaxCols                 !   Fix cursor positionn
  283.   .                         ! Endif
  284.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  285.  
  286. !*************************************************************************
  287. !            Vertical Movement Routines
  288. !*************************************************************************
  289.  
  290. !──────────────────────────────────────────────────────────────────────────
  291. Move_Up         ROUTINE      ! Move one line up
  292. !──────────────────────────────────────────────────────────────────────────
  293.   IF ilRowTop + ibRow = 1 THEN BEEP; EXIT.          ! Exit if at first record
  294.   IF ibRow > 1                     ! If not at first screen row
  295.     ibRow -= 1                     !   Move cursor up
  296.   ELSE                         ! Else
  297.     ilRowTop -= 1                 !   Scroll up
  298.     SCROLL(ibRowOfs+1,ibColOfs+1,ibMaxRows,ibMaxCols,-1)
  299.     GET(tTable,ilRowTop+1)             !   Fill top line
  300.     DO Show_Line                 !
  301.   .                         ! Endif
  302.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  303.  
  304. !──────────────────────────────────────────────────────────────────────────
  305. Move_Down    ROUTINE      ! Move one line down
  306. !──────────────────────────────────────────────────────────────────────────
  307.   IF ilRowTop+ibRow = RECORDS(tTable) THEN BEEP; EXIT. ! Exit if at last record
  308.   IF ibRow < ibMaxRows                 ! If not at last screen row
  309.     ibRow += 1                     !   Move cursor down
  310.   ELSE                         ! Else
  311.     ilRowTop += 1                 !   Scroll down
  312.     SCROLL(ibRowOfs+1,ibColOfs+1,ibMaxRows,ibMaxCols,1)
  313.     GET(tTable,ilRowTop+ibRow)             !   Fill bottom line
  314.     DO Show_Line                 !
  315.   .                         ! Endif
  316.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  317.  
  318. !──────────────────────────────────────────────────────────────────────────
  319. First_Page   ROUTINE      ! Display first page
  320. !──────────────────────────────────────────────────────────────────────────
  321.   ilRowTop = 0                     ! Reset top row
  322.   ibRow       = 1                     ! Move cursor to top line
  323.   DO Show_Page                     ! Display the page
  324.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  325.  
  326. !──────────────────────────────────────────────────────────────────────────
  327. Last_Page    ROUTINE      ! Display last page
  328. !──────────────────────────────────────────────────────────────────────────
  329.   IF RECORDS(tTable) > ibMaxRows         ! If more records than rows
  330.     ilRowTop = RECORDS(tTable) - ibMaxRows     !   Set top row
  331.     ibRow    = ibMaxRows             !   Set cursor row
  332.   ELSE                         ! Else
  333.     ilRowTop = 0                 !   Set top row
  334.     ibRow    = RECORDS(tTable)             !   Set cursor row
  335.   .                         ! Endif
  336.   DO Show_Page                     ! Display page
  337.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  338.  
  339. !──────────────────────────────────────────────────────────────────────────
  340. Page_Up         ROUTINE      ! Scroll one page up
  341. !──────────────────────────────────────────────────────────────────────────
  342.   IF ilRowTop > ibMaxRows             ! If previous page exists
  343.     ilRowTop -= ibMaxRows             !   Display previous page
  344.     DO Show_Page                 !
  345.   ELSE                         ! Else
  346.     DO First_Page                 !  Display first page
  347.   .                         ! Endif
  348.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  349.  
  350. !──────────────────────────────────────────────────────────────────────────
  351. Page_Down    ROUTINE      ! Scroll one page down
  352. !──────────────────────────────────────────────────────────────────────────
  353.   IF ilRowTop + ibMaxRows >= RECORDS(tTable)     ! Exit if no next page
  354.     EXIT                     !
  355.   .                         !
  356.   ilRowTop += ibMaxRows                 ! Set to next page
  357.   IF ilRowTop + ibRow > RECORDS(tTable)         ! If past last record
  358.     ibRow = RECORDS(tTable) - ilRowTop         !   Fix cursor position
  359.   .                         ! Endif
  360.   DO Show_Page                     ! Display page
  361.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  362.  
  363. !*************************************************************************
  364. !            Insertion and Deletion Routines
  365. !*************************************************************************
  366.  
  367. !──────────────────────────────────────────────────────────────────────────
  368. Toggle_Ins   ROUTINE      ! Toggle insert/overwrite mode
  369. !──────────────────────────────────────────────────────────────────────────
  370.   bbInsertMode = BXOR(bbInsertMode,1)         ! Toggle insert flag
  371.  
  372. !──────────────────────────────────────────────────────────────────────────
  373. Newline         ROUTINE      ! Insert a new line, or go to BOL of next line
  374. !──────────────────────────────────────────────────────────────────────────
  375.   bbModified = 1                 ! Set modified flag
  376.   IF bbInsertMode                 ! If insert mode
  377.     DO Split                     !   Split current line
  378.   ELSE                         ! Else
  379.     DO Move_BOL                     !   Move to start-of-line
  380.     DO Move_Down                 !   Move to next line
  381.   .                         ! Endif
  382.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  383.  
  384. !──────────────────────────────────────────────────────────────────────────
  385. Insert_Char  ROUTINE      ! Insert a character
  386. !──────────────────────────────────────────────────────────────────────────
  387.   sTemp = CHR(isKeystroke)             ! Set to last char typed
  388.   DO Insert_Str                     ! Insert into text
  389.  
  390. !──────────────────────────────────────────────────────────────────────────
  391. Insert_Str   ROUTINE      ! Insert a string
  392. !──────────────────────────────────────────────────────────────────────────
  393.   bbModified = 1                 ! Set modified flag
  394.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  395.   ibColNdx = ibCol + BXOR(bbInsertMode,1)     ! Set insert/overwrite column
  396.   IF CLIP(sTemp)                 ! If string not empty
  397.     tTable = SUB(tTable,1,ibCol-1) & |         !   Insert string
  398.          CLIP(sTemp)       & |         !
  399.          SUB(tTable,ibColNdx,255)         !
  400.     ibCol += LEN(CLIP(sTemp))             !   Move cursor
  401.   ELSE                         ! Else
  402.     tTable = SUB(tTable,1,ibCol-1) & |         !   Insert space
  403.          ' '           & |         !
  404.          SUB(tTable,ibColNdx,255)         !
  405.     ibCol += 1                     !   Move cursor
  406.   .                         ! Endif
  407.   PUT(tTable)                     ! Update line table
  408.   DO Show_Line                     ! Refresh display
  409.  
  410.   IF ibCol > ibWrapCol+1             ! If past wrap column
  411.     DO WordWrap                     !   Perform word wrap
  412.   ELSIF LEN(CLIP(tTable)) > ibWrapCol         ! Else if line is too long
  413.     DO Reformat                     !   Reformat paragraph
  414.   .                         ! Endif
  415.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  416.  
  417. !──────────────────────────────────────────────────────────────────────────
  418. Delete_Char  ROUTINE      ! Delete character under cursor
  419. !──────────────────────────────────────────────────────────────────────────
  420.   bbModified = 1                 ! Set modified flag
  421.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  422.   IF ibCol > LEN(CLIP(tTable))             ! If EOL
  423.     DO Join                     !   Join next line
  424.   ELSE                         ! Else
  425.     tTable = SUB(tTable,1,ibCol-1) & |         !   Delete cursor char.
  426.          SUB(tTable,ibCol+1,255)         !
  427.     PUT(tTable)                     !   Update line
  428.     DO Show_Line                 !   Refresh display
  429.     DO Backfill                     !   Backfill empty space
  430.   .                         ! Endif
  431.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  432.  
  433. !──────────────────────────────────────────────────────────────────────────
  434. Backspace    ROUTINE      ! Delete character before cursor
  435. !──────────────────────────────────────────────────────────────────────────
  436.   IF ibCol > 1                     ! If not at BOL
  437.     ibCol -= 1                     !   Move cursor left
  438.     DO Delete_Char                 !   Delete char under cursor
  439.   .                         ! Endif
  440.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  441.  
  442. !──────────────────────────────────────────────────────────────────────────
  443. Delete_EOL   ROUTINE      ! Delete to end-of-line
  444. !──────────────────────────────────────────────────────────────────────────
  445.   bbModified = 1                 ! Set modified flag
  446.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  447.   tTable = SUB(tTable,1,ibCol-1)         ! Delete after cursor
  448.   PUT(tTable)                     ! Update line table
  449.   DO Show_Line                     ! Refresh display
  450.   DO Backfill                     ! Fill in empty space
  451.  
  452. !──────────────────────────────────────────────────────────────────────────
  453. Split         ROUTINE      ! Split line at cursor position
  454. !──────────────────────────────────────────────────────────────────────────
  455.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  456.   sTemp     = SUB(tTable,ibCol,255)         ! Save text after cursor
  457.   tTable = SUB(tTable,1,ibCol-1)         ! Delete part after cursor
  458.   PUT(tTable)                     ! Update line table
  459.   DO Show_Line                     ! Refresh display
  460.   tTable = sTemp                 ! Create a new line
  461.   ADD(tTable,ilRowTop+ibRow+1)             ! with saved text
  462.   DO Move_BOL                     ! Move to BOL
  463.   DO Move_Down                     ! Move down
  464.   DO Show_Partial                 ! Refresh display
  465.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  466.  
  467. !──────────────────────────────────────────────────────────────────────────
  468. Join         ROUTINE      ! Join next line with current line
  469. !──────────────────────────────────────────────────────────────────────────
  470.   GET(tTable,ilRowTop+ibRow+1)             ! Get next line
  471.   IF ERRORCODE() THEN EXIT.             ! Exit if not found
  472.   sTemp = tTable                 ! Save text
  473.   DELETE(tTable)                 ! Delete line
  474.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  475.   tTable = CLIP(tTable) & ' ' & sTemp         ! Join lines
  476.   PUT(tTable)                     ! Update line table
  477.   DO Show_Partial                 ! Refresh display
  478.   GET(tTable,ilRowTop+ibRow)             ! Get current line
  479.   IF ~noReform THEN DO Reformat.                 ! Reformat if not suppressed
  480.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  481.  
  482. !*************************************************************************
  483. !               Word Wrap and Reformatting
  484. !**************************************************************************
  485.  
  486. !──────────────────────────────────────────────────────────────────────────
  487. WordWrap     ROUTINE      ! Perform word wrap
  488. !──────────────────────────────────────────────────────────────────────────
  489.   IF isKeystroke = VAL(' ')             ! If last char was space
  490.     ibCol = 1                     !   Move cursor to 1st column
  491.   ELSE                         ! Else
  492.     ibColNdx = ibCol                 !   Find breakpoint
  493.     DO Word_Left                 !
  494.     sTemp = SUB(tTable,ibColNdx,255)         !
  495.     ibCol = LEN(CLIP(sTemp)) + 1         !   Move cursor to new pos.
  496.     IF ~noReform THEN DO Reformat.               ! Reformat (new b.g.) 
  497.   .                         ! Endif
  498.   IF ilRowTop+ibRow = RECORDS(tTable)         ! If last line
  499.     CLEAR(tTable); ADD(tTable)             !   Add a new one
  500.   .                         ! Endif
  501.   DO Move_Down                     ! Move cursor down one line
  502.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  503.  
  504. !──────────────────────────────────────────────────────────────────────────
  505. Reformat     ROUTINE      ! Reformat paragraph
  506. !──────────────────────────────────────────────────────────────────────────
  507.                          ! Loop for each line
  508.   LOOP ilTblNdx = ilRowTop+ibRow TO RECORDS(tTable)
  509.     IF LEN(CLIP(tTable)) <= ibWrapCol THEN BREAK.!   Break if no wrap needed
  510.     ibColNdx = ibWrapCol+1             !
  511.     DO Word_Left                 !   Find breakpoint
  512.     sTemp  = SUB(tTable,ibColNdx,255)         !   Save excess portion
  513.     tTable = SUB(tTable,1,ibColNdx-1)         !
  514.     PUT(tTable)                     !   Update current line
  515.     GET(tTable,ilTblNdx+1)             !   Get next line
  516.     IF ERRORCODE() OR NOT tTable         !   If not found or empty
  517.       tTable = sTemp                 !     Create a new one
  518.       ADD(tTable,ilTblNdx+1)             !
  519.     ELSE                     !   Else
  520.       tTable = CLIP(sTemp) & ' ' & tTable     !     Add saved section
  521.       PUT(tTable)                 !     Update line
  522.   . .                         ! End loop
  523.   DO Show_Partial                 ! Refresh display
  524.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  525.  
  526. !──────────────────────────────────────────────────────────────────────────
  527. Backfill     ROUTINE      ! Backfill line
  528. !──────────────────────────────────────────────────────────────────────────
  529.     if noReform then exit.                       ! Reformat (new b.g.)
  530.     GET(tTable,ilRowTop+ibRow+1)         ! Get next line
  531.     IF ERRORCODE() OR NOT tTable THEN EXIT.     ! Exit if empty or not found
  532.     sTemp = tTable                 ! Save contents
  533.     DELETE(tTable)                 ! Delete line
  534.     GET(tTable,ilRowTop+ibRow)             ! Get current line
  535.     tTable = CLIP(tTable) & ' ' & sTemp         ! Append saved section
  536.     PUT(tTable)                     ! Update line
  537.     DO Reformat                     ! Reformat paragraph
  538.     DO SetRowCol                                 ! Row/Col Disp (new b.g.)
  539.  
  540. !──────────────────────────────────────────────────────────────────────────
  541. Word_Left    ROUTINE      ! Search for next word to left
  542. !──────────────────────────────────────────────────────────────────────────
  543.   LOOP WHILE (ibColNdx > 0)             ! Loop
  544.     IF SUB(tTable,ibColNdx,1) <> '  ' THEN BREAK.!   Break on non-space
  545.     ibColNdx -= 1                 !   Decrement column index
  546.   .                         ! End loop
  547.   LOOP WHILE (ibColNdx > 0)             ! Loop
  548.     IF SUB(tTable,ibColNdx,1) = '  ' THEN BREAK. !   Break on space
  549.     ibColNdx -= 1                 !   Decrement column index
  550.   .                         ! End loop
  551.   ibColNdx += 1                     ! Adjust column index
  552.  
  553. !──────────────────────────────────────────────────────────────────────────
  554. Word_Right   ROUTINE      ! Search for next word to right
  555. !──────────────────────────────────────────────────────────────────────────
  556.   LOOP WHILE (ibColNdx <= LEN(CLIP(tTable)))     ! Loop
  557.     IF SUB(tTable,ibColNdx,1) = '  ' THEN BREAK. !   Break on space
  558.     ibColNdx += 1                 !   Increment column index
  559.   .                         ! End loop
  560.   LOOP WHILE (ibColNdx <= LEN(CLIP(tTable)))     ! Loop
  561.     IF SUB(tTable,ibColNdx,1) <> '  ' THEN BREAK.!   Break on non-space
  562.     ibColNdx += 1                 !   Increment column index
  563.   .                         ! End loop
  564.  
  565. !*************************************************************************
  566. !               Block Operation Routines
  567. !*************************************************************************
  568.  
  569. !──────────────────────────────────────────────────────────────────────────
  570. Block_Mark   ROUTINE      ! Toggle block marking on/off
  571. !──────────────────────────────────────────────────────────────────────────
  572.   IF NOT bbMarking                 ! If not in marking mode
  573.     ilMarkBegRow = ilRowTop + ibRow         !   Set block start
  574.     ibMarkBegCol = ibCol             !
  575.     ilMarkEndRow = ilMarkBegRow             !   Set block end
  576.     ibMarkEndCol = ibMarkBegCol             !
  577.     bbMarking = 1                 !   Turn marking mode on
  578.   ELSE                         ! Else
  579.     bbMarking = 0                 !   Turn marking mode off
  580.   .                         ! Endif
  581.  
  582. !──────────────────────────────────────────────────────────────────────────
  583. Block_Unmark ROUTINE      ! Unmark any marked blocks
  584. !──────────────────────────────────────────────────────────────────────────
  585.   bbMarking    = 0                 ! Turn marking off
  586.   ilMarkBegRow = 0                 ! Clear mark locations
  587.   ibMarkBegCol = 0                 !
  588.   ilMarkEndRow = 0                 !
  589.   ibMarkEndCol = 0                 !
  590.   DO Show_Page                     ! Refresh screen
  591.  
  592. !──────────────────────────────────────────────────────────────────────────
  593. Block_Delete ROUTINE      ! Delete marked block
  594. !──────────────────────────────────────────────────────────────────────────
  595.   IF NOT ilMarkBegRow THEN EXIT.         ! Exit if nothing marked
  596.  
  597.   bbModified = 1                 ! Set modified flag
  598.   DO CutBlock                     ! Delete block
  599.   IF INRANGE(ilMarkBegRow,ilRowTop+1,ilRowTop+ibMaxRows)
  600.     ibRow = ilMarkBegRow - ilRowTop         ! Update cursor position
  601.     ibCol = ibMarkBegCol             !
  602.   .                         !
  603.   DO Block_Unmark                 ! Unmark the block
  604.   DO BackFill                     ! Backfill empty space
  605.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  606.  
  607. !──────────────────────────────────────────────────────────────────────────
  608. Block_Copy   ROUTINE      ! Copy marked block to cursor location
  609. !──────────────────────────────────────────────────────────────────────────
  610.   IF NOT ilMarkBegRow THEN EXIT.         ! Exit if nothing marked
  611.  
  612.   ilAbsTarget = 255 * (ilRowTop+ibRow) + ibCol     ! Calculate absolute locations
  613.   ilAbsMrkBeg = 255 * ilMarkBegRow + ibMarkBegCol!
  614.   ilAbsMrkEnd = 255 * ilMarkEndRow + ibMarkEndCol!
  615.  
  616.   IF INRANGE(ilAbsTarget,ilAbsMrkBeg,ilAbsMrkEnd)! If target in middle of block
  617.     ! Not implemented                 !   Can't do that!
  618.     EXIT                     !   Exit
  619.   .                         ! Endif
  620.  
  621.   bbModified = 1                 ! Set modified flag
  622.   DO CopyToHold                     ! Copy marked block to hold
  623.   DO CopyFromHold                 ! Copy hold to cursor pos.
  624.   DO Block_Unmark                 ! Unmark the block
  625.   IF ~noReform THEN DO Reformat.                 ! Reformat (new b.g.)
  626.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  627.  
  628. !──────────────────────────────────────────────────────────────────────────
  629. Block_Move   ROUTINE      ! Move marked block to cursor location
  630. !──────────────────────────────────────────────────────────────────────────
  631.   IF NOT ilMarkBegRow THEN EXIT.         ! Exit if nothing marked
  632.  
  633.   ilAbsTarget = 255 * (ilRowTop+ibRow) + ibCol     ! Calculate absolute locations
  634.   ilAbsMrkBeg = 255 * ilMarkBegRow + ibMarkBegCol!
  635.   ilAbsMrkEnd = 255 * ilMarkEndRow + ibMarkEndCol!
  636.  
  637.   IF ilAbsTarget < ilAbsMrkBeg             ! If target before block
  638.     DO CopyToHold                 !   Copy marked block to hold
  639.     DO CutBlock                     !   Delete the block
  640.     DO CopyFromHold                 !   Copy hold to cursor pos.
  641.     DO Block_Unmark                 !   Unmark the block
  642.     bbModified = 1                 !   Set modified flag
  643.   ELSIF ilAbsTarget > ilAbsMrkEnd         ! Else if target after block
  644.     DO CopyToHold                 !   Copy marked block to hold
  645.     DO CopyFromHold                 !   Copy hold to cursor pos.
  646.     DO CutBlock                     !   Delete the block
  647.     DO Block_Unmark                 !   Unmark the block
  648.     bbModified = 1                 !   Set modified flag
  649.   ELSE                         ! Else target is inside block
  650.     ! Not implemented                 !   Can't do that!
  651.   .                         ! Endif
  652.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  653.  
  654. !──────────────────────────────────────────────────────────────────────────
  655. CopyToHold   ROUTINE      ! Copy the marked block to the hold area
  656. !──────────────────────────────────────────────────────────────────────────
  657.   IF NOT ilMarkBegRow THEN EXIT.         ! Exit if nothing marked
  658.  
  659.   FREE(tHold)                     ! Clear hold area
  660.  
  661.   GET(tTable,ilMarkBegRow)             ! Get first marked line
  662.   IF ilMarkBegRow = ilMarkEndRow         ! If only one line marked
  663.     tHold = SUB(tTable,ibMarkBegCol,ibMarkEndCol-ibMarkBegCol+1)
  664.   ELSE                         ! Else
  665.     tHold = SUB(tTable,ibMarkBegCol,255)     !   Get mark to EOL
  666.   .                         ! Endif
  667.   ADD(tHold)                     ! Copy to hold area
  668.  
  669.   LOOP ilTblNdx = ilMarkBegRow+1 TO ilMarkEndRow-1! Loop thru fully marked lines
  670.     GET(tTable,ilTblNdx)             !   Get line
  671.     tHold = tTable                 !   Copy to hold area
  672.     ADD(tHold)                     !
  673.   .                         ! End loop
  674.  
  675.   IF ilMarkBegRow <> ilMarkEndRow         ! If more than one line marked
  676.     GET(tTable,ilMarkEndRow)             !   Get last marked line
  677.     tHold = SUB(tTable,1,ibMarkEndCol)         !   Isolate marked section
  678.     ADD(tHold)                     !   Copy to hold area
  679.   .                         !
  680.  
  681. !──────────────────────────────────────────────────────────────────────────
  682. CopyFromHold ROUTINE      ! Copy hold area to current cursor position
  683. !──────────────────────────────────────────────────────────────────────────
  684.   IF RECORDS(tHold) = 0 THEN EXIT.         ! Exit if hold is empty
  685.  
  686.   ilTblNdx = ilRowTop + ibRow             ! Get current line index
  687.  
  688.   GET(tHold,1)                     ! Get first hold line
  689.   GET(tTable,ilTblNdx)                 ! Get current line
  690.   sTemp     = SUB(tTable,ibCol,255)         ! Save portion past cursor
  691.   tTable = SUB(tTable,1,ibCol-1) & tHold     ! Insert hold at cursor
  692.   PUT(tTable)                     ! Update line
  693.  
  694.   LOOP ilHoldNdx = 2 TO RECORDS(tHold)-1     ! Loop for each hold line
  695.     GET(tHold,ilHoldNdx)             !   Get hold line
  696.     tTable = tHold                 !   Add to line table
  697.     ilTblNdx += 1                 !   Increment table index
  698.     ADD(tTable,ilTblNdx)             !
  699.   .                         ! End loop
  700.  
  701.   IF RECORDS(tHold) = 1                 ! If only one line in hold
  702.     GET(tTable,ilTblNdx)             !   Get displayed line
  703.     tTable = CLIP(tTable) & sTemp         !   Join line and saved sect.
  704.     PUT(tTable)                     !   Update line table
  705.   ELSE                         ! Else
  706.     GET(tHold,RECORDS(tHold))             !   Get last hold line
  707.     tTable = CLIP(tHold) & sTemp         !   Join hold and saved sect.
  708.     ilTblNdx += 1                 !   Increment table index
  709.     ADD(tTable,ilTblNdx)             !   Add to line table
  710.  .                         ! End if
  711.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  712.  
  713. !──────────────────────────────────────────────────────────────────────────
  714. CutBlock     ROUTINE      ! Cut marked block
  715. !──────────────────────────────────────────────────────────────────────────
  716.   GET(tTable,ilMarkEndRow)             ! Get last marked line
  717.   sTemp = SUB(tTable,ibMarkEndCol+1,255)     ! Isolate unmarked section
  718.  
  719.   GET(tTable,ilMarkBegRow)             ! Get first marked line
  720.   tTable = SUB(tTable,1,ibMarkBegCol-1) & sTemp     ! Join unmarked sections
  721.   PUT(tTable)                     ! Update line
  722.  
  723.   LOOP ilTblNdx = ilMarkBegRow+1 TO ilMarkEndRow ! Loop for each marked row
  724.     GET(tTable,ilMarkBegRow+1)             !   Get line
  725.     IF ERRORCODE() THEN CYCLE.             !   Ignore if not found
  726.     DELETE(tTable)                 !   Delete line
  727.   .                         ! End loop
  728.  
  729. !*************************************************************************
  730. !               Display Routines
  731. !*************************************************************************
  732.  
  733. !──────────────────────────────────────────────────────────────────────────
  734. Show_Page    ROUTINE      ! Redisplay entire page
  735. !──────────────────────────────────────────────────────────────────────────
  736.   ibLineNdx = ibRow                 ! Save current row
  737.   LOOP ibRow = 1 TO ibMaxRows             ! Loop thru each row
  738.     GET(tTable,ilRowTop+ibRow)             !   Get line from table
  739.     IF ERRORCODE() THEN CLEAR(tTable).         !   Clear if not found
  740.     DO Show_Line                 !   Display line
  741.   .                         ! End loop
  742.   ibRow = ibLineNdx                 ! Restore current row
  743.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  744.  
  745. !──────────────────────────────────────────────────────────────────────────
  746. Show_Partial ROUTINE      ! Redisplay page from current cursor position
  747. !──────────────────────────────────────────────────────────────────────────
  748.   ibLineNdx = ibRow                 ! Save current row
  749.   LOOP ibRow = ibLineNdx TO ibMaxRows         ! Loop thru each row
  750.     GET(tTable,ilRowTop+ibRow)             !   Get line from table
  751.     IF ERRORCODE() THEN CLEAR(tTable).         !   Clear if not found
  752.     DO Show_Line                 !   Display line
  753.   .                         ! End loop
  754.   ibRow = ibLineNdx                 ! Restore current row
  755.   DO SetRowCol                                   ! Row/Col Disp (new b.g.)
  756.  
  757. !──────────────────────────────────────────────────────────────────────────
  758. Show_Line    ROUTINE      ! Display line, including block marks
  759. !──────────────────────────────────────────────────────────────────────────
  760. ! xLine = tTable                                 ! (new b.g.)
  761.  
  762.   SETHUE(oHueFG,oHueBG)                          ! (new b.g.)
  763.   SHOW(ibRowOfs+ibrow,ibColOfs+1,tTable,@s76)    ! (new b.g.)
  764.   SETHUE
  765.   IF ilMarkBegRow = 0 THEN EXIT.                 ! (new b.g.)
  766.   IF ilMarkEndRow = 0 THEN EXIT.                 ! (new b.g.)
  767.   IF INRANGE(ilRowTop+ibRow,ilMarkBegRow,ilMarkEndRow)
  768.     ibHiCol1 = ibColOfs + 1
  769.     ibHiCol2 = ibColOfs + ibMaxCols
  770.     IF ilRowTop+ibRow = ilMarkBegRow
  771.       ibHiCol1 = ibColOfs + ibMarkBegCol
  772.     .
  773.     IF ilRowTop+ibRow = ilMarkEndRow
  774.       ibHiCol2 = ibColOfs + ibMarkEndCol
  775.     .
  776.     SETHUE(eMarkedFG,eMarkedBG)
  777.     COLOR(ibRowOfs+ibRow,ibHiCol1,1,ibHiCol2-ibHiCol1+1)
  778.     SETHUE
  779.   .
  780.  
  781. !──────────────────────────────────────────────────────────────────────────
  782. CursorSize   ROUTINE      ! Set cursor size
  783. !──────────────────────────────────────────────────────────────────────────
  784.   CLEAR(gRegisters)                 ! Clear group
  785.   isAX    = 0100H                     ! Set Cursor Size request
  786.   isCX    = aCursorSize[1+bbInsertMode]         ! Select cursor size
  787.   ibInt = 10H                     ! ROM-BIOS Video Services
  788.   Interrupt(gRegisters)                 ! Call interrupt handler
  789.  
  790. !*************************************************************************
  791. !            Memo Read/Write Routines
  792. !*************************************************************************
  793.  
  794. !──────────────────────────────────────────────────────────────────────────
  795. LoadMemo     ROUTINE      ! Load memo field into edit table
  796. !──────────────────────────────────────────────────────────────────────────
  797.   FREE(tTable)                     ! Clear edit table
  798.   LOOP ilMemoNdx = ilMemoRows TO 2 BY -1     ! Loop back thru each line
  799.     IF xMemo[ilMemoNdx] THEN BREAK.         !   Find last non-blank line
  800.   .                         ! End loop
  801.   LOOP ilTblNdx = 1 TO ilMemoNdx         ! Loop for each line
  802.     tTable = xMemo[ilTblNdx]             !   Add to edit table
  803.     ADD(tTable)                     !
  804.   .                         ! End loop
  805.  
  806. !──────────────────────────────────────────────────────────────────────────
  807. SaveMemo     ROUTINE      ! Save edit table back to memo field
  808. !──────────────────────────────────────────────────────────────────────────
  809.   CLEAR(xMemo[])                 ! Clear memo field
  810.   LOOP ilTblNdx = 1 TO RECORDS(tTable)         ! Loop for each record
  811.     GET(tTable,ilTblNdx)             !   Get table line
  812.     xMemo[ilTblNdx] = tTable             !   Add to edit table
  813.   .                         ! End loop
  814.  
  815. !-------------------------------------------------------------------------
  816. SetRowCol    ROUTINE      ! Set Display Row And Column (new b.g.)
  817. !-------------------------------------------------------------------------  
  818.    eColumn = ibcol                               ! Display Column (new b.g.)
  819.    eRow    = ilRowTop + ibRow                    ! Display Row    (new b.g.)
  820.