home *** CD-ROM | disk | FTP | other *** search
/ AMOS PD CD / amospdcd.iso / 576-600 / apd600 / ldos_demo / docs / ldosv25.doc < prev    next >
Text File  |  1994-02-02  |  81KB  |  2,214 lines

  1.  
  2.        LDos V1(3) for AMOS1.3 and above.
  3.        LDos is (C) Niklas Sjöberg 1992
  4.  
  5.  
  6.  
  7.  
  8.        What you just have received  is  a  new  fast,  and  efficient
  9.     extension  for  AMOS  V1.3  and higher. It is supposed to correct
  10.     some misfeatures of AMOS and add some functions not available  in
  11.     AMOS.  The  official  name  is 'Ldos' which seemed logical when I
  12.     started out, but since that a lot other functions have been added
  13.     which are far from DOS-functions. I got the idea about Ldos after
  14.     waiting over fifteen (15!) minutes for Line Input to read  a  300
  15.     Kb  textfile from floppy. After 15 minutes I stopped the program,
  16.     it still wasn't finished :-) Then  I  thought,  "while  I  am  at
  17.     it..", and I came up with some new interesting commands.
  18.  
  19.  
  20.  
  21.        Here is a small featurelist of Ldos :
  22.  
  23.  
  24.  
  25.     o New load and save routines.
  26.     o Support for BOTH load and save in the same file without
  27.       reopening it.
  28.     o Ability to save and load from the middle of the file.
  29.     o Up to three channels open simultaneously.
  30.  
  31.     o Commands for setting/reading :
  32.     o filenotes
  33.     o protectionbits
  34.     o dates
  35. *-  o Environmentvariables
  36.  
  37.     o Determine filelength without having to assign a channel to
  38.       the file.
  39.  
  40.     o Determine if a name belongs to a file or a directory.
  41.  
  42.     o New, very easy to use, directorycommands. Doesn't use any
  43.       bufferspace as AMOS dir-command. Only one name is read at
  44.       the time, unlike AMOS dir-command, meaning no bufferover-
  45.       flow, never to many files in a dir and 0 waittime before
  46.       names can be displayed on screen.
  47. *-    Commands for handling recursive reading and/or popping out
  48. *-    of directory-reading and being  able to return to the exact
  49. *-    position later and continue reading. The number of different
  50. *-    active "popped" directories are only limited by your memory.
  51.  
  52. *-  o Commands to list all system- assignments, disks, volumes and
  53. *-    other devices and obtaining further information about disks.
  54.  
  55.     o Fast stringhandling to and from banks. Forget Peek and Poke.
  56.  
  57.     o Fast replace, and filter-out-function.
  58.  
  59.     o "Line Input"-commands from buffer. This routine manages to
  60.       "Line Input" >40 Kb/sec on my machine (with an AdSpeed)
  61.       and that includes loadingtime from HD in 1Kb-blocks!
  62.  
  63.     o Fast time and date-routines. Command for getting the current
  64.       time and date, returned in strings, easy to process. Highly
  65.       optimized.
  66.  
  67.     o Convert to and from datestamps, does not use slow library-
  68.       functions. Highly optimized.
  69.  
  70.     o Support for the filerequester in req.library. Totally
  71.       configurable with optional cache (no need to re-read
  72.       the dir) for floppy-users. Pops up on the Workbench.
  73. *-    Also support for font-mode which lets the user pick a
  74. *-    font in a really neat way.
  75. *-    Set a current dir for the requester which doesn't affect
  76. *-    your programs current directory.
  77.  
  78.     o Commands for decrunching PowerPacker datafiles, all
  79.       compression modes and known versions, without passwordlock.
  80.  
  81. *-  o Cryptation, DeCryptation with password using a pretty 'hard-
  82. *-    to-crack'-algoritm. (see hints for more info)
  83.  
  84.     o Commands to handle any device using an IOSTD-stucture,
  85.       specially written with trackdisk.device in mind.
  86.  
  87.     o Run executable  programs and scripts. Support for I/O in a
  88.       DOS-console window.
  89.  
  90.     o Load fonts from disk, making them available to Get Rom Fonts
  91.       without needing to scan the whole fonts-directory (sigh!)
  92.  
  93.     o A complete set of ARexxsupport commands. Create your host,
  94.       start scripts with any name located anywhere on the disk.
  95.       You may also address and send commands to other hosts directly,
  96.       without starting any scripts. All functions are completely
  97.       bullet-proof (on system-level), meaning no software failures.
  98.  
  99. *-  o Conversion-routine from ANSI/VT100-sequences to AMOS control-codes.
  100. *-    Supports the most frequently used sequences and is much faster
  101. *-    than the console.device's own routines. Highly optimized.
  102.  
  103. *-  o Word- extraction/count which works similar to the ARexxcommands
  104. *-    Word and Words.Greatly enhances the possibilities for the prog-
  105. *-    rammer to parse configurationsfiles and commandlines.
  106.  
  107.  
  108.  
  109.        TO DO IN FUTURE VERSIONS
  110.        ------------------------
  111.        Correct bugs and add features suggested by YOU. Also a lot  of
  112.     new  functions  will be added as soon as I find some time to read
  113.     the new Autodocs. Still locale  isn't  supported  since Commodore
  114.     haven't released this library to the public. We are also  waiting
  115.     for the amigaguide.library to be released... Already some goodies
  116.     available  in  Relase 2, only,  has been  implemented,  and there
  117.     are more on the way.
  118.  
  119.  
  120.  
  121.  
  122.     HOW TO INSTALL LDos
  123.     -------------------
  124.        Simply copy LDos.LIB to the  directory  where  you  have  your
  125.     other  extensions.  Enter LDos.LIB as extension number 10 in your
  126.     *.ENV file(s). Also add LDos.LIB  to  the  same  number  in  your
  127.     compiler-configuration(s). Make sure that you state the full path
  128.     between the brackets { and } in the compiler-configuration.
  129. ++  Alexander Folkesson  pointed out  that in Compiler  V1.34 you must
  130. ++  edit you Ramos.config in order to compile programs without  error-
  131. ++  messages. Haven't had time to check this out myself..
  132.  
  133.  
  134.  
  135.     HOW TO READ THIS MANUAL
  136.     -----------------------
  137.  
  138.        The manual can be read as you like.  For your convenience  the
  139.     manual is splitted into nine general parts.
  140.  
  141.  
  142.  
  143.         1. General file commands, directorycommands etc.
  144.         2. String commands and bufferhandling.
  145.         3. Date commands.
  146.         4. Filerequester in req.library.
  147.         5. Device commands, error codes and CMDcommands.
  148.         6. Misc commands, which didn't fit anywhere else.
  149.         7. ARexx control, making hosts and communicating.
  150.         8. Ldos Errorcodes.
  151.         9. Disclaimers and info. READ THIS!
  152.  
  153.  Text marked with *- are new features added in version 2, so to read
  154.  the  news load your  favorite   texteditor and search for *- if you
  155.  come from version 1 of LDos.
  156.  
  157.  Text marked -- are new stuff for version 2.1
  158.  Text marked ++ are new stuff for version 2.5
  159.  
  160.  
  161.  
  162.  
  163.  
  164.                 PART ONE - General file commands
  165.                 --------------------------------
  166.  
  167.        These commands will in conjunction  with  the  string-commands
  168.     totally  replace  all  AMOS  file  I/O,  except for special bank-
  169.     loading, like sprites music etc. They require  a  bit  more  work
  170.     than  the  standard  commands,  but  gives you total control over
  171.     memoryusage string contents and lengths. And most important, they
  172.     are very fast. Lstr for example is about 13-22 times faster  than
  173.     Chr$(Peek()) when compiled! (This is almost the same as a vanilla
  174.     A500 vs a 33 Mhz 030 card) All loading and saving is done to/from
  175.     banks  meaning  minimal  usage  of  the string-buffer and you may
  176.     easily decide the bank-size and change it at run-time,  which  is
  177.     impossible  with  Set Buffer which is set once and for all. There
  178.     is a bunch of commands which lets you  process  the  bank  before
  179.     copying    it  to  strings  and  thus  eliminates  the  risk  for
  180.     "incorrect" strings, containing unwanted characters.    (see part
  181.     about string-commands for more information)
  182. ++  Since some might find Lload/Lstr a bit hard to use , I decided to
  183. ++  include  some  easy to  change  procedures which  works like Line
  184. ++  Input. See the hint section.
  185.  
  186.  
  187.  
  188.        Lopen - Open a file for input and/or output.
  189.        Lopen Channel,"Name",MODE
  190.  
  191.        where
  192.  
  193.        Channel can range from 1 to 3, MODE  either 0  for opening  an
  194.     existing file or 1 for creating a new. WARNING! If the file exist
  195.     and  MODE is 1 the file will be erased. (the file will be 0 bytes
  196.     long) Both Load- and Save-operations can be  performed  on  files
  197.     opened by Lopen (unlike AMOS standard Open).
  198.     Example: _OLD=0 : Lopen 1,"s:startup-sequence",_OLD
  199.  
  200.  
  201.        Lclose - Close a file.
  202.        Lclose Channel
  203.  
  204.     where
  205.  
  206.        Channel is a previously opened file.  Files  opened  with  the
  207.     standard  AMOS-command Open In or Open Out can not be closed with
  208.     this command
  209.  
  210.        WARNING! Do not ever forget to close a file, especially  those
  211.     you  save  to,  otherwise the file, or even the whole disk can be
  212.     corrupt!!! (Ldos will automatically close all open files when the
  213.     program exits, but if a system-crash occur your file will be lost
  214.     if you haven't closed it)
  215.     Example: Lclose 1
  216.  
  217.  
  218.        Lload - Load any number of bytes from a file.
  219.        A=Lload(Channel,DEST,LENGTH)
  220.  
  221.     where
  222.  
  223.        Channel belongs to  a  file  opened  by  Lopen.  DEST  is  the
  224.     startaddress  of  an  AMOS-bank and LENGTH is the number of bytes
  225.     (characters) you wish to load. A will contain the number of bytes
  226.     actually read. If A is less than LENGTH you reached  the  end  of
  227.     the file. If A equals to -1, a filerror occurred. It is perfectly
  228.     legal to request more data than the file contains,  no error will
  229.     be produced because of this.
  230.     Example: BYTE=Lload(1,Start(10), Length(10))
  231.              If BYTE= -1 Then Print "FileError!" : End
  232.              Print "Loaded ";BYTE;" bytes."
  233.  
  234.  
  235.  
  236.     Lsave - Save any number of bytes to a file.
  237.     A=Lsave(Channel,SOURCE,LENGTH)
  238.  
  239.     where
  240.  
  241.        SOURCE is the startaddress of a bank and LENGTH the number  of
  242.     bytes  you  wish  to  write to disk. If A doesn't equal to LENGTH
  243.     a disk-error probably occurred (like disk full, or  write  error)
  244.     dos.library  should normally return -1 on disk-error, but as soon
  245.     as A doesn't equal to the length you specified you should  regard
  246.     this as an error.
  247.     Example: BYTE=Lsave(1, Start(10), Length(10))
  248.              If BYTE <> Length(10) Then Print "FileError!" : End
  249.  
  250.  
  251.  
  252.     Lseek - Change position in a file.
  253.     P=Lseek(Channel,POS)
  254.  
  255.     where
  256.  
  257.        POS is the offset you wish to move to. (Offsets  are  relative
  258.     to  the BEGINNING of the file). If the operation was successful P
  259.     will contain the same value as POS. If   POS is  <0  no  movement
  260.     will  take  place,  and  the current position in the file will be
  261.     returned.
  262.     Example: Print Lseek(1,0)   : Rem start of file
  263.              Print Lseek(1,100) : Rem move to 100
  264.              Print Lseek(1,-1)  : Report position
  265.  
  266.  
  267.  
  268.     Lold    - MAY CURRENTLY NOT BE USED!!
  269.     Lcreate - MAY CURRENTLY NOT BE USED!!
  270.  
  271.        These are here for  future  versions, currently  the  compiler
  272.     seems  to  mess  up values of reserved variables (or I got it all
  273.     wrong)  (most  likely  I  got  it  wrong,  but  this   type    of
  274.     "instructions"  isn't  explained  in the PD-source that come with
  275.     AMOS)
  276.  
  277.  
  278.  
  279.     Lget Comment - Get a FileNote
  280.     A$=Lget Comment("FileName")
  281.  
  282.     where
  283.  
  284.        A$ will contain nothing if there  was  no  filenote.  This  of
  285.     course also works on directories.
  286.  
  287.  
  288.  
  289.     Lset Comment - Set a FileNote
  290.     Lset Comment "FileName","Comment"
  291.  
  292.     where
  293.  
  294.        "Comment" may not be longer than 79 characters and also  works
  295.     on directories as well.
  296.  
  297.  
  298.  
  299.     Lget Prot - Get the protection-bits of a file
  300.     A=Lget Prot("FileName")
  301.  
  302.     where
  303.  
  304.        A will contain a bit-pattern meaning :
  305.  
  306.  
  307.         Bit 7   =       H       ACTIVE  HIGH (Hidden)
  308.         Bit 6   =       S       ACTIVE  HIGH (Script)
  309.         Bit 5   =       P       ACTIVE  HIGH (Pure)
  310.         Bit 4   =       A       ACTIVE  HIGH (Archived)
  311.         Bit 3   =       R       ACTIVE  LOW  (Readable)
  312.         Bit 2   =       W       ACTIVE  LOW  (Writable)
  313.         Bit 1   =       E       ACTIVE  LOW  (Executable)
  314.         Bit 0   =       D       ACTIVE  LOW  (Deleteable)
  315.  
  316.       This command also works on directories but it  seems  like  DOS
  317.     doesn't  care about  some flags when it comes to directories. For
  318.     instance DOS will let you read a directory  even  if  the  R-flag
  319.     wasn't   activated.  Logically  DOS  shouldn't  let  you  read  a
  320.     directory which isn't readable but this is the way it  works.  If
  321.     you are running Kickstart 1.2 or 1.3 DOS neglects most flags.
  322.        When a flag is active low, it means that when that bit is zero
  323.     the flag  is active. If, for instance, bit 0  would  equal  to  0
  324.     that file or directory wouldn't be deleteable.
  325. ++  Of course above should be  " bit 0 would equal to 1,  that file or
  326. ++  directory wouldn't be deleteable"
  327.  
  328.  
  329.     Lset Prot - Set the protectionflags for a file.
  330.     Lset Prot "FileName",MASK
  331.  
  332.     where
  333.  
  334.        MASK is a bitpattern like above.
  335.     Example: Lset Prot "c:myCommand",%00000000 : Rem ----rwed
  336.              Lset Prot "s:myScript",%01000000  : Rem -s--rwed
  337.  
  338.  
  339.  
  340.     Lsize - Return the size of a file.
  341.     S=Lsize("FileName")
  342.  
  343.     where
  344.  
  345.        S is the filesize. The file do not need to be open.  Note that
  346.     it is legal to to specify a directory as well. If "FileName" is a
  347.     directory zero is always returned.
  348.  
  349.  
  350.  
  351.     Lfile Type - See if the name is a file or a directory.
  352.     A=Lfile Type("FileName")
  353.  
  354.     where
  355.  
  356.        A is greater than 0 if it is a directory, or  negative  if  it
  357.     is  a file. You don't need to supply a directoryname with a slash
  358.     ("/") it will work anyway.
  359.     Example: If Lfile Type(F$) >0
  360.                 Print F$;" is a directory"
  361.              Else
  362.                 Print F$;" is a file"
  363.              EndIf
  364.  
  365.  
  366.  
  367.     Lcat First - "Lock" on a directory.
  368.     F$=Lcat First("Directory")
  369.  
  370.     where
  371.  
  372.        If successful F$ will contain the file- or directoryname. Lcat
  373.     Next will return the next file/dir or an  empty  string.  If  the
  374.     directory  didn't  exist  the  error  "Invalid  Filename" will be
  375.     produced (this is because I wanted to keep as few  error-messages
  376.     as possible)
  377.  
  378.  
  379.  
  380.     Lcat Next - Get the next lock (name) in a directory.
  381.     F$=Lcat Next
  382.  
  383.     where
  384.  
  385.        If F$ is empty, there are no  more  files/directories in  this
  386.     directory.  Lcat  Next won't work if you haven't used Lcat First.
  387.     These two  Lcat-commands  works  almost  as  the  original  AMOS-
  388.     commands  Dir  First$  and Dir Next$ with the exception that Lcat
  389.     First actually returns the path, requested  by  you  and  doesn't
  390.     read  in all the files and directories like Dir First$. Obviously
  391.     Lcat Next, unlike Dir Next$, has to access the disk  to  get  the
  392.     next filename. To produce a directory/file-listing which lets the
  393.     user stop the program at any time, you could  do  something  like
  394.     this :
  395.  
  396.          F$=Lcat First("SYS:")
  397.          Print "Listing contents of ";F$
  398.          Repeat
  399.             Exit If Inkey$<>""
  400.             F$=Lcat Next
  401.             If Lcat Type>0
  402.                F$=F$+At(40,)+Pen$(5)+"(DIRECTORY)"+Pen$(1)
  403.             EndIf
  404.             Print F$
  405.          Until F$=""
  406.  
  407.  
  408.        As you can see Lcat Next only returns the  file/directoryname,
  409.     there  are  no  sizes or "*" which makes it harder to process the
  410.     strings. Instead you can after a call to Lcat First, or Lcat Next
  411.     call any of the other Lcat-commands for  more  information  about
  412.     the  file/directory. Since the file/dir already is examined once,
  413.     none of the other Lcat-commands  actually  needs  to  access  the
  414.     disk. This speed things up a bit and prevents disktrashing.
  415.  
  416.  
  417.  
  418.     Lcat Type - Find out if the name is a directory or a file.
  419.     A=Lcat Type
  420.  
  421.     where
  422.  
  423.        A can be either positive,  for  directories, or  negative  for
  424.     files.  This  is  a bit easier than the "*" provided by Dir Next$
  425.     in front of the directoryname.
  426.  
  427.  
  428.  
  429.     Lcat Prot - Get the protectionflags.
  430.     A=Lcat Prot
  431.  
  432.     where
  433.  
  434.        se above Lget Prot for more information.
  435.  
  436.  
  437.  
  438.     Lcat Size - Get the filesize
  439.     S=Lcat Size
  440.  
  441.     where
  442.  
  443.        S will contain the number of bytes in the file. Note  that  it
  444.     is fully legal to call this command even if the current "file" is
  445.     a  directory!  If  the current name belongs to a directory S will
  446.     contain 0. (Keep in mind that  files  which  are  zero  bytes  do
  447.     exist, so don't use this method instead of Lcat Type)
  448.  
  449.  
  450.  
  451.     Lcat Blocks - Return how many blocks the file occupies.
  452.     B=Lcat Blocks
  453.  
  454.  
  455.        (May be useful when doing size check (copy FFS  ->  SFS).  FFS
  456.     can hold 512 bytes of data in one block, SFS only 488. It is also
  457.     said that 2.x/3.x shall support different block-sizes(?))
  458.  
  459.  
  460.  
  461.     Lcat Stamp - Return the datestamp of the file/directory.
  462.     S=Lcat Stamp
  463.  
  464.        See Ldate, Lstamp for more  information  on  how  to  use  and
  465.     process this stamp. (The format is the same as used by AmigaDOS)
  466.  
  467.  
  468.  
  469.     Lcat Comment - Get the file- or directorynote.
  470.     A$=Lcat Comment
  471.  
  472.        See Lget Comment for more information.
  473.  
  474.  
  475.  
  476. *-  Lcat Push - Store Lcat-info for later use.
  477. *-  Lcat Push ADR
  478.  
  479. *-  where
  480.  
  481. *-     ADR points to a reserved bank where Lcat temporarily can store
  482. *-  its datas.  Each time you push something 264 bytes are  used  and
  483. *-  the  next  datas should thus be copied to ADR+264. As some of you
  484. *-  may have noticed  it  wasn't  possible  to  run  recursive  Lcat-
  485. *-  procedures  before,  since  Lcat always uses the same memory-area
  486. *-  when storing filelocks  and  information.  Using  Lcat  Push  you
  487. *-  simply move this internal data to a bank reserved by you. You may
  488. *-  now  use  Lcat on a different device/directory. When you're ready
  489. *-  call Lcat Pull and you're back exactly where you stopped.
  490.  
  491.  
  492.  
  493.  
  494. *-  Lcat Pull - Restore Lcat-info which has been stored with Lcat Push.
  495. *-  Lcat Pull ADR
  496.  
  497. *-  where
  498.  
  499. *-     ADR points to the start of a block which has been  created  by
  500. *-  Lcat  Push.  Please  note that if this address not contains Lcat-
  501. *-  data AmigaDOS  MAY crash if you're unlucky!!  If  ADR  points  to
  502. *-  NULLs  (empty  bank)  you  will receive the errormessage "No more
  503. *-  entries in this dir!".
  504.  
  505. *-  WARNING!
  506.  
  507. *-     If you don't pull all your pushed datas DOS won't be  able  to
  508. *-  deallocate the memory used for the pushed files/directories. This
  509. *-  means that  whenever your program is  run  available  memory will
  510. *-  decrease and can not be  restored until the system is re-booted.
  511. *-  See different recursive routines for more information.
  512.  
  513.  
  514.  
  515. *-  Ldev First - Get the first device in the systemlist
  516. *-  A$=Ldev First(ADR)
  517.  
  518. *-  where
  519.  
  520. *-     A$ will contain the first device found in your system  (if  it
  521. *-  is  empty  something  is  very wrong). ADR should point to a bank
  522. *-  where optional info can be stored. The info stored in the bank is
  523. *-  mostly  for  advanced  users  to  be  used  in  special    cases.
  524. *-  Interesting info for all users ought to be devicetype, unitnumber
  525. *-  and the name of the device which handles it. Please note that the
  526. *-  devicename  (like  DF0:  etc.)  NOT  contains  a colon (":"). The
  527. *-  information stored at ADR is given below.  The bank  must  be  AT
  528. *-  LEAST 80 bytes large, no checking is done to ensure this.
  529.  
  530. *-  See the example 'Devices.AMOS' for more information and help.
  531.  
  532.  
  533.  
  534. *-  Ldev Next - Get the next name(s) in the systemlist.
  535. *-  A$=Ldev Next(ADR)
  536.  
  537. *-  where
  538.  
  539. *-     This command works almost identically  to  Ldev  First  except
  540. *-  that  it  will return an empty string when the last device in the
  541. *-  list has been returned. If you continue to call Ldev  Next  after
  542. *-  this  an errormessage will be generated. Note that it is possible
  543. *-  at any time to call Ldev First if you for  some  reason  like  to
  544. *-  start over in the list.
  545.  
  546.  
  547. *-  DeviceInfo, returned at ADR and the following 40 longwords:
  548. *-  (entries marked with * are explained below)
  549.  
  550. *-  ADR+0  Devicetype*
  551. *-  ADR+4  Unitnumber
  552. *-  ADR+8  Devicename*
  553. *-  ADR+12 Tablesize (see includes on this)
  554. *-  ADR+16 Blocksize, given in number of longwords
  555. *-  ADR+20 -not used-
  556. *-  ADR+24 Number of heads (surfaces)
  557. *-  ADR+28 -not used-
  558. *-  ADR+32 Number of blocks per track
  559. *-  ADR+36 Reserved blocks (usually 2)
  560. *-  ADR+40 -not used-
  561. *-  ADR+44 Interleave (usually 0)
  562. *-  ADR+48 Starting cylinder
  563. *-  ADR+52 Max cylinder
  564. *-  ADR+56 Number of buffers
  565. *-  ADR+60 BuffMemType (1 for PUBLIC, 3 for FAST and 5 for CHIP)
  566. *-  ADR+64 Maxtransfer
  567. *-  ADR+68 MASK-value (DMA-devices)
  568. *-  ADR+72 Bootpriority
  569. *-  ADR+76 Dostype ($444f5300 for OFS and $444f5301 for FFS)
  570.  
  571. *-     DeviceTypes is zero for all true DOS-devices (like CON:, DF0:,
  572. *-  DH0: etc.), 1 if it is an assignment and 2 for volumes. It can be
  573. *-  a bit tricky to separate non-drive devices, like  CON:/RAW:  etc.
  574. *-  from  normal devices which you can save files to. A rather simple
  575. *-  way to tell which is which is to check ADR+8 (Devicename)  if  it
  576. *-  contains  a devicename. If it does, you can count on that you can
  577. *-  save files to the device. If devicename is empty and type is zero
  578. *-  it is a non-filesystem device.
  579.  
  580. *-     Devicename (ADR+8) contains a pointer to a  transformed  BSTR-
  581. *-  string.  The  first  "character" shows how long the string is, or
  582. *-  zero. Start of the string is thus ST=Leek(ADR+8). Length  of  the
  583. *-  string  is  P=Peek(ST)  and  the  text  starts at ST+1. Note that
  584. *-  Devicename normally is NULL-terminated (ends with a  Chr$(0))  so
  585. *-  it  is  wise to subtract Chr$(0) from the resulting string before
  586. *-  usage.   However,  don't  count  on  that  all  names  are  NULL-
  587. *-  terminated, asdg.vdisk.device for example isn't!
  588.  
  589.  
  590.  
  591. ++  Lldir$ - Change the current directory
  592. ++  LLdir$ "new-dir"
  593.  
  594. ++  where
  595.  
  596. ++     newdir is a device/volume/dirname. If you change the dir using
  597. ++  the Dir$-command and then try to open a  file  using  Lopen,  the
  598. ++  file  probably  couldn't  be found, since Ldos hadn't noticed the
  599. ++  directory-change (as always, AMOS handles this  internal  :-(..).
  600. ++  There are two ways of using LLdir$ in your program:
  601.  
  602. ++     a) Set Dir$ to desired value, and call LLdir$ Dir$. Ldos  will
  603. ++   now work in the same path as AMOS.
  604.  
  605. ++     b) NEVER use Dir$ in your program (or direct mode as  long  as
  606. ++  AMOS  is  running). Instead, use LLdir$, just like you would have
  607. ++  used Dir$. What LLdir$ does is to change the program's (AMOS's or
  608. ++  the compiled program) current directory using a system call. What
  609. ++  AMOS's Dir$-command does is to probably add the new path to  some
  610. ++  internal variable that is appended to all subsequent calls to any
  611. ++  file  related  commands.  However, another problem arises..  When
  612. ++  you bring up AMOS's filerequester AMOS changes the Dir$-string so
  613. ++  Ldos will once again become confused.  If your  compiled  program
  614. ++  never uses AMOS's own filerequester (use Lfreq) stick with LLdir$
  615. ++  If you run the interpreter, use option a).
  616.     Example: LLdir$ Dir$
  617.              LLdir$ "SYS:"
  618.  
  619.  
  620.  
  621.  
  622.          PART TWO - String commands and bufferhandling
  623.          ---------------------------------------------
  624.  
  625.  
  626.     Lstr - Get a string (line) from a bank.
  627.     1) A$=Lstr(START To MAX)
  628.  
  629.     where
  630.  
  631.        START is the address of a bank, and MAX the end  of  the  bank
  632.     (or  the  end  of  the  file loaded). This function will begin at
  633.     START, looking for an end-of-line-terminator  (see  below).  When
  634.     found,  it  will  put  the  contents  into A$. If no end-of-line-
  635.     terminator is found, A$  will  contain  every  character  between
  636.     START  and MAX. The end-of-line-terminator is NOT copied into the
  637.     string, so  the  new  startaddress  of  the  next  line  will  be
  638.     START+Len(A$)+1
  639.  
  640.  
  641.  
  642.     Lstr - Get a string from a bank.
  643.     2) A$=Lstr(START,END)
  644.  
  645.     where
  646.  
  647.        A$ will contain every character  between  START  and  END.  No
  648.     checking  for  end-of-line is done and it is thus faster than the
  649.     other syntax of this command. Mostly useful  when processing text
  650.     where "lines" have no meaning.
  651. ++  PLEASE NOTE THAT I HAVE  MADE AN TYPO IN  OLDER DOCS!  END SHOULD
  652. ++  ACTUALLY BE _LENGTH_! A$=Lstr(START,10) will put 10 characters in
  653. ++  A$.
  654.  
  655.  
  656.  
  657.     Lset Eoln - Change end-of-line-terminator
  658.     Lset Eoln NUM
  659.  
  660.     where
  661.  
  662.        NUM may range from 0 to  255.  Default  is  10,  normal  Amiga
  663.     LineFeed.  (Unlike  AMOS  which  tends  to use 13 for some reason
  664.     (old habit from Atari ST?))
  665.     Example: Lset Eoln 13
  666.              A$=Lstr(_START,_MAX) : _START=START+Len(A$)+1
  667.              A$=A$-Chr$(10) : Rem remove Lf which AMOS use before CR.
  668.  
  669.  
  670.  
  671.     Lbstr - Copy a string to a bank
  672.     Lbstr A$,START
  673.  
  674.     where
  675.  
  676.        START is a bankaddress where A$'s contents may be placed.
  677.  
  678.        No check is done to see whether the bufferlimit  was  exceeded
  679.     or not so make sure there is room for the string.
  680.     Example: Lbstr A$+Chr$(10),_START : _START=_START+Len(A$)+1
  681.  
  682.  
  683.  
  684.     Lreplace - Hunt for a character and then replace it.
  685.     Lreplace SEARCH,SWAP,START To STOP
  686.  
  687.     where
  688.  
  689.        START and STOP are the area to be scanned, SEARCH is an ASCII-
  690.     value to search for. If SEARCH is found it will  be  replaced  by
  691.     the    SWAP-value.    Fx.    Lreplace   9,Asc(" "),Start(10)   To
  692.     Start(10)+Length(10), will replace all tabs with spaces  in  bank
  693.     number  ten. Mostly  useful   when  you  want to convert specific
  694.     unwanted  characters,  like  CR  (Carrige  Return)  or   removing
  695.     characters that you can't display or process.
  696.  
  697.  
  698.  
  699.     Lfilter - Replace within a specific range.
  700.     Lfilter LOW,HIGH,SWAP,START To STOP.
  701.  
  702.     where
  703.  
  704.        START and STOP is the same as above,  LOW  and  HIGH  are  the
  705.     limits. Everything  between LOW and HIGH (INCLUDING LOW and HIGH)
  706.     will be replaced by SWAP.  Fx.  Lfilter  Asc("a"),Asc("z"),Asc("-
  707.     "),Start(10) To Start(10)+Length(10), will replace all lower-case
  708.     characters  with  a  minus "-" sign, leaving any other characters
  709.     untouched.  Very useful when parsing commandfiles.  For  instance
  710.     you  may let the user print comments anywhere in the file as long
  711.     as this is done in CAPITAL  letters.  You  then  filter  out  all
  712.     capitals and convert them to, say ASCII 0. Next when you use Lstr
  713.     to  be  able  to process the  lines, just add a -Chr$(0) after it
  714.     and all comments are masked out.
  715.  
  716.  
  717.  
  718.     Lskip - Find next character NOT being xx.
  719.     ADR=Lskip(CHAR,START To STOP)
  720.  
  721.     where
  722.  
  723.        CHAR is the  ASCII-value  you  want  to  skip,  START  is  the
  724.     startaddress  of the bank, and STOP is the maxaddress where Lskip
  725.     will end if it couldn't find a character which wasn't  CHAR.  ADR
  726.     will  contain the address AFTER the last CHAR.  Useful if you for
  727.     example  would like to skip datas which have been filtered out by
  728.     Lfilter of similar.
  729.     ADR=Lskip(10,_START To _STOP) : Rem Skip empty lines.
  730.  
  731.  
  732.  
  733. *-  Lback Hunt - Find next character being xx, works backwards.
  734. *-  ADR=Lback Hunt(CHAR,START To STOP)
  735.  
  736. *-  where
  737.  
  738. *-     CHAR is the character  you  wish  to  search  for,  START  the
  739. *-  position  to  start searching from and STOP the end-address. Note
  740. *-  that  START  is  greater  than  STOP  since  this  routine  works
  741. *-  backwards.  If  you  want  to  skip  forwards  the standard AMOS-
  742. *-  function 'Hunt' is easier to use. This command is  probably  most
  743. *-  useful  in  page/line-oriented applications, like a textdisplayer
  744. *-  or the like. It was implemented since it is a real  pain  to  use
  745. *-  Hunt  for backwards searching.
  746.     Example: For I = 1 To 10
  747.                  ADR=Lback Hunt(10,ADR To _STOP)
  748.              Next
  749.  
  750.  
  751.  
  752.     Lupbuffer - Convert all characters to UPPER-case.
  753.     Lupbuffer START To STOP
  754.  
  755.     where
  756.  
  757.        all characters between START and STOP  will  be  converted  to
  758.     upper-case.  Just  like  AMOS  Upper$  this  routine won't handle
  759.     national characters (due to AMOS isn't using a standard  keymap).
  760.     Only A-Z and a-z are processed.
  761.  
  762.  
  763.  
  764.     Llowbuffer - Convert all characters to lower-case.
  765.     Llowbuffer START To STOP.
  766.  
  767.  
  768.     where
  769.  
  770.        everything works  like  above,  but  all  characters  will  be
  771.     converted to lower-case.
  772.  
  773.  
  774.  
  775. *-  Lmatch - Search for for patterns in strings using wildcards.
  776. *-  L=Lmatch(SOURCE$,S$)
  777.  
  778.     THIS FUNCTION REQUIRES Release 2.
  779.  
  780. *-  where
  781.  
  782. *-     SOURCE$ is the string you want to search in  and  S$ contains
  783. *-  the  pattern.  PLEASE  NOTE  THAT  BOTH  STRINGS  MUST  BE  NULL-
  784. *-  TERMINATED (+Chr$(0)). This routine  is  case-sensitive,  so  use
  785. *-  Upper$ or Lower$ if required. Valid wildcards currently are :
  786. *-
  787. *-
  788. *-      ?       Matches a single character.
  789. *-      #       Matches the following expression 0 or more times.
  790. *-      (ab|cd) Matches any one of the items seperated by '|'.
  791. *-      ~       Negates the following expression.  It matches all strings
  792. *-              that do not match the expression (aka ~(foo) matches all
  793. *-              strings that are not exactly "foo").
  794. *-      [abc]   Character class: matches any of the characters in the class.
  795. *-      [~bc]   Character class: matches any of the characters not in the
  796. *-              class.
  797. *-      a-z     Character range (only within character classes).
  798. *-      %       Matches 0 characters always (useful in "(foo|bar|%)").
  799. *-      *       Synonym for "#?", not available by default in 2.0.  Available
  800. *-              as an option that can be turned on.
  801. *-       "Expression"  in  the  above  table  means  either  a  single
  802. *-  character (ex: "#?"), or an alternation (ex: "#(ab|cd|ef)"), or a
  803. *-  character class (ex: "#[a-zA-Z]").
  804.     Example: See Lcat_pat* example. Useful for experimenting.
  805.  
  806.  
  807.  
  808. --  Lwild - Find out if a string contains a valid wildcard
  809. --  TEST=Lwild(A$)
  810.  
  811. --  THIS FUNCTION REQUIRES Release 2.
  812.  
  813. --  where
  814.  
  815. --     TEST will be false  (zero)  if  A$  contains  no  wildcard(s),
  816. --  otherwise TEST may contain anything (usually 1). Always use Lwild
  817. --  before  calling  Lmatch  to  prevent Lmatch to cause an overflow-
  818. --  error.
  819.     Example: If Lwild(A$) Then Gosub _MATCH
  820.  
  821.  
  822.  
  823. *-  Lwords - Count the number of words in a string.
  824. *-  NUM=Lwords(STRING$)
  825.  
  826. *-  where
  827.  
  828. *-     NUM will contain the number of words  in  STRING$.  Words  are
  829. *-  separated  by  either  TAB (ASCII-value 9), comma (','), space or
  830. *-  doublequote ('"'). If doublequotes aren't matched, all text  from
  831. *-  the    first  doublequote  will  be  treated  as  one  word.  Two
  832. *-  doublequotes without any text between  them will  be  treated  as
  833. *-  one word (this is a  'NULL'-word,  useful when for instance omit-
  834. *-  ting a  parameter). If there are more than  one  separator  (TAB,
  835. *-  SPACE, COMMA)  following  each  other they  will be  ignored. You
  836. *-  can thus not use ',,' to produce  an empty  word  (use  '""'  in-
  837. *-  stead).  If STRING$ is empty zero is returned.
  838.  
  839. *-  Some examples (TAB means ASCII-value 9 which isn't visible):
  840.  
  841. *-  Lwords("TAB Hi,, this TAB is just me") -> 5
  842. *-  Lwords('Hi, "this is just" "" me')     -> 4
  843. *-  Lwords('Hi "this is just" me')         -> 3
  844. *-  Lwords('"Hi this is just me')          -> 1
  845.  
  846. *-  Do not confuse with Lword.
  847.  
  848.  
  849.  
  850. *-  Lword - Mask out any word of a string, without changing the
  851. *-           source
  852. *-  A$=Lword(WORD,STRING$)
  853.  
  854. *-  where
  855.  
  856. *-     WORD is the word you  wish  to  extract.  The  first  word  in
  857. *-  STRING$ is 1 (not zero) up to the value returned by Lwords.If you
  858. *-  request a word which doesn't exist an error will be produced. The
  859. *-  same  rules as apply to Lwords applies here,  with one  exception
  860. *-  which you might not expect: If a 'NULL'-word is specified  ('""')
  861. *-  an  empty  string will not be returned, but both the doublequotes
  862. *-  will be returned. Even if there are text between the doublequotes
  863. *-  they still are returned  in  A$.  This  makes  it  easy  for  the
  864. *-  programmer  to tell when more than one word (containing commas or
  865. *-  tabs etc. just check Left$(A$,1) for '"') are to be  regarded  as
  866. *-  ONE  word.  If  only  one doublequote  is supplied the rest of A$
  867. *-  will be  treated  as  one  word.  If  the  last  character  is  a
  868. *-  doublequote,  only  '"'  will  be  returned.  It  is  up  to  the
  869. *-  programmer to decide how to handle this. It could be regarded  as
  870. *-  a  'NULL'-word,  but in most cases it probably is a syntax error.
  871. *-  If you do not wish TABs, spaces or commas to be treated as a word
  872. *-  separator (or wish to be able  to  use  more  than  one  of  them
  873. *-  directly  after  each  other)  you  simply  quote  the  text  and
  874. *-  everything between the quotes will be untouched and  regarded  as
  875. *-  one word. If WORD is zero an empty string will be returned
  876.  
  877.  
  878.  
  879.  
  880.  
  881.                    PART THREE - Date commands
  882.                    --------------------------
  883.  
  884.        Please note! All Ldate* commands only work within the range  1
  885.      Jan 1978 to 31 Dec 2099!
  886.  
  887.  
  888.     Ldate - Convert a datestamp to an ACSII-string.
  889.     A$=Ldate(STAMP)
  890.  
  891.     where
  892.  
  893.        stamp is the number of days since 1 Jan 1978. A$  will  be  in
  894.     the  form  of "YYMMDD". Fx. 780101 or 920325. If the datestamp is
  895.     less than zero (below 1 Jan  1978)  the  string  780101  will  be
  896.     returned.  Also, this routine will only generate valid dates upto
  897.     2099 (which should be enough?)
  898.  
  899.  
  900.     Lstamp - Convert year,month and day into a datestamp
  901.     S=LStamp(YEAR,MONTH,DAY)
  902.  
  903.     where
  904.  
  905.        S will be in the standard  datestamp-form  :  number  of  days
  906.     since  1  Jan  1978. If the date is before 1 Jan 1978, 1 Jan 1978
  907.     will still be returned.
  908.  
  909.     Fx. Print Ldate(LStamp(1991,10,23)) --> 911023
  910.  
  911.  
  912.  
  913.     Lsys Stamp - Get the current system-datestamp.
  914.     A=Lsys Stamp
  915.  
  916.     where
  917.  
  918.        A will contain a datestamp which can be  used  in  conjunction
  919.     with Ldate to print the current date.
  920.  
  921.  
  922.  
  923.     Lsys Time - Get the current system-time.
  924.     A$=Lsys Time
  925.  
  926.     where
  927.  
  928.        A$ will be in the form "HHMMSS", hours, minutes, seconds.
  929.  
  930.        No extra ":","." or "-"  is  added  so  that  you  easily  can
  931.     process this string to the format you like.
  932.  
  933.  
  934.  
  935.  
  936. --  Lset File Date - Change the datestamp of a file or a directory
  937. --  TEST=Lset File Date("name",STAMP,MIN,TICKS)
  938.  
  939. --  THIS FUNCTION REQUIRES Release 2
  940.  
  941. --  where
  942.  
  943. --     TEST will be true (-1) if the call was successful.  "name"  is
  944. --  of  course  the  (path and) name of the file OR directory that is
  945. --  to be changed. STAMP is a normal datestamp like the one  returned
  946. --  by  Lstamp  (see  above), MIN are the number of minutes that have
  947. --  passed since midnight. TICKS are the number of  ticks  that  have
  948. --  passed during the last minute (1 tick is the same as a VBL = 1/50
  949. --  sec).  I  didn't mind adding conversionroutines for MIN and TICKS
  950. --  since they are so easy to calculate. It  is  probably  harder  to
  951. --  convert  a  userspecified  datestring to a format that my routine
  952. --  could convert. The datestamp, which are  a  bit  harder,  can  be
  953. --  converted easily with Lstamp.
  954.  
  955. --     Please note that many filesystems (like OFS and  FFS)  doesn't
  956. --  allow  you to change the date of the root-directory (this date is
  957. --  used to separate disks with the same name)
  958.     Example: If Lset File Date("t:temp",Lstamp(1992,7,25), 480,1850)
  959.                 Print "Date is now 92-07-25, 08:00:37"
  960.              Else
  961.                 Print "Set date failed!"
  962.              EndIf
  963.  
  964.  
  965.  
  966.  
  967.  
  968.                    PART FOUR - Filerequester
  969.                    -------------------------
  970.  
  971.  
  972.     Lfreq - Bring up the filerequester.
  973.     A$=Lfreq("Title",FLAGS)
  974.  
  975.  
  976.     where
  977.  
  978.        A$ will contain the full path and filename after the call.  If
  979.     the  user  clicked  cancel, A$ will be empty. "Title" is the text
  980.     you want as a headline in the requester fx. "Load  an  IFF-file".
  981.     FLAGS  decides  how  the  requester  will  act. Every function is
  982.     assigned to a bit, and here are  their  values  (to  choose  many
  983.     options, just add the values, fx. FLAGS=$2+$4+$1000)
  984.  
  985.  
  986.  
  987.     $1  -   Show .info-files. Hidden otherwise
  988.     $2  -   Extended select. Not supported by Ldos.
  989.     $4  -   Dir cache. The  latest used directory will be
  990.             remembered so it won't have to be read again at
  991.             the next call.
  992. *-  $8  -   Bring up font requester. Supported in V2 and above.
  993. *-          Use Lfontsize Freq to get hold of the size of the
  994. *-          font. A$ will contain the full path and name of the
  995. *-          font and you may thus let the user select a font from
  996. *-          any path and then load it using Ldisk Font. HINT, use
  997. *-          Lget Freq Dir to mask out everything except the font-
  998. *-          name if you intend to use Get Rom Fonts. See the inc-
  999. *-          luded example Lfonts for more hints.
  1000.     $10 -   Create a hide-'.info'-gadget
  1001.     $20 -   Do not create any hide- and showgadgets
  1002.     $40 -   Use absolute x,y for the requester. Otherwise it
  1003.             is placed directly under the mousepointer. (x and
  1004.             y are hard-coded to the upper left on the screen)
  1005. *-          Version 2 and higher allows re-position of the re-
  1006. *-          quester if $40-flag is used.
  1007.     $80 -   Purge cache whenever the datestamp of the directory
  1008.             changes (in other words, re-read the directory
  1009.             whenever it is changed)
  1010.     $100 -  Don't cache anything until the whole directory is
  1011.             read.
  1012.     $200 -  Do not sort the files.
  1013.     $400 -  Do not create a scrollbar.
  1014.     $800 -  Used when choosing a file to save. Currently it have
  1015.             no function, but are reserved for future use.
  1016.     $1000 - Used when choosing a file to load. Currently it have
  1017.             no function, but are reserved for future use.
  1018.     $2000 - Let the user select directories only, does not
  1019.             display any files at all.
  1020.  
  1021.        You should ALWAYS set $800 or $1000 depending on  if  you  are
  1022.     going to load or save a file.
  1023.  
  1024.  
  1025.  
  1026.     Lget Freq Dir - Get only the path which the user picked the
  1027.                     last time the filerequester was used.
  1028.     A$=Lget Freq Dir
  1029.  
  1030.     where
  1031.  
  1032.        A$ will hold the LAST selected dir. A$ will NOT be empty  even
  1033.      if  the  user clicked  CANCEL  and something  has  been selected
  1034.      through the filerequester before.
  1035.  
  1036.  
  1037.  
  1038.     Lget Freq File - Get only the filename which the user picked the
  1039.                      last time the filerequester was active.
  1040.     A$=Lget Freq File
  1041.  
  1042.     where
  1043.  
  1044.        A$ will hold the LAST selected file. A$ will NOT empty even if
  1045.     the  user   clicked  CANCEL,  and  something  has  been  selected
  1046.     through the filerequester before.
  1047.  
  1048.  
  1049.  
  1050.     Lset Freq Dir - Set the default (current) directory for the
  1051.                     filerequester.
  1052.     Lset Freq Dir "Path"
  1053.  
  1054.     where
  1055.  
  1056.        If you haven't set  path,  the  filerequester  will  use  your
  1057.     programs  current  directory. Whenever the user changes directory
  1058.     it will be remembered by Ldos. This path does not  affect  AMOS's
  1059.     (Dir$) path in any way.
  1060.  
  1061.  
  1062.  
  1063. *-  Lpos Freq - Change the hardcoded X and Y position of the requester.
  1064. *-  Lpos Freq X,Y
  1065.  
  1066. *-  where
  1067.  
  1068. *-     X and Y are specified in pixels. These positions will only  be
  1069. *-  used  if  the $40-flag is specified, otherwise the requester pops
  1070. *-  up at the mousepointer. Default positions are 3,11.
  1071.  
  1072.  
  1073.  
  1074. *-  Lcust Freq - Change size of the requester's fields.
  1075. *-  Lcust Freq DEVWIDTH,FILEWIDTH,FILES
  1076.  
  1077. *-  where
  1078.  
  1079. *-     DEVWIDTH specifies how many characters  wide  the  devicefield
  1080. *-  will  be,  FILEWIDTH  does the same but affect the file-name/size
  1081. *-  window. FILES specifies how many files/dir that will be displayed
  1082. *-  (height). Default values are 12,30,14.
  1083.  
  1084.  
  1085.  
  1086. *-  Lfontsize Freq - Return the fontsize when the requester has been
  1087. *-  in font-mode.
  1088. *-  S=Lfontsize Freq
  1089.  
  1090. *-  where
  1091.  
  1092. *-     S contains the fontsize of the last  chosen  font.  Note  that
  1093. *-  you must set the filerequester to font-mode ($8-flag) in order to
  1094. *-  update this  field. Currently the req.library doesn't support CG-
  1095. *-  fonts.  Hopefully  there  will be a new version out soon (when/if
  1096. *-  CED V3 is coming?)
  1097.  
  1098.  
  1099.  
  1100.  
  1101.                   PART FIVE - Device Commands
  1102.                   ---------------------------
  1103.  
  1104.  
  1105.     Ldevice Open - Open a device for use. Only one device may be
  1106.                    open at the same time.
  1107.     S=Ldevice Open("name",UNIT,FLAGS)
  1108.  
  1109.     where
  1110.  
  1111.        name is the devicename, like "trackdisk.device". UNIT  is  the
  1112.     unit  number, 0 for Dh0: and Df0:, 1 for Dh1: and Df1: etc. FLAGS
  1113.     may be set to zero, if you're a non "pro-devicer".. A is zero  if
  1114.     successful, non zero if the device couldn't be opened.
  1115.  
  1116.  
  1117.  
  1118.     Ldevice Close - Close the device opened by Ldevice Open.
  1119.     Ldevice Close
  1120.  
  1121.  
  1122.  
  1123.     Ldevice - Send a command to the currently open device.
  1124.     A=Ldevice(COMMAND,BUFFER,LENGTH,OFFSET)
  1125.  
  1126.     where
  1127.  
  1128.        BUFFER is a pointer to where data is to  be  fetched  or  put.
  1129.     LENGTH  is  the number of bytes you wish to read or write. OFFSET
  1130.     is where you wish to read or write. A is the  parameter  returned
  1131.     from  the  device  (IO_ACTUAL)  and may mean different things for
  1132.     different devices/commands  (see  below).  If  a  read  or  write
  1133.     operation  took place A will contain the number of bytes actually
  1134.     read or written. COMMAND is one of the  following  (for  standard
  1135.     devices,  for  specialdevices  like  trackdisk,  serial  etc. see
  1136.     documentation or C= includefiles):
  1137.  
  1138.  
  1139.  
  1140.         #       Description
  1141.         -       ------------
  1142.         0       Invalid. (Does it do anything?)
  1143.         1       Reset. Act as newly re-started.
  1144.         2       Read
  1145.         3       Write
  1146.         4       Update (write all buffers)
  1147.         5       Clear all buffers.
  1148.         6       Stop all i/o
  1149.         7       Restart after stop.
  1150.         8       Flush, abort all queue
  1151.  
  1152.  
  1153.  
  1154.     The trackdisk.device has some special commands :
  1155.  
  1156.  
  1157.  
  1158.        (Remember about trackdisk : ALL buffers must be in  CHIP.  ALL
  1159.     offsets and lengths must be a multiple of 512. Offsets are always
  1160.     given in bytes, fx. Root-block is 880*512)
  1161.  
  1162.  
  1163.     Command # & Description
  1164.     -----------------------
  1165.     2  Read, buffer MUST be in CHIP-mem!
  1166.     3  Write, buffer MUST be in CHIP-mem!
  1167.     4  Update, write the (internal) buffer to disk.
  1168.        (You can also force this by reading another track.)
  1169.     5  Clear the (internal) buffer and thus force the
  1170.        device to read the next block from disk, even
  1171.        though it may have been in the buffer (used to
  1172.        make sure no other process have done anything
  1173.        to the disk via hardware-programming without
  1174.        updating the buffer or if the buffer was trashed).
  1175.     9  Turn motor OFF (set LENGTH to 0) or ON (LENGTH=1)
  1176.     10 Seek, move head to OFFSET, but doesn't perform any
  1177.        read to ensure it hit the right block.
  1178.     11 Format tracks. LENGTH must be 22*512(*2) bytes. (You
  1179.        can use format instead of write if you wish to
  1180.        copy to an unformatted disk)
  1181.     12 Remove interrupt. Only for pro's. Do not use.
  1182.     13 Return the number of diskchanges.
  1183.     14 Determine if a disk is inserted. (255 = No disk in drive)
  1184.     15 Determine if a disk is writeprotected. (0 it not)
  1185.     16 RawRead, only for pro's. Do not use.
  1186.     17 RawWrite - " " -         Do not use
  1187.     18 Determine drivetype. (1 = 3.5", 2=5.25")
  1188.     19 Determine number of tracks.
  1189.     20 Change interrupt. Only for pro's. Do not use.
  1190.     21 Remove change interrupt. Only for pro's. Do not use.
  1191.     22 Determine last command.
  1192.  
  1193.  
  1194.  
  1195.        Those commands marked "Only for pro's" should NOT be used from
  1196.     Ldos because of many things,  to  complicated  and  off-topic  to
  1197.     explain here!
  1198.  
  1199.  
  1200.  
  1201.        Extended devicecommands are not supported by Ldos  (so  please
  1202.     use LSerial.LIB and not Ldevice to perform serial I/O).
  1203.  
  1204.  
  1205.  
  1206.     Ldevice Error - Determine if any (and if so which) error
  1207.                     occurred during the last operation.
  1208.     A=Ldevice Error
  1209.  
  1210.     where
  1211.  
  1212.        A can be IF trackdisk is used :
  1213.  
  1214.  
  1215.     ## Description
  1216.     -- -----------
  1217.     0  "Operation Successful."
  1218.     20 "Unknown Error."
  1219.     21 "No Sector Header Present."
  1220.     22 "Invalid Sector Header."
  1221.     23 "Invalid Sector ID."
  1222.     24 "Incorrect Header Checksum."
  1223.     25 "Incorrect Sector Checksum."
  1224.     26 "Not Enough Sectors Available."
  1225.     27 "Illegal Sector Header."
  1226.     28 "Disk Is Writeprotected."
  1227.     29 "Disk Was Changed."
  1228.     30 "Track Not Found."
  1229.     31 "Not Enough Memory."
  1230.     32 "Illegal Sector Number."
  1231.     33 "Illegal Drive Type."
  1232.     34 "Drive In Use."
  1233.     35 "Reset Phase!!"
  1234.  
  1235.  
  1236.  
  1237. *-  Lchk Data - Calculate the checksum of a data-block.
  1238. *-  CHK=Lchk Data(ADR)
  1239.  
  1240. *-  where
  1241.  
  1242. *-     ADR points to a buffer containing the datablock  (512  bytes).
  1243. *-  CHK will contain the checksum itself.
  1244.  
  1245.  
  1246.  
  1247. *-  Lchk Boot - Calculate the checksum of the bootblocks.
  1248. *-  CHK=Lchk Boot(ADR)
  1249.  
  1250. *-  where
  1251.  
  1252. *-     See above.
  1253.  
  1254.  
  1255. *-  A word about checksums :
  1256.  
  1257. *-     As  you  already  may  have  guessed  the  bootchecksum  isn't
  1258. *-  calculated  in  the  same  way  as  the  checksum of other blocks
  1259. *-  (Udir,Data,Root etc. etc.) so you must not use Lchk Data for  the
  1260. *-  bootblock  and  Lchk  Boot  for  datablocks. Also notice that the
  1261. *-  bootblock actually consists of TWO  blocks  (which    always  are
  1262. *-  reserved  on the disk) and ADR should thus point to the TWO first
  1263. *-  blocks of the disk  when  calculating   this  checksum.  The  new
  1264. *-  filesystem  (FFS)  doesn't  use  checksums for datablocks anymore
  1265. *-  since FFS uses the full 512  bytes for data (SFS uses only 488).
  1266.  
  1267. *-     To alter the checksum on a SFS disk simply call Lchk  xxxx  to
  1268. *-  obtain  the  new  (and  valid) checksum, if it is the bootblocks,
  1269. *-  Loke this value into the second longword, if it  is  a  datablock
  1270. *-  (or  other, except bitmap) longword 6 should be changed. In other
  1271. *-  words, for boot : Loke ADR+4,CHKSUM and for  other blocks :  Loke
  1272. *-  ADR+20,CHKSUM.
  1273.  
  1274.  
  1275.  
  1276.  
  1277.                     PART SIX - Misc commands
  1278.                     ------------------------
  1279.  
  1280.  
  1281.     Lpp Mem - Determine how much memory a file crunched by
  1282.               PowerPacker will need to decrunch.
  1283.     SIZE=Lpp Mem(END)
  1284.  
  1285.     where
  1286.  
  1287.        END is the end of the previously loaded file. It must  not  be
  1288.     the    end    of    the    bank,    but  the  end  of  the  file,
  1289.     Start(Bank)+Lsize("FileName"). (AMOS's banks are  always  rounded
  1290.     off  to  the nearest multiple of 4 and may differ from the actual
  1291.     filesize) No check is done to see that the bank really contains a
  1292.     powerpacked file so make sure you have loaded one before.
  1293.  
  1294.  
  1295.  
  1296.     Lpp Decrunch - Decrunch a PowerPacked datafile.
  1297.     Lpp Decrunch START,END To DEST
  1298.  
  1299.     where
  1300.  
  1301.        START is the start of the loaded file,  END,  see  above.  The
  1302.     file will be unpacked to address DEST. This bank must be at least
  1303.     Lpp  Mem  bytes  large. Again, no test is done to see if the bank
  1304.     really contains a powerpacked file! Be careful!
  1305.  
  1306.  
  1307.  
  1308.     Llargest Free - Return the size of largest block of free memory
  1309.     A=Llargest Free(TYPE)
  1310.  
  1311.     where
  1312.  
  1313.        TYPE is either 0 for CHIP-memory of 1 for FAST-memory. A  will
  1314.     contain  the  size of the memoryblock. This value is NOT the same
  1315.     as the AMOS commands Fast Free and Chip Free, they  return  total
  1316.     unallocated memory-size, not the largest size you can allocate in
  1317.     one  bank.  Always  use  this  command before reserving a  larger
  1318.     amount of memory in a single bank.
  1319.  
  1320.  
  1321.  
  1322.     Lrun - Run a program.
  1323.     A=Lrun("command(s)","WINDOW")
  1324.  
  1325.     where
  1326.  
  1327.        "commands" is the program(s) you wish to run. Since a new  CLI
  1328.     is  opened  to  execute  your  program(s) you may wish to set the
  1329.     stack for the program, and you  MUST  set  the  fail-level  (with
  1330.     failat) to a very high value, otherwise a program may fail with a
  1331.     returncode  >0 and the Shell/CLI-window will never be closed! (at
  1332.     least not until the user types endcli >NIL:) After every  command
  1333.     a   linefeed,  Chr$(10)  MUST  follow.  "WINDOW"  is  a  standard
  1334.     CON:/NEWCON: (please always use CON: since NEWCON: isn't used any
  1335.     more in Release 2) with the normal syntax :  "CON:x/y/xx/yy/name"
  1336.     name  should  preferably  not contain any spaces. To use Lrun you
  1337.     must have the following commands on the disk (system:) :
  1338.  
  1339.         c:Run
  1340.         c:NewCli
  1341.         c:EndCli
  1342.        (c:FailAt)
  1343.  
  1344.        You also  must  have  assigned  t:  to  somewhere  or  have  a
  1345.     directory named "t" on the disk and have the disk write enabled.
  1346.  
  1347.  
  1348.  
  1349.     An example :
  1350.  
  1351.         T$=Chr$(10)
  1352.         A$="Failat 10000"+T$
  1353.         A$=A$+"Stack 8000"+T$
  1354.         A$=A$+"Lha l dh0:download/*.lha"+T$
  1355.         A$=A$+"Wait 2 secs"+T$ : Rem, pause to read the output
  1356.         A=Lrun(A$,"CON:10/10/600/180/AMOS-Output")
  1357.  
  1358.     where
  1359.  
  1360.        A will contain any number (see Technote  below).  Please  note
  1361.     that  you  should  NOT  use EndCli as the last command, Ldos will
  1362.     automatically append this. Always make sure  that  the  requested
  1363.     commands  exists  on  disk,  because  there  is  no   way (that I
  1364.     currently know of) to ignore a "command not found"-error and your
  1365.     script will fail, leaving the window open and  AMOS  waiting.  If
  1366.     you follow these rules you will be enable to run just about every
  1367.     program from AMOS!
  1368.  
  1369.        Note! Under KS1.3 a "unknown command"-error always breaks  the
  1370.     CLI  on  my  system.  I  do not know why, it works perfectly well
  1371.     under KS2.04 and other 1.3-systems if FailAt has been used.
  1372.  
  1373.  
  1374.     Technotes:
  1375.  
  1376.        Some of you might wonder  why  it  takes  so  much  to  run  a
  1377.     program?  I  will  try  to  explain a bit.. Normally Execute() in
  1378.     dos.library is used to start programs. Execute() use the  command
  1379.     Run  in  order to start the program (that is why you have to have
  1380.     it available on the boot-disk). It SHOULD  also  be  possible  to
  1381.     pass  two  channels  for  I/O,  for  example a newly opened CON:-
  1382.     window. Now there has always been troubles with Execute() because
  1383.     if you wish to use an inputchannel Execute won't  complete  until
  1384.     EOF  (End  Of File) is written to the inputchannel. Since an  EOF
  1385.     never is  sent  the  input/output-window  is  never  closed,  and
  1386.     Execute waits, and waits..and waits. The only way to make Execute
  1387.     continue is by typing EndCli >NIL: in the window. I tried sending
  1388.     a string like "dir dh0: opt i"+LF+"EndCli >NIL:"+LF (LF=LineFeed)
  1389.     but  this  didn't work if the program just executed fails. Failat
  1390.     also needed to be used. At this time I realized you would need  a
  1391.     whole  script  (EndCli, Failat, Stack etc.) to execute a program.
  1392.     It seemed much smarter to write all the  commands  to  a  script-
  1393.     file,  and  use NewCli FROM script-file + a window specification.
  1394.     This way you can execute a number of commands  and  the  I/O  re-
  1395.     direction  is  taken  care of automatically! All this works fine,
  1396.     but two new problems arose. First I  haven't  found  any  way  of
  1397.     getting  hold  of  the  returncode  from  Execute()  since it now
  1398.     returns directly after the NewCli-command is run (a  new  process
  1399.     is created). Secondly, control would return to AMOS directly, and
  1400.     one newer knew when the script was finished! I still have no idea
  1401.     of  how  to get hold of the returncode from the executed programs
  1402.     in the script but the other problems was solved in this way :
  1403.  
  1404.  
  1405.  
  1406.     1) Your commands is written to a script-file, t:ld.t
  1407.     2) Two commands are added "t:sig_ldos" and "EndCLi >NIL:"
  1408.     3) A program called t:sig_ldos is created by Ldos in t:.
  1409.     4) A messageport is created by Ldos.
  1410.     5) A NewCli is launched FROM t:ld.t CON:?/?/?/?/Title
  1411.     6) Ldos directly start to look for a message in the msg.port.
  1412.     7) The script reaches the line t:sig_ldos.
  1413.     8) sig_ldos send a message to Ldos that script now is at the end.
  1414.     9) EndCli is executed, the window close, Ldos cleans up and
  1415.        control returns to AMOS.
  1416.  
  1417.  
  1418.        Sometimes it can be hard to start a  program  correctly  on  a
  1419.     multitasking computer.......
  1420.  
  1421.  
  1422.  
  1423.     Lexecute - Start a program which doesn't need CLI I/O
  1424.     A=Lexecute("programname")
  1425.  
  1426.        Works almost like Lrun above, but only one program may be run.
  1427.     The  program  to be run can not use any CLI-I/O. Started programs
  1428.     should  open  their  own  screen/window  to  function   properly.
  1429.     Lexecute  is perfect for starting editors, wordprocessors or just
  1430.     any other program which isn't designed to print or receive  input
  1431.     to/from a CLI-window.  If the  program detatches  itself  control
  1432.     will return to AMOS directly.
  1433.  
  1434.     where
  1435.  
  1436.        A will be True if successful, False otherwise.
  1437.  
  1438.  
  1439.  
  1440.     Ldisk Font - Load a font from disk, making it directly
  1441.                  available to Get Rom Fonts
  1442.     A=Ldisk Font("name.font",SIZE)
  1443.  
  1444.     where
  1445.  
  1446.        name is the fontname, ".font" MUST follow it. SIZE is the size
  1447.     of the font you wish to load. A will be >0 if the font loaded OK.
  1448.     If a <1 the font wasn't on the disk or already in memory.
  1449.  
  1450.  
  1451.  
  1452.        Since this routine is designed to always try to scale the sel-
  1453.     ected font with a best match, it may return true even though  the
  1454.     requested  font wasn't available. Say you try to load diamond/10,
  1455.     (which doesn't  exist) then diamond/12 will be loaded instead.
  1456. ++  Note that above ("designed fonts") may differ  a bit depending on
  1457. ++  which diskfont.library you have. A nice feature of diskfont  V36+
  1458. ++  is that you may specify a  full path  for the  fontname and  thus
  1459. ++  don't have to have the font located in fonts:. Always make use of
  1460. ++  V36+ routines if you can..  To bad for those who haven't upgraded
  1461. ++  but they probably will :)
  1462.  
  1463.  
  1464.  
  1465. *-  Lcrypt - Encode a buffer containing data.
  1466. *-  Lcrypt START,LONGS,"password"
  1467.  
  1468. *-  where
  1469.  
  1470. *-     START is the startaddress of a bank and LONGS  is  the  length
  1471. *-  divided by four. Fx LONGS=Length(10)/4. "password" is your secret
  1472. *-  code  which  also  is used to DEcode your data later. Please note
  1473. *-  that an error will be produced if the password  is  less  than  4
  1474. *-  characters long. Also note that the password is casesensitive!
  1475.  
  1476.  
  1477.  
  1478.  
  1479. *-  Ldecrypt - Decode a buffer containing coded data.
  1480. *-  Ldecrypt START,LONGS,"password"
  1481.  
  1482. *-  See above for more information.
  1483.  
  1484.  
  1485. *-  A word about cryptation :
  1486.  
  1487. *-     Using crypted data on a computer (or anywhere)  is  never  100
  1488. *-  percent  safe.  If  somebody  really wants to decode your data he
  1489. *-  will simply load  his  favorite   monitor  and  single-step  your
  1490. *-  program  at  machine-level  until he finds either the code or the
  1491. *-  decoded data itself. This however demands quite  some  skill  and
  1492. *-  patience  and  can be very time consuming. Data coded with Lcrypt
  1493. *-  uses quite a simple formula which easily can be picked up in  the
  1494. *-  code, however, even though the algorithm is know there a millions
  1495. *-  of  combinations  that  have    to be tried if the password isn't
  1496. *-  known. There  are  about  4300  millions  of  different   combin-
  1497. *-  ations...  To make your code VERY hard to crack try to follow any
  1498. *-  (or more) of these steps.
  1499.  
  1500. *-  1) Use non-visable  codes as  password (linefeed, tab etc.
  1501. *-  etc.)
  1502.  
  1503. *-  2) Don't type  the password like A$="MyPassword". This can
  1504. *-  easily be spotted in the code. Try using Data's reading them with
  1505. *-  an  special  offset  (use each third char or something)
  1506.  
  1507. *-  3) If you HAVE typed your code directly in the source you could
  1508. *-  always do something like A$=A$-" "-"a"-"M" which makes it very
  1509. *-  much harder for a "single-stepper"-cracker to follow at machine-
  1510. *-  level.
  1511.  
  1512. *-  4) First code half your  bank with one password, the other half
  1513. *-  with another and then code the whole bank with a third.
  1514.  
  1515. *-  5) Code Powerpacked files or Powerpack your coded files.
  1516.  
  1517. *-  6) If not compiled, lock the procedure containing the code and
  1518. *-  decryption part.
  1519.  
  1520. *-     Normally you wont have to take any of these steps, most people
  1521. *-  haven't got the  skill  or  the  time  to  mess  around  in  your
  1522. *-  programs...
  1523.  
  1524.  
  1525.  
  1526.  
  1527. *-  Lset Var - Assign a value to a global environmentvariable.
  1528. *-  T=LSet Var("Name","VALUE")
  1529.  
  1530. *-  THIS FUNCTION REQUIRES Release 2.
  1531.  
  1532. *-  where
  1533.  
  1534. *-     "Name" is the  name  of  the  variable  (must  not  exceed  50
  1535. *-  characters)  and  "VALUE"  is  a  ASCII-string  containing either
  1536. *-  digits or text. The value-string must not exceed  50  characters.
  1537. *-  This  function  will  return  true  if  successful.  Name  of the
  1538. *-  variable is not case-sensitive.
  1539.  
  1540.  
  1541.  
  1542. *-  Lget Var - Get the value from a global environmentvariable.
  1543. *-  A$=Lget Var("Name")
  1544.  
  1545. *-  THIS FUNCTION REQUIRES Release 2.
  1546.  
  1547. *-  where
  1548.  
  1549. *-     A$ either contains the value (or text) or is empty. If  A$  is
  1550. *-  empty  the  variable  didn't  exist.  Name of the variable is not
  1551. *-  case-sensitive.
  1552.  
  1553.  
  1554.  
  1555. *-  Ldelete Var - Remove a global environmentvariable from memory.
  1556. *-  T=Ldelete Var("Name")
  1557.  
  1558. *-  THIS FUNCTION REQUIRES Release 2.
  1559. *-  where
  1560.  
  1561. *-     T will be true if a variable with the name  "Name"  was  found
  1562. *-  and removed. If T is zero the variable didn't exist.
  1563.  
  1564.  
  1565.  
  1566. *-  Lansi - Convert ANSI-sequences to AMOS's format.
  1567. *-  S$=Lansi(A$)
  1568.  
  1569. *-  where
  1570.  
  1571. *-     S$ will contain a sequence containing AMOS control characters.
  1572. *-  A$ is a normal ANSI-sequence which doesn't have to be complete if
  1573. *-  the rest of the sequence follow in the next call(s).
  1574.  
  1575. *-  Currently supported ANSI controlcodes :
  1576.  
  1577.  
  1578. *-  ANSI-sequence RESULT
  1579. *-  ------------- ------
  1580. *-  $C (*)        Clw/Home
  1581. *-  ESC[n;n;n;nm  Style,  foreground or   background.  Lansi  detects
  1582. *-                if  style or colour is to be changed. It  is  legal
  1583. *-                to   omit  any  of  the  parameters  as long as you
  1584. *-                specify at least one, and end the sequence with  m.
  1585. *-                Supported styles are: Italics (shaded), Inverse and
  1586. *-                Underline,  other styles are simply ignored. Please
  1587. *-                note  that  changing  from  one  style  to  another
  1588. *-                doesn't  turn  off the last used style. To reset to
  1589. *-                pen-colour 1, background-colour 0 and no style, use
  1590. *-                ESC[0m.
  1591. *-  ESC[0         Cursor invisible, ignored
  1592. *-  ESC[0 p       Cursor visible, ignored
  1593. *-  ESC[xA        Cursor up x lines. x may be omitted.
  1594. *-  ESC[xB        Cursor down x lines. x may be omitted
  1595. *-  ESC[xC        Cursor right x columns. x may be omitted.
  1596. *-  ESC[xD        Cursor left x columns. x may be omitted.
  1597. *-  ESC[y;xH      Locate x,y. y may be omitted.
  1598. *-  ESC[x@        Insert x spaces. x may be omitted.
  1599. *-  ESC[L         Insert line.
  1600. *-  $a            Linefeed. Passed on to AMOS.
  1601. *-  $d            Carrige return. Passed on to AMOS.
  1602. *-  $8            Backspace. passed on to AMOS.
  1603. *-  ESC[2J        Clw. To my knowledge it isn't possible to  support
  1604. *-                "Clear  window at cursor" so even if only ESC[J is
  1605. *-                printed the whole window is cleared.
  1606. *-  ESC[K        Clear line at cursor.
  1607. *-  ESC[M        Clear line.
  1608.  
  1609. *-     (*) $C really isn't a ANSI-code but is  supported  since  many
  1610. *-  BBS-programs (and AmigaDOS + others) use this.
  1611.  
  1612. *-  How it works:
  1613.  
  1614. *-     The Lansi-routine is a 'smart'  routine  which  remembers  old
  1615. *-  incomplete  sequences  and  codes. This means that you may 'Print
  1616. *-  Lansi("ESC[0");' (ESC means Chr$(27)) and nothing  is  output  on
  1617. *-  the    screen!    If   you  directly  afterwards  execute  'Print
  1618. *-  Lansi("m");' a string which resets  style  and  colours  will  be
  1619. *-  printed (it isn't visible). Lansi doesn't buffer the actual ANSI-
  1620. *-  sequence  but rather store datas in its own format and it is thus
  1621. *-  very important that the ANSI-sequence is valid since Lansi  can't
  1622. *-  'go  back  and  check'.  The  most  important  thing in the ANSI-
  1623. *-  sequence is the sequence-terminator,  like "m"  for  colour/style
  1624. *-  or @ for insert etc. Lansi will happily collect  and convert data
  1625. *-  until  a  sequence-terminator  is  received and return nothing to
  1626. *-  AMOS if it isn't received. This may result in lost characters  if
  1627. *-  no valid sequence-terminator is sent.
  1628.  
  1629. *-  Speed & Problems:
  1630.  
  1631. *-     I have tried to make the Lansi-routine as fast as possible and
  1632. *-  this have resulted in TOTALLY unstructured code, more labels than
  1633. *-  a grown up man can count and  repeated  codesections  instead  of
  1634. *-  slower/more  general subroutines. Because of the many sections in
  1635. *-  the  code  which  writes  to  a  temporary  destination  it    is
  1636. *-  (currently)  almost  impossible to add an effective routine which
  1637. *-  checks for overflow. This means that you  must  be  very  careful
  1638. *-  when  using  Lansi with files with very long lines. Programs like
  1639. *-  DiEd (ANSI-editor) may  output an animation  which  is  one  line
  1640. *-  'long'  and  over  10 kb big! Lansi has  no way to figure out how
  1641. *-  big the finished string will be.  The  internal  buffer  used  by
  1642. *-  Lansi  is  2000  bytes  big  so  in  general  lines up to 400-500
  1643. *-  characters is ok. Sometimes the resulting string is shorter  than
  1644. *-  the  ANSI-sequence but I have still not added support for repeat$
  1645. *-  so the ANSI-sequence ESC[99A will evaluate to 99  bytes.  I  will
  1646. *-  look into the possibility of making use of repeat$ later on. Right
  1647. *-  now  I'm more than happy that this routine just works :-) (I know
  1648. *-  that anybody who has tried to write ANSI-emulation  know  what  I
  1649. *-  mean...)
  1650.  
  1651. *-     Now, what do you gain on my sloppy and unnecessary large code?
  1652. *-  I made a comparison  between typing an animationfile in Shell and
  1653. *-  printing it using Lansi in AMOS. Both routines used a  4  colour-
  1654. *-  screen.  The  file  I tested with was Per-Anim_Animation which is
  1655. *-  included with DiEd by Per Raue. The file is 11760 bytes long  and
  1656. *-  mostly  contains  movementsequences  and  about  a half screen of
  1657. *-  text. I was equipped with some fastmem, an AdSpeed and a fast  HD
  1658. *-  in both tests.
  1659.  
  1660. *-  Type Per-Anim_Animation       took: 09.52
  1661. *-  Type >NIL: Per-Anim_Animation took: 02.46
  1662.                                   -----------
  1663. *-  Actual time excluding loading       07.06
  1664.  
  1665. *-  Lansi with output    took: 02.02
  1666. *-  Lansi without output took: 00.76
  1667.  
  1668. *-  Please  note that these  figures may  have  changed since you got
  1669. *-  Ldos  since I'm  still changing  in this  part of the code. I now
  1670. *-  also have an A3000/25 to test with :-)
  1671.  
  1672. *-     Both Lansi-testroutines used Lset Eoln and Lstr to  split  the
  1673. *-  file  into  1357 lines (every cursor movement). Lansi gained some
  1674. *-  hundreds of seconds since it didn't need to process bold, on  the
  1675. *-  other  hand  it  had to split (and load from HD) the file in 1357
  1676. *-  lines, allocate stringmemory  etc. The time  was  measured  using
  1677. *-  'Timer'  in  AMOS and the timingfunction in Csh. The AMOS-program
  1678. *-  was run uncompiled.
  1679.  
  1680.  
  1681.  
  1682.  
  1683.  
  1684.                        PART SEVEN - ARexx control
  1685.                        ----------   -------------
  1686.  
  1687.     Please note! ALL STRINGS PASSED ON TO ANY Rexx-commands MUST BE
  1688.     NULL-TERMINATED: A$=A$+Chr$(0)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1689.  
  1690.  
  1691.     ("LRexx" in this part applies to all ARexx-commands)
  1692.  
  1693.        LRexx is an AMOS-interface to the library rexxhost. LRexx will
  1694.     let you set up an ARexx-port and  execute  an  ARexx-script.  Any
  1695.     other program may use the port created by LRexx to send commands.
  1696.     LRexx  will  also  take  care  of  some  things for you, like de-
  1697.     allocating replies from the ARexx-server automatically  etc. etc.
  1698.     In  general,  you  don't have to bother with what's going on. You
  1699.     just  have to get messages,   process  them and then reply to the
  1700.     server.
  1701.  
  1702.        To use LRexx you need the complete ARexx-package (supplied  in
  1703.      Release 2) and the library rexxhost.library located in libs: You
  1704.     will  also  need  some  knowledge  about ARexx, understanding how
  1705.     messages are sent from an ARexx-script and knowing how to get/set
  1706.     resultcodes.
  1707.  
  1708. ++  Using ARexx on the Amiga by Abacus,is HIGHLY recommended! Authors
  1709. ++  are Chris,  Zamara  and Nick, Sullivan. ISBN 1-55755-114-6 ($35).
  1710. ++  This  book is much  better than  the  original  ARexx-manuals and
  1711. ++  comes with a free disk with lot of examples.
  1712.  
  1713.  
  1714.        NOTE! If you run from WB2.x you MUST  use  Loadlib  (supplied)
  1715.     to load rexxhost.library into memory. Kickstart2.x simply refuses
  1716.     to  open  rexxhost.library..  WHY?  I  don't  know!  A  few other
  1717.     libraries that  I got shows the same  symptoms.  Under  Kickstart
  1718.     1.3  you won't need to use LoadLib. LRexx (and AMOS when LRexx is
  1719.     installed)  will  refuse  to  boot  if  it  is  unable  to   open
  1720.     rexxhost.library.
  1721. *-  Removed this stupid thing in V2. AMOS now boot correctly  even if
  1722. *-  rexxhost.library couldn't be opened.
  1723. ++  V37+ version of rexxhost opens just fine. Throw away Loadlib!
  1724.  
  1725.  
  1726.  
  1727.     LRexx Make Host - Create an ARexx host (port)
  1728.     FAIL=LRexx Make Host("Name")
  1729.  
  1730.     where
  1731.  
  1732.        FAIL will differ from zero it the port was added.  (FAIL  will
  1733.     contain  a pointer to the port-structure). If FAIL equals to zero
  1734.     LRexx was unable to create the port, probably due to another port
  1735.     already existed with the same name.
  1736.  
  1737.  
  1738.  
  1739.     LRexx Remove Host - Remove an ARexx host (port)
  1740.     LRexx Remove
  1741.  
  1742.  
  1743.  
  1744.     LRexx Get Msg - Get a message from another host or script.
  1745.     A$=LRexx Get Msg(WAIT)
  1746.  
  1747.     where
  1748.  
  1749.        A$ will contain the message (see below)  or  be  empty  if  no
  1750.     message  was  available.  If  WAIT equals to 1 LRexx Get Msg will
  1751.     wait until a  message is received and control won't  be  returned
  1752.     to AMOS until a message is received.
  1753.  
  1754.        If A$ equals to "LRexx0" it  means  that  the  started  script
  1755.     reached  the  end.  This  message  can NOT be replied to since it
  1756.     actually is an answer from the Rexx-server that the script ended.
  1757.     LRexx will de-allocate this reply automatically. If you know that
  1758.     you successfully have started a script (see  LRexx  Execute)  you
  1759.     may  safely  call  LRexx  Get Msg with WAIT set to 1 since LRexx0
  1760.     always will be returned even  if  no  other  commands  are  sent.
  1761.     However, if your  script has failed and you call with WAIT set to
  1762.     1,  AMOS may be locked forever! Please use WAIT in a sensible way
  1763.     If your program goes to "sleep" WAIT is ideal to use.
  1764. ++  "Locked forever" made some of you upset :) Well, you program will
  1765. ++  be locked until a command is sent to your host. Best way  in AMOS
  1766. ++  (if you wish to sleep but be able to react on other things) is to
  1767. ++  use WAIT=0 in a mainloop which HEAVILY calls Multi Wait and  also
  1768. ++  checks keyboard and other things. This method isn't the best in a
  1769. ++  multitasking system, but if you call Multi Wait a couple of times
  1770. ++  in your main loop,nobody will notice the difference. To bad  AMOS
  1771. ++  never was designed like other programs... :-(((
  1772.  
  1773.  
  1774.  
  1775.     LRexx Execute - Execute an ARexx-program
  1776.     A=LRexx Execute("Name")
  1777.  
  1778.     where
  1779.  
  1780.         A  will  be  true  if  the  program  was  found  and  started
  1781.     successfully.  Name  is the full path and name of the scriptfile.
  1782.     NOTE that "Name" MUST be NULL-terminated (A$="Name"+Chr$(0))
  1783.  
  1784.  
  1785.  
  1786.     LRexx Send Msg - Send a command to another host (port) directly
  1787.     A$=LRexx Send Msg("Host-name","Message",RESULT)
  1788.  
  1789.     where
  1790.  
  1791.        A$ will contain the result returned by the host you addressed.
  1792.     If RESULT is set to zero A$ will always be empty. "Host-name"  is
  1793.     the  name  of  the  host that you wish to pass on the command to.
  1794.     "Message" may contain any valid command that the application that
  1795.     you address understand. Note that Host-name and Message  MUST  be
  1796.     NULL-terminated!! Also note that control isn't returned until the
  1797.     application has executed (and replied to) the sent command.
  1798.  
  1799.  
  1800.  
  1801.     LRexx Reply - Tell ARexx you are ready processing the last
  1802.                   message and want to prepare for the next.
  1803.     LRexx Reply "String",Result1,Result2
  1804.  
  1805.     where
  1806.  
  1807.        "String" may be any result/string you wish to return to ARexx.
  1808.     Result1 and Result2 are the results  to be returned.  (Result1 ==
  1809.     rc) Note that you can not  use  LRexx  Get  Msg  until  you  have
  1810.     replied  to the previous message using LRexx Reply. Do NOT try to
  1811.     reply to a message which contains the string "LRexx0" (see above)
  1812.  
  1813.  
  1814.  
  1815.     LRexx Result1 - Get the value from rm_Result1
  1816.     A=LRexx Result1
  1817.  
  1818.     where
  1819.  
  1820.     A will hold the returncode of the last message.
  1821.  
  1822.  
  1823.  
  1824.     LRexx Result2 - Get the second result.
  1825.  
  1826.     see above
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.                     PART EIGHT - Errorcodes
  1833.                     -----------------------
  1834.        As mentioned before,  errorhandling  isn't  perfect,  but  I'm
  1835.     working on it!
  1836.  
  1837.  
  1838.     Ldos Errorcodes :
  1839.  
  1840.     # Description
  1841.     - -----------
  1842.     0 Invalid Channel = Channel not >0 and <4
  1843.     1 LFile already assigned to channel = Channel not free for use
  1844.     2 LFile not found = File didn't exist
  1845.     3 Invalid filename = To long or short filename or file/dir didn't
  1846.       exist (used by some commands because I felt it was unecessary to
  1847.       implement even more errorcodes. See docs for some of the commands)
  1848.     4 Examine failed = Some files can't be locked. May be busy
  1849.       while another program is writing to it or even creating it!!
  1850.     5 Invalid comment = To long or short comment (MAX 79 characters)
  1851.     6 Unable to set protectionflags = See 4. May be diskerror
  1852.     7 No more entries in this dir = Lcat First wasn't a directory or
  1853.       you keep on calling Lcat Next after it has returned an empty
  1854.       string.
  1855.     8 Start is greater than max limit = Oops, check your addresses
  1856.       in Lstr-calls. Otherwise your string will be as long as all
  1857.       your memory installed.
  1858.     9 Device already open = Use Ldevice Close before opening a new
  1859.       device.
  1860.     10 Device not open = LDevice Open may have failed, or you have
  1861.        closed the device.
  1862.     11 Unable to open diskfont.library = diskfont.library MUST be in
  1863.        libs: on the boot-disk (SYS:) in order to use Ldisk Font (also
  1864.        required by AMOS Get Fonts)
  1865.     12 Host not created = Rexxhost.lib has been expunged or a host
  1866.        with the same name already exists. (LREXX)
  1867.     13 Old message not replied! = You tried to read the next message
  1868.        before the last was replied to. (LREXX)
  1869.     14 No message to reply to! = You replied to a already replied
  1870.        message. (LREXX)
  1871. *-  15 You need dos.library 37+ = You tried to use a command which
  1872. *-     need a higher version of this library (Kickstart 2.0-only)
  1873. *-  16 "To long pattern/overflow/or no pattern" = Either you used a
  1874. *-     wildcard which actually doesn't contain any wildcards, or you
  1875. *-     used a pattern >100 chars, or there was a bufferoverflow in
  1876. *-     the dos.library
  1877. *-  17 Password to short. Lcrypt requires at least for chars as pass-
  1878. *-     word. (This is not because of the algorithm, but for your own
  1879. *-     safety)
  1880. *-  18 You can not call with an empty argument = This command req-
  1881. *-     uires that you do not supply an "empty" argument such as ""
  1882. *-     or zero.
  1883. *-  19 Stop is greater than start = Think twice when using Lback Hunt
  1884. *-     since START actually is greater than STOP.
  1885. *-  20 No more devices in system! = Stop calling Ldev Next when it has
  1886. *-     returned an empty string.
  1887. *-  21 Not enough words in string! = You tried to extract a word with
  1888. *-     Lword which didn't exist. Use Lwords to find out how many words
  1889. *-     the string contains.
  1890. ++  22 LLdir$ can't find directory! = You tried to change the current
  1891. ++     directory to something that didn't exist.
  1892. ++  23 Command need NULL-terminated string! = You forgot to add Chr$(0)
  1893. ++     to a string before you called a command which doesn't terminate
  1894. ++     the string itself (saves both space and time).
  1895. ++  24 Missing part of ARexx (lib/server) = rexxhost can't work if it
  1896. ++     can't find rexx*-libs and the server running. This error will
  1897. ++     ONLY be generated when you call Lrexx Make Host so you should ALWAYS
  1898. ++     try to make a port (host) before you try any of the other Lrexx-
  1899. ++     commands 
  1900.  
  1901.  
  1902.        All LDos errors are trapable so there is  no  excuse  for  not
  1903.     providing your programs with an errorhandling-routine.
  1904.  
  1905.  
  1906.  
  1907.  
  1908.                PART NINE       -       Disclaimer
  1909.                ----------              ----------
  1910.  
  1911.  
  1912.        Even though I have tested Ldos as much as possible  there  may
  1913.     be  some  bugs  left. Many of the Ldos-commands involve access to
  1914.     dos and are naturally dangerous to misuse. Ldos handles most kind
  1915.     of errors, but I have skipped some checking in order to make  the
  1916.     code  smaller and some functions faster. Because of this Ldos can
  1917.     crasch if you  try  to  call  some  functions with  totally  wild
  1918.     arguments.  For example Ldisk Font, Lset Comment etc. will behave
  1919.     very strange if you call with an empty string as  argument  (now,
  1920.     why would anybody want to do that?). If you use Ldos under normal
  1921.     circumstances calling with valid parameters it should be stable.
  1922.  
  1923.  
  1924.     If you use Ldos it is understood that :
  1925.  
  1926.  
  1927.     o You can not hold me responsible for any kind of damage like
  1928.       lost file or crashed disks.
  1929.     o You are using it on your own risk.
  1930.     o If you like to use LDos in a commercial product you should
  1931.       contact me first.
  1932.     o If you use it in a Shareware-program (or anything like that)
  1933.       I would like to receive a registered copy of your program.
  1934.       This won't cost you more than a disk and a stamp.
  1935.     o If you are using LDos in Licensware-programs I would also like
  1936.        to receive a copy of the program.
  1937.     o LDos may not be sold for money.
  1938. ++  Yack! This must be the largest bugs of all!! This text was included
  1939. ++  in V1 of Ldos. Of course registered users will have FULL rights to
  1940. ++  use Ldos/Lserial in any way. OF COURSE I do not require that you
  1941. ++  should send SW/LW-programs to me. Please forgive me for missing this
  1942. ++  part when I released the manual for 2.0/2.1!!
  1943.  
  1944.  
  1945.  
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.     HINTS AND TIPS FOR USING LDOS
  1960.     -----------------------------
  1961.  
  1962.  
  1963.        If you find the protection-bits hard to handle  when  four  of
  1964.     the  bits  are  active  high  and  four are active low you can do
  1965.     something like the following to make all bits active high :
  1966.  
  1967.  
  1968.  
  1969.         B=Lget Prot("FileName")
  1970.         T=B and %11110000
  1971.         B=Not(B and %1111)
  1972.         T=T or(B and %1111)
  1973.  
  1974.  
  1975.  
  1976.        all flags are now active high. Do not forget  to  switch  back
  1977.     before you use Lset Prot
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.        After using Lfilter on a wide range (lets say  from  a-z)  you
  1984.     shall  use Lskip to determine the next start-address which hasn't
  1985.     been filtered and swapped. Example :
  1986.  
  1987.     Lfilter Asc("a"),Asc("z"),10,START To END
  1988.  
  1989.        Since there will be a  LOT  of  empty  lines  (all  lower-case
  1990.     characters   will  become  linefeed)  Lstr  may  take  a  lot  of
  1991.     unnecessary time only fetching empty lines.
  1992.  
  1993.  
  1994.  
  1995.        You should then use :
  1996.  
  1997.     Lskip 10,START To STOP
  1998.  
  1999.        to obtain the next address not containing a linefeed.
  2000.  
  2001.  
  2002.  
  2003. ++     If Lload/Lstr gives you a hard time,try these procedures (they
  2004. ++  will only work with one file at the time though):
  2005.  
  2006. Set Buffer 10
  2007. ' Dedicated to Andy Whitely who thought Lload and Lstr was a bit  
  2008. ' rough to use, and Line Input much to slow. Using these two procedures  
  2009. ' You can 'emulate' AMOS's Line Input-command. To use it you must
  2010. ' have LINESTART, LINESTOP (buffer "cursors"), SIZE (load-buffer given 
  2011. ' in Kb), FEOF (internal procedure variable), CHAN (the channel you
  2012. ' wish to use) and RAD$ (where the read line is placed) GLOBAL!  
  2013. '
  2014. ' To use these procedures, simply: 
  2015. ' a) Set CHAN to a number between one and three
  2016. ' b) Set SIZE to desired size. 4-8 Kb is enoough in most cases 
  2017. ' c0)Set Lset Eoln To desired value (normally 10)
  2018. ' c) Call _LINEOPEN with the filename
  2019. ' d) Check Param for errors
  2020. ' e) Call _LINEINPUT in a loop, until Param is false.
  2021. '
  2022. ' RAD$ will hold your read line. The procedure automatically calls 
  2023. ' Free every time the buffer is re-filled (ie. another block is
  2024. ' loaded) to prevent AMOS from crashing due to garbage collection. 
  2025. '
  2026. ' Please note that these procedures erase and use buffer 8 (you might
  2027. ' want to change that) and can't handle multiple files (unless you 
  2028. ' re-write the routines :) 
  2029. '
  2030. ' Have fun with AMOS!
  2031. '
  2032. Global LINESTART,LINESTOP
  2033. Global CHAN,RAD$,FEOF,SIZE
  2034. '
  2035. '
  2036. Screen Open 1,640,256,2,Hires : Paper 0 : Clw 
  2037. '
  2038. CHAN=3 : Rem These you need to init 
  2039. SIZE=4
  2040. Lset Eoln 10
  2041. '
  2042. '---- Open a file for _Lineinput. CHAN is set to 3, buffer 4Kb.
  2043. Proc _LINEOPEN["df0:docs/LdosV21.doc"]
  2044. If Not Param
  2045.    Print "Error opening file!"
  2046.    End 
  2047. End If 
  2048. Do 
  2049.    Proc _LINEINPUT
  2050.    Exit If Not Param : Rem End of file
  2051.    '   Print RAD$ : Rem Wait Key      
  2052. Loop 
  2053. Lclose CHAN
  2054. '
  2055. '
  2056. Procedure _LINEINPUT
  2057.    If LINESTART>=LINESTOP : Rem Do we need to re-fill the buffer?
  2058.       If Not FEOF         : Rem first check if end of file
  2059.          Gosub _LOAD
  2060.       Else 
  2061.          SUC=False        : Rem End of file & buffer reached, return FALSE
  2062.          Goto SLUT2
  2063.       End If 
  2064.    End If 
  2065.    '
  2066.    RAD$=Lstr(LINESTART To LINESTOP)
  2067.    LINESTART=LINESTART+Len(RAD$)+1
  2068.    If(LINESTART>=LINESTOP) and Not(FEOF) and(Peek(LINESTOP)<>10)
  2069.       Gosub _LOAD             : Rem A line may be splitted and we should thus
  2070.       D$=Lstr(LINESTART To LINESTOP): Rem pick up the rest by re-filling buffer
  2071.       LINESTART=LINESTART+Len(D$)+1 : RAD$=RAD$+D$
  2072.    End If 
  2073.    SUC=True
  2074.    Goto SLUT2
  2075.    '
  2076.    _LOAD:
  2077.    DUMMY=Free          : Rem While doing heavy string usage, ALWAYS call Free!
  2078.    LINESTART=Start(8)
  2079.    A=Lload(CHAN,LINESTART,SIZE*1024)
  2080.    If A<SIZE*1024
  2081.       LINESTOP=LINESTART+A : Rem If we didn't get as may chars as we
  2082.       FEOF=True            : Rem requested, we reached end of file.
  2083.    End If 
  2084.    Return 
  2085.    SLUT2:
  2086. End Proc[SUC]
  2087.  
  2088. ' You MUST use this procedure to open the file!
  2089. Procedure _LINEOPEN[F$]
  2090.    FEOF=False
  2091.    Erase 8 : Reserve As Work 8,SIZE*1024 : Rem x Kb buffer
  2092.    LINESTART=Start(8)
  2093.    LINESTOP=LINESTART+SIZE*1024
  2094.    If Not Exist(F$)
  2095.       Goto SLUT
  2096.    Else 
  2097.       If Lfile Type(F$)>0 : Rem Directory won't be easy to read :-)
  2098.          Goto SLUT
  2099.       End If 
  2100.    End If 
  2101.    SUC=True
  2102.    If Lsize(F$)<1 : Rem Zero files are of no use to us because
  2103.       SUC=False   : Rem there are nothing to "LineInput"!
  2104.    End If 
  2105.    Lopen CHAN,F$,0
  2106.    A=Lload(CHAN,LINESTART,SIZE*1024) : Rem Load first block
  2107.    If A<SIZE*1024
  2108.       LINESTOP=LINESTART+A
  2109.       FEOF=True
  2110.    End If 
  2111.    SLUT:
  2112. End Proc[SUC]
  2113.  
  2114. Procedure _LPOF[POS]
  2115.    ' Can be used a AMOS Pof() 
  2116.    ' If POS is <0 the current position is returned and no movement takes place
  2117.    A=Lseek(CHAN,POS)
  2118.    If POS<0                    : Rem Current position requested
  2119.       A=A+(LINESTART-LINESTOP) : Rem Don't forget we have data in the buffer
  2120.    EndIf                       : Rem and POS is actually file-pos + bufferpos!
  2121.    LINESTART=LINESTOP+10       : Rem Force buffer to reload at next call!
  2122. End Proc[A]
  2123.  
  2124. ++     See, it isn't that  hard.  Even though these  procedures keeps
  2125. ++  track of a lot, they  are reasonably fast.  About 100K/sec  on my
  2126. ++  machine. If you try to load files which AMOS has created and con-
  2127. ++  tains that silly Chr$(13), you might want to modify _LINEINPUT to
  2128. ++  "SLUT2:
  2129. ++   RAD$=RAD$-Chr$(13)"
  2130.  
  2131.  
  2132.  
  2133.        If you have problems with strange gurus  or  AMOS  locking  up
  2134.     please  try to increase your stringbuffer and call D=Free once in
  2135.     a while.  AMOS  seems  to  have  problems  to  determine  when  a
  2136.     garbagecollection is to be performed.
  2137.  
  2138.  
  2139.  
  2140.  
  2141.     Please send suggestions and bugreports to :
  2142.  
  2143.     Niklas Sjöberg
  2144.     Karolineborgsv. 8
  2145.     S-302 41 Halmstad
  2146.     SWEDEN
  2147.  
  2148.     or
  2149.  
  2150.     2:203/415.3@Fidonet (Address to Sjoberg, NOT Sjöberg)
  2151.     PLEASE: DO NOT USE THE PHONE!! See IMPORTANT.TXT!!
  2152.  
  2153.  
  2154.  
  2155.                              AKNOWLEDGEMENTS
  2156.                              ---------------
  2157.  
  2158.     From Req.doc:
  2159.  
  2160.     "  The req.library is a  run  time  re-entrant  library  that is
  2161.     designed  to make it easier for programmers to use powerful, easy
  2162.     to use requesters for communicating  with  users.  The  requester
  2163.     library  includes  such  functions  as  a  color  requester, file
  2164.     requester, message display requester and many functions  to  make
  2165.     the creation of gadgets for your own custom requesters easier.
  2166.  
  2167.        Req.library was written by Colin Fox (of Pyramyd Designs)  and
  2168.     Bruce  Dawson  (of  CygnusSoft Software). Req.library is a freely
  2169.     distributable library that may be  used  in  commercial  products
  2170.     without  paying  any  royalties.  We  encourage  you  to  use the
  2171.     requester library in all of your programs, to make them easier to
  2172.     write, and to use."
  2173.  
  2174.     From Rexxhost.doc:
  2175.     "
  2176.     ============================== Credits ===============================
  2177.     ======================================================================
  2178.        rexxhost.library was built from example  source  code  written
  2179.     by Gary Samad & Bill Hawes (fancydemo.c), extensions & additional
  2180.     functions were created by Olaf 'Olsen' Barthel.
  2181.  
  2182.        The entire contents of this library package may  be  used  for
  2183.     any  purpose,  no regard whether commercial or non-commercial. No
  2184.     credit must be given to the creator, nor must a registration  fee
  2185.     be paid (though I wouldn't mind if anybody did).
  2186.  
  2187.                       THIS IS TRULY PUBLIC DOMAIN!
  2188.  
  2189.     =============================== Author ===============================
  2190.     ======================================================================
  2191.  
  2192.                         Olaf 'Olsen' Barthel, MXM
  2193.                             Brabeckstrasse 35
  2194.                            D-3000 Hannover 71
  2195.  
  2196.                        Federal Republic of Germany"
  2197.  
  2198.  
  2199.  
  2200. Soft- and hardware used when developing Ldos :
  2201.  
  2202. Amiga 2000 with AdSpeed (version 1)
  2203. Amiga 3000 25 Mhz       (version 2-)
  2204. AMOS 1.34
  2205. TextPlus3.0 for formatting text
  2206. CygnusEd    for writing text
  2207. DME         for quickrefs in Autodocs/include
  2208. DevPac 3    680x0 assembler
  2209. PowerPacker for testing Ppdecrunch
  2210. Died        (ANSI-editor and animator, for testing Lansi)
  2211.  
  2212. and heavy usage of MonAm :-)
  2213.  
  2214.