├── LICENSE ├── Makefile ├── README.md ├── ast.inc ├── cmds.mac ├── cpmio.mac ├── dcb.inc ├── docs ├── Changelog.txt ├── LICENSE.txt ├── ted-ref.txt ├── ted.txt └── vmem.txt ├── errors.inc ├── fcb.inc ├── fileio.mac ├── main.mac ├── mkted.cmd ├── mkted.sub ├── qio.inc ├── rsxio.mac ├── scrn.mac ├── sysfn.inc ├── syslib.lib ├── tcb.inc ├── ted.inc └── termdef.mac /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Path to Linux utilities 2 | ZXCC = zxcc 3 | VOL180 = ../Tools/linux/vol180/vol180 4 | 5 | # Path to CP/M utilities 6 | ZSM4 = ../Tools/cpm/zsm4.com 7 | DRLINK = ../Tools/cpm/drlink.com 8 | TKB = ../Tools/cpm/tkb.com 9 | 10 | .PREFIX: 11 | .PREFIX: .mac .rel 12 | 13 | SRCS = main.mac \ 14 | termdef.mac \ 15 | fileio.mac \ 16 | scrn.mac \ 17 | cmds.mac \ 18 | cpmio.mac \ 19 | rsxio.mac 20 | 21 | OBJS = $(SRCS:.mac=.rel) 22 | 23 | all: ted.com ted.tsk 24 | 25 | $(OBJS): %.rel: %.mac *.inc 26 | $(ZXCC) $(ZSM4) -"=$<" 27 | 28 | ted.com: $(OBJS) 29 | $(ZXCC) $(DRLINK) -"ted=termdef,main,fileio,scrn,cmds,cpmio" 30 | mv ted.sym tedcpm.sym 31 | 32 | ted.tsk: $(OBJS) syslib.lib 33 | $(ZXCC) $(TKB) -"ted/ofmt=tsk,tedrsx.sym=termdef,main,fileio,scrn,cmds,rsxio,syslib/lb/task=...TED/ident="`date +%y%m%d`"/pri=65" 34 | 35 | copy: 36 | cpmrm -f p112 /dev/fd0 0:ted.com 37 | cpmcp -f p112 /dev/fd0 ted.com 0: 38 | 39 | clean: 40 | rm -f ted.com ted.tsk *.rel *.sym *.prn *.map *.crf core *~ *.\$$\$$\$$ 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [TED](http://p112.sourceforge.net/index.php?ted) - Text Editor 2 | 3 | This is a clone of the editor of the same name that once was available for 4 | the DEC's RT-11 OS. 5 | 6 | It is not identical to the original. In particular, this version implements 7 | smart tab handling like the old Borland editors did (the original simply 8 | converted all tabs to spaces), and has a different set of screen editing 9 | commands which is more WordStar-like. 10 | 11 | This version is for a Z80 CPU and runs under CP/M or RSX180. Can edit files 12 | larger than the available RAM, up to approx 1Mbyte. 13 | -------------------------------------------------------------------------------- /ast.inc: -------------------------------------------------------------------------------- 1 | ; AST control/event block structure 2 | 3 | A.LNK equ 0 ; link to next item in list (2 bytes) 4 | A.SIZ equ A.LNK + 2 ; size of data area (1 byte) 5 | A.TYP equ A.SIZ + 1 ; event type (1 byte) 6 | A.ADDR equ A.TYP + 1 ; AST entry address (2 bytes) 7 | A.DAT equ A.ADDR + 2 ; start of data area (variable length) 8 | 9 | ; AST control block size = AST event header size 10 | 11 | ACBSZ equ A.DAT 12 | 13 | ; AST types 14 | 15 | AST.IO equ 1 ; I/O completion 16 | AST.UC equ 2 ; unsolicited char from attached terminal 17 | AST.RD equ 3 ; data received 18 | AST.CK equ 4 ; clock (mark time) 19 | AST.ST equ 5 ; status (from offspring) 20 | AST.AB equ 6 ; abort/exit 21 | AST.CL equ 7 ; command line (CLIs only) 22 | 23 | -------------------------------------------------------------------------------- /cmds.mac: -------------------------------------------------------------------------------- 1 | ;**********************************************************************; 2 | ; ; 3 | ; This file is part of TED, a clone of the screen-oriented text ; 4 | ; editor that was once available for the RT-11 OS. ; 5 | ; Copyright (C) 2011-2020, Hector Peraza. ; 6 | ; ; 7 | ; This program is free software; you can redistribute it and/or ; 8 | ; modify it under the terms of the GNU General Public License as ; 9 | ; published by the Free Software Foundation; either version 2 of ; 10 | ; the License, or (at your option) any later version. ; 11 | ; ; 12 | ; This program is distributed in the hope that it will be useful, ; 13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; 14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; 15 | ; GNU General Public License for more details. ; 16 | ; ; 17 | ; You should have received a copy of the GNU General Public License ; 18 | ; along with this program; if not, write to the Free Software ; 19 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; 20 | ; ; 21 | ;**********************************************************************; 22 | 23 | .Z80 24 | 25 | title TED - Text Editor 26 | subttl Delete, Copy, Move and Substitute commands 27 | 28 | include TED.INC 29 | 30 | ;======================================================================= 31 | 32 | ; D E L E T E , C O P Y , M O V E , S U B S T I T U T E 33 | 34 | public CMDPR,CMDD,CMDSU,CMDM,CMDMD 35 | 36 | extrn CURREC,CURLN,CURPOS,EDLEN,STRBUF,EDREC,NXTREC 37 | extrn CMDPTR,N1D,N3,ARGLEN,ARGSTR,CKDSTR,SEARCH,UCASE 38 | extrn WFOV,GTDSTR,GETPAR,GETC,TMPBUF,ADDHLA,PSTRN 39 | extrn DELBUF,STORE,GETARG,PUTC,EEXTRA,GETTXP,CPDEHL 40 | extrn INSBUF,GTTXP0,SETTXP,EXPAND,PUTSTR,HLDEC,EDITBF 41 | extrn UCASE,NUMVAL 42 | 43 | ;----------------------------------------------------------------------- 44 | 45 | cseg 46 | 47 | ; PR command 48 | 49 | CMDPR: call GETARG ; process arguments 50 | ret c ; on error return 51 | call GTTXPA 52 | ret c ; on error return 53 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 54 | ld (CLINE),de ; store start line 55 | ld (CREC),hl ; and it's record number 56 | ld a,h 57 | or l 58 | ret z ; return if zero, no lines to print 59 | call GETTXP 60 | ret c ; on error return 61 | ld hl,(CLINE) 62 | ex de,hl 63 | ld (ENDLN),hl ; store end line 64 | call CPDEHL 65 | ex de,hl 66 | jr nc,cmdpr1 ; jump if end line >= start line 67 | ld hl,IBERR ; else error - 'ILLEGAL BOUNDS' 68 | jp PUTSTR ; output string and return 69 | 70 | cmdpr1: call EEXTRA ; display error if extra parameters 71 | ret c ; on error return 72 | cmdpr2: ld de,(CLINE) ; check current line 73 | ld hl,(ENDLN) 74 | call CPDEHL ; past end line? 75 | ret c ; return if yes 76 | ld hl,(CREC) ; get record number into HL 77 | ld a,h 78 | or l 79 | ret z ; return if zero (no more lines) 80 | ld de,STRBUF ; get buffer address into DE 81 | call EXPAND ; expand line 82 | ld hl,(NXTREC) 83 | ld (CREC),hl ; store next line's record# 84 | ld hl,(CLINE) ; get line number into HL 85 | ld a,'0' ; filler 86 | call HLDEC ; output decimal value 87 | ld a,TAB ; and a TAB 88 | call PUTC ; to align text line on next tab stop 89 | ld hl,STRBUF 90 | ld a,(EDLEN) ; get expanded length 91 | ld c,a ; into C 92 | call PSTRN ; output string @HL, length in C 93 | ld hl,(CLINE) ; increment line number 94 | inc hl 95 | ld (CLINE),hl 96 | jp cmdpr2 ; loop 97 | 98 | IBERR: db 'Illegal bounds',LF,CR,0 99 | 100 | ; D command 101 | 102 | CMDD: call GETARG ; process arguments 103 | ret c ; on error return 104 | push hl 105 | ld hl,0 106 | ld (COUNT),hl ; init line count 107 | pop hl 108 | call GTTXPA 109 | ret c ; on error return 110 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 111 | ld (CLINE),de ; store start line 112 | ld (CREC),hl ; and it's record number 113 | ld a,h 114 | or l 115 | jr z,cmdd3 ; jump if zero, no lines to delete 116 | call GETTXP 117 | ret c ; on error return 118 | ld hl,(CLINE) 119 | ex de,hl 120 | call CPDEHL 121 | ex de,hl 122 | jr nc,cmdd1 ; jump if end line >= start line 123 | ld hl,IBERR ; else error - 'ILLEGAL BOUNDS' 124 | jp PUTSTR ; output string and return 125 | 126 | cmdd1: call EEXTRA ; display error if extra parameters 127 | ret c ; on error return 128 | ld bc,(CLINE) ; get start line into BC 129 | ld hl,(CREC) ; and it's record number into HL 130 | ld a,e 131 | sub c 132 | ld e,a 133 | ld a,d 134 | sbc a,b 135 | ld d,a ; DE = end line - start line 136 | inc de ; now number of lines to delete 137 | cmdd2: call DELBUF ; delete line from text buffer 138 | ld hl,(COUNT) ; increment number of lines deleted 139 | inc hl 140 | ld (COUNT),hl 141 | ld hl,(NXTREC) ; get next line's record number into HL 142 | ld a,h 143 | or l 144 | jr z,cmdd3 ; jump if zero (no next line) 145 | dec de ; decrement line count 146 | ld a,d ; (note no need to adjust line number in BC 147 | or e ; since we always delete the current line) 148 | jr nz,cmdd2 ; loop 149 | cmdd3: ld hl,(COUNT) 150 | call DECOUT ; output decimal value and a space 151 | ld hl,LDMSG ; 'LINES DELETED' 152 | jp PUTSTR ; output string and return 153 | 154 | ; M command - copy lines 155 | 156 | CMDM: xor a 157 | jr cmdm1 158 | 159 | ; MD command - move lines 160 | 161 | CMDMD: ld a,1 162 | cmdm1: ld (OPMODE),a ; set mode 163 | ld hl,(CURREC) 164 | ld (SAVREC),hl ; save current record number 165 | ld hl,(CURLN) 166 | ld (SAVLN),hl ; save current line number 167 | ld a,(CURPOS) 168 | ld (SAVCI),a ; save current character index 169 | ld hl,0 170 | ld (COUNT),hl ; clear number of lines copied/moved 171 | call GETARG ; process arguments 172 | ret c ; on error return 173 | call GTTXPA 174 | ret c ; on error return 175 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 176 | ld (CLINE),de ; store start line number 177 | ld (CREC),hl ; and its record number 178 | call GTTXPA 179 | ret c ; on error return 180 | ld hl,(CLINE) 181 | ex de,hl 182 | ld (ENDLN),hl ; store end line number 183 | call CPDEHL ; compare with start line number 184 | jr c,cmdm2 ; error if end line < start line 185 | sbc hl,de ; HL = end line - start line (note CY clear) 186 | inc hl 187 | ld (COUNT2),hl ; save number of lines to move 188 | ld hl,(SAVREC) 189 | ld (CURREC),hl ; restore saved current record number 190 | ld hl,(SAVLN) 191 | ld (CURLN),hl ; restore saved current line number 192 | ld a,(SAVCI) 193 | ld (CURPOS),a ; restore saved character index 194 | call GTTXPA 195 | ret c ; on error return 196 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 197 | ld (DSTREC),hl ; store record number of dest line 198 | ld hl,(CLINE) ; get start line number 199 | ex de,hl ; into DE 200 | ld (DSTLN),hl ; store dest line number 201 | call CPDEHL ; compare with start line number 202 | jr c,cmdm3 ; jump if dest line < start line 203 | ex de,hl ; get dest line number back into DE 204 | ld hl,(ENDLN) ; get end line number into HL 205 | call CPDEHL ; compare line numbers 206 | jr c,cmdm3 ; jump if dest line > end line 207 | cmdm2: ld hl,IBERR ; else error (overlap) - 'ILLEGAL BOUNDS' 208 | jp PUTSTR ; output string and return 209 | 210 | cmdm3: call EEXTRA ; display error if extra parameters 211 | ret c ; on error return 212 | cmdm4: ld bc,(CLINE) ; get next line number into BC 213 | ; (for call to DELBUF) 214 | ld hl,(CREC) ; check next record number 215 | ld a,h 216 | or l 217 | jp z,cmdm7 ; exit loop if zero (no more lines) 218 | ld de,EDITBF ; get address of edit line buffer into DE 219 | call EXPAND ; expand line 220 | push hl 221 | ld hl,(NXTREC) 222 | ld (CREC),hl ; store next line's record# 223 | pop hl 224 | ld a,(OPMODE) ; check M/MD mode 225 | or a 226 | jr z,cmdm5 ; jump if M (copy lines) 227 | call DELBUF ; else delete line from text buffer 228 | ld hl,(DSTLN) 229 | ex de,hl 230 | ld l,c 231 | ld h,b 232 | call CPDEHL 233 | jr nc,cmdm5 ; jump if BC >= DSTLN 234 | ex de,hl 235 | dec hl 236 | ld (DSTLN),hl 237 | cmdm5: ld bc,(DSTLN) 238 | ld hl,(DSTREC) 239 | ld de,EDITBF ; get address of edit line buffer into DE 240 | call INSBUF ; insert a line into text buffer 241 | jp c,WFOV ; on error print 'WORK FILE OVERFLOW' 242 | ; and go back to command mode 243 | ld hl,(EDREC) 244 | ld (DSTREC),hl ; save record number of current line 245 | ld e,c 246 | ld d,b 247 | ld hl,(CLINE) 248 | jr c,cmdm6 ; jump if BC > current line 249 | inc hl 250 | ld (CLINE),hl 251 | cmdm6: ld hl,(COUNT) ; increment number of lines copied 252 | inc hl 253 | ld (COUNT),hl 254 | ld hl,(COUNT2) 255 | dec hl ; decrement number of lines to copy 256 | ld (COUNT2),hl 257 | ld a,h 258 | or l ; reached zero? 259 | jp nz,cmdm4 ; loop if not 260 | cmdm7: ld hl,(COUNT) ; get number of lines moved/deleted 261 | call DECOUT ; output decimal value and a space 262 | ld a,(OPMODE) ; check M/MD mode 263 | or a ; and output message accordingly 264 | ld hl,LMMSG ; 'LINES MOVED' 265 | jp nz,PUTSTR 266 | ld hl,LCMSG ; 'LINES COPIED' 267 | jp PUTSTR ; output string 268 | 269 | ; SU command - substitute 270 | 271 | CMDSU: xor a 272 | ld (OPMODE),a ; set default SU mode 273 | ld hl,0 274 | ld (COUNT2),hl ; init substitutions counter 275 | ld hl,(CMDPTR) ; get pointer to command into HL 276 | call CKDSTR ; look for delimited string 277 | ret c ; on error return 278 | jr z,cmds1 ; jump if alphanumeric 279 | jp cmds7 ; else delimited string found 280 | 281 | cmds1: call GETARG ; process arguments 282 | ret c ; on error return 283 | ld a,c 284 | cp 1 ; argument type = single numeric? 285 | jr nz,cmds2 ; jump if not 286 | ld a,(OPMODE) 287 | or 40h ; else set flag 288 | ld (OPMODE),a 289 | ld hl,(NUMVAL) 290 | ld (COUNT),hl ; COUNT = numeric value 291 | ld a,h 292 | or a 293 | jp m,cmds4 ; error if <= 0 294 | or l 295 | jr z,cmds4 296 | jr cmds6 297 | 298 | cmds2: cp 3 ; argument type = string? 299 | jr nz,cmds5 ; jump if not 300 | ld hl,STRBUF ; get addr of string arg buffer into HL 301 | ld a,(hl) ; fetch byte 302 | call UCASE 303 | cp 'M' ; 'M' (multiple) option? 304 | jr nz,cmds3 ; jump if not 305 | ld a,(OPMODE) 306 | or 80h ; else set flag 307 | ld (OPMODE),a 308 | inc hl ; advance pointer 309 | ld a,(hl) 310 | cmds3: cp LF ; LF? (ensure single char specified) 311 | jr z,cmds6 ; jump if yes 312 | cmds4: ld hl,IPERR ; else error - 'ILLEGAL PARAMETER' 313 | jp PUTSTR ; output string and return 314 | 315 | cmds5: or a ; any other kind of argument? 316 | jr nz,cmds4 ; error if yes - ILLEGAL PARAMETER 317 | cmds6: ld hl,(CMDPTR) ; else get pointer to command into HL 318 | call CKDSTR ; look for delimited string 319 | ret c ; on error return 320 | jr z,cmds4 ; error if alphanumeric 321 | cmds7: ld a,b 322 | ld (ARGLEN),a ; store string arg length 323 | or a 324 | jr nz,cmds8 ; jump if not zero 325 | ld hl,ESERR ; else error - 'EMPTY SEARCH STRING' 326 | jp PUTSTR ; output string and return 327 | 328 | cmds8: ld (ARGSTR),de ; store string arg address 329 | call GTDSTR ; get delimited string (delimiter still in C) 330 | ret c ; return on error (delimiter not found) 331 | ld a,b 332 | ld (WLEN),a ; store word length 333 | ld (WSTART),de ; store word start 334 | call GETPAR ; process argument of type (N1,N2)+N3 335 | ret c ; return on error 336 | ld de,(N3) ; check N3 337 | ld a,d 338 | or e 339 | jr z,cmds9 ; jump if N3 is zero 340 | ld hl,IDERR ; else error - 'ILLEGAL DISPLACEMENT' 341 | jp PUTSTR ; output string and return 342 | 343 | cmds9: ld (CMDPTR),hl ; store command line pointer 344 | call GETTXP 345 | ret c ; on error return 346 | call EEXTRA ; display error if extra parameters 347 | ret c ; on error return 348 | cmds10: call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 349 | ld a,(OPMODE) 350 | and 80h ; check mode 351 | jp z,cmds11 ; jump if M option not set 352 | ld hl,(CURLN) 353 | call DECOUT ; output current line number and a space 354 | ld hl,EDITBF ; get address of edit line buffer into HL 355 | ld c,b ; get current char pos into C 356 | call PSTRN ; output string @HL, length in C 357 | ld a,'"' 358 | call PUTC ; output quote 359 | ld a,c 360 | call ADDHLA ; HL = current char address 361 | ld a,(ARGLEN) ; get string arg length 362 | ld c,a ; into C 363 | call PSTRN ; output string @HL, length in C 364 | ld a,'"' 365 | call PUTC ; output quote 366 | ld a,c 367 | call ADDHLA 368 | ld a,(EDLEN) ; get line length 369 | sub c ; subtract string arg length 370 | sub b ; subtract current char pos 371 | ld c,a ; and we have tail length 372 | call PSTRN ; output string @HL, length in C 373 | ld a,(ARGLEN) 374 | add a,c ; add string arg length to C 375 | ld (N1D),a ; and we have next char index for SEARCH 376 | call ASK ; Y-CR-^C ? 377 | jp c,cmds16 ; if ^C 378 | jr z,cmds14 ; if CR 379 | cmds11: ld hl,EDITBF ; else here if Y - get src into HL 380 | ld de,TMPBUF ; and dst into DE 381 | ld a,(CURPOS) ; get current character index 382 | ld c,a ; into C 383 | ld b,0 ; reset resulting string length 384 | call STNCPY ; copy string @HL to @DE, length in C 385 | ld hl,(WSTART) 386 | ld a,(WLEN) 387 | ld c,a 388 | call STNCPY ; copy string @HL to @DE, length in C 389 | ld a,b ; get resulting string length 390 | cp MAXLEN+1 ; compare to max line length 391 | jr c,cmds12 392 | ld a,MAXLEN ; truncate if necessary 393 | cmds12: ld (N1D),a ; set next char index for SEARCH 394 | ld a,(CURPOS) ; get current character index 395 | ld c,a 396 | ld a,(ARGLEN) ; add string arg length 397 | add a,c 398 | ld c,a ; save value 399 | ld hl,EDITBF 400 | call ADDHLA ; index into edit buffer 401 | ld a,(EDLEN) ; get line length 402 | sub c ; subtract (CURPOS + ARGLEN) 403 | ld c,a 404 | call STNCPY ; copy string @HL to @DE, length in C 405 | ld hl,(CURLN) 406 | call DECOUT ; output current line number and a space 407 | ld hl,TMPBUF 408 | ld a,b ; get cumulated length 409 | cp MAXLEN+1 ; cpmpare to max line length 410 | jr c,cmds13 411 | ld a,MAXLEN ; truncate if necessary 412 | cmds13: ld c,a 413 | push hl 414 | call ADDHLA 415 | dec hl 416 | ld (hl),LF 417 | dec hl 418 | ld (hl),CR 419 | pop hl 420 | call PSTRN ; output string @HL, length in C 421 | ld de,TMPBUF 422 | ld hl,(CURREC) ; get current record number into HL 423 | call STORE ; store line into record(s) 424 | jp c,WFOV ; on error print 'WORK FILE OVERFLOW' 425 | ; and go back to command mode 426 | ld hl,(COUNT2) 427 | inc hl ; increment substitutions counter 428 | ld (COUNT2),hl 429 | cmds14: ld a,(OPMODE) 430 | and 40h ; check mode 431 | jr z,cmds15 ; jump if not SU # 432 | ld hl,(COUNT) 433 | dec hl ; else decrement # 434 | ld (COUNT),hl 435 | ld a,h 436 | or l 437 | jr z,cmds16 ; finish when # reaches zero 438 | cmds15: call SEARCH ; search for ARGSTR string in N1..N2 439 | jp nc,cmds10 ; loop while match found 440 | cmds16: ld hl,(COUNT2) 441 | call DECOUT ; output decimal value and a space 442 | ld hl,SUMSG ; 'SUBSTS' 443 | jp PUTSTR ; output string and return 444 | 445 | IPERR: db 'Illegal parameter',LF,CR,0 446 | IDERR: db 'Illegal displacement',LF,CR,0 447 | ESERR: db 'Empty search string',LF,CR,0 448 | 449 | LDMSG: db 'lines deleted',LF,CR,0 450 | LMMSG: db 'lines moved',LF,CR,0 451 | LCMSG: db 'lines copied',LF,CR,0 452 | SUMSG: db 'substitutions',LF,CR,0 453 | 454 | ; Get text pointer (record #, line # and char index) from argument type 455 | 456 | GTTXPA: ld a,c 457 | dec a ; argument type = single numeric? 458 | jp z,GTTXP0 ; if yes, setup text pointers and return 459 | dec a ; argument type = (N1,N2)+N3? 460 | jp z,GTTXP0 ; if yes, setup text pointers and return 461 | ld hl,MPERR ; else error - 'MISSING PARAMETER' 462 | call PUTSTR ; output string 463 | scf ; and return with CY set 464 | ret 465 | 466 | MPERR: db 'Missing parameter',LF,CR,0 467 | 468 | ; Display Y-CR-^C prompt and get response 469 | ; Returns CY if ^C, Z if CR, else is 'Y' 470 | 471 | ASK: push hl 472 | ld hl,YNSTR ; 'Y--<^C>? ' 473 | call PUTSTR ; output prompt 474 | ask1: call GETC ; get input char into A 475 | call UCASE ; convert to uppercase 476 | cp 3 ; ^C? 477 | scf 478 | jr z,ask2 ; return with CY set if yes 479 | cp CR ; CR? 480 | jr z,ask2 ; return with Z set if yes 481 | cp 'N' 482 | jr z,ask2 ; also accept an explicit 'N' 483 | cp 'Y' ; 'Y'? 484 | jr nz,ask1 ; loop if not 485 | call PUTC ; else output char 486 | or 0FFh ; and return NZ 487 | ask2: push af 488 | ld a,LF ; LF 489 | call PUTC ; output char 490 | ld a,CR ; CR 491 | call PUTC ; output char 492 | pop af 493 | pop hl 494 | ret 495 | 496 | YNSTR: db 'Y--<^C> ? ',0 497 | 498 | ; Copy string @HL to @DE (up to MAXLEN chars), length in C 499 | ; B accumulates resulting string size, up to MAXLEN. 500 | 501 | STNCPY: ld a,c 502 | or a 503 | ret z 504 | ret m 505 | scpy1: ld a,(hl) 506 | inc hl 507 | push hl 508 | ld l,a 509 | ld a,b 510 | cp MAXLEN 511 | ld a,l 512 | pop hl 513 | jr nc,scpy2 ; jump if B >= MAXLEN 514 | ld (de),a 515 | inc de 516 | inc b 517 | scpy2: dec c 518 | jr nz,scpy1 519 | ret 520 | 521 | ; Output HL as decimal number followed by a space 522 | 523 | DECOUT: ld a,'0' ; filler 524 | call HLDEC ; output value 525 | ld a,' ' 526 | jp PUTC 527 | 528 | ;----------------------------------------------------------------------- 529 | 530 | dseg 531 | 532 | COUNT: ds 2 ; number of lines moved, deleted, etc. 533 | CLINE: ds 2 ; current line number in PR, M, MD, etc. 534 | ENDLN: ds 2 ; end line number 535 | CREC: ds 2 ; current record number 536 | COUNT2: ds 2 ; number of lines to move, subst count, etc. 537 | DSTLN: ds 2 ; dest line number in copy/move 538 | DSTREC: ds 2 ; dest record number 539 | OPMODE: ds 1 ; M/MD cmd: 0 = copy lines, 1 = move lines 540 | ; SU cmd: 0 = normal, 40h = SU #, 80h = SU M 541 | SAVREC: ds 2 ; saved record number 542 | SAVLN: ds 2 ; saved line number 543 | SAVCI: ds 1 ; saved character index 544 | 545 | WSTART: ds 2 ; start of word during substitution 546 | WLEN: ds 1 ; word length 547 | 548 | end 549 | -------------------------------------------------------------------------------- /cpmio.mac: -------------------------------------------------------------------------------- 1 | ;**********************************************************************; 2 | ; ; 3 | ; This file is part of TED, a clone of the screen-oriented text ; 4 | ; editor that was once available for the RT-11 OS. ; 5 | ; Copyright (C) 2011-2020, Hector Peraza. ; 6 | ; ; 7 | ; This program is free software; you can redistribute it and/or ; 8 | ; modify it under the terms of the GNU General Public License as ; 9 | ; published by the Free Software Foundation; either version 2 of ; 10 | ; the License, or (at your option) any later version. ; 11 | ; ; 12 | ; This program is distributed in the hope that it will be useful, ; 13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; 14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; 15 | ; GNU General Public License for more details. ; 16 | ; ; 17 | ; You should have received a copy of the GNU General Public License ; 18 | ; along with this program; if not, write to the Free Software ; 19 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; 20 | ; ; 21 | ;**********************************************************************; 22 | 23 | .Z80 24 | 25 | title TED - Text Editor 26 | subttl I/O routines - CP/M version 27 | 28 | include TED.INC 29 | 30 | WBOOT equ 0 31 | BDOS equ 5 32 | 33 | .DIRIO equ 06h 34 | .OPEN equ 0Fh 35 | .CLOSE equ 10h 36 | .ERASE equ 13h 37 | .READ equ 14h 38 | .WRITE equ 15h 39 | .MAKE equ 16h 40 | .GETDSK equ 19h 41 | .SETDMA equ 1Ah 42 | .RREAD equ 21h 43 | .RWRITE equ 22h 44 | 45 | CPMFCB equ 5Ch 46 | CPMBUF equ 80h 47 | 48 | ;======================================================================= 49 | 50 | ; S Y S T E M - D E P E N D E N T R O U T I N E S 51 | 52 | public GETC,UNGETC,PUTC,TTQCLR,TTINIT,UCASE,HLDEC 53 | 54 | public FCREAT,WCREAT,FOPEN,FCLOSE,WCLOSE,FREAD,FWRITE 55 | public FDELET,WDELET,MKFCB,PRFNAM,FGETC,FPUTC,PADEOF 56 | public GETTOP,GETCML,EXIT 57 | 58 | extrn UFLAG,UPDST,CPDEHL 59 | 60 | ;----------------------------------------------------------------------- 61 | 62 | cseg 63 | 64 | ; Terminal routines 65 | 66 | ; init terminal (attach, etc) 67 | 68 | TTINIT: call TTQCLR 69 | ret 70 | 71 | ; release terminal 72 | 73 | ; Output char in A to terminal 74 | 75 | PUTC: push hl 76 | push de 77 | push bc 78 | push af 79 | and 7Fh 80 | ld e,a 81 | ld c,.DIRIO 82 | call BDOS 83 | pop af 84 | pop bc 85 | pop de 86 | pop hl 87 | ret 88 | 89 | ; Get input char into A. If the input queue is empty, wait for character. 90 | 91 | GETC: push hl 92 | push de 93 | push bc 94 | ld a,(TTQLEN) ; check TTY queue length 95 | or a 96 | jr nz,gc1 97 | call WAITC 98 | jr gc3 99 | gc1: ld hl,(TTQOUT) ; get TTY queue out pointer into HL 100 | ld a,(hl) ; get byte from queue 101 | inc hl 102 | and 7Fh ; strip parity bit, leave ASCII 103 | ld c,a 104 | ld de,TTFIFO+64 105 | call CPDEHL ; pointer at end of buffer? 106 | jr nz,gc2 ; jump if not 107 | ld hl,TTFIFO ; else wrap back to start 108 | gc2: ld (TTQOUT),hl ; store pointer 109 | ld hl,TTQLEN 110 | dec (hl) ; decrement TTY input queue length 111 | ld a,c 112 | gc3: pop bc 113 | pop de 114 | pop hl 115 | ret 116 | 117 | ; Wait for character from terminal 118 | 119 | WAITC: ld b,200 120 | wtc1: push bc 121 | ld e,0FFh 122 | ld c,6 123 | call BDOS 124 | pop bc 125 | and 7Fh ; strip parity bit, leave ASCII 126 | ret nz 127 | djnz wtc1 128 | ld a,(UFLAG) 129 | or a 130 | call nz,UPDST 131 | jr WAITC 132 | 133 | ; Store char in C to console queue. 134 | 135 | UNGETC: push hl 136 | push de 137 | ld a,(TTQLEN) 138 | cp 64 ; check console input queue length 139 | jr z,tti2 ; return if queue full 140 | ld hl,(TTQIN) ; else get queue in pointer into HL 141 | ld (hl),c ; store incoming char 142 | inc hl ; and advance pointer 143 | ld de,TTFIFO+64 144 | call CPDEHL ; pointer at end of buffer? 145 | jr nz,tti1 ; jump if not 146 | ld hl,TTFIFO ; else wrap back to start 147 | tti1: ld (TTQIN),hl ; store pointer back 148 | ld hl,TTQLEN ; increment queue length 149 | inc (hl) 150 | tti2: pop de 151 | pop hl 152 | ret 153 | 154 | ; Reset console input queue 155 | 156 | TTQCLR: ld hl,(TTQOUT) 157 | ld (TTQIN),hl ; make out ptr = in ptr 158 | xor a 159 | ld (TTQLEN),a ; clear queue length (no bytes stored) 160 | ret 161 | 162 | ;----------------------------------------------------------------------- 163 | 164 | ; Disk I/O routines 165 | 166 | ; Create work file. Returns CY set on error. 167 | 168 | WCREAT: push hl 169 | push de 170 | push bc 171 | ld de,TMPFCB 172 | jr fcr1 173 | 174 | ; Create output file. Returns CY set on error. 175 | 176 | FCREAT: push hl 177 | push de 178 | push bc 179 | ld de,CPMFCB 180 | fcr1: push de 181 | call RSTFCB ; ensure FCB is clear 182 | ld c,.ERASE 183 | call BDOS 184 | pop de 185 | ld c,.MAKE 186 | call BDOS 187 | ld hl,0 188 | ld (NUMWR),hl ; clear output byte count 189 | ld hl,CPMBUF 190 | ld (FIOPTR),hl ; set output file buffer address 191 | pop bc 192 | pop de 193 | pop hl 194 | inc a 195 | or a 196 | ret nz 197 | scf 198 | ret 199 | 200 | ; Open input file. Returns CY set on error. 201 | 202 | FOPEN: push hl 203 | push de 204 | push bc 205 | ld de,CPMFCB 206 | call RSTFCB ; ensure FCB is clear 207 | ld c,.OPEN 208 | call BDOS 209 | ld hl,0 210 | ld (NUMRD),hl ; clear number of bytes read 211 | pop bc 212 | pop de 213 | pop hl 214 | inc a 215 | or a 216 | ret nz 217 | scf 218 | ret 219 | 220 | ; Close work file 221 | 222 | WCLOSE: push hl 223 | push de 224 | push bc 225 | ld de,TMPFCB 226 | jr fcl1 227 | 228 | ; Close input and/or edited file 229 | 230 | FCLOSE: push hl 231 | push de 232 | push bc 233 | ld de,CPMFCB 234 | fcl1: ld c,.CLOSE 235 | call BDOS 236 | pop bc 237 | pop de 238 | pop hl 239 | inc a 240 | or a 241 | ret nz 242 | scf 243 | ret 244 | 245 | ; Pad last disk record with EOF characters and save it before closing file 246 | 247 | PADEOF: ld hl,(NUMWR) ; check output byte count 248 | ld a,l 249 | cp 128 ; record full? 250 | jr z,pad1 ; jump if yes (last record) 251 | ld c,1Ah 252 | call FPUTC ; fill rest of record with EOF marker 253 | jr PADEOF ; loop 254 | pad1: call WRREC ; write last disk record 255 | ret 256 | 257 | ; Read 512-byte block from work file. HL = disk I/O address, DE = blk number 258 | 259 | FREAD: push hl 260 | push de 261 | push bc 262 | ex de,hl ; HL = blk num, DE = I/O buffer address 263 | add hl,hl 264 | add hl,hl ; obtain CP/M record number 265 | ld c,4 ; 4 CP/M records to read 266 | fr1: ld (TMPFCB+33),hl ; set record number in TMPFCB 267 | push hl 268 | push de 269 | push bc 270 | ld c,.SETDMA 271 | call BDOS 272 | ld de,TMPFCB 273 | ld c,.RREAD 274 | call BDOS 275 | pop bc 276 | pop de 277 | ld hl,80h 278 | add hl,de 279 | ex de,hl 280 | pop hl 281 | inc hl ; increment CP/M record number 282 | or a 283 | scf 284 | jp nz,fr2 285 | dec c 286 | jp nz,fr1 287 | xor a 288 | fr2: pop bc 289 | pop de 290 | pop hl 291 | ret 292 | 293 | ; Write 512-byte block to work file. HL = disk I/O address, DE = blk number 294 | 295 | FWRITE: push hl 296 | push de 297 | push bc 298 | ex de,hl ; HL = blk num, DE = I/O buffer address 299 | add hl,hl 300 | add hl,hl ; obtain CP/M record number 301 | ld c,4 ; 4 CP/M records to write 302 | fw1: ld (TMPFCB+33),hl ; set record number in TMPFCB 303 | push hl 304 | push de 305 | push bc 306 | ld c,.SETDMA 307 | call BDOS 308 | ld de,TMPFCB 309 | ld c,.RWRITE 310 | call BDOS 311 | pop bc 312 | pop de 313 | ld hl,80h 314 | add hl,de 315 | ex de,hl 316 | pop hl 317 | inc hl ; increment CP/M record number 318 | or a 319 | scf 320 | jp nz,fw2 321 | dec c 322 | jp nz,fw1 323 | xor a 324 | fw2: pop bc 325 | pop de 326 | pop hl 327 | ret 328 | 329 | ; Get byte from input file 330 | ; Return CY set on error or EOF 331 | 332 | FGETC: push hl 333 | ld hl,(NUMRD) ; check byte count 334 | ld a,h 335 | or l 336 | jr nz,fgc1 ; jump if not zero 337 | call RDREC ; else read next disk record 338 | jr c,fgc2 ; on error return 339 | fgc1: ld hl,(FIOPTR) 340 | ld a,(hl) ; get char from file buffer 341 | inc hl ; inc ptr 342 | ld (FIOPTR),hl 343 | ld hl,(NUMRD) 344 | dec hl 345 | ld (NUMRD),hl ; decrement byte count 346 | cp 1Ah ; EOF? 347 | scf ; return with CY set if yes 348 | jr z,fgc2 349 | or a 350 | fgc2: pop hl 351 | ret 352 | 353 | ; Read 128-byte disk record from input file 354 | 355 | RDREC: push hl 356 | push de 357 | push bc 358 | ld hl,128 359 | ld (NUMRD),hl ; set byte count 360 | ld hl,CPMBUF 361 | ld (FIOPTR),hl ; set file buffer address 362 | ex de,hl 363 | ld c,.SETDMA 364 | call BDOS 365 | ld de,CPMFCB 366 | ld c,.READ 367 | call BDOS 368 | or a 369 | jr z,r1 370 | scf 371 | r1: pop bc 372 | pop de 373 | pop hl 374 | ret 375 | 376 | ; Write byte in C to output file 377 | 378 | FPUTC: ld hl,(NUMWR) ; get output byte count 379 | ld a,l 380 | cp 128 ; record buffer full? 381 | jr nz,fpc1 ; jump if not 382 | call WRREC ; write disk record to file 383 | ret c ; on error return 384 | fpc1: ld hl,(NUMWR) 385 | inc hl ; inc output byte count 386 | ld (NUMWR),hl 387 | ld hl,(FIOPTR) ; store byte in output file buffer 388 | ld (hl),c 389 | inc hl ; advance ptr 390 | ld (FIOPTR),hl 391 | or a 392 | ret 393 | 394 | ; Write 128-byte disk record to output file 395 | 396 | WRREC: push hl 397 | push de 398 | push bc 399 | ld hl,0 400 | ld (NUMWR),hl ; clear byte count 401 | ld hl,CPMBUF 402 | ld (FIOPTR),hl ; reset output file buffer address 403 | ex de,hl 404 | ld c,.SETDMA 405 | call BDOS 406 | ld de,CPMFCB 407 | ld c,.WRITE 408 | call BDOS 409 | or a 410 | jr z,w1 411 | scf 412 | w1: pop bc 413 | pop de 414 | pop hl 415 | ret 416 | 417 | ; Delete work file 418 | 419 | WDELET: push hl 420 | push de 421 | push bc 422 | ld de,TMPFCB 423 | jr fd1 424 | 425 | ; Delete output file 426 | 427 | FDELET: push hl 428 | push de 429 | push bc 430 | ld de,CPMFCB 431 | fd1: ld c,.ERASE 432 | call BDOS 433 | pop bc 434 | pop de 435 | pop hl 436 | ret 437 | 438 | ; Reset FCB for FOPEN/FCREAT 439 | 440 | RSTFCB: push hl 441 | ld hl,12 442 | add hl,de 443 | ex de,hl 444 | ld b,35-12 445 | call MKFILL 446 | ex de,hl 447 | pop hl 448 | ret 449 | 450 | ; Parse file name and build FCB from string in HL. 451 | 452 | MKFCB: ld de,CPMFCB 453 | push bc 454 | xor a 455 | ld (de),a ; clear disk field 456 | ld a,(hl) 457 | cp CR 458 | jr z,nodsk 459 | cp LF 460 | jr z,nodsk 461 | inc hl 462 | ld a,(hl) 463 | dec hl 464 | cp ':' ; explicit disk specification? 465 | jr nz,nodsk 466 | ld a,(hl) 467 | call UCASE 468 | sub 'A' 469 | jr c,badfn 470 | cp 10h 471 | ccf 472 | jr c,badfn 473 | inc a 474 | ld (de),a 475 | inc hl ; skip over disk spec 476 | inc hl 477 | nodsk: inc de 478 | ld b,8 479 | call GETNAM 480 | mkf1: ld a,(hl) 481 | call CKENDF 482 | jr z,mkf2 483 | inc hl 484 | cp '.' 485 | jr nz,mkf1 486 | mkf2: ld b,3 487 | call GETNAM 488 | ld b,24 489 | xor a 490 | call MKFILL ; clear rest of FCB 491 | or a 492 | badfn: pop bc 493 | ret 494 | 495 | GETNAM: ld a,(hl) 496 | call CHKDOT 497 | jr z,endnam 498 | call UCASE 499 | ld (de),a 500 | inc hl 501 | inc de 502 | djnz GETNAM 503 | endnam: xor a 504 | or b 505 | ret z 506 | ld a,' ' ; fill rest of name field with spaces 507 | MKFILL: ld (de),a 508 | inc de 509 | djnz MKFILL 510 | ret 511 | 512 | CHKDOT: cp '.' 513 | ret z 514 | CKENDF: cp CR 515 | ret z 516 | cp LF 517 | ret z 518 | cp ' ' 519 | ret 520 | 521 | ; Display file name using system conventions 522 | 523 | PRFNAM: push hl 524 | push de 525 | push bc 526 | ld hl,CPMFCB 527 | ld a,(hl) 528 | inc hl 529 | or a ; zero disk code? 530 | jr nz,prfn1 531 | push hl 532 | ld c,.GETDSK 533 | call BDOS ; get default disk from CP/M if not 534 | pop hl 535 | inc a 536 | prfn1: add a,'A'-1 537 | call PUTC 538 | ld a,':' 539 | call PUTC 540 | ld b,8 541 | call prfn2 542 | ld a,'.' 543 | call PUTC 544 | ld b,3 545 | call prfn2 546 | pop bc 547 | pop de 548 | pop hl 549 | ret 550 | 551 | prfn2: ld a,(hl) 552 | cp ' ' 553 | call nz,PUTC 554 | inc hl 555 | djnz prfn2 556 | ret 557 | 558 | ;----------------------------------------------------------------------- 559 | 560 | ; Misc routines 561 | 562 | ; Get top of memory 563 | 564 | GETTOP: ld hl,(BDOS+1) 565 | ret 566 | 567 | ; Get CLI command line 568 | 569 | GETCML: ld hl,CPMBUF 570 | ld b,(hl) ; return command length in B 571 | inc hl ; and string address in HL 572 | ret 573 | 574 | ; Exit to system 575 | 576 | EXIT: jp WBOOT 577 | 578 | ; Convert char in A to uppercase 579 | 580 | UCASE: cp 'a' 581 | ret c 582 | cp 'z'+1 583 | ret nc 584 | and 5Fh 585 | ret 586 | 587 | ; Display value in HL as decimal (with trailing zeros). 588 | 589 | HLDEC: ld (FILLER),a 590 | push hl 591 | push de 592 | push bc 593 | ld b,0 ; 0 for no trailing zeros 594 | ld de,-10000 595 | call SBCNT 596 | ld de,-1000 597 | call SBCNT 598 | ld de,-100 599 | call SBCNT 600 | ld de,-10 601 | call SBCNT 602 | ld a,l 603 | add a,'0' 604 | call PUTC 605 | inc b 606 | res 7,b 607 | ld a,b 608 | pop bc 609 | pop de 610 | pop hl 611 | ret 612 | 613 | SBCNT: ld c,'0'-1 614 | sb1: inc c 615 | add hl,de 616 | jr c,sb1 617 | sbc hl,de 618 | bit 7,b 619 | jr nz,sb3 620 | ld a,c 621 | cp '0' 622 | jr nz,sb2 623 | ld a,(FILLER) 624 | or a 625 | ret z 626 | ld c,a 627 | jr sb3 628 | sb2: set 7,b 629 | sb3: ld a,c 630 | call PUTC 631 | inc b 632 | ret 633 | 634 | ;----------------------------------------------------------------------- 635 | 636 | dseg 637 | 638 | TTQLEN: db 0 ; TTY queue length (number of chars in queue) 639 | TTQOUT: dw TTFIFO ; TTY queue out pointer 640 | TTQIN: dw TTFIFO ; TTY queue in pointer 641 | 642 | TTFIFO: ds 64 ; 64 bytes used for input queue 643 | 644 | TMPFCB: db 0,'EDITOR TMP' ; temporary work file on current disk 645 | db 0,0,0,0 646 | dw 0,0,0,0,0,0 647 | dw 0,0,0,0,0,0 648 | db 0,0,0 649 | 650 | FILLER: ds 1 651 | FIOPTR: dw 0 ; file I/O pointer 652 | NUMRD: dw 0 ; number of bytes read 653 | NUMWR: dw 0 ; number of bytes written 654 | 655 | end 656 | -------------------------------------------------------------------------------- /dcb.inc: -------------------------------------------------------------------------------- 1 | ; Device Control Block structure, one per loaded device 2 | 3 | D.LNK equ 0 ; link to next DCB in device list (2 bytes) 4 | D.ST equ D.LNK + 2 ; status (1 byte) 5 | D.TCNT equ D.ST + 1 ; timeout counter (2 bytes) 6 | D.NAME equ D.TCNT + 2 ; device name (2 bytes) 7 | D.UNITS equ D.NAME + 2 ; number of units (1 byte) 8 | D.UCBL equ D.UNITS + 1 ; link to list of UCBs (2 bytes) 9 | D.BANK equ D.UCBL + 2 ; device driver page (BBR) (1 byte) 10 | D.START equ D.BANK + 1 ; device driver start address (2 bytes) 11 | D.END equ D.START + 2 ; device driver end address (2 bytes) 12 | D.EPT equ D.END + 2 ; device driver jump table entry point (2 bytes) 13 | 14 | ; DCB size 15 | 16 | DCBSZ equ D.EPT + 2 17 | 18 | ; Status bit numbers 19 | 20 | DS.RES equ 0 ; resident (unloadable) 21 | 22 | ; Unit Control Block structure, one per device unit (statically allocated) 23 | 24 | U.LNK equ 0 ; link to next UCB in list (2 bytes) 25 | U.UNIT equ U.LNK + 2 ; physical unit number (1 byte) 26 | U.ST equ U.UNIT + 1 ; status bits (1 byte) 27 | U.DCB equ U.ST + 1 ; pointer to the corresponding DCB (2 bytes) 28 | U.SCB equ U.DCB + 2 ; pointer to the related SCB (2 bytes) 29 | U.RED equ U.SCB + 2 ; redirect pointer (2 bytes) 30 | U.CTL equ U.RED + 2 ; control bits (1 byte) 31 | U.CW equ U.CTL + 1 ; characteristics word (2 bytes) 32 | U.ATT equ U.CW + 2 ; TCB of attached task (0=detached) (2 bytes) 33 | U.ACP equ U.ATT + 2 ; TCB of ACP task (0=no ACP) (2 bytes) 34 | U.LCB equ U.ACP + 2 ; LCB of owner (2 bytes) 35 | 36 | ; Unit control bit numbers 37 | 38 | UC.ATT equ 0 ; send attach/detach notifications 39 | 40 | ; UCB min size 41 | 42 | UCBSZ equ U.LCB + 2 43 | 44 | ; UCB status bit numbers 45 | 46 | US.OFL equ 0 ; unit is offline 47 | US.BSY equ 1 ; unit busy 48 | US.MNT equ 2 ; unit mounted 49 | US.PUB equ 3 ; unit is public 50 | US.DMO equ 4 ; unit is being dismounted (file access denied) 51 | US.RED equ 5 ; unit can be redirected 52 | US.AST equ 6 ; generate AST on I/O completion for the attached task 53 | 54 | ; Device/Unit Characteristics Word bit numbers: Lo-byte 55 | 56 | DV.REC equ 0 ; record-oriented (block) device 57 | DV.TTY equ 1 ; terminal (character) device 58 | DV.DIR equ 2 ; directory device 59 | DV.MNT equ 3 ; device mountable 60 | DV.PSE equ 4 ; pseudo-device 61 | 62 | ; Device/Unit Characteristics Word bit numbers: Hi-byte (device-dependent) 63 | ; Terminal characteristics bits 64 | 65 | TC.TTS equ 0 ; misc terminal operation sync bit 66 | TC.BIN equ 1 ; binary mode (pass-all) 67 | TC.NEC equ 2 ; no-echo mode 68 | TC.SCP equ 3 ; scope mode 69 | TC.SLV equ 4 ; slave mode 70 | TC.SMR equ 5 ; uppercase conversion on input disabled 71 | TC.NBR equ 6 ; not receiving broadcast messages 72 | TC.ANS equ 7 ; ANSI terminal 73 | 74 | ; Additional Terminal characteristics codes, not present in U.CW 75 | 76 | TC.SPD equ 8 ; serial speed, if supported 77 | TC.PAR equ 9 ; parity, if supported (0=none, 1=odd, 3=even) 78 | TC.BPC equ 10 ; bits per character, if supported 79 | TC.STP equ 11 ; stop bits, if supported 80 | TC.FLC equ 12 ; flow control type, if supported 81 | 82 | ; Status Control Block, one per controller (statically allocated) 83 | 84 | S.ST equ 0 ; controller status (1 byte) 85 | S.PKTL equ S.ST + 1 ; link to I/O packet queue (2 bytes) 86 | S.CPKT equ S.PKTL + 2 ; address of current I/O packet (2 bytes) 87 | 88 | ; SCB min size 89 | 90 | SCBSZ equ S.CPKT + 2 91 | 92 | ; Logical device assignment structure, one per logical device 93 | 94 | N.LNK equ 0 ; link to next item in list (2 bytes) 95 | N.TYPE equ N.LNK + 2 ; assignment type (1 byte) 96 | N.TI equ N.TYPE + 1 ; UCB of terminal (2 bytes) 97 | N.NAME equ N.TI + 2 ; logical device name (2 bytes) 98 | N.UNIT equ N.NAME + 2 ; logical device unit (1 byte) 99 | N.UCB equ N.UNIT + 1 ; UCB of physical device (2 bytes) 100 | 101 | ; Logical Assignment structure size 102 | 103 | LASZ equ N.UCB + 2 104 | 105 | ; Assignment types 106 | 107 | N.LCL equ 0 ; local 108 | N.LGN equ 1 ; login 109 | N.GBL equ 2 ; global 110 | 111 | -------------------------------------------------------------------------------- /docs/Changelog.txt: -------------------------------------------------------------------------------- 1 | Changelog 2 | --------- 3 | 4 | (Old Changelog going back to 2011 was lost) 5 | 6 | 03/02/16 7 | 8 | - System-dependent routines now in a separate file. The RSX180 version can 9 | already read files. 10 | 11 | 12 | 05/02/16 13 | 14 | - Got the virtual memory working under RSX180 (TED writes data to work file 15 | leaving gaps or "holes" that may get filled later; since RSX180 does not 16 | support "holes" yet, a workaround had to be implemented in the code.) 17 | 18 | A bug appeared: 19 | 'run $ted/inc=10000' and read a large file, e.g.: 'r [test]snake.lst', 20 | then 'pr 1 $' shows only 905 lines instead of 1833. 21 | 22 | 23 | 06/02/16 24 | 25 | - Fixed the bug above. It was in the main code and affected the CP/M version 26 | as well (NEWBUF routine modified register B, so the 'dirty' flag set by 27 | LDRECD was lost and the corresponding modified buffer was not saved back 28 | to disk). 29 | 30 | - TED now processes the RSX180 command line. File read and write practically 31 | finished, so the editor is now usable. 32 | 33 | 34 | 21/02/16 35 | 36 | - Use existing filename from R command for W command without arguments (this 37 | affected the CP/M version as well). 38 | 39 | 40 | 23/11/16 41 | 42 | - RSX180 file I/O routines converted to filesystem v4. 43 | 44 | 45 | 11/01/18 46 | 47 | - Implementing soft-tab handling: 48 | * STORE and EXPAND routines modified, tabs are now stored in the virtual 49 | memory records. 50 | * DISPLE routine modified, so display appears correctly. 51 | * FPUTC1 routine modified, so file output does not contain soft-spaces. 52 | 53 | - Ruler now displays 2-digit numbers if > 10 (does not wrap back to 0). 54 | 55 | - INSert mode now shown on status line. 56 | 57 | 58 | 12/01/18 59 | 60 | - CR now splits line at cursor column. 61 | 62 | - Removed the rather-useless ^A ^B ^O ^P screen mode commands. 63 | 64 | - Refresh screen now keeps the original cursor position. 65 | 66 | - Default mode is now insert (tired of toggling it every time). 67 | 68 | - Insert character routine now checks for smart tabs. 69 | 70 | 71 | 13/01/18 72 | 73 | - Insert/replace (soft) tab now works. 74 | 75 | - Delete char right working. 76 | 77 | 78 | 14/01/18 79 | 80 | - Automatically scroll screen left/right when moving cursor beyond right/left 81 | edge. 82 | 83 | - Split and join now handle tabs correctly. 84 | 85 | - Delete char left working. 86 | 87 | - CURX now represents character index in screen mode and not screen cursor 88 | position, this optimizes somewhat character access (no need to add SCRX 89 | every time.) 90 | 91 | - SETCUR now scrolls screen left/right so cursor always stays in window. 92 | 93 | - JOIN now truncates resulting line if too long. 94 | 95 | - Better line overflow checks, but not perfect yet. 96 | 97 | 98 | 17/01/18 99 | 100 | - Source converted to Z80 mnemonics, the old 8080 version will be kept but 101 | no longer updated. 102 | 103 | 104 | 21/01/18 105 | 106 | - Revised/fixed SHRLN and SRLLN routines. 107 | 108 | - Optimized SHRLN8 and SHRLN8 routines of the smart-tab support. 109 | 110 | - Optimized tab insertion/deletion. 111 | 112 | - Soft-tab handling almost complete. 113 | 114 | - P command now accepts a second argument (cursor column). 115 | 116 | - RSX180 version now uses SYSLIB routines (not fully done yet). 117 | 118 | 119 | 22/01/18 120 | 121 | - Fixed end of line case when inserting chars. 122 | 123 | - Status line now always shows the current cursor line (after a small delay). 124 | 125 | 126 | 24/01/18 127 | 128 | - Track file modifications and issue a warning if the user tries to exit or 129 | clear the buffer without saving. 130 | 131 | 132 | 17/03/18 133 | 134 | - RSX180 version now uses the new IO.RVB/WVB for work file I/O. 135 | 136 | 137 | 20/03/18 138 | 139 | - Entering ^Z at the command prompt now exits the program, ^G replaces the 140 | old ^Z function (reenter last command). 141 | 142 | 143 | 24/03/18 144 | 145 | - RSX180 version now uses IO.RVB/WVB for regular file I/O. 146 | 147 | 148 | 23/05/18 149 | 150 | - Use scroll region if supported by the terminal (VT100, etc.). 151 | 152 | 153 | 04/11/18 154 | 155 | - Fixed a stupid bug in the delete-line function of the screen mode (LASTLN 156 | is a 16-bit value, but was used as 8-bit value in a comparison operation!). 157 | 158 | 159 | 01/05/19 160 | 161 | - Use WS-like cursor movement in command line too, in addition to the VT 162 | arrow keys. 163 | 164 | 165 | 17/05/19 166 | 167 | - Set terminal mode to binary under RSX180. 168 | 169 | 170 | 14/02/21 171 | 172 | - Fix wrong cursor position after using backspace on first column of the 173 | last line of text. 174 | 175 | - RSX180: display file version as 16-bit decimal. 176 | 177 | 178 | 04/12/22 179 | 180 | - RSX180: switch to VT52 escape sequences if the terminal is not set to 181 | ANSI. 182 | 183 | -------------------------------------------------------------------------------- /docs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /docs/ted-ref.txt: -------------------------------------------------------------------------------- 1 | TED - Quick Reference 2 | 3 | Command mode 4 | ------------ 5 | 6 | Commands are ended with Return or Ctrl-C. When the last one is used, the 7 | screen mode is entered after command execution. 8 | 9 | EX or Ctrl-Z - exit editor (note: without saving) 10 | CL - clear buffer, delete all text 11 | R FILE - insert FILE 12 | R (P) FILE (N1,N2) - insert FILE from line N1 to N2 after P 13 | W [P1 P2] [FILE] [N] - save text to FILE 14 | WU [P1 P2] [FILE] [N] - save text to FILE, update current version 15 | F - show default file name 16 | FR - show available memory 17 | PR P1 [P2] - print lines on terminal 18 | D P1 [P2] - delete lines 19 | M P1 P2 P3 - copy lines 20 | MD P1 P2 P3 - move lines 21 | SU /OLD/NEW/[(N1 [N2])] - search (and replace) 22 | SU M /OLD/NEW/[(N1 [N2])] - same, but ask for confirmation 23 | SU N /OLD/NEW/[(N1 [N2])] - same, but N times 24 | S [P] - enter screen editor 25 | P [P [C]] - show/set text index 26 | /TEXT/ - search for TEXT and enter screen editor 27 | 28 | Screen edit mode 29 | ---------------- 30 | 31 | Arrow keys - move cursor 32 | HOME (Ctrl-L) - cursor start/end of line 33 | Ctrl-T - cursor top/bottom 34 | Ctrl-F - move to prev tab stop 35 | Ctrl-Q - move to next tab stop 36 | TAB (Ctrl-I) - insert tab 37 | RETURN (Ctrl-M) - split line 38 | Ctrl-R - redraw screen 39 | Ctrl-Y or Ctrl-^ - delete line 40 | Ctrl-K - insert line above 41 | LF (Ctrl-J) - insert line below 42 | DEL or Ctrl-H - delete char left 43 | Ctrl-G or Ctrl-] - delete char right 44 | Ctrl-P - duplicate line 45 | Ctrl-V - toggle insert mode 46 | Ctrl-B or Ctrl-N - enter browse mode 47 | Ctrl-C or Ctrl-Z - exit back to command mode 48 | 49 | Browse mode 50 | ----------- 51 | 52 | Arrow up/down - page up/down 53 | Arrow left/right - shift screen 10 columns left/right 54 | CR, Ctrl-C or Ctrl-Z - exit back to screen edit mode 55 | -------------------------------------------------------------------------------- /docs/ted.txt: -------------------------------------------------------------------------------- 1 | TED - Text Editor 2 | 3 | 1. Introduction 4 | 5 | TED is a screen-oriented text editor that can be used to create new files 6 | and edit existing ones. It is a clone of an editor of the same name that 7 | ran under RT-11, although not an identical one. In particular, this 8 | version implements smart tab handling the way the old Borland editors 9 | did, and has a different set of screen editing commands which is more 10 | WordStar-like. 11 | 12 | The editor does not operate directly on the original text file. Instead, it 13 | loads the text file entirely into its virtual memory buffer, where the 14 | modifications are actually made. When TED is first started, the buffer is 15 | empty. A Read command loads the contents of the file to be edited into the 16 | internal buffer, making it available for edit. Another command, Write, saves 17 | the buffer back into a file. 18 | 19 | The three main operations (read, edit and write) are independent of each 20 | other and can be executed in any arbitrary order. To create a new file, 21 | just enter the screen editor and start typing. After saving the text into 22 | a file, we can edit it again and save a different version under a different 23 | file name. With a buffer CLear command we can start again from the beginning. 24 | 25 | The editor has two main modes of operation: command and screen. Command mode 26 | is used mainly for those operations that require one or more parameters to be 27 | specified (e.g. deleting or moving a number of lines, reading a file 28 | fully of partially, etc.) In screen mode, the user can modify the text 29 | directly by positioning the cursor using the arrow keys and typing or 30 | deleting characters and lines. 31 | 32 | The maximum line length allowed by the editor is 162 characters. The maximum 33 | file size is limited to about 1 Mbyte, and does not depend on the amount of 34 | RAM available. 35 | 36 | 37 | 2. Command mode 38 | 39 | In the command description below we use the following terms and conventions: 40 | 41 | * Square brackets enclose optional parameters. 42 | 43 | * FILE represents a standard file specification by the operating system 44 | standards. 45 | 46 | * N, N1, N2 are decimal numeric values, often representing line numbers. 47 | The special dollar-sign character "$" can be used to address the last 48 | line in the text buffer or file, depending of the context. 49 | 50 | * P, P1, P2 are text indexes, and represent a specific position in the 51 | text buffer. Text indexes specify both line number and character position 52 | within the line. The first character in a line has always an index value 53 | of zero. The index specification can be: 54 | 55 | - A decimal line number, the character $ (representing the number of 56 | the last line of text) and/or an expression using the arithmetic + and 57 | and - operators. If the resulting value of the expression is greater 58 | than the number of lines currently in the buffer, then the number of 59 | the last line is used. This type of text index specification always 60 | sets the character position to the start of the line. 61 | 62 | - A search string consisting of at least one character. The editor will 63 | try to find the string in the text buffer and, if found, the index will 64 | be set to the first character of the matched string in the text. The 65 | search string must be delimited with one of the following characters: 66 | 67 | ! " % & ' = : \ / ? < > 68 | 69 | The search string in the description that follow will be represented as: 70 | 71 | /STRING/ 72 | 73 | where in place of "/" any of the characters listed above can be used, 74 | and STRING is any non-empty sequence of characters that does not 75 | contain the delimiter. When such an index is specified, the search 76 | begins from the current cursor position until the end of the text is 77 | reached. If desired, a different start line number can be specified 78 | like this: 79 | 80 | /STRING/(N) 81 | 82 | in this case, search starts from the N-th line (see above for the N 83 | specification). Search limits can also be specified as: 84 | 85 | /STRING/(N1,N2) 86 | 87 | The following forms are also allowed: 88 | 89 | /STRING/(,N2) 90 | /STRING/(N1,N2)+N 91 | 92 | 93 | 2.1 Command descriptions 94 | 95 | TED commands are one or two characters long, optionally followed by one or 96 | more arguments separated by spaces, tabs or a comma. 97 | 98 | Commands are ended with either Return or Ctrl-C. When Ctrl-C is used, the 99 | screen editor is entered after command execution. 100 | 101 | An empty command is also allowed (e.g. by pressing Return or Ctrl-C at the 102 | prompt). That simply causes the editor to enter the screen mode. 103 | 104 | The commands are described below: 105 | 106 | Ctrl-Z or EX 107 | 108 | Exit the editor and return to the operating system. The current buffer 109 | contents are not saved, so any changes made will be lost. 110 | 111 | CL 112 | 113 | Clear the text buffer. Any modifications or new text added will be lost 114 | unless saved to a file first. 115 | 116 | R [(P)] FILE (N1,N2) 117 | 118 | Read the file FILE into the text buffer: 119 | 120 | * If N1 and N2 are specified, only the fragment from line N1 to N2 is 121 | read, otherwise the whole file is loaded. 122 | 123 | * If P is specified, then the file is inserted following the line P in 124 | the current buffer, otherwise the file is appended to the end. 125 | 126 | * The FILE parameter cannot be omitted. 127 | 128 | * All trailing spaces in the line are removed. 129 | 130 | W [P1 P2] [FILE] [N] 131 | 132 | Write the contents of the text buffer from line P1 to P2 into file FILE 133 | after line N: 134 | 135 | * If P1 and P2 are omitted, the whole contents of the text buffer is 136 | written to the file. If only one parameter is specified, then only the 137 | specified line is written. 138 | 139 | * If FILE is omitted, the file name from the latest R command will be 140 | used. 141 | 142 | * N can be either zero of the dollar sign "$". In the first case the 143 | output file is truncated, erasing any old file contents. In the second 144 | case, the file will be opened in append mode and the contents of the 145 | text buffer will be added following the last text line of the file. 146 | If the parameter is not specified, zero is assumed. 147 | 148 | F 149 | 150 | Display the name of the file read by the last R command. This is the 151 | name that will be used by the W command if the FILE parameter is omitted. 152 | 153 | PR P1 [P2] 154 | 155 | Output (PRint) text lines from P1 to P2 to the terminal. If P2 is omitted, 156 | only one line will be displayed. P2 can also be the dollar sign, which 157 | represents the last line of the text. Any control characters are output 158 | as ^X. 159 | 160 | D P1 [P2] 161 | 162 | Delete lines from P1 to P2 inclusive. If P2 is not specified, then only 163 | a single line is deleted. 164 | 165 | M P1 P2 P3 166 | 167 | Copy lines from P1 to P2 after line P3. If P2 equals P1, only a single 168 | line is copied. 169 | 170 | MD P1 P2 P3 171 | 172 | Move lines from P1 to P2 after line P3. The original lines in the range 173 | P1 to P2 are then deleted. If P2 equals P1 then only a single line is 174 | moved. 175 | 176 | SU /OLD/NEW/[(N1[,N2])] 177 | SU M /OLD/NEW/[(N1[,N2])] 178 | SU N /OLD/NEW/[(N1[,N2])] 179 | 180 | Search and replace text (SUbstitute). OLD is the string to search for, 181 | while NEW is the text that will replace OLD. NEW can be an empty string, 182 | but OLD cannot. Valid delimiter characters are listed in the section 2 183 | above. 184 | 185 | The substitute command can work in one of the following modes: 186 | 187 | * The substitution is made everywhere in the text where OLD is found. 188 | This is the default behavior. 189 | 190 | * When M is specified as the first parameter, lines containing OLD are 191 | displayed on the terminal with the OLD portion enclosed in double-quotes, 192 | followed by a "Y--^C" prompt: 193 | 194 | - to replace text and continue, press Y. 195 | 196 | - to skip the current matched string and continue, press Enter. 197 | 198 | - to abort the current and all following substitutions, press Ctrl-C. 199 | 200 | * If the number of substitutions to do is known beforehand, then the 201 | value N can be specified in place of the first parameter. In this case 202 | the editor will not ask for confirmation. 203 | 204 | In every case the editor displays on the terminal the line after the 205 | substitutions are made. 206 | 207 | If necessary, a range of lines where substitutions should be made can be 208 | specified right after NEW, enclosed in parenthesis. 209 | 210 | S [P] 211 | 212 | Enter screen mode. The top line of the screen will be set to parameter 213 | P, if specified, or to the current text marker. 214 | 215 | P [P] 216 | 217 | Set text marker to line P. If P is not specified, the current cursor 218 | position is displayed. 219 | 220 | FR 221 | 222 | Displays the amount of available memory. 223 | 224 | 225 | 2.2 Command line edition 226 | 227 | The command mode allows simple editing of command lines. The editor always 228 | remembers the last command entered, which can be later recalled fully or 229 | partially. 230 | 231 | Ctrl-U or Ctrl-^ 232 | 233 | Delete the current line. 234 | 235 | DEL, Backspace or Ctrl-H 236 | 237 | Delete one character left. 238 | 239 | Left Arrow (Ctrl-S) 240 | 241 | Delete one character left. 242 | 243 | Right Arrow (Ctrl-D) 244 | 245 | Restore one character from the previous command at the current cursor 246 | position. 247 | 248 | Up Arrow (Ctrl-E) 249 | 250 | Restore (recall) all remaining characters from the previous command 251 | starting from the current cursor position. 252 | 253 | Ctrl-G 254 | 255 | Same as above, but the command is entered and executed immediately. 256 | Used mostly to repeat the last command entered by typing Ctrl-G at 257 | the editor prompt. 258 | 259 | 260 | 3. Screen mode. 261 | 262 | This is the main mode of text edition. The cursor can be moved around the 263 | screen, text entered and/or deleted, etc. 264 | 265 | Printable characters are entered at the current cursor position, moving the 266 | cursor one column to the right afterwards. Other operations are performed 267 | via Ctrl-key combinations or dedicated terminal keys: 268 | 269 | Ctrl-C or Ctrl-Z 270 | 271 | Exit screen mode back to command mode. 272 | 273 | Left Arrow (Ctrl-S) 274 | 275 | Moves the cursor one column left. 276 | 277 | Right Arrow (Ctrl-D) 278 | 279 | Moves the cursor one column right. 280 | 281 | Up Arrow (Ctrl-E) 282 | 283 | Moves the cursor one row up. If the cursor is at the top of the 284 | screen, the text is scrolled down. 285 | 286 | Down Arrow (Ctrl-X) 287 | 288 | Moves the cursor one row down. If the cursor is at the bottom of the 289 | screen, the text is scrolled up. 290 | 291 | Home (Ctrl-L) 292 | 293 | Moves the cursor to the start of the line, or to the end if the cursor 294 | was already on the start column. 295 | 296 | Ctrl-T 297 | 298 | Moves the cursor to the top line of the screen, or to the bottom one 299 | if the cursor already was on the top line. 300 | 301 | Ctrl-F 302 | 303 | Moves the cursor to the next tab stop. 304 | 305 | Ctrl-Q 306 | 307 | Moves the cursor to the previous tab stop. 308 | 309 | Tab (Ctrl-I) 310 | 311 | Inserts a tab character. 312 | 313 | Return or Enter (Ctrl-M) 314 | 315 | Splits the line at the current cursor location and moves the cursor 316 | to the start of the next line. 317 | 318 | Ctrl-R or Ctrl-_ 319 | 320 | Redraws the screen. 321 | 322 | Ctrl-Y or Ctrl-^ 323 | 324 | Delete current line, shifting the lines below it one row up. 325 | 326 | LF (Ctrl-J) 327 | 328 | Inserts an empty line below the current one. The cursor is moved down 329 | to the new line, same column. 330 | 331 | Ctrl-K 332 | 333 | Inserts an empty line at the current cursor position, shifting the 334 | existing text one row down. The cursor remains on the same location. 335 | 336 | DEL or Backspace (Ctrl-H) 337 | 338 | Delete char left, shifting the rest of the line one column left. 339 | 340 | Ctrl-] or Ctrl-G 341 | 342 | Delete character right, shifting the rest of the line one column left. 343 | 344 | Ctrl-P 345 | 346 | Duplicates the current line. The new line is placed below the current 347 | one, shifting any existing text one row down. 348 | 349 | Ctrl-V 350 | 351 | Toggle insert/overwrite mode. Default editing mode is overwrite, where 352 | typed characters overwrite the existing text. In insert mode, the text 353 | on the line is shifted one column to the right starting from the cursor 354 | position before the typed character is stored. 355 | 356 | Ctrl-B or Ctrl-N 357 | 358 | Enter "browse" mode. The cursor jumps to the bottom of the screen, 359 | below the ruler and the number to the right shows the line number the 360 | cursor was on. In browse mode the cursor movement keys work as 361 | described below: 362 | 363 | Left Arrow (Ctrl-S) 364 | 365 | Shift screen window 10 columns left (the text appears to move 10 366 | columns right). 367 | 368 | Right Arrow (Ctrl-D) 369 | 370 | Shift screen window 10 columns right (the text appears to move 371 | 10 columns left). 372 | 373 | Up Arrow (Ctrl-E) 374 | 375 | Shift screen window 21 lines up (the text appears to scroll 21 376 | lines down, so the top line becomes the bottom one). 377 | 378 | Down Arrow (Ctrl-X) 379 | 380 | Shift screen window 21 lines down (the text appears to scroll 21 381 | lines up, so the bottom line becomes the top one). 382 | 383 | Ctrl-C, Ctrl-Z or Return exits browse mode. 384 | -------------------------------------------------------------------------------- /docs/vmem.txt: -------------------------------------------------------------------------------- 1 | Virtual Memory structures used by TED 2 | ------------------------------------- 3 | 4 | The code and the descriptions below use the following naming conventions: 5 | 6 | 1 block = 1 disk sector = 512 bytes 7 | 1 record = 16 bytes, there are 32 records in a block 8 | 9 | Text lines are stored internally in a double-linked list of records with the 10 | following format: 11 | 12 | Head record: 13 | +------+------+------+----------------------------------+ 14 | | cont | next | prev | text, 10 chars max | 15 | +------+------+------+----------------------------------+ 16 | 17 | Continuation record: 18 | +------+------+------+----------------------------------+ 19 | | cont | text, 14 chars max | 20 | +------+------+------+----------------------------------+ 21 | 22 | Free list record: 23 | +------+------------------------------------------------+ 24 | | next | unused | 25 | +------+------------------------------------------------+ 26 | 27 | The continuation field is set to zero for the last record in a sequence. 28 | 29 | Similarly, the prev and next fields set to zero indicate end of the list. 30 | 31 | The text field ends with a CR, which is stored only if there are less chars 32 | than the maximum (i.e. a single overflowing CR is never stored in a new 33 | record). 34 | 35 | Multiple contiguous spaces are compressed into a single byte with the high 36 | bit set and the lower 7 bits indicating the actual number of spaces. 37 | 38 | Since record numbers are kept in a word, the maximum work file size (and 39 | therefore the maximum editable file size) is limited to 65536/32 = 2048 40 | blocks, or about 2048*512 = 1048576 bytes (1 Mbyte). In practice, the 41 | maximum file size is somewhat less than that due to the overhead of pointers 42 | (one word per record) and length fields (one additional word in the line 43 | header records). The multiple space compression mentioned above compensates 44 | somewhat for the space lost by the pointers and length fields. 45 | 46 | The maximum allowed line length is 162 bytes. 47 | 48 | Buffers for blocks in memory are allocated from top of memory down and 49 | are 516 bytes long (2 words + 32 records of 16 bytes). The first two words 50 | contain: 51 | 52 | 1. (offset 0): LRU count (low 15 bits), high bit set = 'dirty' 53 | 2. (offset 2): block number, used to index into the block map area 54 | 55 | Block map grows from low memory up, and has a max size of 2048 bytes. 56 | A value of zero indicates that the block has been swapped out, while a 57 | non-zero value points to the buffer containing the block in memory. Note 58 | that since 64K can only hold up to 128 buffers (65536/512 = 128), one byte 59 | is enough to represent buffer numbers in memory. 60 | 61 | -------------------------------------------------------------------------------- /errors.inc: -------------------------------------------------------------------------------- 1 | ; System error codes 2 | 3 | E.OK equ 0 ; No error 4 | E.EOF equ -1 ; End of file 5 | E.FNF equ -2 ; File not found 6 | E.DNF equ -3 ; Directory not found 7 | E.NODIR equ -4 ; Not a directory 8 | E.BADF equ -5 ; Bad file specification 9 | E.DSKF equ -6 ; Disk full 10 | E.IDXF equ -7 ; Index file full 11 | E.IDXE equ -8 ; Index file error 12 | E.BADOP equ -9 ; Invalid operation 13 | E.CHOPN equ -10 ; Channel already in use 14 | E.IO equ -11 ; Channel I/O error 15 | E.PERM equ -12 ; Access denied 16 | E.INV equ -13 ; Invalid value 17 | E.LUN equ -14 ; Invalid LUN 18 | E.NOBUF equ -15 ; Out of disk buffers 19 | E.DEVNM equ -16 ; Device not mounted 20 | E.DEVAM equ -17 ; Device already mounted 21 | E.DMOP equ -18 ; Dismount in progress 22 | E.OFL equ -19 ; Unit offline 23 | E.BADVT equ -20 ; Invalid volume type 24 | E.UNA equ -21 ; Reading unallocated block (unwritten data) 25 | E.FLCK equ -22 ; File access is locked 26 | E.NODEV equ -23 ; No such device 27 | E.EXIST equ -24 ; File exists 28 | E.DNE equ -25 ; Directory not empty 29 | E.VLIM equ -26 ; File version limit reached 30 | E.BADFN equ -27 ; Invalid system call 31 | E.BADTH equ -28 ; Invalid task header 32 | E.TCKS equ -29 ; Task image checksum error 33 | E.BADTF equ -30 ; Invalid or corrupt task image file 34 | E.TNF equ -31 ; Task not found 35 | E.TNU equ -32 ; Task name in use 36 | E.FNC equ -33 ; File not contiguous 37 | E.NCSPC equ -34 ; No contiguous space on device 38 | E.NOMEM equ -35 ; Not enough room 39 | E.PEND equ -36 ; I/O request pending 40 | E.TRUN equ -37 ; Task already running 41 | E.TSTP equ -38 ; Task already stopped 42 | E.TDLY equ -39 ; Task already delayed 43 | E.TFIX equ -40 ; Task already fixed 44 | E.TNFIX equ -41 ; Task not fixed 45 | E.TACT equ -42 ; Task active 46 | E.TNAC equ -43 ; Task not active 47 | E.TNIU equ -44 ; Task name in use 48 | E.TABO equ -45 ; Task abort in progress 49 | E.FAIL equ -46 ; Operation failed 50 | E.ABOP equ -47 ; Operation aborted 51 | E.TMO equ -48 ; Operation timed out 52 | E.PRIV equ -49 ; Privileged command 53 | E.PBIG equ -50 ; Program too big 54 | E.QEMP equ -51 ; Queue empty 55 | E.BADFL equ -52 ; Invalid flag number 56 | E.PBSY equ -53 ; Partition busy 57 | E.PNF equ -54 ; Partition not found 58 | E.SSNF equ -55 ; Session not found 59 | E.SSNA equ -56 ; Session not active 60 | E.CLNF equ -57 ;- CLI not found 61 | E.DMOI equ -58 ;- Dismount initiated 62 | E.NLI equ -59 ;- Not logged in 63 | E.ULI equ -60 ;- Already (Other user) logged in 64 | 65 | ; Task exit status codes (lo-byte, hi-byte is reserved for user codes) 66 | 67 | EX.WRN equ 0 ; Warning 68 | EX.SUC equ 1 ; Success 69 | EX.ERR equ 2 ; Error 70 | EX.SEV equ 4 ; Severe 71 | 72 | -------------------------------------------------------------------------------- /fcb.inc: -------------------------------------------------------------------------------- 1 | ; FCB structure offsets 2 | 3 | F.LNK equ 0 ; link to next FCB in list (2 bytes) 4 | F.ATTR equ F.LNK + 2 ; file attributes and flags (1 byte) 5 | F.DEV equ F.ATTR + 1 ; device name (2 characters) 6 | F.UNIT equ F.DEV + 2 ; device unit (1 byte) 7 | F.DIR equ F.UNIT + 1 ; directory name (9 characters) 8 | F.NAME equ F.DIR + 9 ; file name (9 characters) 9 | F.EXT equ F.NAME + 9 ; file ext (3 characters) 10 | F.VER equ F.EXT + 3 ; file version (2 bytes) 11 | F.USER equ F.VER + 2 ; user code (1 byte) 12 | F.GROUP equ F.USER + 1 ; group code (1 byte) 13 | F.PROT equ F.GROUP + 1 ; protection bits (2 bytes) 14 | F.LCNT equ F.PROT + 2 ; link count (2 bytes) 15 | F.SEQNO equ F.LCNT + 2 ; sequence number (2 bytes) 16 | F.INODE equ F.SEQNO + 2 ; index file entry number (2 bytes) 17 | F.NALOC equ F.INODE + 2 ; total data blocks allocated (3 bytes) 18 | F.NUSED equ F.NALOC + 3 ; data blocks actually used (3 bytes) 19 | F.LBCNT equ F.NUSED + 3 ; last block byte count (2 bytes) 20 | F.BMAP equ F.LBCNT + 2 ; block map (6*3 bytes) 21 | F.CALBN equ F.BMAP + 6*3 ; cached logical alloc block number (3 bytes) 22 | F.CAVBN equ F.CALBN + 3 ; cached virtual alloc block number (2 bytes) 23 | F.REFS equ F.CAVBN + 2 ; reference count (2 bytes) 24 | 25 | ; Fields present in fileinfo and FDB structures, but not in FCB 26 | 27 | F.WAT equ F.LNK + 0 ; field bit for IO.WAT function (1 byte) 28 | F.WLDC equ F.WAT + 1 ; wildcards in filespec (1 byte) 29 | F.TCRE equ F.CALBN + 0 ; created timestamp (7 bytes) 30 | F.TMOD equ F.TCRE + 7 ; last modified timestamp (7 bytes) 31 | 32 | ; F.ATTR flag bits (for both FCB and index file entries unless otherwise noted) 33 | 34 | FA.DIR equ 80h ; file is a directory 35 | FA.FILE equ 01h ; file is a regular file 36 | FA.CTG equ 08h ; file is contiguous 37 | FA.LCK equ 10h ; file is locked 38 | FA.RD equ 02h ; file is open for read (FCB only) 39 | FA.WR equ 04h ; file is open for write (FCB only) 40 | FA.SHR equ 20h ; file is open in shared mode (FCB only) 41 | FA.MODF equ 40h ; file has been modified (FCB only) 42 | 43 | ; F.WAT field bit masks 44 | 45 | FA.USER equ 01h ; set F.USER 46 | FA.GRP equ 02h ; set F.GROUP 47 | FA.PROT equ 04h ; set F.PROT 48 | FA.TCRE equ 10h ; set IE.TCRE 49 | FA.TMOD equ 20h ; set IE.TMOD 50 | 51 | ; PFN filespec parsing result bits 52 | 53 | FN.DEV equ 01h ; device name specified 54 | FN.DIR equ 02h ; directory specified 55 | FN.NAME equ 04h ; file name specified 56 | FN.EXT equ 08h ; extension specified 57 | FN.VER equ 10h ; version specified 58 | 59 | ; File protection bit masks 60 | 61 | FP.R equ 08h ; read 62 | FP.W equ 04h ; write 63 | FP.E equ 02h ; execute (not used) 64 | FP.D equ 01h ; delete 65 | 66 | ; Structure sizes 67 | 68 | FCBSZ equ F.REFS + 2 ; FCB size 69 | FDBSZ equ F.PROT + 2 ; size of descriptor used by file open/create, etc. 70 | FNSZ equ F.VER + 2 ; size of filespec part, used by parsefn 71 | FINFSZ equ F.TMOD + 7 ; size of fileinfo structure 72 | 73 | ; Directory entry layout 74 | 75 | DE.INDX equ 0 ; index file entry (inode) number (2 bytes) 76 | DE.NAME equ DE.INDX + 2 ; file name (9 characters) 77 | DE.EXT equ DE.NAME + 9 ; file externsion (3 characters) 78 | DE.VER equ DE.EXT + 3 ; file version (2 bytes) 79 | 80 | DESZ equ DE.VER + 2 ; directory entry size 81 | 82 | ; Index file entry (inode) layout 83 | 84 | IE.LCNT equ 0 ; link count (2 bytes) 85 | IE.ATTR equ IE.LCNT + 2 ; file attributes (1 byte) 86 | IE.CLF equ IE.ATTR + 1 ; cluster factor (1 byte) 87 | IE.SEQN equ IE.CLF + 1 ; file sequence number (2 bytes) 88 | IE.USER equ IE.SEQN + 2 ; user code (1 byte) 89 | IE.GRP equ IE.USER + 1 ; group code (1 byte) 90 | IE.ALOC equ IE.GRP + 1 ; total data blocks allocated (3 bytes) 91 | IE.USED equ IE.ALOC + 3 ; total data blocks used (3 bytes) 92 | IE.LBCN equ IE.USED + 3 ; last block byte count (2 bytes) 93 | IE.TCRE equ IE.LBCN + 2 ; created timestamp (7 bytes) 94 | IE.TMOD equ IE.TCRE + 7 ; last modified timestamp (7 bytes) 95 | IE.PROT equ IE.TMOD + 7 ; protection bits (2 bytes) 96 | IE.BMAP equ IE.PROT + 2 ; block map (6*3 bytes) 97 | IE.NAME equ IE.BMAP + 6*3 ; original file name (9 characters) 98 | IE.EXT equ IE.NAME + 9 ; original file extension (3 characters) 99 | IE.VERS equ IE.EXT + 3 ; original file version (2 bytes) 100 | 101 | IESZ equ IE.VERS + 2 ; index file entry (inode) size (64 bytes) 102 | 103 | -------------------------------------------------------------------------------- /fileio.mac: -------------------------------------------------------------------------------- 1 | ;**********************************************************************; 2 | ; ; 3 | ; This file is part of TED, a clone of the screen-oriented text ; 4 | ; editor that was once available for the RT-11 OS. ; 5 | ; Copyright (C) 2011-2020, Hector Peraza. ; 6 | ; ; 7 | ; This program is free software; you can redistribute it and/or ; 8 | ; modify it under the terms of the GNU General Public License as ; 9 | ; published by the Free Software Foundation; either version 2 of ; 10 | ; the License, or (at your option) any later version. ; 11 | ; ; 12 | ; This program is distributed in the hope that it will be useful, ; 13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; 14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; 15 | ; GNU General Public License for more details. ; 16 | ; ; 17 | ; You should have received a copy of the GNU General Public License ; 18 | ; along with this program; if not, write to the Free Software ; 19 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; 20 | ; ; 21 | ;**********************************************************************; 22 | 23 | .Z80 24 | 25 | title TED - Text Editor 26 | subttl File I/O routines 27 | 28 | include TED.INC 29 | 30 | ;======================================================================= 31 | 32 | ; F I L E I / O S E C T I O N 33 | 34 | public CMDF,CMDR,CMDW 35 | 36 | extrn GETARG,PUTC,EEXTRA,EDLEN,STRBUF,GETTXP,INSBUF 37 | extrn NUMD,GTTXP0,SETTXP,LASTLN,EDREC,NXTREC,ARGTYP 38 | extrn NUMVAL,EXPAND,HLDEC,CRLF,PUTSTR,CPDEHL,UCASE 39 | extrn FOPEN,FMODF,FCREAT,FCLOSE,FGETC,FPUTC,PADEOF 40 | extrn PRFNAM,MKFCB,ERRWFO 41 | 42 | ;----------------------------------------------------------------------- 43 | 44 | cseg 45 | 46 | ; R command - read file 47 | 48 | CMDR: call GETARG ; process argument 49 | ret c ; return if error 50 | ld de,(LASTLN) ; get last line number into DE 51 | call GETTXP 52 | ret c ; on error return 53 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 54 | ld (EDREC),hl ; store curr rec# for initial INSBUF call below 55 | ld c,e 56 | ld b,d ; get current line number into BC (for INSBUF) 57 | call RARGS ; process R command arguments 58 | ret c ; on error return 59 | call EEXTRA ; display error if extra parameters 60 | ret c ; on error return 61 | ld a,(FMODF) 62 | push af ; save current file modified flag 63 | ld a,MAXLEN+2 ; 164 = size of STRBUF buffer 64 | ld (RDMAX),a ; store it for file I/O routine 65 | ld hl,STRBUF ; get address of line buffer into HL 66 | ld (RDPTR),hl ; store for file I/O routine 67 | ld hl,0 68 | ld (LNCNT),hl ; clear line count 69 | rloop: call FRDLIN ; open file, read a line 70 | jr c,rdeof ; jump on error (EOF) 71 | ld hl,(EDREC) ; get record number of current line into HL 72 | ld de,STRBUF 73 | call INSBUF ; insert line into text buffer 74 | jr c,rdwfov ; jump on error - WORK FILE OVERFLOW 75 | inc bc ; increment current line number 76 | ld hl,(LNCNT) 77 | inc hl ; increment number of lines read 78 | ld (LNCNT),hl 79 | ld a,l 80 | and 7 ; check lower 3 bits of line count 81 | call z,PRLINE ; output number of lines read every 8 82 | jr rloop ; loop until all lines read 83 | 84 | rdwfov: ld hl,ERRWFO ; '*WORK FILE OVERFLOW' 85 | call PUTSTR ; output string 86 | rdeof: pop af 87 | ld (FMODF),a ; restore old file modified flag 88 | ld hl,(LNCNT) 89 | call PRLINE ; output ' NNNNN LINES ' (value in HL) 90 | ld hl,MSGRDF ; 'READ FROM "' 91 | call PUTSTR ; output string 92 | call PRFNAM 93 | call PUTSTR 94 | call CLSINP ; close input file 95 | ret 96 | 97 | ; F command 98 | 99 | CMDF: ld a,(VALIDF) ; valid filename? 100 | or a 101 | jr z,nofn ; jump if not 102 | call PRFNAM ; else output current file name 103 | call CRLF 104 | call GETARG ; process arguments 105 | ret c ; on error return 106 | jp EEXTRA ; display error if extra parameters 107 | nofn: ld hl,MSGIFN ; 'MISSING OR ILLEGAL FILE NAME' 108 | jp PUTSTR ; display message 109 | 110 | MSGIFN: db 'Missing or illegal file name',LF,CR,0 111 | 112 | ; W command - write to file 113 | 114 | CMDW: call GETARG ; process arguments 115 | ret c ; on error return 116 | ld de,1 117 | call GTTXP0 118 | ret c ; on error return 119 | call SETTXP ; curr rec <- HL, curr ln <- DE, chr pos <- B 120 | ld (CREC),hl ; save current record 121 | ld (CLINE),de ; set start line = current line 122 | ld a,(ARGTYP) ; check argumnet type from GETARG above 123 | dec a ; arg type = 1? (number) 124 | jr z,wr2 ; jump if yes 125 | dec a ; end line = 2? (N1,N2)+N3 126 | jr z,wr2 ; jump if yes 127 | ld de,(LASTLN) ; get last line number into DE 128 | wr2: call GETTXP 129 | ret c ; on error return 130 | ld hl,(CLINE) 131 | ex de,hl 132 | ld (ENDLN),hl ; set end line 133 | call CPDEHL 134 | jr nc,wr3 ; jump if end line >= start line 135 | ld hl,MSGILB ; 'ILLEGAL BOUNDS' 136 | call PUTSTR ; else error - output string 137 | ret ; and return 138 | 139 | wr3: call WARGS ; process arguments for W command 140 | ret c ; on error return 141 | call EEXTRA ; display error if extra parameters 142 | ret c ; on error return 143 | ld hl,STRBUF ; get address of line buffer 144 | ld (WRPTR),hl ; into WRPTR 145 | wloop: ld de,(CLINE) 146 | ld hl,(ENDLN) 147 | call CPDEHL ; past end line? 148 | jr c,wend ; exit loop if yes 149 | ld hl,(CREC) ; get record number into HL 150 | ld a,h 151 | or l 152 | jr z,wend ; exit loop if zero (no more lines) 153 | ld de,STRBUF ; get buffer address into DE 154 | call EXPAND ; expand line 155 | ld a,(EDLEN) 156 | ld (WRLEN),a ; store expanded length for file write function 157 | ld hl,(NXTREC) 158 | ld (CREC),hl ; store next line's record# 159 | call FWRLIN ; write line to output file 160 | jr c,wend ; on error, close file and return 161 | ld hl,(CLINE) ; increment number of lines written 162 | inc hl 163 | ld (CLINE),hl 164 | ld hl,(LNCNT) 165 | ld a,l 166 | and 7 ; check lower 3 bits of line count 167 | call z,PRLINE ; output number of lines written every 8 168 | jr wloop ; loop 169 | wend: xor a 170 | ld (FMODF),a ; clear file modified flag 171 | ld hl,(LNCNT) 172 | call PRLINE ; output number of lines written 173 | ld hl,MSGWRT ; 'WRITTEN INTO "' 174 | call PUTSTR 175 | call PRFNAM 176 | call PUTSTR 177 | call CLSOUT ; close output file 178 | ret 179 | 180 | MSGILB: db 'Illegal bounds',LF,CR,0 181 | 182 | ; Process arguments for R command (parse filename, get line numbers, etc.) 183 | 184 | RARGS: push hl 185 | push de 186 | push bc 187 | ld hl,0 188 | ld (NREAD),hl ; clear number of lines read 189 | ld a,(ARGTYP) 190 | cp 3 ; arg type = string? 191 | jr z,ra1 ; jump if yes 192 | ld hl,MSGIFN ; else error - 'MISSING OR ILLEGAL FILE NAME' 193 | call PUTSTR ; display message 194 | scf ; set error flag 195 | jr ra6 ; and return 196 | 197 | ra1: call GETFN ; get file name 198 | jr c,ra6 ; on error return 199 | ld hl,1 200 | ld (CLINE),hl ; default start line = 1 201 | ld hl,65535 202 | ld (ENDLN),hl ; default end line = 65535 203 | call GETARG ; process additional arguments 204 | jr c,ra6 ; on error return 205 | ld a,c 206 | or a ; any arguments? 207 | jr z,ra2 ; jump if not 208 | dec a ; argument type = single numeric? 209 | jr nz,ra5 ; jump if not 210 | ld hl,(NUMVAL) 211 | ld (CLINE),hl ; else set start line 212 | ld a,(NUMD) ; check displacement flag 213 | or a 214 | jp m,ra4 ; error if from end of file 215 | ra2: call GETARG ; process more arguments 216 | jr c,ra6 ; on error return 217 | ld a,c 218 | cp 1 ; argument type = single numeric? 219 | jr nz,ra5 ; jump if not 220 | ld a,(NUMD) ; check displacement flag 221 | or a 222 | jp p,ra3 ; jump if absolute or relative 223 | ld a,d ; if from end, offset is zero? 224 | or e 225 | jr nz,ra4 226 | ld de,65535 ; if yes, set end line = 65535 227 | ra3: ld hl,(NUMVAL) 228 | ld (ENDLN),hl ; set end line 229 | call GETARG ; process more arguments 230 | jr c,ra6 ; on error return 231 | jr ra5 232 | ra4: ld hl,MSGILB ; error - 'ILLEGAL BOUNDS' 233 | call PUTSTR ; output string 234 | scf ; set error flag 235 | jr ra6 ; and return 236 | 237 | ra5: ld de,(CLINE) 238 | ld hl,(ENDLN) 239 | call CPDEHL ; start line > end line? 240 | jr c,ra4 ; jump if yes 241 | ra6: pop bc 242 | pop de 243 | pop hl 244 | ret 245 | 246 | ; Read line from input file, open file first if necessary. 247 | 248 | FRDLIN: push hl 249 | push de 250 | push bc 251 | ld de,(ENDLN) ; get end line into DE 252 | ld hl,(NREAD) ; get number of lines read so far into HL 253 | ld a,h 254 | or l 255 | jr nz,frl1 ; jump if not zero (file already open) 256 | call OPNINP ; else open input file 257 | jr c,frl2 ; on error return 258 | frl1: inc hl ; increment number of lines read 259 | call CPDEHL ; above end line? 260 | jr nc,frl2 ; return if yes (note CY not set) 261 | call FGETLN ; read line from input file 262 | jr c,frl2 ; on error return 263 | push de 264 | ld de,(CLINE) 265 | call CPDEHL ; start line reached? 266 | pop de 267 | jr c,frl1 ; loop if not 268 | ld (NREAD),hl ; store number of lines read 269 | ld (CLINE),hl ; set start line 270 | or a ; clear error flag 271 | frl2: pop bc 272 | pop de 273 | pop hl 274 | ret 275 | 276 | ; Process arguments for W command 277 | 278 | WARGS: push hl 279 | push de 280 | push bc 281 | ld hl,0 282 | ld (LNCNT),hl ; clear number of lines written into file 283 | call GETFN ; get file name 284 | jr c,wa4 ; on error return 285 | call GETARG ; process arguments 286 | jr c,wa4 ; on error return 287 | ld hl,0 288 | ld a,c 289 | cp 1 ; argument type = single numeric? 290 | jr nz,wa3 ; jump if not (set value = 0) 291 | ld hl,(NUMVAL) ; else get numeric value 292 | ld a,h 293 | or l ; zero? 294 | jr z,wa1 ; jump if yes 295 | ld hl,MSGILN ; else error - 'ILLEGAL LINE#' 296 | call PUTSTR ; output string 297 | scf ; set error flag 298 | jr wa4 ; and return 299 | 300 | wa1: ld a,(NUMD) ; check displacement flag 301 | or a 302 | jr z,wa2 ; jump if absolute or relative 303 | ld a,l ; else negate value 304 | cpl 305 | ld l,a 306 | ld a,h 307 | cpl 308 | ld h,a 309 | inc hl 310 | wa2: call GETARG ; process arguments 311 | jr c,wa4 ; on error return 312 | wa3: ld (WRARG),hl ; store line number [not used?] 313 | or a 314 | wa4: pop bc 315 | pop de 316 | pop hl 317 | ret 318 | 319 | MSGILN: db 'Illegal line number',LF,CR,0 320 | 321 | ; Write line to output file. Create file first if necessary. 322 | 323 | FWRLIN: push hl 324 | push de 325 | push bc 326 | ld hl,(LNCNT) ; any lines written? 327 | ld a,h 328 | or l 329 | jr nz,fwl1 ; jump if yes, file already created 330 | call CREOUT ; else create output file 331 | jr c,fwl2 ; on error return 332 | fwl1: ld hl,(LNCNT) ; increment count of written lines 333 | inc hl 334 | ld (LNCNT),hl 335 | call FWRSTR ; write string to file 336 | ;jr c,fwl2 ; on error return 337 | ;or a ; else clear CY 338 | fwl2: pop bc 339 | pop de 340 | pop hl 341 | ret 342 | 343 | ; Close output file 344 | 345 | CLSOUT: call PADEOF ; pad record with EOF marker 346 | jr nc,cls1 347 | push hl 348 | ld hl,MSGDKF ; 'DISK OR DIRECTORY FULL' 349 | ld a,(CLEFLG) 350 | or a 351 | call nz,PUTSTR 352 | pop hl 353 | ld a,1 354 | ld (CLEFLG),a 355 | scf 356 | cls1: push af ; save error flag from PADEOF 357 | call FCLOSE ; close file 358 | jr nc,cls2 ; jump on success 359 | ld hl,MSGDKF 360 | ld a,(CLEFLG) 361 | or a 362 | call nz,PUTSTR ; else display error message 363 | pop af 364 | scf ; and set CY on result from PADEOF 365 | push af 366 | cls2: pop af 367 | ret 368 | 369 | MSGDKF: db 'Disk or directory full',LF,CR,0 370 | 371 | ; Create output file. TODO: check for existing file? 372 | 373 | CREOUT: push hl 374 | push de 375 | push bc 376 | xor a 377 | ld (CLEFLG),a 378 | call FCREAT 379 | jr nc,cre1 380 | ld hl,MSGDKF ; 'DISK OR DIRECTORY FULL' 381 | call PUTSTR ; display error message 382 | ld a,1 383 | ld (CLEFLG),a 384 | scf ; set error flag 385 | cre1: pop bc 386 | pop de 387 | pop hl 388 | ret 389 | 390 | ; Get file name 391 | 392 | GETFN: push hl 393 | push de 394 | ld a,(ARGTYP) 395 | cp 3 ; arg type = string? 396 | jr nz,pfn0 ; jump if not 397 | ld hl,STRBUF ; src 398 | call MKFCB 399 | jr c,pfn1 400 | ld a,1 401 | ld (VALIDF),a 402 | jr pfn2 ; return if no error 403 | pfn0: ld a,(VALIDF) ; we have a valid FCB? 404 | or a 405 | jr nz,pfn2 ; return if yes, use it 406 | pfn1: ld hl,MSGIFN ; 'MISSING OR ILLEGAL FILE NAME' 407 | call PUTSTR ; output error message 408 | scf ; and return with CY flag set 409 | pfn2: pop de 410 | pop hl 411 | ret 412 | 413 | ; Open input file 414 | 415 | OPNINP: push hl 416 | push de 417 | push bc 418 | call FOPEN 419 | jr nc,opn1 420 | ld hl,MSGFNF ; 'FILE NOT FOUND' 421 | call PUTSTR ; display error message 422 | scf ; set error flag 423 | jr opn2 424 | opn1: ld a,1 425 | ld (OPNFLG),a ; set file open flag for close function 426 | or a 427 | opn2: pop bc 428 | pop de 429 | pop hl 430 | ret 431 | 432 | MSGFNF: db 'File not found',LF,CR,0 433 | 434 | ; Close input file 435 | 436 | CLSINP: ld a,(OPNFLG) 437 | or a 438 | ret z 439 | xor a 440 | ld (OPNFLG),a 441 | call FCLOSE 442 | ret 443 | 444 | ; Read line from input file 445 | 446 | FGETLN: push hl 447 | ld c,1 ; read string length 448 | ld hl,(RDPTR) ; get dst ptr into HL 449 | fget1: call FGETC ; get byte from input file 450 | jr c,fget2 ; on error (EOF) return 451 | and 7Fh ; strip hi-bits, leave ASCII 452 | ld (hl),a ; store char 453 | inc hl 454 | cp LF ; end of line? 455 | jr z,fget2 ; if yes, return with CY clear 456 | inc c ; increment length 457 | ld a,(RDMAX) 458 | cp c ; check if max length reached 459 | jr nc,fget1 ; loop if not, else return with CY set 460 | fget2: pop hl 461 | ret 462 | 463 | ; Write string to output file 464 | 465 | FWRSTR: ld hl,(WRPTR) ; get ptr to string into HL 466 | ld a,(WRLEN) ; get string length 467 | ld b,a ; into B 468 | fws1: ld c,(hl) ; get char 469 | push hl 470 | call FPUTC1 ; write it to output file 471 | pop hl 472 | ret c ; on error return 473 | inc hl 474 | djnz fws1 ; decrement string char count and loop 475 | ret ; return with CY clear (OK) 476 | 477 | ; Write byte in C to output file 478 | 479 | FPUTC1: ld a,c 480 | cp SSPC ; do not output soft spaces 481 | ret z 482 | call FPUTC 483 | ret nc 484 | ld hl,MSGDKF ; 'DISK OR DIRECTORY FULL' 485 | call PUTSTR 486 | scf 487 | ret 488 | 489 | ; Display number of lines (value in HL) 490 | 491 | PRLINE: push hl 492 | ld a,CR 493 | call PUTC ; cursor to start of line 494 | ld a,'0' ; filler 495 | call HLDEC ; output value as decimal 496 | ld hl,MSGLNS ; ' LINES ' 497 | call PUTSTR ; output string 498 | pop hl 499 | ret 500 | 501 | MSGLNS: db ' lines ',0 502 | MSGRDF: db 'read from "',0,'"',LF,CR,0 503 | MSGWRT: db 'written to "',0,'"',LF,CR,0 504 | 505 | ;----------------------------------------------------------------------- 506 | 507 | dseg 508 | 509 | ; Param block for FGETLN 510 | 511 | RDMAX: ds 1 ; max length 512 | RDPTR: ds 2 ; dest ptr 513 | 514 | CLINE: ds 2 ; start line for file I/O operations 515 | ENDLN: ds 2 ; end line for file I/O operations 516 | NREAD: ds 2 ; number of lines read from file 517 | 518 | ; Param block for FWRSTR 519 | 520 | WRLEN: ds 1 ; string length 521 | WRPTR: ds 2 ; ptr to string 522 | 523 | WRARG: dw 0 ; W command argument [not used?] 524 | LNCNT: ds 2 ; number of lines read/written 525 | CREC: dw 0 ; line record # 526 | 527 | OPNFLG: ds 1 ; file open flag 528 | CLEFLG: ds 1 ; suppress further close/write error msgs 529 | VALIDF: ds 1 ; 1 = valid FCB (form last R or W command) 530 | 531 | end 532 | -------------------------------------------------------------------------------- /mkted.cmd: -------------------------------------------------------------------------------- 1 | mac main=main 2 | mac termdef=termdef 3 | mac fileio=fileio 4 | mac scrn=scrn 5 | mac cmds=cmds 6 | mac rsxio=rsxio 7 | tkb ted/ot=termdef,main,fileio,scrn,cmds,rsxio/task=...TED/pri=65 8 | -------------------------------------------------------------------------------- /mkted.sub: -------------------------------------------------------------------------------- 1 | m80 =main 2 | m80 =termdef 3 | m80 =fileio 4 | m80 =scrn 5 | m80 =cmds 6 | m80 =cpmio 7 | link ted=termdef,main,fileio,scrn,cmds,cpmio 8 |  -------------------------------------------------------------------------------- /qio.inc: -------------------------------------------------------------------------------- 1 | ; QDB structure offsets 2 | 3 | Q.FUNC equ 0 ; function code (1 byte) 4 | Q.SUBF equ Q.FUNC + 1 ; subfunction (1 byte) 5 | Q.LUN equ Q.SUBF + 1 ; logical unit number (1 byte) 6 | Q.EFN equ Q.LUN + 1 ; event flag number (1 byte) 7 | Q.WAIT equ Q.EFN + 1 ; wait flag (1 byte) 8 | Q.IOSB equ Q.WAIT + 1 ; I/O Status Block address (2 bytes) 9 | Q.AST equ Q.IOSB + 2 ; AST routine address (2 bytes) 10 | Q.P1 equ Q.AST + 2 ; function-dependent param 1 (2 bytes) 11 | Q.P2 equ Q.P1 + 2 ; function-dependent param 2 (2 bytes) 12 | Q.P3 equ Q.P2 + 2 ; function-dependent param 3 (2 bytes) 13 | Q.P4 equ Q.P3 + 2 ; function-dependent param 4 (2 bytes) 14 | Q.P5 equ Q.P4 + 2 ; function-dependent param 5 (2 bytes) 15 | Q.P6 equ Q.P5 + 2 ; function-dependent param 6 (2 bytes) 16 | 17 | QDBSZ equ Q.P6 + 2 ; QDB size 18 | 19 | ; Standard parameter mapping 20 | 21 | Q.BUF equ Q.P1 ; buffer address in user space (2 bytes) 22 | Q.LEN equ Q.P2 ; byte count (2 bytes) 23 | Q.VFC equ Q.P3 ; vertical format control (2 bytes) 24 | Q.TMO equ Q.P3 ; read timeout (2 bytes) 25 | Q.BLK equ Q.P4 ; block number (4 bytes) 26 | Q.OFS equ Q.P6 ; offset within block (2 bytes) 27 | Q.PRB equ Q.P4 ; prompt buffer address (2 bytes) 28 | Q.PRL equ Q.P5 ; prompt length (2 bytes) 29 | Q.PVF equ Q.P6 ; prompt vertical format control (2 bytes) 30 | 31 | ; QIO function codes 32 | 33 | ; Standard functions 34 | 35 | IO.KIL equ 0 ; cancel I/O requests 36 | IO.ATT equ 1 ; attach device 37 | IO.DET equ 2 ; detach device 38 | IO.RLB equ 3 ; read logical block 39 | IO.WLB equ 4 ; write logical block 40 | IO.SEC equ 5 ; sense characteristics 41 | 42 | ; Additional disk driver functions 43 | 44 | IO.RPB equ 6 ; read physical block 45 | IO.WPB equ 7 ; write physical block 46 | IO.FMT equ 8 ; format track 47 | IO.IDN equ 9 ; read drive identification (IDE) 48 | 49 | ; Additional terminal functions 50 | 51 | IO.RPR equ 9 ; read with prompt 52 | IO.HNG equ 10 ; hangup remote line 53 | SF.GMC equ 11 ; get multiple characteristics 54 | SF.SMC equ 12 ; set multiple characteristics 55 | 56 | ; Special functions 57 | 58 | IO.LOV equ 16 ; load overlay 59 | 60 | ; Terminal sub-functions (some can be ORed) 61 | 62 | TF.AST equ 01h ; attach with AST 63 | TF.RNE equ 01h ; read with no echo 64 | TF.RAL equ 02h ; read all bits (unfiltered) 65 | TF.WAL equ 02h ; write all bits 66 | TF.TMO equ 04h ; read with timeout 67 | TF.WBT equ 08h ; break-through write 68 | TF.CCO equ 10h ; cancel ^O 69 | TF.XOF equ 20h ; send XOFF 70 | 71 | ; Filesystem requests 72 | 73 | IO.CRE equ 20 ; create file 74 | IO.ACC equ 21 ; access (open) file 75 | IO.DEA equ 22 ; deaccess (close) file 76 | IO.RVB equ 23 ; read virtual block 77 | IO.WVB equ 24 ; write virtual block 78 | IO.RAT equ 25 ; read attributes 79 | IO.WAT equ 26 ; write attributes 80 | IO.UNL equ 27 ; unlock file 81 | IO.DEL equ 28 ; delete file 82 | IO.REN equ 29 ; rename file 83 | IO.CLN equ 30 ; cleanup file 84 | IO.EXT equ 31 ; extend file 85 | IO.TRN equ 32 ; truncate file 86 | IO.MNT equ 33 ; mount device 87 | IO.DSM equ 34 ; dismount device 88 | IO.FFS equ 35 ; flush all disk buffers 89 | 90 | ; File I/O subfunctions (can be ORed) 91 | 92 | SF.ACR equ 01h ; access (open) for read 93 | SF.ACW equ 02h ; access (open) for write 94 | SF.SHR equ 08h ; open in shared mode 95 | SF.FID equ 10h ; access (open) by file ID 96 | SF.TMP equ 20h ; create temporary file (delete on close) 97 | SF.DIR equ 40h ; create directory 98 | SF.CTG equ 80h ; create contiguous file 99 | 100 | SF.TRU equ 20h ; truncate unused blocks 101 | 102 | ; RSX-11M style QIO macros 103 | 104 | QIO$ macro func,lun,efn,wait,iosb,ast,args 105 | dw func ;; note: 16-bit Q.FUNC + Q.SUBF 106 | db lun,efn ;; Q.LUN, Q.EFN 107 | ifb 108 | db 0 ;; Q.WAIT = 0 109 | else 110 | db wait ;; Q.WAIT 111 | endif 112 | dw iosb ;; Q.IOSB 113 | ifb 114 | dw 0 ;; Q.AST = 0 115 | else 116 | dw ast ;; Q.AST 117 | endif 118 | irp arg, 119 | ifb 120 | dw 0 121 | else 122 | dw arg ;; Q.P1..P6 123 | endif 124 | endm 125 | endm 126 | 127 | QIO$S macro func,lun,efn,wait,iosb,ast,args 128 | local n 129 | push ix 130 | ld ix,-QDBSZ 131 | add ix,sp 132 | ld sp,ix 133 | ld (ix+Q.FUNC),low func 134 | ld (ix+Q.SUBF),high func 135 | ld (ix+Q.LUN),lun 136 | ld (ix+Q.EFN),efn 137 | ifb 138 | ld (ix+Q.WAIT),0 139 | else 140 | ld (ix+Q.WAIT),wait 141 | endif 142 | ld hl,iosb 143 | ld (ix+Q.IOSB),l 144 | ld (ix+Q.IOSB+1),h 145 | ifb 146 | ld hl,0 147 | else 148 | ld hl,ast 149 | endif 150 | ld (ix+Q.AST),l 151 | ld (ix+Q.AST+1),h 152 | n defl 0 153 | irp arg, 154 | ifb 155 | ld hl,0 156 | else 157 | ld hl,arg 158 | endif 159 | ld (ix+Q.P1+n),l 160 | ld (ix+Q.P1+n+1),h 161 | n defl n+2 162 | endm 163 | push ix 164 | pop hl 165 | SC .QIO 166 | ld hl,QDBSZ 167 | add hl,sp 168 | ld sp,hl 169 | pop ix 170 | rlca ;; restore carry bit from error code sign 171 | rra ;; (works since all errors are negative) 172 | endm 173 | 174 | QIOW$ macro func,lun,efn,iosb,ast,args 175 | QIO$ func,lun,efn,1,iosb,ast, 176 | endm 177 | 178 | QIOW$S macro func,lun,efn,iosb,ast,args 179 | QIO$S func,lun,efn,1,iosb,ast, 180 | endm 181 | 182 | -------------------------------------------------------------------------------- /rsxio.mac: -------------------------------------------------------------------------------- 1 | ;**********************************************************************; 2 | ; ; 3 | ; This file is part of TED, a clone of the screen-oriented text ; 4 | ; editor that was once available for the RT-11 OS. ; 5 | ; Copyright (C) 2011-2023, Hector Peraza. ; 6 | ; ; 7 | ; This program is free software; you can redistribute it and/or ; 8 | ; modify it under the terms of the GNU General Public License as ; 9 | ; published by the Free Software Foundation; either version 2 of ; 10 | ; the License, or (at your option) any later version. ; 11 | ; ; 12 | ; This program is distributed in the hope that it will be useful, ; 13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; 14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; 15 | ; GNU General Public License for more details. ; 16 | ; ; 17 | ; You should have received a copy of the GNU General Public License ; 18 | ; along with this program; if not, write to the Free Software ; 19 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; 20 | ; ; 21 | ;**********************************************************************; 22 | 23 | .Z80 24 | 25 | title TED - Text Editor 26 | subttl I/O routines - RSX180 version 27 | 28 | include AST.INC 29 | include DCB.INC 30 | include FCB.INC 31 | include TCB.INC 32 | include QIO.INC 33 | include SYSFN.INC 34 | include ERRORS.INC 35 | include TED.INC 36 | 37 | TTLUN equ 5 ; LUN for terminal I/O 38 | EFLUN equ 1 ; LUN for edit file 39 | WFLUN equ 2 ; LUN for work file 40 | 41 | EFN equ 3 ; event flag number for QIO 42 | ASTEFN equ 4 ; event flag for AST 43 | 44 | ;======================================================================= 45 | 46 | ; S Y S T E M - D E P E N D E N T R O U T I N E S 47 | 48 | public GETC,UNGETC,PUTC,TTQCLR,TTINIT 49 | 50 | public FCREAT,WCREAT,FOPEN,FCLOSE,WCLOSE,FREAD,FWRITE 51 | public FDELET,WDELET,MKFCB,PRFNAM,FGETC,FPUTC,PADEOF 52 | public GETTOP,GETCML,EXIT 53 | 54 | extrn TRMNAM,TTCLR,TTFLSH,PUTCH,PFN,ADEC,HLDEC 55 | 56 | extrn UFLAG,UPDST,UCASE,CPDEHL,QIOSB 57 | 58 | ;TODO: do not enter screen mode if could not open the file specified 59 | ; in the command line. 60 | 61 | ;----------------------------------------------------------------------- 62 | 63 | cseg 64 | 65 | ; Terminal routines 66 | 67 | ; Init terminal 68 | 69 | TTINIT: call TTCLR ; init output buffer 70 | call TTQCLR ; reset input queue 71 | ld hl,TCKSEC 72 | ld c,I.TCKS 73 | SC .GIN ; get ticks/sec for timing functions 74 | ld de,'TI' 75 | ld c,0 76 | ld b,TTLUN 77 | SC .ALUN ; assign TTLUN to TI: 78 | ld l,IO.ATT ; attach 79 | ld h,TF.AST ; with AST 80 | ld (QIOATT+Q.FUNC),hl 81 | ld hl,QIOATT 82 | SC .QIO ; .QIOW 83 | ret c ; return error if queuing failed 84 | ld hl,QIOGMC ; get terminal type 85 | SC .QIO 86 | ret c 87 | ld a,(TCANS+1) 88 | or a ; ANSI terminal? 89 | jr nz,ini1 ; yes, use VT100 definitions 90 | call TRMNAM 91 | ex de,hl 92 | ld hl,vt52 ; else use VT52 definitions 93 | ld bc,deflen 94 | ldir 95 | ini1: ld hl,QIOSMC ; set terminal mode to binary 96 | SC .QIO 97 | ret c 98 | ld a,LF ; don't overwrite RSX180 prompt 99 | jp PUTC 100 | 101 | vt52 equ $ 102 | db 'VT52',0,0,0,0,0,0,0,0,0,0 103 | db 80,24 104 | db 4,ESC,'H',ESC,'J',0,0,0 105 | db 2,ESC,'J',0,0,0,0,0 106 | db 2,ESC,'K',0,0,0,0,0 107 | db 2,ESC,'A',0,0,0,0,0 108 | db 2,ESC,'B',0,0,0,0,0 109 | db 2,ESC,'C',0,0,0,0,0 110 | db 2,ESC,'D',0,0,0,0,0 111 | db 2,ESC,'H',0,0,0,0,0 112 | db 2,ESC,'Y',0,0,0,0,0 113 | db 0,0,0,0,0,0,0,0 114 | db 0,0,0,0,0,0,0,0 115 | db FALSE 116 | db 32 117 | db 32 118 | db FALSE 119 | db 1,LF,0,0,0,0,0,0 120 | db 2,ESC,'I',0,0,0,0,0 121 | db 0,0,0,0,0,0,0,0 122 | db 0,0,0,0,0,0,0,0 123 | db 0,0,0,0,0,0,0,0 124 | deflen equ $-vt52 125 | 126 | ; Output char in A to terminal, buffered. 127 | 128 | PUTC: push af 129 | push bc 130 | and 7Fh 131 | ld c,a 132 | call PUTCH 133 | pop bc 134 | pop af 135 | ret 136 | 137 | ; Get input char into A. If the input queue is empty, wait for character. 138 | 139 | GETC: push hl 140 | push de 141 | push bc 142 | call TTFLSH 143 | gc0: ld e,ASTEFN 144 | SC .CLEF ; clear event flag 145 | 146 | ld a,(TTQLEN) ; check TTY queue length 147 | or a 148 | jr nz,gc1 149 | 150 | ld hl,ASTFLG 151 | bit 0,(hl) ; time mark? 152 | jr z,gc3 153 | 154 | res 0,(hl) 155 | call UPDST 156 | call TTFLSH 157 | 158 | gc3: ld a,(UFLAG) 159 | or a 160 | jr z,gc4 161 | 162 | ld bc,0 163 | ld e,0 164 | SC .CMKT ; cancel any outstanding mark time requests 165 | 166 | ld a,(TCKSEC) 167 | rrca 168 | rrca 169 | and 3Fh ; 0.25 secs 170 | ld l,a 171 | ld h,0 172 | ld d,1 ; units = ticks 173 | ld e,0 ; no EFN 174 | ld bc,TMAST ; AST routine address 175 | SC .MRKT 176 | 177 | gc4: ld e,ASTEFN 178 | SC .WTSE 179 | jr gc0 180 | 181 | gc1: ld hl,(TTQOUT) ; get TTY queue out pointer into HL 182 | ld a,(hl) ; get byte from queue 183 | inc hl 184 | and 7Fh ; strip parity bit, leave ASCII 185 | ld c,a 186 | ld de,TTFIFO+64 187 | call CPDEHL ; pointer at end of buffer? 188 | jr nz,gc2 ; jump if not 189 | ld hl,TTFIFO ; else wrap pointer back to start 190 | gc2: ld (TTQOUT),hl ; store pointer 191 | ld hl,TTQLEN 192 | dec (hl) ; decrement TTY input queue length 193 | ld a,c 194 | pop bc 195 | pop de 196 | pop hl 197 | ret 198 | 199 | ; Store char in C to console queue (this is also called from AST). 200 | 201 | UNGETC: push hl 202 | push de 203 | ld a,(TTQLEN) 204 | cp 64 ; check console input queue length 205 | jr z,tti2 ; return if queue full 206 | ld hl,(TTQIN) ; else get queue in pointer into HL 207 | ld (hl),c ; store incoming char 208 | inc hl ; and advance pointer 209 | ld de,TTFIFO+64 210 | call CPDEHL ; pointer at end of buffer? 211 | jr nz,tti1 ; jump if not 212 | ld hl,TTFIFO ; else wrap pointer back to start 213 | tti1: ld (TTQIN),hl ; store pointer back 214 | ld hl,TTQLEN ; increment queue length 215 | inc (hl) 216 | tti2: pop de 217 | pop hl 218 | ret 219 | 220 | ; Reset console input queue 221 | 222 | TTQCLR: ld c,0 223 | SC .ASTCT ; disable ASTs 224 | ld hl,(TTQOUT) 225 | ld (TTQIN),hl ; make out ptr = in ptr 226 | xor a 227 | ld (TTQLEN),a ; clear queue length (no bytes stored) 228 | ld c,1 229 | SC .ASTCT ; enable ASTs 230 | ret 231 | 232 | ; AST terminal input 233 | 234 | TTAST: ex (sp),hl ; fetch argument 235 | push de 236 | push bc 237 | ld c,l ; get the char 238 | call UNGETC ; store it 239 | ld hl,ASTFLG 240 | set 1,(hl) ; signal char arrived 241 | ld e,ASTEFN 242 | SC .SETF ; and set event flag 243 | pop bc 244 | pop de 245 | pop hl 246 | SC .ASTX 247 | 248 | ; AST mark-time 249 | 250 | TMAST: ex (sp),hl ; drop argument, push regs 251 | push de 252 | ld hl,ASTFLG 253 | set 0,(hl) ; signal time event arrived 254 | ld e,ASTEFN 255 | SC .SETF ; and set event flag 256 | pop de 257 | pop hl 258 | SC .ASTX 259 | 260 | ;----------------------------------------------------------------------- 261 | 262 | ; Disk I/O routines 263 | 264 | ; Create and open work file. Returns CY set on error. 265 | 266 | WCREAT: push hl 267 | push de 268 | push bc 269 | ld de,(WFDB+F.DEV) 270 | ld a,(WFDB+F.UNIT) ; device name in DE-C 271 | ld c,a 272 | ld b,WFLUN ; LUN in B 273 | SC .ALUN 274 | jr c,wc1 275 | ld l,IO.CRE ; function code 276 | ld h,SF.TMP ; non-contiguous file, temporary 277 | ld (QIOWF+Q.FUNC),hl 278 | ld hl,WFDB ; FDB 279 | ld (QIOWF+Q.P1),hl 280 | ld hl,0 ; no preallocated blocks 281 | ld (QIOWF+Q.P2),hl 282 | ld hl,QIOWF 283 | SC .QIO ; .QIOW 284 | jr c,wc1 ; if queuing failed 285 | ld a,(QIOSB) ; fetch return code 286 | or a ; check result 287 | scf 288 | jr nz,wc1 289 | ld hl,IO.RAT ; function code 290 | ld (QIOWF+Q.FUNC),hl 291 | ld hl,WFDB ; buffer address 292 | ld (QIOWF+Q.BUF),hl 293 | ld hl,FINFSZ ; length 294 | ld (QIOWF+Q.LEN),hl 295 | ld hl,QIOWF 296 | SC .QIO ; .QIOW 297 | jr c,wc1 ; if queuing failed 298 | ;; ld hl,(QIOSB+2) ;;; not used [check value?] 299 | ld a,(QIOSB) 300 | or a ; check result 301 | scf 302 | jr nz,wc1 303 | ld a,FN.DEV OR FN.DIR OR FN.NAME OR FN.EXT OR FN.VER 304 | ld (WFDB+F.ATTR),a 305 | xor a 306 | wc1: pop bc 307 | pop de 308 | pop hl 309 | ret 310 | 311 | ; Create output file. Returns CY set on error. 312 | 313 | FCREAT: push hl 314 | push de 315 | push bc 316 | ld a,(EFDB+F.ATTR) 317 | and NOT FN.VER 318 | ld (EFDB+F.ATTR),a 319 | ld hl,0 320 | ld (EFDB+F.VER),hl ; create new version [except for WU command] 321 | ld de,(EFDB+F.DEV) 322 | ld a,(EFDB+F.UNIT) ; device name in DE-C 323 | ld c,a 324 | ld b,EFLUN ; LUN in B 325 | SC .ALUN 326 | jr c,fc1 327 | ld l,IO.CRE ; function code 328 | ld h,0 ; non-contiguous file 329 | ld (QIOEF+Q.FUNC),hl 330 | ld hl,EFDB ; FDB 331 | ld (QIOEF+Q.P1),hl 332 | ld hl,0 ; no preallocated blocks 333 | ld (QIOEF+Q.P2),hl 334 | ld (QIOEF+Q.P2+2),hl 335 | ld hl,QIOEF 336 | SC .QIO ; .QIOW 337 | jr c,fc1 ; if queuing failed 338 | ld a,(QIOSB) ; fetch return code 339 | or a ; check result 340 | scf 341 | jr nz,fc1 342 | ld hl,IO.RAT ; function code 343 | ld (QIOEF+Q.FUNC),hl 344 | ld hl,EFDB ; buffer address 345 | ld (QIOEF+Q.BUF),hl 346 | ld hl,FINFSZ ; length 347 | ld (QIOEF+Q.LEN),hl 348 | ld hl,QIOEF 349 | SC .QIO ; .QIOW 350 | jr c,fc1 ; if queuing failed 351 | ;; ld hl,(QIOSB+2) ;;; not used [check value?] 352 | ld a,(QIOSB) 353 | or a ; check result 354 | scf 355 | jr nz,fc1 356 | ld a,FN.DEV OR FN.DIR OR FN.NAME OR FN.EXT OR FN.VER 357 | ld (EFDB+F.ATTR),a 358 | xor a 359 | fc1: ld hl,0 360 | ld (NUMWR),hl ; clear output byte count 361 | ld (FIOBLK),hl ; init sequential block number 362 | ld hl,IOBUF 363 | ld (FIOPTR),hl ; init output pointer 364 | pop bc 365 | pop de 366 | pop hl 367 | ret 368 | 369 | ; Open input file. Assumes EFDB has been set. Returns CY set on error. 370 | 371 | FOPEN: push hl 372 | push de 373 | push bc 374 | ld de,(EFDB+F.DEV) 375 | ld a,(EFDB+F.UNIT) ; device name in DE-C 376 | ld c,a 377 | ld b,EFLUN ; LUN in B 378 | SC .ALUN 379 | jr c,fop1 380 | ld l,IO.ACC ; function code 381 | ld h,SF.ACR OR SF.SHR 382 | ld (QIOEF+Q.FUNC),hl 383 | ld hl,EFDB ; FDB 384 | ld (QIOEF+Q.P1),hl 385 | ld hl,QIOEF 386 | SC .QIO ; .QIOW 387 | jr c,fop1 ; if queuing failed 388 | ld a,(QIOSB) ; fetch return code 389 | or a ; check result 390 | scf 391 | jr nz,fop1 392 | ld hl,IO.RAT ; function code 393 | ld (QIOEF+Q.FUNC),hl 394 | ld hl,EFDB ; buffer address 395 | ld (QIOEF+Q.BUF),hl 396 | ld hl,FINFSZ ; length 397 | ld (QIOEF+Q.LEN),hl 398 | ld hl,QIOEF 399 | SC .QIO ; .QIOW 400 | jr c,fop1 ; if queuing failed 401 | ;; ld hl,(QIOSB+2) ;;; not used [check value?] 402 | ld a,(QIOSB) 403 | or a ; check result 404 | scf 405 | jr nz,fop1 406 | ld a,FN.DEV OR FN.DIR OR FN.NAME OR FN.EXT OR FN.VER 407 | ld (EFDB+F.ATTR),a 408 | xor a 409 | fop1: ld hl,0 410 | ld (NUMRD),hl ; clear number of bytes read 411 | ld (FIOBLK),hl ; init sequential block number 412 | pop bc 413 | pop de 414 | pop hl 415 | ret 416 | 417 | ; Close work file 418 | 419 | WCLOSE: push hl 420 | ld hl,IO.DEA ; function code 421 | ld (QIOWF+Q.FUNC),hl 422 | ld hl,QIOWF 423 | SC .QIO ; .QIOW 424 | jp c,wcl1 ; if queuing failed 425 | ld a,(QIOSB) 426 | or a ; check result 427 | jp z,wcl1 428 | scf 429 | wcl1: pop hl 430 | ret 431 | 432 | ; Close input and/or edited file 433 | 434 | FCLOSE: push hl 435 | ld hl,IO.DEA ; function code 436 | ld (QIOEF+Q.FUNC),hl 437 | ld hl,QIOEF 438 | SC .QIO ; .QIOW 439 | jp c,fcl1 ; if queuing failed 440 | ld a,(QIOSB) 441 | or a ; check result 442 | jp z,fcl1 443 | scf 444 | fcl1: pop hl 445 | ret 446 | 447 | ; Pad last disk block with EOF characters and save it before closing file 448 | 449 | PADEOF: push hl 450 | ld hl,(NUMWR) ; padding not required for RSX180 451 | ld a,h 452 | or l 453 | pop hl 454 | call nz,WRBLK ; write any remaining chars 455 | ret 456 | 457 | ; Read 512-byte block from work file. HL = buffer address, DE = blk number 458 | 459 | FREAD: push hl 460 | ld (QIOWF+Q.BUF),hl ; buffer address 461 | ld hl,512 462 | ld (QIOWF+Q.LEN),hl ; length 463 | ld (QIOWF+Q.BLK),de ; block number 464 | ld hl,0 465 | ld (QIOWF+Q.OFS),hl ; offset 466 | ld (QIOWF+Q.TMO),hl 467 | ld hl,IO.RVB ; function code 468 | ld (QIOWF+Q.FUNC),hl 469 | ld hl,QIOWF 470 | SC .QIO ; .QIOW 471 | jp c,frd1 ; if queuing failed 472 | ;; ld hl,(QIOSB+2) ;;; not used [check value?] 473 | ld a,(QIOSB) 474 | or a ; check result 475 | jr z,frd1 476 | scf 477 | frd1: pop hl 478 | ret 479 | 480 | ; Write 512-byte block to work file. HL = buffer address, DE = blk number 481 | 482 | FWRITE: push hl 483 | ld (QIOWF+Q.BUF),hl ; buffer address 484 | ld hl,512 485 | ld (QIOWF+Q.LEN),hl ; length 486 | ld (QIOWF+Q.BLK),de ; block number 487 | ld hl,0 488 | ld (QIOWF+Q.OFS),hl ; offset 489 | ld (QIOWF+Q.VFC),hl 490 | ld hl,IO.WVB ; function code 491 | ld (QIOWF+Q.FUNC),hl 492 | ld hl,QIOWF 493 | SC .QIO ; .QIOW 494 | jr c,fwr1 ; if queuing failed 495 | ;; ld hl,(QIOSB+2) 496 | ld a,(QIOSB) 497 | or a ; check result 498 | jr z,fwr1 499 | scf 500 | fwr1: pop hl 501 | ret 502 | 503 | ; Get byte from input file 504 | ; Return CY set on error or EOF 505 | 506 | FGETC: push hl 507 | ld hl,(NUMRD) ; check byte count 508 | ld a,h 509 | or l 510 | jr nz,fgc1 ; jump if not zero 511 | call RDBLK ; else read next block 512 | jr c,fgc2 ; on error return 513 | fgc1: ld hl,(FIOPTR) 514 | ld a,(hl) ; get char from file buffer 515 | inc hl ; inc ptr 516 | ld (FIOPTR),hl 517 | ld hl,(NUMRD) 518 | dec hl 519 | ld (NUMRD),hl ; decrement byte count 520 | cp 1Ah ; EOF? 521 | scf ; return with CY set if yes 522 | jr z,fgc2 523 | or a 524 | fgc2: pop hl 525 | ret 526 | 527 | ; Read next block from input file 528 | 529 | RDBLK: push hl 530 | ld hl,IOBUF 531 | ld (FIOPTR),hl ; set pointer to begin of file buffer 532 | ld (QIOEF+Q.BUF),hl ; buf 533 | ld hl,512 534 | ld (NUMRD),hl ; set byte count 535 | ld (QIOEF+Q.LEN),hl ; len 536 | ld hl,(FIOBLK) 537 | ld (QIOEF+Q.BLK),hl ; blkno 538 | ld hl,0 539 | ld (QIOEF+Q.OFS),hl ; offset 540 | ld (QIOEF+Q.TMO),hl 541 | ld hl,IO.RVB 542 | ld (QIOEF+Q.FUNC),hl ; function code 543 | ld hl,QIOEF 544 | SC .QIO ; .QIOW 545 | jr c,rdr1 ; if queueing failed 546 | ld hl,(QIOSB+2) 547 | ld (NUMRD),hl ; set byte count 548 | ld a,(QIOSB) 549 | or a ; check result 550 | scf 551 | jr nz,rdr1 552 | ld hl,(FIOBLK) 553 | inc hl ; next sequential block number 554 | ld (FIOBLK),hl 555 | xor a 556 | rdr1: pop hl 557 | ret 558 | 559 | ; Write byte in C to output file 560 | 561 | FPUTC: ld hl,(NUMWR) ; get output byte count 562 | push de 563 | ld de,512 564 | call CPDEHL ; disk buffer full? 565 | pop de 566 | jr nz,fpc1 ; jump if not 567 | call WRBLK ; else write block to file 568 | ret c ; on error return 569 | fpc1: ld hl,(NUMWR) 570 | inc hl ; inc output byte count 571 | ld (NUMWR),hl 572 | ld hl,(FIOPTR) ; store byte in output file buffer 573 | ld (hl),c 574 | inc hl ; advance ptr 575 | ld (FIOPTR),hl 576 | or a 577 | ret 578 | 579 | ; Write next block to output file 580 | 581 | WRBLK: push hl 582 | push de 583 | ld hl,IOBUF 584 | ld (FIOPTR),hl ; set pointer to begin of file buffer 585 | ld (QIOEF+Q.BUF),hl ; buf 586 | ld hl,(NUMWR) 587 | ld (QIOEF+Q.LEN),hl ; len 588 | ld hl,(FIOBLK) 589 | ld (QIOEF+Q.BLK),hl ; blkno 590 | ld hl,0 591 | ld (QIOEF+Q.OFS),hl ; offset 592 | ld (QIOEF+Q.VFC),hl 593 | ld hl,IO.WVB 594 | ld (QIOEF+Q.FUNC),hl ; function code 595 | ld hl,QIOEF 596 | SC .QIO ; .QIOW 597 | jr c,wrr1 ; if queueing failed 598 | ld de,(QIOSB+2) ; get number of bytes written 599 | ld hl,(NUMWR) 600 | call CPDEHL ; value must match 601 | ld a,E.IO ; else is error 602 | scf 603 | jr nz,wrr1 604 | ld hl,0 605 | ld (NUMWR),hl ; clear byte count 606 | ld a,(QIOSB) 607 | or a ; check result 608 | scf 609 | jr nz,wrr1 610 | ld hl,(FIOBLK) 611 | inc hl ; next sequential block number 612 | ld (FIOBLK),hl 613 | xor a 614 | wrr1: pop de 615 | pop hl 616 | ret 617 | 618 | ; Delete work file 619 | 620 | WDELET: 621 | if 0 622 | push hl 623 | ld a,FN.DIR OR FN.NAME OR FN.EXT OR FN.VER 624 | ld (WFDB+F.ATTR),a 625 | ld hl,IO.DEL ; function code 626 | ld (QIOWF+Q.FUNC),hl 627 | ld hl,WFDB ; FDB 628 | ld (QIOWF+Q.P1),hl 629 | ld hl,QIOWF 630 | SC .QIO ; .QIOW 631 | jr c,wd1 ; if queuing failed 632 | ld a,(QIOSB) 633 | or a ; check result 634 | jr z,wd1 635 | scf 636 | wd1: pop hl 637 | ret 638 | else 639 | xor a ; temporary file automatically deleted by system 640 | ret 641 | endif 642 | 643 | ; Delete output file 644 | 645 | FDELET: 646 | scf 647 | ret 648 | 649 | ; Parse file name and build FCB from string in HL. 650 | ; Input: 651 | ; HL = address of filespec string in the form 'dev:[dir]fname.ext;ver' 652 | ; Output 653 | ; FCB fields setup, the F.ATTR field containing a bit mask 654 | ; representing which filespec components were specified. 655 | ; CY set on error 656 | 657 | MKFCB: push bc 658 | ld ix,EFDB ; dest FDB 659 | call PFN 660 | pop bc 661 | ret 662 | 663 | ; Display file name using system conventions 664 | 665 | PRFNAM: push hl 666 | push de 667 | push bc 668 | ld hl,EFDB 669 | inc hl 670 | inc hl 671 | inc hl 672 | ld a,(hl) 673 | call UCASE 674 | call PUTC 675 | inc hl 676 | ld a,(hl) 677 | call UCASE 678 | call PUTC 679 | inc hl 680 | ld a,(hl) 681 | call ADEC 682 | inc hl 683 | ld a,':' 684 | call PUTC 685 | ld a,(hl) 686 | cp ' ' 687 | push af 688 | ld a,'[' 689 | call nz,PUTC 690 | ld b,9 691 | prf1: ld a,(hl) 692 | cp ' ' 693 | call nz,PUTC 694 | inc hl 695 | djnz prf1 696 | prf2: pop af 697 | ld a,']' 698 | call nz,PUTC 699 | ld b,9 700 | prf3: ld a,(hl) 701 | cp ' ' 702 | call nz,PUTC 703 | inc hl 704 | djnz prf3 705 | ld a,'.' 706 | call PUTC 707 | ld b,3 708 | prf4: ld a,(hl) 709 | cp ' ' 710 | call nz,PUTC 711 | inc hl 712 | djnz prf4 713 | ld a,';' 714 | call PUTC 715 | ld a,(hl) 716 | inc hl 717 | ld h,(hl) 718 | ld l,a 719 | xor a 720 | call HLDEC 721 | pop bc 722 | pop de 723 | pop hl 724 | ret 725 | 726 | ;----------------------------------------------------------------------- 727 | 728 | ; Misc routines 729 | 730 | ; Get top of memory into HL 731 | 732 | GETTOP: push de 733 | ld hl,0 734 | ld de,GTKBUF 735 | SC .GTSK 736 | ld hl,(GTKBUF+GT.END) 737 | pop de 738 | ret 739 | 740 | ; Get CLI command line 741 | 742 | GETCML: push de 743 | ld hl,CMLBUF 744 | ld e,79 745 | SC .GTCMD 746 | pop de 747 | ld b,(hl) ; get length into B 748 | skiptn: inc hl 749 | ld a,(hl) 750 | call ISDELIM ; skip our task name 751 | ret z 752 | djnz skiptn 753 | ret 754 | 755 | ISDELIM: 756 | or a 757 | ret z 758 | cp ' ' 759 | ret z 760 | cp TAB 761 | ret z 762 | cp '!' 763 | ret z 764 | cp '=' 765 | ret z 766 | cp '/' 767 | ret z 768 | cp '>' 769 | ret z 770 | cp '<' 771 | ret z 772 | cp '|' 773 | cp CR 774 | ret z 775 | cp LF 776 | ret 777 | 778 | ; Exit to system 779 | 780 | EXIT: call TTFLSH 781 | ld hl,IO.DET ; detach terminal 782 | ld (QIOATT+Q.FUNC),hl 783 | ld hl,QIOATT 784 | SC .QIO ; .QIOW 785 | ld hl,EX.SUC 786 | SC .EXIT ; exit with success status 787 | jp $ 788 | 789 | ;----------------------------------------------------------------------- 790 | 791 | dseg 792 | 793 | GTKBUF: ds GTKSZ 794 | 795 | QIOATT: QIOW$ IO.ATT,TTLUN,EFN,QIOSB,, 796 | QIOGMC: QIOW$ SF.GMC,TTLUN,EFN,QIOSB,, 797 | QIOSMC: QIOW$ SF.SMC,TTLUN,EFN,QIOSB,, 798 | QIOEF: QIOW$ IO.ACC,EFLUN,EFN,QIOSB,,<,,,,,> 799 | QIOWF: QIOW$ IO.CRE,WFLUN,EFN,QIOSB,,<,,,,,> 800 | TCANS: db TC.ANS,0 801 | TCBIN: db TC.BIN,1 802 | 803 | TTQLEN: db 0 ; TTY queue length (number of chars in queue) 804 | TTQOUT: dw TTFIFO ; TTY queue out pointer 805 | TTQIN: dw TTFIFO ; TTY queue in pointer 806 | 807 | TTFIFO: ds 64 ; 64 bytes used for input queue 808 | 809 | TCKSEC: ds 2 810 | ASTFLG: ds 1 811 | CMLBUF: ds 80 812 | 813 | WFDB: dw 0 ; FDB for temporary work file on current disk 814 | db FN.DEV OR FN.NAME OR FN.EXT 815 | db 'SY',0 816 | db ' ' 817 | db 'EDITOR ','TMP' 818 | dw 0 819 | szwfn equ $-WFDB 820 | ds FINFSZ-szwfn ; size = FINFSZ 821 | 822 | EFDB: ds FINFSZ ; FDB for user file 823 | 824 | IOBUF: ds 512 ; file I/O buffer 825 | 826 | ATTR: ds 1 827 | 828 | FIOPTR: dw 0 ; file I/O pointer 829 | NUMRD: dw 0 ; number of bytes read 830 | NUMWR: dw 0 ; number of bytes written 831 | FIOBLK: dw 0 ; current sequential I/O block number 832 | 833 | end 834 | -------------------------------------------------------------------------------- /sysfn.inc: -------------------------------------------------------------------------------- 1 | ; System function equates 2 | 3 | .EXIT equ 0 ; exit program 4 | .EXIF equ 1 ; exit program if event flag not set 5 | .EMTST equ 2 ; emit status 6 | .QIO equ 3 ; queue I/O packet 7 | .CONN equ 4 ; connect to task 8 | .GTCMD equ 5 ; get command line arguments 9 | .SEND equ 6 ; send data 10 | .RECV equ 7 ; receive data 11 | .WTDAT equ 8 ; wait for data 12 | .ASTDF equ 9 ; declare AST service routine 13 | .ASTCT equ 10 ; AST control (enable/disable AST types) 14 | .ASTX equ 11 ; exit AST service routine 15 | .ALUN equ 12 ; assign LUN to device 16 | .GTLUN equ 13 ; get LUN information 17 | .GDIR equ 14 ; get current dir name 18 | .SDIR equ 15 ; set current dir 19 | .GDAT equ 16 ; get date and time 20 | .SDAT equ 17 ; set date and time 21 | .RQST equ 18 ; request installed task 22 | .RPOI equ 19 ; request and pass offspring information 23 | .ABORT equ 20 ; abort a task 24 | .STOP equ 21 ; stop task 25 | .RESUM equ 22 ; resume task 26 | .CLEF equ 23 ; clear event flag 27 | .SETF equ 24 ; set single event flag 28 | .RDEF equ 25 ; read event flag 29 | .WTSE equ 26 ; wait for single event flag 30 | .STSE equ 27 ; stop for single event flag 31 | .WTLO equ 28 ; wait for logical OR of event flags 32 | .STLO equ 29 ; stop for logical OR of event flags 33 | .RUN equ 30 ; request installed task at specified time 34 | .CSRQ equ 31 ; cancel scheduled task request 35 | .MRKT equ 32 ; mark time request 36 | .CMKT equ 33 ; cancel mark time request 37 | .EXTSK equ 34 ; extend task size 38 | .ALTPR equ 35 ; change task priority 39 | .SUPER equ 36 ; enter/exit supervisor mode 40 | .GTSK equ 37 ; get task info 41 | .GTPAR equ 38 ; get partition info 42 | .GCII equ 39 ; get command interpreter info 43 | .GIN equ 40 ; get general info 44 | 45 | MAXFN equ 40 46 | 47 | SYSRST equ 20h ; system call RST is RST 4 48 | DBGRST equ 30h ; debug breakpoint RST is RST 6 49 | 50 | ; .GDIR subfunction codes 51 | 52 | GD.TSK equ 0 ; get task's current directory 53 | GD.TI equ 1 ; get terminal's current directory 54 | GD.LOG equ 2 ; get terminal's login directory 55 | 56 | ; .SDIR subfunction codes 57 | 58 | SD.TSK equ 0 ; set task's current directory 59 | SD.TI equ 1 ; set terminal's current directory 60 | 61 | ; .GIN subfunction codes 62 | 63 | I.VERS equ 0 ; get system version 64 | I.SMEM equ 1 ; get system memory info 65 | I.USCB equ 2 ; get user's SCB 66 | I.TSCB equ 3 ; get SCB of terminal device 67 | I.HOST equ 4 ; get host name 68 | I.TCKS equ 5 ; get ticks per second 69 | I.FEAT equ 6 ; get feature bits 70 | 71 | ; Macro to call system services 72 | 73 | SC MACRO func 74 | rst SYSRST 75 | db func 76 | ENDM 77 | 78 | -------------------------------------------------------------------------------- /syslib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hperaza/TED/7da2e1e39ae4cb57b45d84cf715b88fabbeadd17/syslib.lib -------------------------------------------------------------------------------- /tcb.inc: -------------------------------------------------------------------------------- 1 | ; Task Control Block structure 2 | 3 | T.LNK equ 0 ; utility link field (2 bytes) 4 | T.TCBL equ T.LNK + 2 ; link to next TCB in directory list (2 bytes) 5 | T.ACTL equ T.TCBL + 2 ; link to next TCB in active task list (2 bytes) 6 | T.ATTR equ T.ACTL + 2 ; attributes (1 byte) 7 | T.ST equ T.ATTR + 1 ; status (2 bytes) 8 | T.DPRI equ T.ST + 2 ; default priority (1 byte) 9 | T.PRI equ T.DPRI + 1 ; current priority (1 byte) 10 | T.SPRI equ T.PRI + 1 ; current swap priority (1 byte) 11 | T.NAME equ T.SPRI + 1 ; task name (6 characters) 12 | T.VID equ T.NAME + 6 ; task version identification (6 characters) 13 | T.CMD equ T.VID + 6 ; pointer to command line block (2 bytes) 14 | T.IOC equ T.CMD + 2 ; outstanding I/O count (1 byte) 15 | T.RCVL equ T.IOC + 1 ; pointer to receive queue (2 bytes) 16 | T.OCBL equ T.RCVL + 2 ; pointer to list of OCBs (2 bytes) 17 | T.SAST equ T.OCBL + 2 ; pointer to list of specified ASTs (2 bytes) 18 | T.ASTL equ T.SAST + 2 ; pointer to list of AST events (2 bytes) 19 | T.SVST equ T.ASTL + 2 ; saved task status during AST (2 bytes) 20 | T.FLGS equ T.SVST + 2 ; task event flags (4 bytes = 32 flags) 21 | T.WAIT equ T.FLGS + 4 ; flag wait mask (4 bytes) 22 | T.CTX equ T.WAIT + 4 ; pointer to Context Block (2 bytes) 23 | T.TI equ T.CTX + 2 ; UCB of terminal device (2 bytes) 24 | T.LDEV equ T.TI + 2 ; UCB of load device (2 bytes) 25 | T.SBLK equ T.LDEV + 2 ; task starting disk block number (4 bytes) 26 | T.NBLK equ T.SBLK + 4 ; task size in disk blocks (2 bytes) 27 | T.PCB equ T.NBLK + 2 ; pointer to PCB (2 bytes) 28 | T.CPCB equ T.PCB + 2 ; pointer to checkpoint PCB (2 bytes) 29 | T.STRT equ T.CPCB + 2 ; start address (2 bytes) 30 | T.DEND equ T.STRT + 2 ; default end address (2 bytes) 31 | T.END equ T.DEND + 2 ; current end address (2 bytes) 32 | T.EPT equ T.END + 2 ; entry point (2 bytes) 33 | T.SP equ T.EPT + 2 ; task SP (2 bytes) 34 | 35 | ; TCB size 36 | 37 | TCBSZ equ T.SP + 2 38 | 39 | ; Attribute bit numbers 40 | 41 | TA.PRV equ 0 ; task is privileged 42 | TA.REM equ 1 ; remove on exit 43 | TA.AST equ 2 ; AST recognition enabled 44 | TA.FIX equ 3 ; task fixed in memory 45 | TA.MCR equ 4 ; task is external MCR function 46 | TA.CLI equ 5 ; task is a CLI 47 | TA.ACP equ 6 ; task is an ACP 48 | TA.CKD equ 7 ; checkpointing disabled 49 | 50 | ; Status bit numbers 51 | 52 | TS.ACT equ 0 ; task active 53 | TS.AST equ 1 ; task is executing an AST 54 | TS.SUP equ 2 ; task is in supervisor mode 55 | TS.CKR equ 3 ; checkpoint requested 56 | 57 | T2.STP equ 0 ; stopped \ 58 | T2.SEF equ 1 ; stopped for event flag | 59 | T2.EFW equ 2 ; event flag waiting | "blocking" bits: 60 | T2.WTD equ 3 ; waiting for data | all zero means 61 | T2.OUT equ 4 ; task is out of memory | task is executing 62 | T2.CKP equ 5 ; task is checkpointed | 63 | T2.LDR equ 6 ; task is being loaded | 64 | T2.ABO equ 7 ; task is being aborted / 65 | 66 | ; Task Context Block structure 67 | 68 | TX.UID equ 0 ; protection user ID (1 byte) 69 | TX.GID equ TX.UID + 1 ; protection group ID (1 byte) 70 | TX.DIR equ TX.GID + 1 ; task's current directory (9 bytes) 71 | TX.SWM equ TX.DIR + 9 ; saved flag wait mask during AST (4 bytes) 72 | TX.LUT equ TX.SWM + 4 ; LUN translation table (64 bytes) 73 | 74 | ; Context Block size 75 | 76 | CTXSZ equ TX.LUT + 64 77 | 78 | ; Task Descriptor Block 79 | 80 | TD.NAME equ 0 ; task name (6 characters) 81 | TD.CMD equ TD.NAME + 6 ; address of command line block (2 bytes) 82 | TD.CML equ TD.CMD + 2 ; length of command (2 bytes) 83 | TD.ATTR equ TD.CML + 2 ; initial attributes (1 byte) 84 | TD.USR equ TD.ATTR + 1 ; user number (1 byte) 85 | TD.GRP equ TD.USR + 1 ; group number (1 byte) 86 | TD.TI equ TD.GRP + 1 ; console device and unit (3 bytes) 87 | TD.SDAT equ TD.TI + 3 ; address of data block to send (2 bytes) 88 | TD.SLEN equ TD.SDAT + 2 ; size of data block to send (2 bytes) 89 | 90 | ; TDB size 91 | 92 | TDBSZ equ TD.SLEN + 2 93 | 94 | ; Offspring Control Block 95 | 96 | O.LNK equ 0 ; link to next OCB in list (2 bytes) 97 | O.PTCB equ O.LNK + 2 ; address of parent's TCB (2 bytes) 98 | O.EFN equ O.PTCB + 2 ; event flag number (1 byte) 99 | O.ESB equ O.EFN + 1 ; addr of parent's exit status block (2 bytes) 100 | O.ST equ O.ESB + 2 ; status (2 bytes) 101 | 102 | ; OCB size 103 | 104 | OCBSZ equ O.ST + 2 105 | 106 | ; Structure returned by the .GTSK Get Task Info system call 107 | 108 | GT.ATTR equ 0 ; task attributes (1 byte) 109 | GT.ST equ GT.ATTR + 1 ; task status (2 bytes) 110 | GT.DPRI equ GT.ST + 2 ; default priority (1 byte) 111 | GT.PRI equ GT.DPRI + 1 ; current priority (1 byte) 112 | GT.NAME equ GT.PRI + 1 ; task name (6 characters) 113 | GT.VID equ GT.NAME + 6 ; task version identification (6 characters) 114 | GT.TI equ GT.VID + 6 ; console device and unit (3 bytes) 115 | GT.LDEV equ GT.TI + 3 ; load device and unit (3 bytes) 116 | GT.SBLK equ GT.LDEV + 3 ; task starting disk block number (4 bytes) 117 | GT.NBLK equ GT.SBLK + 4 ; task size in disk blocks (2 bytes) 118 | GT.PAR equ GT.NBLK + 2 ; partition name (6 bytes) 119 | GT.STRT equ GT.PAR + 6 ; start address (2 bytes) 120 | GT.DEND equ GT.STRT + 2 ; default end address (2 bytes) 121 | GT.END equ GT.DEND + 2 ; end address (2 bytes) 122 | GT.EPT equ GT.END + 2 ; entry point (2 bytes) 123 | 124 | ; GTIB size 125 | 126 | GTKSZ equ GT.EPT + 2 127 | 128 | -------------------------------------------------------------------------------- /ted.inc: -------------------------------------------------------------------------------- 1 | FALSE equ 0 2 | TRUE equ not FALSE 3 | 4 | CR equ 0Dh 5 | LF equ 0Ah 6 | TAB equ 09h 7 | ESC equ 1Bh 8 | SSPC equ ' '+80h 9 | 10 | BLKSIZ equ 512 ; disk block size 11 | BUFSIZ equ BLKSIZ+4 ; memory buffer size (516 bytes) 12 | 13 | MAXLEN equ 162 ; max line length 14 | -------------------------------------------------------------------------------- /termdef.mac: -------------------------------------------------------------------------------- 1 | ;**********************************************************************; 2 | ; ; 3 | ; This file is part of TED, a clone of the screen-oriented text ; 4 | ; editor that was once available for the RT-11 OS. ; 5 | ; Copyright (C) 2011-2020, Hector Peraza. ; 6 | ; ; 7 | ; This program is free software; you can redistribute it and/or ; 8 | ; modify it under the terms of the GNU General Public License as ; 9 | ; published by the Free Software Foundation; either version 2 of ; 10 | ; the License, or (at your option) any later version. ; 11 | ; ; 12 | ; This program is distributed in the hope that it will be useful, ; 13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; 14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; 15 | ; GNU General Public License for more details. ; 16 | ; ; 17 | ; You should have received a copy of the GNU General Public License ; 18 | ; along with this program; if not, write to the Free Software ; 19 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; 20 | ; ; 21 | ;**********************************************************************; 22 | 23 | .Z80 24 | 25 | title TED - Text Editor 26 | subttl Terminal I/O routines 27 | 28 | include TED.INC 29 | 30 | VT100 equ TRUE 31 | 32 | ;======================================================================= 33 | 34 | ; T E R M I N A L C O N T R O L M O D U L E 35 | 36 | ; (Link as first module) 37 | 38 | public HOME,CLS,CLREOS,CLREOL,CSRUP,CSRDN,CSRLFT 39 | public CSRRGT,PUTCUR,FWDIDX,REVIDX,INSLIN,DELLIN 40 | public HASSRG,SCRLRG,TRMNAM 41 | 42 | extrn PUTC 43 | 44 | ;-------------------------------------------------------------- 45 | 46 | cseg 47 | 48 | ; Display patch area 49 | 50 | org 10h-3 51 | 52 | if VT100 53 | 54 | vtname: db 'VT100',0,0,0,0,0,0,0,0,0 55 | vtsize: db 80,24 ; width, height 56 | vclscr: db 6,ESC,'[H',ESC,'[J',0 57 | vcleos: db 3,ESC,'[J',0,0,0,0 58 | vcleol: db 3,ESC,'[K',0,0,0,0 59 | vcurup: db 3,ESC,'[A',0,0,0,0 60 | vcurdn: db 3,ESC,'[B',0,0,0,0 61 | vcurrgt:db 3,ESC,'[C',0,0,0,0 62 | vcurlft:db 3,ESC,'[D',0,0,0,0 63 | vhome: db 3,ESC,'[H',0,0,0,0 64 | vcurprf:db 2,ESC,'[',0,0,0,0,0 65 | vcursep:db 1,';',0,0,0,0,0,0 66 | vcurpst:db 1,'H',0,0,0,0,0,0 67 | vcurbcd:db TRUE 68 | vcuryof:db 1 69 | vcurxof:db 1 70 | vxfirst:db FALSE 71 | vfwdidx:db 2,ESC,'D',0,0,0,0,0 72 | vrevidx:db 2,ESC,'M',0,0,0,0,0 73 | vinsln: db 0,0,0,0,0,0,0,0 ; VT220/240 only? 74 | vdelln: db 0,0,0,0,0,0,0,0 75 | vscrlrg:db 1,'r',0,0,0,0,0,0 76 | 77 | else 78 | 79 | vtname: db 'VT52',0,0,0,0,0,0,0,0,0,0 80 | vtsize: db 80,24 ; width, height 81 | vclscr: db 4,ESC,'H',ESC,'J',0,0,0 82 | vcleos: db 2,ESC,'J',0,0,0,0,0 83 | vcleol: db 2,ESC,'K',0,0,0,0,0 84 | vcurup: db 2,ESC,'A',0,0,0,0,0 85 | vcurdn: db 2,ESC,'B',0,0,0,0,0 86 | vcurrgt:db 2,ESC,'C',0,0,0,0,0 87 | vcurlft:db 2,ESC,'D',0,0,0,0,0 88 | vhome: db 2,ESC,'H',0,0,0,0,0 89 | vcurprf:db 2,ESC,'Y',0,0,0,0,0 90 | vcursep:db 0,0,0,0,0,0,0,0 91 | vcurpst:db 0,0,0,0,0,0,0,0 92 | vcurbcd:db FALSE 93 | vcuryof:db 32 94 | vcurxof:db 32 95 | vxfirst:db FALSE 96 | vfwdidx:db 1,LF,0,0,0,0,0,0 97 | vrevidx:db 2,ESC,'I',0,0,0,0,0 98 | vinsln: db 0,0,0,0,0,0,0,0 99 | vdelln: db 0,0,0,0,0,0,0,0 100 | vscrlrg:db 0,0,0,0,0,0,0,0 101 | 102 | endif 103 | 104 | org 0B0h-3 105 | 106 | ;-------------------------------------------------------------- 107 | 108 | TRMNAM: ld hl,vtname 109 | ret 110 | 111 | CLS: push hl 112 | ld hl,vclscr 113 | jp pseq 114 | 115 | CLREOS: push hl 116 | ld hl,vcleos 117 | jp pseq 118 | 119 | CLREOL: push hl 120 | ld hl,vcleol 121 | jp pseq 122 | 123 | HOME: push hl 124 | ld hl,vhome 125 | ld a,(hl) 126 | or a 127 | jp nz,pseq 128 | ld hl,0 129 | call PUTCUR 130 | pop hl 131 | ret 132 | 133 | ; H = x coord, L = y coord 134 | 135 | PUTCUR: push hl 136 | push de 137 | push bc 138 | 139 | if TRUE 140 | 141 | ex de,hl 142 | ld hl,(vcuryof) ; H = vcurxof, L = vcuryof 143 | add hl,de ; should not generate any CY from L to H 144 | ex de,hl 145 | 146 | else 147 | 148 | ld a,(vcurxof) ; this is the same as above, but takes 149 | add a,h ; more bytes 150 | ld d,a 151 | ld a,(vcuryof) 152 | add a,l 153 | ld e,a 154 | 155 | endif 156 | 157 | ld a,(vxfirst) 158 | or a 159 | jr z,noswap 160 | ld a,e 161 | ld e,d 162 | ld d,a 163 | noswap: ld hl,vcurprf ; prefix 164 | call putseq 165 | ld c,e ; y coord 166 | call pcurnum 167 | ld hl,vcursep ; separator 168 | call putseq 169 | ld c,d ; x coord 170 | call pcurnum 171 | ld hl,vcurpst ; postfix 172 | call putseq 173 | pop bc 174 | pop de 175 | pop hl 176 | ret 177 | 178 | ; H = bottom line, L = top line 179 | 180 | SCRLRG: ld a,(vscrlrg) 181 | or a 182 | ret z 183 | 184 | push hl 185 | push de 186 | push bc 187 | 188 | if FALSE 189 | 190 | ex de,hl 191 | ld hl,(vcuryof) ; H = vcurxof, L = vcuryof 192 | add hl,de ; should not generate any CY from L to H 193 | ex de,hl 194 | 195 | else 196 | 197 | ld a,(vcurxof) ; this prevents carry from L to H 198 | add a,h ; in case HL = -1 (reset region) 199 | ld d,a 200 | ld a,(vcuryof) 201 | add a,l 202 | ld e,a 203 | 204 | endif 205 | 206 | ld a,(vxfirst) 207 | or a 208 | jr z,noswp 209 | ld a,e 210 | ld e,d 211 | ld d,a 212 | noswp: ld hl,vcurprf ; prefix 213 | call putseq 214 | ld c,e ; y coord 215 | call pcurnum 216 | ld hl,vcursep ; separator 217 | call putseq 218 | ld c,d ; x coord 219 | call pcurnum 220 | ld hl,vscrlrg ; postfix 221 | call putseq 222 | pop bc 223 | pop de 224 | pop hl 225 | ret 226 | 227 | HASSRG: ld a,(vscrlrg) 228 | or a ; return NZ if terminal supports scroll region 229 | ret 230 | 231 | pcurnum:ld a,(vcurbcd) 232 | or a 233 | ld a,c 234 | jp z,PUTC 235 | ; fall thru 236 | 237 | ; Display A as decimal number (up to 3 digits, no leading zeros) 238 | 239 | adec: push de 240 | push bc 241 | ld d,0 242 | ld b,100 243 | call ad1 244 | ld b,10 245 | call ad1 246 | add a,'0' 247 | call PUTC 248 | pop bc 249 | pop de 250 | ret 251 | ad1: ld c,'0'-1 252 | ad2: inc c 253 | sub b 254 | jr nc,ad2 255 | add a,b 256 | push af 257 | ld a,c 258 | cp '0' 259 | jr nz,ad4 260 | inc d 261 | dec d 262 | jr z,ad5 263 | ad4: call PUTC 264 | ld d,1 265 | ad5: pop af 266 | ret 267 | 268 | CSRUP: push hl 269 | ld hl,vcurup 270 | jr pseq 271 | 272 | CSRDN: push hl 273 | ld hl,vcurdn 274 | jr pseq 275 | 276 | CSRLFT: push hl 277 | ld hl,vcurlft 278 | jr pseq 279 | 280 | CSRRGT: push hl 281 | ld hl,vcurrgt 282 | jr pseq 283 | 284 | FWDIDX: push hl 285 | ld hl,vfwdidx 286 | jr pseq 287 | 288 | REVIDX: push hl 289 | ld hl,vrevidx 290 | jr pseq 291 | 292 | INSLIN: push hl 293 | ld hl,vinsln 294 | jr putseq 295 | 296 | DELLIN: push hl 297 | ld hl,vdelln 298 | pseq: call putseq 299 | pop hl 300 | ret 301 | 302 | putseq: ld a,(hl) 303 | or a 304 | ret z 305 | push bc 306 | ld b,a 307 | inc hl 308 | pseq1: ld a,(hl) 309 | call PUTC 310 | inc hl 311 | djnz pseq1 312 | pop bc 313 | ret 314 | 315 | end 316 | --------------------------------------------------------------------------------