home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / mg2a / part12 < prev    next >
Encoding:
Text File  |  1989-02-03  |  58.3 KB  |  2,433 lines

  1. Path: xanth!mcnc!ncsuvx!lll-winken!lll-tis!ames!necntc!ncoast!allbery
  2. From: BLARSON@ECLA.USC.EDU (Bob Larson)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i036: mg 2a part 12 of 15
  5. Message-ID: <12401301117.47.BLARSON@ECLA.USC.EDU>
  6. Date: 26 May 88 05:01:37 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: BLARSON@ECLA.USC.EDU (Bob Larson)
  9. Lines: 2420
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. comp.sources.misc: Volume 3, Issue 36
  13. Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU>
  14. Archive-Name: mg2a/Part12
  15.  
  16. #    This is a shell archive.
  17. #    Remove everything above and including the cut line.
  18. #    Then run the rest of the file through sh.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar:    Shell Archiver
  22. #    Run the following text with /bin/sh to create:
  23. #    sys/atari/readme.1st
  24. #    sys/atari/alloc.c
  25. #    sys/atari/build.g
  26. #    sys/atari/cinfo.c
  27. #    sys/atari/diredsup.c
  28. #    sys/atari/fileio.c
  29. #    sys/atari/gemstart.s
  30. #    sys/atari/getn.s
  31. #    sys/atari/makesys.mwc
  32. #    sys/atari/mg.ini
  33. #    sys/atari/mglink.inp
  34. #    sys/atari/misc.c
  35. #    sys/atari/sysdef.h
  36. #    sys/atari/term.c
  37. #    sys/atari/ttydef.h
  38. #    sys/atari/ttyio.c
  39. #    sys/atari/varargs.h
  40. # This archive created: Mon May 23 18:14:08 1988
  41. # By:    blarson
  42. if test -d sys
  43. then true
  44. else mkdir sys
  45. fi
  46. if test -d sys/atari
  47. then true
  48. else mkdir sys/atari
  49. fi
  50. cat << \SHAR_EOF > sys/atari/readme.1st
  51. This file documents the Atari-specific features of MG2A.  Please refer
  52. to the MG manual and the tutorial for more general information about
  53. how to use MG.
  54.  
  55. This version of MG has been brought to you by....
  56.  
  57.     Sandra Loosemore (sandra@cs.utah.edu, utah-cs!sandra)
  58.     Marion Hakanson (hakanson@cs.orst.edu, orstcs!hakanson)
  59.  
  60.  
  61.  
  62. Keyboard Handling:
  63. ------------------
  64.  
  65. The ALT key acts as the META key.  The command meta-key-mode can be 
  66. used to toggle this behavior.  (On non-US keyboards, the ALT key is 
  67. normally used as a modifier with certain other keys to produce printing 
  68. characters.)
  69.  
  70. MG supports 8-bit characters, although since neither of us have
  71. European keyboards we have not been able to test this thoroughly.
  72.  
  73. The function keys may be bound to commands, although there are no 
  74. default bindings established for these keys.  F1-F10 are as on the 
  75. keyboard, F11-F20 are the shifted F1-F10, and F21-F28 are Help, Undo, 
  76. Insert, Up, Clr/Home, Left, Down, and Right, respectively.
  77.  
  78.  
  79. Startup Files:
  80. --------------
  81.  
  82. MG looks for its startup file first as MG.INI in the current directory,
  83. and it then looks for the file specified by the environment variable
  84. MGINIT if that fails.  The code to look up the environment variables
  85. checks for all of the various environment styles that are supported
  86. by common shells such as the MWC shell and Gulam, as well as the one
  87. built for the desktop by GEMBOOT.
  88.  
  89.  
  90. Spawning a Shell:
  91. -----------------
  92.  
  93. The suspend-emacs command checks the SHELL environment variable to
  94. determine what program to run.  If the environment variable is not
  95. set, or if the attempt to execute the program fails (i.e., the program
  96. is not found), MG will prompt for a command to execute.
  97.  
  98.  
  99. Other Options:
  100. --------------
  101.  
  102. Most of the optional features described in the MG manual are enabled,
  103. including the GOSMACS and DIRED features.  The major piece of missing
  104. functionality is the regular expression code, which is nonportable and
  105. won't compile on the ST.  There is also no support for backup files yet.
  106.  
  107.  
  108. Rebuilding MG:
  109. --------------
  110.  
  111. MG has been developed using both the Alcyon (v4.14) and Mark Williams 
  112. (v2.0) C compilers.  Makefiles (maketop.mwc and makesys.mwc) are provided 
  113. for MWC, and a Gulam shell script (build.g, also mglink.inp) for Alcyon.  
  114. You may need to tweak these files if you have moved things around.
  115.  
  116. Here is a list of the ST-specific source files:
  117.  
  118.     chrdef.h    Character macro definition file
  119.     sysdef.h    ST-specific definitions
  120.     ttydef.h    More ST-specific definitions
  121.     varargs.h       Definitions for varargs macros
  122.     alloc.c        New "malloc" for Alcyon C, also used by MWC.
  123.     cinfo.c        Character functions.
  124.     diredsup.c    Functions to support the "cd" and "dired" features.
  125.     fileio.c    File i/o functions.
  126.     misc.c        Functions to support "spawn", etc.
  127.     term.c        High-level screen manipulation functions.
  128.     ttyio.c        Low-level terminal i/o functions.
  129.     getn.s        Functions to determine screen resolution.
  130.     gemstart.s      Needed for Alcyon C
  131.  
  132.  
  133. Changes since MG1B:
  134. -------------------
  135.  
  136. File and terminal i/o have been completely rewritten to use low-level
  137. GemDOS functions instead of their C equivalents.  It's now much faster.
  138.  
  139. Improved memory management (new implementation of "malloc" and friends
  140. for Alcyon C) makes the "spawn" command more useful.
  141.  
  142. The use of the ALT key as a meta key and support for 8-bit characters is
  143. new.
  144.  
  145. The old "dirlist" function has been replaced by dired mode.
  146.  
  147. Environment variables are now used to specify the startup file and the
  148. shell to run for suspend-emacs.
  149.  
  150. A few minor cleanups and optimizations, some of which speed things
  151. up markedly.
  152.  
  153.  
  154. Bugs
  155. ----
  156.  
  157. There is a bug in TOS that may result in MG creating multiple copies of
  158. files with the same name.  It only seems to happen with very short files.
  159.  
  160. There has been some question raised about the use of the "conterm"
  161. system variable on the "new" (Mega-ST) TOS ROMs, even though such use
  162. is documented in the MWC manual, and elsewhere.  Perhaps someone can
  163. test this code on such a system and let us know if there are problems.
  164. A workaround would be to use Getshifts() separately, instead of having
  165. the kbshift value returned by Bconin().
  166.  
  167. SHAR_EOF
  168. cat << \SHAR_EOF > sys/atari/alloc.c
  169. /* alloc.c -- replacement malloc and friends
  170.  *
  171.  * author :  Sandra Loosemore
  172.  * date   :  24 Oct 1987
  173.  *
  174.  * This file is a replacement for the usual definitions of malloc and free.
  175.  * The ST Malloc routine is called to get more memory from the system.
  176.  * Note that the memory that is Malloc'ed is never Mfree'd.
  177.  *
  178.  */
  179.  
  180.  
  181. #include <osbind.h>
  182. #define NULL 0L
  183.  
  184.  
  185. /* This is the default size for grabbing memory from the system with Malloc.
  186.  *    If you try to malloc a piece bigger than this, it will Malloc a
  187.  *    piece exactly the right size.  Ideally, it should be quite a bit
  188.  *    larger than the average size of things you are allocating (assuming
  189.  *    you are going to allocate lots of them).
  190.  */
  191.  
  192. static long mchunk = 16384L;           /* Size for grabbing memory */
  193.  
  194.  
  195. /* Each call to malloc returns a chunk; freeing it puts the chunk on
  196.  *    the free list.  The "next" field is only used for freed blocks.
  197.  *      The "nbytes" field is the size of the body of the chunk, not
  198.  *    the entire chunk.
  199.  */
  200.  
  201. typedef struct chunk {
  202.     long nbytes;
  203.     union {
  204.         struct chunk *next;
  205.         char body[1];
  206.         } info;
  207.     } CHUNK;
  208.  
  209. #define Nbytes(c) (c)->nbytes
  210. #define Next(c) (c)->info.next
  211. #define Body(c) (c)->info.body
  212.  
  213. static CHUNK *freelist = NULL;
  214.  
  215.  
  216. /* Return a block at least "size" bytes long.  Grab more memory if there
  217.  *     isn't anything on the free list that big.  If the block is just big
  218.  *     enough, remove it from the free list and return the whole thing.
  219.  *    Otherwise, carve a piece off the front.
  220.  * Note that the size is rounded up to make it an even number, and it must
  221.  *    also be at least big enough to hold the next pointer when the block
  222.  *    is freed.
  223.  */
  224.  
  225. char *alloc (size)
  226.     long size;
  227. {   register CHUNK *this, *last, *new;
  228.     long temp;
  229.     size = (size + 1) & 0xfffe;                       /* Word alignment */
  230.     if (size < sizeof(CHUNK *))  size = sizeof(CHUNK *);   /* Minimum size */
  231.     this = freelist;
  232.     last = NULL;
  233.     while (this != NULL)  {
  234.         if (Nbytes(this) >= size)  break;
  235.         last = this;
  236.         this = Next(this);
  237.         }
  238.     if (this == NULL)  {
  239.         temp = ((size < mchunk) ? mchunk : size);
  240.         this = (CHUNK *) Malloc (temp + sizeof(long));
  241.         if (!this)  return(NULL);
  242.         Nbytes(this) = temp;
  243.     free(Body(this));
  244.         this = freelist;
  245.     last = NULL;
  246.     while (this != NULL)  {
  247.             if (Nbytes(this) >= size)  break;
  248.             last = this;
  249.             this = Next(this);
  250.         }
  251.         }
  252.     temp = Nbytes(this) - size - sizeof(long);
  253.     if (temp <= sizeof(CHUNK))  {               /* Use the whole thing */
  254.         if (last)
  255.         Next(last) = Next(this);
  256.     else
  257.         freelist = Next(this);
  258.         return(Body(this));
  259.         }
  260.     else  {                                         /* Grab some off end */
  261.         new = (CHUNK *) ((char *)this + size + sizeof(long));
  262.     Nbytes(new) = temp;
  263.     Next(new) = Next(this);
  264.     if (last)
  265.         Next(last) = new;
  266.     else
  267.         freelist = new;
  268.     Nbytes(this) = size;
  269.     return(Body(this));
  270.         }
  271.     }
  272.  
  273.  
  274.  
  275. /* These are the user-accessible entry points */
  276.  
  277. char *malloc (size)
  278.     unsigned size;
  279. {   return (alloc((long)size));
  280.     }
  281.  
  282. #if 0    /* calloc not used in mg */
  283. char *calloc (number, size)
  284.     unsigned number, size;
  285. {   return (alloc ((long)number*size));
  286.     }
  287. #endif
  288.  
  289. char *realloc (oldptr, newsize)
  290.     register char *oldptr;
  291.     unsigned newsize;
  292. {   long oldsize;
  293.     register char *newptr;
  294.     register unsigned i;
  295.     CHUNK *block;
  296.     block = (CHUNK *) (oldptr - sizeof(long));
  297.     oldsize = Nbytes(block);
  298.     if (newsize > oldsize)  {
  299.         newptr = alloc((long)newsize);
  300.         for (i=0; i<oldsize; i++)
  301.         newptr[i] = oldptr[i];
  302.         free(oldptr);        
  303.     return(newptr);
  304.         }
  305.     else
  306.         return(oldptr);
  307.     }
  308.  
  309.     
  310. /* Free a pointer.  The freelist is maintained in sorted order, so loop
  311.  *    through until we find the block on either side of the one we're
  312.  *    freeing.  Then see if we can merge this block with either one.
  313.  */
  314.  
  315. free (ptr)
  316.     char *ptr;
  317. {   register CHUNK *last, *this, *block;
  318.  
  319.     /* Find where to insert the block in the free list. */
  320.  
  321.     block = (CHUNK *)(ptr - sizeof(long));
  322.     this = freelist;
  323.     last = NULL;
  324.     while (this && (this < block))  {
  325.         last = this;
  326.     this = Next(this);
  327.     }
  328.  
  329.     /* Can we merge it with the next block?  */
  330.  
  331.     if (this && ((ptr + Nbytes(block)) == this))  {
  332.         Nbytes(block) = Nbytes(block) + Nbytes(this) + sizeof(long);
  333.     Next(block) = Next(this);
  334.     }
  335.     else
  336.         Next(block) = this;
  337.  
  338.     /* Can we merge it with the previous block?  */
  339.  
  340.     if (last && ((Body(last) + Nbytes(last)) == block))  {
  341.         Nbytes(last) = Nbytes(last) + Nbytes(block) + sizeof(long);
  342.     Next(last) = Next(block);
  343.         }
  344.     else if (last)
  345.         Next(last) = block;
  346.     else
  347.         freelist = block;
  348.     }
  349.  
  350.  
  351. /* A debug routine to help me make sure that the freelist is compacted
  352.  *    properly.
  353.  */
  354.  
  355. #ifdef DEBUG
  356.  
  357. dumpfree ()
  358. {   CHUNK *junk;
  359.     printf ("Dump of free list:\n");
  360.     junk = freelist;
  361.     while (junk)  {
  362.         printf ("    Base %ld, size %ld\n", (long)(Body(junk)), Nbytes(junk));
  363.     junk = Next(junk);
  364.     }
  365.     }
  366. #endif
  367. SHAR_EOF
  368. cat << \SHAR_EOF > sys/atari/build.g
  369. # build file for MG using Alcyon C and the GULAM shell
  370. # execute this from the directory sys\atari 
  371. #
  372. #
  373. # First make sure that there are stubs for the include files at top level 
  374. cd ..\..  
  375. if { -e chrdef.h } == 0
  376.     echo '#include "sys\atari\chrdef.h"' > chrdef.h
  377.     endif
  378. if { -e sysdef.h } == 0
  379.     echo '#include "sys\atari\sysdef.h"' > sysdef.h
  380.     endif
  381. if { -e ttydef.h } == 0
  382.     echo '#include "sys\atari\ttydef.h"' > ttydef.h
  383.     endif
  384. if { -e varargs.h } == 0
  385.     echo '#include "sys\atari\varargs.h"' > varargs.h
  386.     endif
  387. #
  388. #
  389. # Recompile all the top-level files
  390. #
  391. cc basic
  392. cc buffer
  393. cc dir
  394. cc dired
  395. cc display
  396. cc echo
  397. cc extend
  398. cc file
  399. cc help
  400. cc kbd
  401. cc keymap
  402. cc line
  403. cc macro
  404. cc main
  405. cc match
  406. cc modes
  407. cc paragrap
  408. cc random
  409. cc re_searc
  410. cc regex
  411. cc region
  412. cc search
  413. cc version
  414. cc window
  415. cc word
  416. #
  417. #
  418. # Now do all of the system-specific ones
  419. #
  420. cd sys\atari
  421. cc alloc
  422. cc cinfo
  423. cc diredsup
  424. cc fileio
  425. cc misc
  426. cc term
  427. cc ttyio
  428. as68 -l -u -s c: gemstart.s
  429. as68 -l -u -s c: getn.s
  430. #
  431. #
  432. # Now do the link
  433. #
  434. aln -c mglink.inp
  435. SHAR_EOF
  436. cat << \SHAR_EOF > sys/atari/cinfo.c
  437. /* cinfo.c -- character class tables for the Atari ST 8-bit character set
  438.  *
  439.  * author :  Sandra Loosemore
  440.  * date   :  26 Oct 1987
  441.  *
  442.  */
  443.  
  444. #include    "..\..\def.h"
  445.  
  446. /*
  447.  * This table, indexed by a character drawn
  448.  * from the 256 member character set, is used by my
  449.  * own character type macros to answer questions about the
  450.  * type of a character. It handles the full multinational
  451.  * character set, and lets me ask some questions that the
  452.  * standard "ctype" macros cannot ask.
  453.  */
  454.  
  455. char cinfo[256] = {
  456.     _C,        _C,        _C,        _C,    /* 0x0X */
  457.     _C,        _C,        _C,        _C,
  458.     _C,        _C,        _C,        _C,
  459.     _C,        _C,        _C,        _C,
  460.     _C,        _C,        _C,        _C,    /* 0x1X */
  461.     _C,        _C,        _C,        _C,
  462.     _C,        _C,        _C,        _C,
  463.     _C,        _C,        _C,        _C,
  464.     0,        _P,        0,        0,    /* 0x2X */
  465.     _W,        _W,        0,        _W,
  466.     0,        0,        0,        0,
  467.     0,        0,        _P,        0,
  468.     _W,        _W,        _W,        _W,    /* 0x3X */
  469.     _W,        _W,        _W,        _W,
  470.     _W,        _W,        0,        0,
  471.     0,        0,        0,        _P,
  472.     0,        _U|_W,        _U|_W,        _U|_W,    /* 0x4X */
  473.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  474.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  475.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  476.     _U|_W,        _U|_W,        _U|_W,        _U|_W,    /* 0x5X */
  477.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  478.     _U|_W,        _U|_W,        _U|_W,        0,
  479.     0,        0,        0,        0,
  480.     0,        _L|_W,        _L|_W,        _L|_W,    /* 0x6X */
  481.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  482.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  483.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  484.     _L|_W,        _L|_W,        _L|_W,        _L|_W,    /* 0x7X */
  485.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  486.     _L|_W,        _L|_W,        _L|_W,        0,
  487.     0,        0,        0,        _C,
  488.     _U|_W,        _L|_W,        _L|_W,        _L|_W,    /* 0x8X */
  489.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  490.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  491.     _L|_W,        _L|_W,        _U|_W,        _U|_W,
  492.     _U|_W,        _L|_W,        _U|_W,        _L|_W,    /* 0x9X */
  493.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  494.     _L|_W,        _U|_W,        _U|_W,        0,
  495.     0,        0,        _L|_W,        0,
  496.     _L|_W,        _L|_W,        _L|_W,        _L|_W,    /* 0xAX */
  497.     _L|_W,        _U|_W,        _L|_W,        _L|_W,
  498.     0,        0,        0,        0,
  499.     0,        0,        0,        0,
  500.     _L|_W,        _L|_W,        _U|_W,        _L|_W,    /* 0xBX */
  501.     _L|_W,        _U|_W,        _U|_W,        _U|_W,
  502.     _U|_W,        0,        0,        0,
  503.     0,        0,        0,        0,
  504.     _L|_W,        _U|_W,        0,        0,    /* 0xCX */
  505.     0,        0,        0,        0,
  506.     0,        0,        0,        0,
  507.     0,        0,        0,        0,
  508.     0,        0,        0,        0,    /* 0xDX */
  509.     0,        0,        0,        0,
  510.     0,        0,        0,        0,
  511.     0,        0,        0,        0,
  512.     0,        0,        0,        0,    /* 0xEX */
  513.     0,        0,        0,        0,
  514.     0,        0,        0,        0,
  515.     0,        0,        0,        0,
  516.     0,        0,        0,        0,    /* 0xFX */
  517.     0,        0,        0,        0,
  518.     0,        0,        0,        0,
  519.     0,        0,        0,        0
  520. };
  521.  
  522.  
  523. /* Convert upper to lower and vice versa.  This is borrowed from
  524.  * Bernhard Nebel.
  525.  */
  526.  
  527. char cupper[256] = {
  528.     0x00,    0x01,    0x02,    0x03,    0x04,    0x05,    0x06,    0x07,
  529.     0x08,    0x09,    0x0a,    0x0b,    0x0c,    0x0d,    0x0e,    0x0f,
  530.     0x10,    0x11,    0x12,    0x13,    0x14,    0x15,    0x16,    0x17,
  531.     0x18,    0x19,    0x1a,    0x1b,    0x1c,    0x1d,    0x1e,    0x1f,
  532.     0x20,    0x21,    0x22,    0x23,    0x24,    0x25,    0x26,    0x27,
  533.     0x28,    0x29,    0x2a,    0x2b,    0x2c,    0x2d,    0x2e,    0x2f,
  534.     0x30,    0x31,    0x32,    0x33,    0x34,    0x35,    0x36,    0x37,
  535.     0x38,    0x39,    0x3a,    0x3b,    0x3c,    0x3d,    0x3e,    0x3f,
  536.     0x40,    0x41,    0x42,    0x43,    0x44,    0x45,    0x46,    0x47,
  537.     0x48,    0x49,    0x4a,    0x4b,    0x4c,    0x4d,    0x4e,    0x4f,
  538.     0x50,    0x51,    0x52,    0x53,    0x54,    0x55,    0x56,    0x57,
  539.     0x58,    0x59,    0x5a,    0x5b,    0x5c,    0x5d,    0x5e,    0x5f,
  540.     0x40,    0x41,    0x42,    0x43,    0x44,    0x45,    0x46,    0x47,
  541.     0x48,    0x49,    0x4a,    0x4b,    0x4c,    0x4d,    0x4e,    0x4f,
  542.     0x50,    0x51,    0x52,    0x53,    0x54,    0x55,    0x56,    0x57,
  543.     0x58,    0x59,    0x5a,    0x7b,    0x7c,    0x7d,    0x7e,    0x7f,
  544.     0x80,    0x9a,    0x90,    0x41,    0x8e,    0xb6,    0x8f,    0x80,
  545.     0x45,    0x45,    0x45,    0x49,    0x49,    0x49,    0x8e,    0x8f,
  546.     0x90,    0x92,    0x92,    0x4f,    0x99,    0x4f,    0x55,    0x55,
  547.     0x59,    0x99,    0x9a,    0x9b,    0x9c,    0x9d,    0x9e,    0x9f,
  548.     0x41,    0x49,    0x4f,    0x55,     0xa5,    0xa5,    0x41,    0x4f,
  549.     0xa8,    0xa9,    0xaa,    0xab,    0xac,    0xad,    0xae,    0xaf,
  550.     0xb7,    0xb8,    0xb2,    0xb2,    0xb5,    0xb5,    0xb6,    0xb7,
  551.     0xb8,    0xb9,    0xba,    0xbb,    0xbc,    0xbd,    0xbe,    0xbf,
  552.     0xc1,    0xc1,    0xc2,    0xc3,    0xc4,    0xc5,    0xc6,    0xc7,
  553.     0xc8,    0xc9,    0xca,    0xcb,    0xcc,    0xcd,    0xce,    0xcf,
  554.     0xd0,    0xd1,    0xd2,    0xd3,    0xd4,    0xd5,    0xd6,    0xd7,
  555.     0xd8,    0xd9,    0xda,    0xdb,    0xdc,    0xdd,    0xde,    0xdf,
  556.     0xe0,    0xe1,    0xe2,    0xe3,    0xe4,    0xe5,    0xe6,    0xe7,
  557.     0xe8,    0xe9,    0xea,    0xeb,    0xec,    0xed,    0xee,    0xef,
  558.     0xf0,    0xf1,    0xf2,    0xf3,    0xf4,    0xf5,    0xf6,    0xf7,
  559.     0xf8,    0xf9,    0xfa,    0xfb,    0xfc,    0xfd,    0xfe,    0xff
  560.     };
  561.  
  562. char clower[256] = {
  563.     0x00,    0x01,    0x02,    0x03,    0x04,    0x05,    0x06,    0x07,
  564.     0x08,    0x09,    0x0a,    0x0b,    0x0c,    0x0d,    0x0e,    0x0f,
  565.     0x10,    0x11,    0x12,    0x13,    0x14,    0x15,    0x16,    0x17,
  566.     0x18,    0x19,    0x1a,    0x1b,    0x1c,    0x1d,    0x1e,    0x1f,
  567.     0x20,    0x21,    0x22,    0x23,    0x24,    0x25,    0x26,    0x27,
  568.     0x28,    0x29,    0x2a,    0x2b,    0x2c,    0x2d,    0x2e,    0x2f,
  569.     0x30,    0x31,    0x32,    0x33,    0x34,    0x35,    0x36,    0x37,
  570.     0x38,    0x39,    0x3a,    0x3b,    0x3c,    0x3d,    0x3e,    0x3f,
  571.     0x60,    0x61,    0x62,    0x63,    0x64,    0x65,    0x66,    0x67,
  572.     0x68,    0x69,    0x6a,    0x6b,    0x6c,    0x6d,    0x6e,    0x6f,
  573.     0x70,    0x71,    0x72,    0x73,    0x74,    0x75,    0x76,    0x77,
  574.     0x78,    0x79,    0x7a,    0x5b,    0x5c,    0x5d,    0x5e,    0x5f,
  575.     0x60,    0x61,    0x62,    0x63,    0x64,    0x65,    0x66,    0x67,
  576.     0x68,    0x69,    0x6a,    0x6b,    0x6c,    0x6d,    0x6e,    0x6f,
  577.     0x70,    0x71,    0x72,    0x73,    0x74,    0x75,    0x76,    0x77,
  578.     0x78,    0x79,    0x7a,    0x7b,    0x7c,    0x7d,    0x7e,    0x7f,
  579.     0x87,    0x81,    0x82,    0x83,    0x84,    0x85,    0x86,    0x87,
  580.     0x88,    0x89,    0x8a,    0x8b,    0x8c,    0x8d,    0x84,    0x86,
  581.     0x82,    0x91,    0x91,    0x93,    0x94,    0x95,    0x96,    0x97,
  582.     0x98,    0x94,    0x81,    0x9b,    0x9c,    0x9d,    0x9e,    0x9f,
  583.     0xa0,    0xa1,    0xa2,    0xa3,    0xa4,    0xa4,    0xa6,    0xa7,
  584.     0xa8,    0xa9,    0xaa,    0xab,    0xac,    0xad,    0xae,    0xaf,
  585.     0xb0,    0xb1,    0xb1,    0xb3,    0xb4,    0xb4,    0x85,    0xb0,
  586.     0xb1,    0xb9,    0xba,    0xbb,    0xbc,    0xbd,    0xbe,    0xbf,
  587.     0xc0,    0xc0,    0xc2,    0xc3,    0xc4,    0xc5,    0xc6,    0xc7,
  588.     0xc8,    0xc9,    0xca,    0xcb,    0xcc,    0xcd,    0xce,    0xcf,
  589.     0xd0,    0xd1,    0xd2,    0xd3,    0xd4,    0xd5,    0xd6,    0xd7,
  590.     0xd8,    0xd9,    0xda,    0xdb,    0xdc,    0xdd,    0xde,    0xdf,
  591.     0xe0,    0xe1,    0xe2,    0xe3,    0xe4,    0xe5,    0xe6,    0xe7,
  592.     0xe8,    0xe9,    0xea,    0xeb,    0xec,    0xed,    0xee,    0xef,
  593.     0xf0,    0xf1,    0xf2,    0xf3,    0xf4,    0xf5,    0xf6,    0xf7,
  594.     0xf8,    0xf9,    0xfa,    0xfb,    0xfc,    0xfd,    0xfe,    0xff
  595.     };
  596.     
  597.  
  598. /*
  599.  * Find the name of a keystroke.  Needs to be changed to handle 8-bit printing
  600.  * characters and function keys better.     Returns a pointer to the terminating
  601.  * '\0'.
  602.  */
  603.  
  604. char *keyname(cp, k)
  605. register char *cp;
  606. register int k;
  607. {
  608.     register char *np;
  609. #ifdef    FKEYS
  610.     extern char *keystrings[];
  611. #endif /* FKEYS */
  612.  
  613.     if(k<0) k &= 0377;               /* if char was sign extened */
  614.     switch(k) {
  615.     case CCHR('@'): np = "NUL"; break;
  616.     case CCHR('I'): np = "TAB"; break;
  617.     case CCHR('J'): np = "LFD"; break; /* yuck, but that's what GNU calls it */
  618.     case CCHR('M'): np = "RET"; break;
  619.     case CCHR('['): np = "ESC"; break;
  620.     case ' ':    np = "SPC"; break; /* yuck again */
  621.     case CCHR('?'): np = "DEL"; break;
  622.     default:
  623. #ifdef    FKEYS
  624.         if(k >= KFIRST && k <= KLAST &&
  625.             (np = keystrings[k - KFIRST]) != NULL)
  626.         break;
  627. #endif /* FKEYS */
  628.         if(k > CCHR('?') || k < CCHR('@')) {
  629.         *cp++ = '0';
  630.         *cp++ = ((k>>6)&7) + '0';
  631.         *cp++ = ((k>>3)&7) + '0';
  632.         *cp++ = (k&7) + '0';
  633.         *cp = '\0';
  634.         return cp;
  635.         }
  636.         if(k < ' ') {
  637.         *cp++ = 'C';
  638.         *cp++ = '-';
  639.         k += '@';
  640.         if(ISUPPER(k)) k = TOLOWER(k);
  641.         }
  642.         *cp++ = k;
  643.         *cp = '\0';
  644.         return cp;
  645.     }
  646.     (VOID) strcpy(cp, np);
  647.     return cp + strlen(cp);
  648. }
  649. SHAR_EOF
  650. cat << \SHAR_EOF > sys/atari/diredsup.c
  651. /* diredsup.c -- Atari ST functions for handling DIR and DIRED features
  652.  *
  653.  * author :  Sandra Loosemore
  654.  * date   :  20 Dec 1987
  655.  *
  656.  */
  657.  
  658. #include "..\..\def.h"
  659.  
  660.  
  661. /* ST-specific code to support the DIR features in dir.c
  662.  */
  663.  
  664. #ifndef NO_DIR
  665.  
  666. char *getwd (buffer)
  667.     char *buffer;
  668. {   int drive, i;
  669.     drive = Dgetdrv();
  670.     buffer[0] = (char)drive + 'a';
  671.     buffer[1] = ':';
  672.     Dgetpath (&buffer[2], drive+1);
  673.     for (i=2; buffer[i] != '\0'; i++)
  674.         buffer[i] = TOLOWER(buffer[i]);
  675.     return(buffer);
  676.     }
  677.  
  678. int chdir (buffer)
  679.     char *buffer;
  680. {   int drive;
  681.     if (buffer[1] == ':')  {
  682.         drive = TOLOWER(buffer[0]) - 'a';
  683.     (VOID) Dsetdrv (drive);
  684.     buffer = buffer + 2;
  685.         }
  686.     return ((int)Dsetpath (buffer));
  687.     }
  688.  
  689. #endif
  690.  
  691.  
  692. /* ST-specific code to support the DIRED features in dired.c.
  693.  */
  694.  
  695. #ifndef NO_DIRED
  696.  
  697. #include "..\..\kbd.h"
  698.  
  699.  
  700. /* Various file manipulation functions.  */
  701.  
  702. int rename (fromname, toname)
  703.     char *fromname, *toname;
  704. {   if (Frename(0, fromname, toname) == 0)
  705.         return(0);
  706.     else  {
  707.         ewprintf ("Rename failed.");
  708.         return(-1);
  709.     }
  710.     }
  711.  
  712. int copy (fromname, toname)
  713.     char *fromname, *toname;
  714. {   int from, to, count;
  715.     char buffer[256];
  716.     if ((from = Fopen (fromname, 0)) < 0)  {
  717.         ewprintf ("Could not open input file %s.", fromname);
  718.         return(-1);
  719.         }
  720.     (VOID) Fdelete (toname);
  721.     if ((to = (Fcreate (toname, 0))) < 0)  {
  722.         ewprintf ("Could not open output file %s.", toname);
  723.         Fclose(from);
  724.     return(-1);
  725.         }
  726.     while ((count = Fread(from, (long)256, buffer)) > 0)
  727.         (VOID) Fwrite (to, (long)count, buffer);
  728.     (VOID) Fclose(from);
  729.     (VOID) Fclose(to);
  730.     return(0);
  731.     }
  732.  
  733. int unlink (fname)
  734.     char *fname;
  735. {   if (Fdelete(fname) == 0)
  736.         return(0);
  737.     else
  738.         return(-1);
  739.     }
  740.  
  741. int unlinkdir (fname)
  742.     char *fname;
  743. {   if (Ddelete(fname) == 0)
  744.         return(0);
  745.     else
  746.         return(-1);
  747.     }
  748.  
  749.  
  750. /* Create a dired buffer for the given directory name.  */
  751.  
  752. BUFFER *dired_(dirname)
  753. char *dirname;
  754. {
  755.     register BUFFER *bp;
  756.     BUFFER *findbuffer();
  757.  
  758.     /* Create the dired buffer */
  759.  
  760.     if ((dirname = adjustname(dirname)) == NULL) {
  761.     ewprintf("Bad directory name");
  762.     return NULL;
  763.         }
  764.     if ((bp = findbuffer(dirname)) == NULL) {
  765.     ewprintf("Could not create buffer");
  766.     return NULL;
  767.         }
  768.     if (bclear(bp) != TRUE) return FALSE;
  769.  
  770.     /* Now fill it in.  */
  771.  
  772.     if (!dirlist (bp, dirname))  {
  773.         ewprintf("Could not read directory");
  774.         return FALSE;
  775.         }
  776.  
  777.     /* Clean up and return */
  778.  
  779.     bp->b_dotp = lforw(bp->b_linep);        /* go to first line */
  780.     (VOID) strncpy(bp->b_fname, dirname, NFILEN);
  781.     if((bp->b_modes[0] = name_mode("dired")) == NULL) {
  782.     bp->b_modes[0] = &map_table[0];
  783.     ewprintf("Could not find mode dired");
  784.     return NULL;
  785.         }
  786.     return bp;
  787.     }
  788.  
  789.  
  790. /* Take the name from the line in the buffer and make a filename out of it.
  791.  */
  792.  
  793. d_makename(lp, fn)
  794. register LINE *lp;
  795. register char *fn;
  796. {
  797.     register char *cp;
  798.     register char ch;
  799.     int i;
  800.  
  801.     if(llength(lp) < 55) return ABORT;
  802.     (VOID) strcpy (fn, curbp->b_fname);
  803.     cp = fn + strlen(fn);
  804.     *cp++ = '\\';
  805.     i = 2;
  806.     while ((ch = lgetc(lp,i)) != ' ')  {
  807.         *cp++ = ch;
  808.     i++;
  809.     }
  810.     *cp = '\0';
  811.     return lgetc(lp, 52) == 'd';
  812. }
  813.  
  814.  
  815. /* Here is all the messy code for getting a directory listing.
  816.  *    It is printed out like
  817.  *
  818.  * 0         1         2         3         4         5
  819.  * 01234567890123456789012345678901234567890123456789012345
  820.  *   name----------><-----size  dd-mmm-yyyy  hh:mm:ss  drw
  821.  *
  822.  */
  823.  
  824. typedef struct dta {
  825.     char junk[21];
  826.     char attrib;
  827.     unsigned int timestamp;
  828.     unsigned int datestamp;
  829.     long filesize;
  830.     char name[14];
  831.     } DTA;
  832.  
  833. static char* months[] = {
  834.     "???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", 
  835.     "Aug", "Sep", "Oct", "Nov", "Dec"};
  836.  
  837.  
  838. /* Print a number into the character buffer, bumping up the pointer */
  839.  
  840. static char* printit (str, number, width, fill, zero)
  841.     char* str;
  842.     long number;
  843.     int width;
  844.     char fill;
  845. {   int i;
  846.     if (number == 0)   {
  847.         for (i=1; i<width; i++)
  848.         *str++ = fill;
  849.         if (width == 0)
  850.             ;
  851.         else if (zero) 
  852.         *str++ = '0';
  853.         else
  854.         *str++ = fill;
  855.         return (str);
  856.         }
  857.     else  {
  858.         str = printit (str, (number/10), width-1, fill, FALSE);
  859.         *str++ = (char) ((number%10) + (int) '0');
  860.         return (str);
  861.         }
  862.     }
  863.  
  864.  
  865. /* Print a null-terminated string into the buffer */
  866.  
  867. static char* copyit (to, from, width, fill)
  868.     char *from, *to;
  869.     int width;
  870.     char fill;
  871. {   int i;
  872.     char ch;
  873.     i = 0;
  874.     while (*from != '\0')  {
  875.         ch = *from++;
  876.         *to++ = TOLOWER(ch);
  877.         i++;
  878.     }
  879.     while (i < width)  {
  880.         *to++ = fill;
  881.         i++;
  882.         }
  883.     return (to);
  884.     }
  885.  
  886.  
  887. static char* getdate (datestamp, buffer)
  888.     unsigned int datestamp;
  889.     char* buffer;
  890. {   int date, month, year;
  891.  
  892.     date = datestamp & 31;
  893.     month = (datestamp >> 5) & 15;
  894.     year = (datestamp >> 9) + 1980;
  895.     *buffer++ = ' ';
  896.     *buffer++ = ' ';
  897.     buffer = printit (buffer, (long) date, 2, '0', TRUE);
  898.     *buffer++ = '-';
  899.     buffer = copyit (buffer, months[month], 3, ' ');
  900.     *buffer++ = '-';
  901.     buffer = printit (buffer, (long) year, 4, ' ', TRUE);
  902.     return (buffer);
  903.     }
  904.  
  905.  
  906. static char* gettime (timestamp, buffer)
  907.     unsigned int timestamp;
  908.     char* buffer;
  909. {   int second, minute, hour;
  910.  
  911.     second = (timestamp & 31) * 2;
  912.     minute = (timestamp >> 5) & 63;
  913.     hour = (timestamp >> 11);
  914.     *buffer++ = ' ';
  915.     *buffer++ = ' ';
  916.     buffer = printit (buffer, (long) hour, 2, '0', TRUE);
  917.     *buffer++ = ':';
  918.     buffer = printit (buffer, (long) minute, 2, '0', TRUE);
  919.     *buffer++ = ':';
  920.     buffer = printit (buffer, (long) second, 2, '0', TRUE);
  921.     return (buffer);
  922.     }
  923.  
  924.  
  925. static dirlist (bp, dirname)
  926.     BUFFER *bp;
  927.     char *dirname;
  928. {   
  929.     char fname[NFILEN], buf[NFILEN];
  930.     int status;
  931.     DTA my_dta, *old_dta;
  932.     char *bufptr;
  933.  
  934.     (VOID) strcpy (fname, dirname);
  935.     (VOID) strcat (fname, "\\*.*");
  936.     old_dta = (DTA *) Fgetdta ();
  937.     Fsetdta (&my_dta);
  938.     status = Fsfirst (fname, 0x11);
  939.     while (status == 0)  {
  940.         bufptr = buf;
  941.     *bufptr++ = ' ';
  942.     *bufptr++ = ' ';
  943.         bufptr = copyit (bufptr, my_dta.name, 15, ' ');
  944.         bufptr = printit (bufptr, my_dta.filesize, 10, ' ', TRUE);
  945.         bufptr = getdate (my_dta.datestamp, bufptr);
  946.         bufptr = gettime (my_dta.timestamp, bufptr);
  947.     *bufptr++ = ' ';
  948.     *bufptr++ = ' ';
  949.         *bufptr++ = (my_dta.attrib) ? 'd' : '-';  /* directory */
  950.     *bufptr++ = 'r';
  951.         *bufptr++ = (my_dta.attrib) ? '-' : 'w';  /* read-only */
  952.         *bufptr = '\0';
  953.         if (addline(bp, buf) == FALSE)  {
  954.             Fsetdta (old_dta);
  955.             return (FALSE);
  956.             }
  957.         status = Fsnext ();
  958.         }
  959.     Fsetdta (old_dta);
  960.     return (TRUE);
  961.     }
  962.  
  963. #endif
  964. SHAR_EOF
  965. cat << \SHAR_EOF > sys/atari/fileio.c
  966. /* fileio.c -- Atari ST file system interface for MG
  967.  *
  968.  * author :  Sandra Loosemore (from an earlier version by dec-rex!conroy)
  969.  * date   :  24 Oct 1987
  970.  * changes:  Marion Hakanson -- Jan 1988
  971.  *
  972.  */
  973. #include    "..\..\def.h"
  974.  
  975.  
  976. /* Adjustname regularizes a filename.  This fills in the current drive
  977.  *    and directory onto the front if they are not already provided, and
  978.  *    also lowercases it so a case-sensitive string compare can be used
  979.  *    on filenames.
  980.  * This doesn't do the right things with collapsing "..\" and ".\" -- it
  981.  *      doesn't check for them being embedded in pathnames, only at the
  982.  *    front.  Sigh.
  983.  */
  984.  
  985. static char adbuffer[128];
  986.  
  987. char* adjustname (fname)
  988.     char *fname;
  989. {   int i, j, k;
  990.     char pathbuf[128];
  991.  
  992.     if (fname[1] == ':')  {
  993.         j = 2;
  994.         adbuffer[0] = TOLOWER(fname[0]);
  995.     }
  996.     else  {
  997.         adbuffer[0] = (char)Dgetdrv() + 'a';
  998.         j = 0;
  999.         }
  1000.     adbuffer[1] = ':';
  1001.     i = 2;
  1002.     if (fname[j] != '\\')  {
  1003.         Dgetpath(pathbuf, (int)(adbuffer[0] - 'a' + 1));
  1004.         for (k=0; pathbuf[k] != '\0'; k++)  {
  1005.         adbuffer[i] = TOLOWER(pathbuf[k]);
  1006.         i++;
  1007.         }
  1008.         adbuffer[i] = '\\';
  1009.     i++;
  1010.         }
  1011.     if (fname[j] == '.')  {
  1012.         if (fname[j+1] == '.')  {
  1013.             i = i - 2;
  1014.             while (adbuffer[i] != '\\')  i--;
  1015.             j = j + 2;
  1016.             }
  1017.         else  {
  1018.             j = j + 1;
  1019.             i = i - 1;
  1020.         }
  1021.         }
  1022.     while (fname[j] != '\0')  {
  1023.         adbuffer[i] = TOLOWER(fname[j]);
  1024.         i++;
  1025.         j++;
  1026.         }
  1027.     adbuffer[i] = '\0';
  1028.     return(adbuffer);
  1029.     }
  1030.  
  1031.  
  1032. /* Define some things used later on */
  1033.  
  1034. static int handle;
  1035. #define RBUFSIZE 512
  1036. static char rbuffer[RBUFSIZE];
  1037. static int rbufmax, rbufnext, rbufcr;
  1038. static int rbufeof;
  1039.  
  1040.  
  1041. /* Open and close files.  Store the file handle in "handle".  We'll use 
  1042.  *    it later in the routines that read and write to the file.
  1043.  */
  1044.  
  1045.  
  1046. ffropen (fn)
  1047.     char *fn;
  1048. {   handle = Fopen(fn, 0);
  1049.     if (handle < 0)
  1050.         return(FIOFNF);
  1051.     else  {
  1052.         rbufmax = 0;
  1053.         rbufnext = 0;
  1054.     rbufcr = FALSE;
  1055.     rbufeof = FALSE;
  1056.         return(FIOSUC);
  1057.     }
  1058.     }
  1059.  
  1060.  
  1061. ffwopen (fn)
  1062.     char *fn;
  1063. {   (VOID) Fdelete(fn);
  1064.     handle = Fcreate(fn, 0);
  1065.     if (handle < 0)  {
  1066.     ewprintf("Open of %s failed with error code %d.", fn, handle);
  1067.     return (FIOERR);
  1068.     }
  1069.     else
  1070.     return (FIOSUC);
  1071.     }
  1072.  
  1073. ffclose ()
  1074. {   (VOID) Fclose(handle);
  1075.     return (FIOSUC);
  1076.     }
  1077.  
  1078.  
  1079. /* Write an entire buffer to the already open file.  The last line of 
  1080.  *     the buffer does not have an implied newline.
  1081.  */
  1082.  
  1083. static char *crlf = "\r\n";
  1084.  
  1085. ffputbuf (buf)
  1086.     BUFFER *buf;
  1087. {   LINE *line, *last;
  1088.  
  1089.     last = buf->b_linep;       /* Header line is empty */
  1090.     line = last->l_fp;         /* The first real line */
  1091.  
  1092.     while (line->l_fp != last)  {
  1093.         if ((Fwrite (handle, (long)line->l_used, line->l_text) < 0) ||
  1094.         (Fwrite (handle, 2l, crlf) < 0))  {
  1095.         ewprintf("File write error");
  1096.         return (FIOERR);
  1097.                 }
  1098.         line = line->l_fp;
  1099.         }
  1100.     if (line->l_used > 0)  {
  1101.         if (Fwrite (handle, (long)line->l_used, line->l_text) < 0)  {
  1102.         ewprintf("File write error");
  1103.         return (FIOERR);
  1104.                 }
  1105.         }
  1106.     return(FIOSUC);
  1107.     }
  1108.  
  1109.  
  1110. /* Read a line from the file up to nbuf long.  Set *nbytes to the actual
  1111.  *    count read (excluding the end-of-line marker).  Returns:
  1112.  *        FIOSUC if all is well.
  1113.  *        FIOLONG if no newline was found yet.
  1114.  *        FIOEOF on end-of-file.
  1115.  *        FIOERR if any random errors happened.
  1116.  * The GemDos routine Fread does not break on end-of-line; it will read
  1117.  *    however many characters you tell it to.  So we do a little buffering.
  1118.  *    Remember that crlf is the line terminator.  Cr's and lf's that appear
  1119.  *    by themselves are passed on.
  1120.  */
  1121.  
  1122.  
  1123. ffgetline (buf, nbuf, nbytes)
  1124.     char buf[];
  1125.     int nbuf;
  1126.     int *nbytes;
  1127. {   register int i;
  1128.     register char ch;
  1129.  
  1130.     for (i=0; i<nbuf; i++)  {
  1131.         if (rbufmax == rbufnext)  {
  1132.         if (rbufeof || 
  1133.               ((rbufmax = Fread(handle, (long)RBUFSIZE, rbuffer)) == 0))  {
  1134.                 (*nbytes) = i;
  1135.                 return (FIOEOF);
  1136.                 }
  1137.             else if (rbufmax < 0)  {
  1138.              ewprintf("File read error");
  1139.             return (FIOERR);
  1140.                 }
  1141.         else  {
  1142.         if (rbufmax < RBUFSIZE)  rbufeof = TRUE;
  1143.                 rbufnext = 0;
  1144.         }
  1145.             }
  1146.         ch = rbuffer[rbufnext];
  1147.         rbufnext++;
  1148.         if (rbufcr && (ch == '\n'))  {
  1149.         rbufcr = FALSE;
  1150.         (*nbytes) = i-1;
  1151.             return (FIOSUC);
  1152.             }
  1153.         else  {
  1154.         buf[i] = ch;
  1155.         rbufcr = (ch == '\r');
  1156.             }
  1157.     }
  1158.     return (FIOLONG);
  1159.     }
  1160.  
  1161.  
  1162. #ifndef NO_BACKUP
  1163.  
  1164. /*
  1165.  * Finish this routine when you decide
  1166.  * what the right thing to do when renaming a
  1167.  * file for backup purposes.
  1168.  */
  1169.  
  1170. fbackupfile(fname)
  1171. char    *fname;
  1172. {
  1173.     return (TRUE);
  1174. }
  1175.  
  1176. #endif
  1177.  
  1178.  
  1179.  
  1180. #ifndef NO_STARTUP
  1181.  
  1182. /* Look for a startup file as MG.INI in the current directory, then for
  1183.  *    the file specified by the environment variable MGINIT.
  1184.  */
  1185.  
  1186. char* startupfile (ignore)
  1187.     char *ignore;
  1188. {   int handle;
  1189.     char *foo;
  1190.     extern char *getenv();
  1191.  
  1192.     if ((handle = Fopen ("MG.INI", 0)) >= 0)  {
  1193.         (VOID) Fclose (handle);
  1194.         return("MG.INI");
  1195.         }
  1196.     else if (((foo = getenv("MGINIT")) != NULL) &&
  1197.              ((handle = Fopen (foo, 0)) >= 0))  {
  1198.         (VOID) Fclose (handle);
  1199.         return(foo);
  1200.         }
  1201.     else
  1202.         return(NULL);
  1203.     }
  1204.  
  1205. #endif
  1206.  
  1207. SHAR_EOF
  1208. cat << \SHAR_EOF > sys/atari/gemstart.s
  1209. ******************************************************************************
  1210. *
  1211. *    C runtime startup for CP/M-68k.
  1212. *
  1213. ******************************************************************************
  1214. *
  1215. ltpa=0            * Low TPA address
  1216. htpa=4            * High TPA address
  1217. lcode=8            * Code segment start
  1218. codelen=12        * Code segment length
  1219. ldata=16        * Data segment start
  1220. datalen=20        * Data segment length
  1221. lbss=24            * Bss  segment start
  1222. bsslen=28        * Bss  segment length
  1223. freelen=32        * free segment length
  1224. resvd=36        * Reserved
  1225. fcb2=56            * 2nd parsed fcb
  1226. fcb1=92            * 1st parsed fcb
  1227. command=128        * Command tail
  1228. prtstr=9        * Print string BDOS Call
  1229. exit=0            * BDOS exit call
  1230. .globl    __main
  1231. .globl    __exit
  1232. .globl    __break
  1233. .globl    ___cpmrv
  1234. .globl    __base
  1235. .globl  _sw_
  1236. .globl    __sovf
  1237.  
  1238.  
  1239.     .globl    _crystal
  1240.     .globl    _ctrl_cnts
  1241.  
  1242.  
  1243.         .text
  1244.  
  1245.  
  1246. *
  1247. *  Must be first object file in link statement
  1248. *
  1249.     move.l    a7,a5        * save a7 so we can get the base page address
  1250.     move.l    4(a5),a5    * a5=basepage address
  1251.     move.l    a5,__base    * save for C startup
  1252.     move.l    $c(a5),d0
  1253.     add.l    $14(a5),d0
  1254.     add.l    $1c(a5),d0
  1255.     add.l    #$2000,d0    * d0=basepage+textlen+datalen+bsslen
  1256. *                  (plus room for user stack)
  1257.     move.l    d0,d1
  1258.     add.l    a5,d1        * compute stack top
  1259.     and.l    #-2,d1        * ensure even byte boundary
  1260.     move.l    d1,a7        * setup user stack, 1K above end of BSS
  1261.  
  1262.     move.l    d0,-(sp)
  1263.     move.l    a5,-(sp)
  1264.     clr.w    -(sp)        * junk word
  1265.     move    #$4a,-(sp)    * return excess storage
  1266.     trap    #1
  1267.     add.l    #12,sp
  1268.  
  1269.  
  1270.         move.l    __base,a0        *    Load C external
  1271.         move.l    lbss(a0),a1        *    a1 -> bss region
  1272.         adda.l    bsslen(a0),a1        *    a1 -> 1st heap loc
  1273.  
  1274.         move.l    a1,__break        *    Put in "break" loc
  1275.         lea.l    command(a0),a2        *    a2 -> command line
  1276.         move.b    (a2)+,d0        *    d0 = byte count
  1277.         andi.l    #$ff,d0            *    clear junk
  1278.         move.w    d0,-(a7)        *    push length
  1279.         move.l    a2,-(a7)        *    Push commnd
  1280.         clr.l    a6            *    Clear frame pointer
  1281.         jsr    __main            *    call main routine
  1282.         jmp    __exit            *    call "exit"
  1283.  
  1284. *
  1285. *    For GEMAES calls from AESBIND.ARC or cryslib.o
  1286. *
  1287. _crystal:
  1288.     move.l    4(a7),d1
  1289.     move.w    #200,d0
  1290.     trap    #2
  1291.     rts
  1292.  
  1293. *
  1294. *    control array for vdibind
  1295. *
  1296.     .data
  1297.         .even
  1298. _ctrl_cnts:                 *    Application Manager
  1299.     .dc.b    0, 1, 0            * func 010        
  1300.         .dc.b    2, 1, 1            * func 011        
  1301.         .dc.b    2, 1, 1         * func 012        
  1302.     .dc.b    0, 1, 1            * func 013        
  1303.     .dc.b    2, 1, 1            * func 014        
  1304.     .dc.b    1, 1, 1            * func 015        
  1305.     .dc.b    0, 0, 0            * func 016        
  1306.     .dc.b    0, 0, 0            * func 017        
  1307.     .dc.b    0, 0, 0            * func 008        
  1308.     .dc.b    0, 1, 0            * func 019        
  1309. *                             Event Manager
  1310.     .dc.b    0, 1, 0            * func 020        
  1311.     .dc.b    3, 5, 0            * func 021        
  1312.     .dc.b    5, 5, 0            * func 022        
  1313.     .dc.b    0, 1, 1            * func 023        
  1314.     .dc.b    2, 1, 0            * func 024        
  1315.     .dc.b    16, 7, 1         * func 025        
  1316.     .dc.b    2, 1, 0            * func 026        
  1317.     .dc.b    0, 0, 0            * func 027        
  1318.     .dc.b    0, 0, 0            * func 028        
  1319.     .dc.b    0, 0, 0            * func 009        
  1320. *                             Menu Manager
  1321.     .dc.b    1, 1, 1            * func 030        
  1322.     .dc.b    2, 1, 1            * func 031        
  1323.     .dc.b    2, 1, 1            * func 032        
  1324.     .dc.b    2, 1, 1            * func 033        
  1325.     .dc.b    1, 1, 2            * func 034        
  1326.     .dc.b    1, 1, 1            * func 005        
  1327.     .dc.b    0, 0, 0            * func 006        
  1328.     .dc.b    0, 0, 0            * func 007        
  1329.     .dc.b    0, 0, 0            * func 008        
  1330.     .dc.b    0, 0, 0            * func 009        
  1331. *                             Object Manager
  1332.     .dc.b    2, 1, 1            * func 040        
  1333.     .dc.b    1, 1, 1            * func 041        
  1334.       .dc.b    6, 1, 1            * func 042        
  1335.     .dc.b    4, 1, 1            * func 043        
  1336.     .dc.b    1, 3, 1            * func 044        
  1337.     .dc.b    2, 1, 1            * func 045        
  1338.     .dc.b    4, 2, 1            * func 046        
  1339.     .dc.b    8, 1, 1            * func 047        
  1340.     .dc.b    0, 0, 0            * func 048        
  1341.     .dc.b    0, 0, 0            * func 049        
  1342. *                             Form Manager
  1343.     .dc.b    1, 1, 1            * func 050        
  1344.     .dc.b    9, 1, 1            * func 051        
  1345.     .dc.b    1, 1, 1            * func 002        
  1346.     .dc.b    1, 1, 0            * func 003        
  1347.     .dc.b    0, 5, 1            * func 004        
  1348.     .dc.b    0, 0, 0            * func 005        
  1349.     .dc.b    0, 0, 0            * func 006        
  1350.     .dc.b    0, 0, 0            * func 007        
  1351.     .dc.b    0, 0, 0            * func 008        
  1352.     .dc.b    0, 0, 0            * func 009        
  1353. *                             Dialog Manager
  1354.     .dc.b    0, 0, 0            * func 060        
  1355.     .dc.b    0, 0, 0            * func 061        
  1356.     .dc.b    0, 0, 0            * func 062        
  1357.     .dc.b    0, 0, 0            * func 003        
  1358.     .dc.b    0, 0, 0            * func 004        
  1359.     .dc.b    0, 0, 0            * func 005        
  1360.     .dc.b    0, 0, 0            * func 006        
  1361.     .dc.b    0, 0, 0            * func 007        
  1362.     .dc.b    0, 0, 0            * func 008        
  1363.     .dc.b    0, 0, 0            * func 009        
  1364. *                            Graphics Manager
  1365.     .dc.b    4, 3, 0            * func 070        
  1366.     .dc.b    8, 3, 0            * func 071        
  1367.     .dc.b    6, 1, 0            * func 072        
  1368.     .dc.b    8, 1, 0            * func 073        
  1369.     .dc.b    8, 1, 0            * func 074        
  1370.     .dc.b    4, 1, 1            * func 075        
  1371.     .dc.b    3, 1, 1            * func 076        
  1372.     .dc.b    0, 5, 0            * func 077        
  1373.     .dc.b    1, 1, 1            * func 078        
  1374.     .dc.b    0, 5, 0            * func 009        
  1375. *                            Scrap Manager
  1376.     .dc.b    0, 1, 1            * func 080        
  1377.     .dc.b    0, 1, 1            * func 081        
  1378.     .dc.b    0, 0, 0            * func 082        
  1379.     .dc.b    0, 0, 0            * func 083        
  1380.     .dc.b    0, 0, 0            * func 084        
  1381.     .dc.b    0, 0, 0            * func 005        
  1382.     .dc.b    0, 0, 0            * func 006        
  1383.     .dc.b    0, 0, 0            * func 007        
  1384.     .dc.b    0, 0, 0            * func 008        
  1385.     .dc.b    0, 0, 0            * func 009        
  1386. *                            fseler Manager
  1387.     .dc.b    0, 2, 2            * func 090        
  1388.     .dc.b    0, 0, 0            * func 091        
  1389.     .dc.b    0, 0, 0            * func 092        
  1390.     .dc.b    0, 0, 0            * func 003        
  1391.     .dc.b    0, 0, 0            * func 004        
  1392.     .dc.b    0, 0, 0            * func 005        
  1393.     .dc.b    0, 0, 0            * func 006        
  1394.     .dc.b    0, 0, 0            * func 007        
  1395.     .dc.b    0, 0, 0            * func 008        
  1396.     .dc.b    0, 0, 0         * func 009        
  1397. *                            Window Manager
  1398.     .dc.b    5, 1, 0            * func 100        
  1399.     .dc.b    5, 1, 0            * func 101        
  1400.     .dc.b    1, 1, 0            * func 102        
  1401.     .dc.b    1, 1, 0            * func 103        
  1402.     .dc.b    2, 5, 0            * func 104        
  1403.     .dc.b    6, 1, 0            * func 105        
  1404.     .dc.b    2, 1, 0            * func 106        
  1405.     .dc.b    1, 1, 0            * func 107        
  1406.     .dc.b    6, 5, 0            * func 108        
  1407.     .dc.b    0, 0, 0         * func 009        
  1408. *                            Resource Manger
  1409.     .dc.b    0, 1, 1            * func 110        
  1410.     .dc.b    0, 1, 0            * func 111        
  1411.     .dc.b    2, 1, 0            * func 112        
  1412.     .dc.b    2, 1, 1            * func 113        
  1413.     .dc.b    1, 1, 1            * func 114        
  1414.     .dc.b    0, 0, 0            * func 115        
  1415.     .dc.b    0, 0, 0            * func 006
  1416.     .dc.b    0, 0, 0            * func 007
  1417.     .dc.b    0, 0, 0            * func 008
  1418.     .dc.b    0, 0, 0            * func 009
  1419. *                            Shell Manager
  1420.     .dc.b    0, 1, 2            * func 120
  1421.     .dc.b    3, 1, 2            * func 121
  1422.     .dc.b    1, 1, 1            * func 122
  1423.     .dc.b    1, 1, 1            * func 123
  1424.     .dc.b    0, 1, 1            * func 124
  1425.     .dc.b    0, 1, 2            * func 125
  1426.  
  1427.     .bss
  1428.     .even
  1429. __base:        .ds.l    1            *    -> Base Page
  1430. __break:    .ds.l    1            *    Break function
  1431. ___cpmrv:    .ds.w    1            *    Last CP/M return val
  1432.  
  1433.  
  1434.  
  1435. *
  1436. *
  1437. .globl    _brk
  1438.         .text
  1439. _brk:        
  1440.         movea.l    4(sp),a0        *    New break?
  1441.         move.l     a0,d0
  1442.         lea    $100(a0),a0        *    Chicken factor
  1443.         cmpa.l    a0,sp            *    Compare
  1444.         bhis    brkok            *    OK, continue
  1445.         move.l    #-1,d0            *    Load return reg
  1446.         rts                *    Return
  1447. brkok:
  1448.         move.l    d0,__break        *    Save the break
  1449.         clr.l    d0            *    Set OK return
  1450.         rts                *    return
  1451.         
  1452. .globl    ___BDOS
  1453. ___BDOS:    link    a6,#0            *    link
  1454.         move.w    8(sp),d0        *    Load func code
  1455.         move.l    10(sp),d1        *    Load Paramter
  1456.         trap    #2            *    Enter BDOS
  1457.         cmpa.l    __break,sp        *    Check for stack ovf
  1458.         bhis    noovf            *    NO overflow, continue
  1459. __sovf:        move.w    #prtstr,d0        *    String print
  1460.         lea    ovf,a0            *    a0-> message
  1461.         move.l    a0,d1            *    load proper reg
  1462.         trap    #2            *    Issue message
  1463. __exit:        move.w    #exit,d0        *    Exit
  1464.         trap    #2            *        now
  1465. noovf:                        *    Here if all OK
  1466.         unlk    a6            *
  1467.         rts                *    Back to caller
  1468. *
  1469. *    Block Fill function:
  1470. *
  1471. *    blkfill(dest,char,cnt);
  1472. *
  1473. *    BYTE    *dest;        /* -> area to be filled    */
  1474. *    BYTE    char;        /* =  char to fill    */
  1475. *    WORD    cnt;        /* =  # bytes to fill   */
  1476. *
  1477.     .globl    _blkfill
  1478. _blkfill:
  1479.     move.l    4(a7),a0            *    -> Output area
  1480.     move.w    8(a7),d1            *    =  output char
  1481.     move.w    10(a7),d0            *    =  output count
  1482.     ext.l    d0                *    make it long
  1483.     subq.l    #1,d0                *    decrement
  1484.     ble    filldone            *    Done if le
  1485. fillit:    move.b    d1,(a0)+            *    move a byte
  1486.     dbra    d0,fillit            *    Continue
  1487. filldone: clr.l    d0                *    always return 0
  1488.     rts                    *
  1489.  
  1490. *
  1491. *    Index function to find out if a particular character is in a string.
  1492. *
  1493.     .globl    _index
  1494.     .globl    _strchr
  1495. _index:
  1496. _strchr:
  1497.     move.l    4(a7),a0            *    a0 -> String
  1498.     move.w    8(a7),d0            *    D0 = desired character
  1499. xindex:    tst.b    (a0)                *    EOS?
  1500.     bne    notend                *    No, continue to look
  1501.     clr.l    d0                *    Not found
  1502.     rts                    *    Quit
  1503. notend:    cmp.b    (a0)+,d0            *    check for character
  1504.     bne    xindex                *    
  1505.     move.l    a0,d0                *    Found it
  1506.     subq.l    #1,d0                *    set return pointer
  1507.     rts                    *
  1508. *
  1509. *    Data area
  1510. *
  1511.         .data
  1512.         .globl    ___pname        *    Program Name
  1513.         .globl    ___tname        *    Terminal Name
  1514.         .globl    ___lname        *    List device name
  1515.         .globl    ___xeof            *    ^Z byte
  1516. ovf:        .dc.b    'Stack Overflow$'    *    Error message
  1517. ___pname:    .dc.b    'C runtime',0        *    Program name
  1518. ___tname:    .dc.b    'CON:',0        *    Console name
  1519. ___lname:    .dc.b    'LST:',0        *    List device name
  1520. ___xeof:    .dc.b    $1a            *    Control-Z
  1521.         .end
  1522. SHAR_EOF
  1523. cat << \SHAR_EOF > sys/atari/getn.s
  1524. * Routines to read the size of the display.
  1525. * MicroEMACS works even on a screen that has been blessed
  1526. * by the "hi50" program.
  1527. * MicroEMACS version 30, for the Atari.
  1528.  
  1529.     .text
  1530.  
  1531. * getnrow() -- get number of rows.
  1532.  
  1533.     .globl    _getnrow
  1534.  
  1535. _getnrow:
  1536.  
  1537.     move.l    a2, -(sp)
  1538.     move.l    d2, -(sp)
  1539.     dc.w    $A000
  1540.     move.l    (sp)+, d2
  1541.     movea.l    (sp)+, a2
  1542.  
  1543.     move.w    -42(a0), d0
  1544.     addq.w    #1, d0
  1545.     ext.l    d0
  1546.  
  1547.     rts
  1548.  
  1549. * getncol() -- get number of columns.
  1550.  
  1551.     .globl    _getncol
  1552.  
  1553. _getncol:
  1554.     move.l    a2, -(sp)
  1555.     move.l    d2, -(sp)
  1556.     dc.w    $A000
  1557.     move.l    (sp)+, d2
  1558.     movea.l    (sp)+, a2
  1559.  
  1560.     move.w    -44(a0), d0
  1561.     addq.w    #1, d0
  1562.     ext.l    d0
  1563.  
  1564.     rts
  1565. SHAR_EOF
  1566. cat << \SHAR_EOF > sys/atari/makesys.mwc
  1567. #
  1568. # MWC Makefile for MG (Atari ST) -- system library
  1569. #
  1570. #    Marion Hakanson        Jan '88
  1571.  
  1572. # Note that this Makefile expects the sources to be in ..\..\,
  1573. # as do the source files here.
  1574.  
  1575. # SYSLIB and CFLAGS should be defined by the top level Makefile.
  1576. # These are defaults in case this Makefile is called manually.
  1577. SYSLIB    = libsys.a
  1578.  
  1579. CDEFS    = -DPREFIXREGION
  1580. CFLAGS    = -O -DMWC $(CDEFS)
  1581.  
  1582. OBJ    = cinfo.o fileio.o misc.o term.o ttyio.o
  1583. IND    = diredsup.o alloc.o getn.o
  1584. OBJS    = $(OBJ) $(IND)
  1585. INC    = ..\..\def.h
  1586. OINC    = chrdef.h sysdef.h ttydef.h
  1587.  
  1588.  
  1589. all:    $(SYSLIB)
  1590.     @echo $(SYSLIB) completed.
  1591.  
  1592. $(SYSLIB): $(OBJS)
  1593.     ar rcv $@ $?
  1594.  
  1595.  
  1596. $(OBJ):        $(INC) $(OINC)
  1597.  
  1598. diredsup.o:    $(INC) $(OINC) ..\..\kbd.h
  1599.  
  1600. getn.o:        getn.s
  1601.     as68toas < $? > tmp.s; $(AS) $(ASFLAGS) -o $@ tmp.s; rm tmp.s
  1602.  
  1603.  
  1604. clean:
  1605.     -rm $(OBJS) tmp.s $(SYSLIB)
  1606.  
  1607. SHAR_EOF
  1608. cat << \SHAR_EOF > sys/atari/mg.ini
  1609. (bsmap-mode 1)    ; enable
  1610. ; auto-indent globally
  1611. (global-set-key "\^J" newline)
  1612. (global-set-key "\^M" newline-and-indent)
  1613. ; blink-matching-paren globally
  1614. (global-set-key ")" blink-matching-paren-hack)
  1615. (global-set-key "}" blink-matching-paren-hack)
  1616. (global-set-key "]" blink-matching-paren-hack)
  1617. ; set up special keys (ST)
  1618. (global-set-key "\F21" help)
  1619. (global-set-key "\F21\F21" help-help)
  1620. (global-set-key "\F22" keyboard-quit)
  1621. (global-set-key "\F24" previous-line)
  1622. (global-set-key "\F26" backward-char)
  1623. (global-set-key "\F27" next-line)
  1624. (global-set-key "\F28" forward-char)
  1625. SHAR_EOF
  1626. cat << \SHAR_EOF > sys/atari/mglink.inp
  1627. -u -o ..\..\mg.ttp gemstart.o
  1628.     ..\..\basic.o
  1629.     ..\..\buffer.o
  1630.     ..\..\dir.o
  1631.     ..\..\dired.o
  1632.     ..\..\display.o
  1633.     ..\..\echo.o
  1634.     ..\..\extend.o
  1635.     ..\..\file.o
  1636.     ..\..\help.o
  1637.     ..\..\kbd.o
  1638.     ..\..\keymap.o
  1639.     ..\..\line.o
  1640.     ..\..\macro.o
  1641.     ..\..\main.o
  1642.     ..\..\match.o
  1643.     ..\..\modes.o
  1644.     ..\..\paragrap.o
  1645.     ..\..\random.o
  1646.     ..\..\re_searc.o
  1647.     ..\..\regex.o
  1648.     ..\..\region.o
  1649.     ..\..\search.o
  1650.     ..\..\version.o
  1651.     ..\..\window.o
  1652.     ..\..\word.o
  1653.     alloc.o
  1654.     cinfo.o
  1655.     diredsup.o
  1656.     fileio.o
  1657.     misc.o
  1658.     term.o
  1659.     ttyio.o
  1660.     getn.o
  1661.     C:osbind.o c:gemlib c:libf
  1662. SHAR_EOF
  1663. cat << \SHAR_EOF > sys/atari/misc.c
  1664. /* misc.c -- Miscellaneous ST-specific code for MG.
  1665.  *
  1666.  * author :  Sandra Loosemore
  1667.  * date   :  24 Oct 1987
  1668.  * changes:  Marion Hakanson -- Jan 1988
  1669.  *
  1670.  */
  1671.  
  1672.  
  1673. #include    "..\..\def.h"
  1674.  
  1675. #ifdef MWC
  1676. static char *
  1677. mwc_cpr="Portions of this program, copyright 1984, Mark Williams Co.";
  1678. #endif /* MWC */
  1679.  
  1680.  
  1681. /* Exit as quickly as possible.  */
  1682.  
  1683. VOID panic (s)
  1684.     char* s;
  1685. {   Cconws (s);
  1686.     Pterm (-1);
  1687.     }
  1688.  
  1689.  
  1690. #ifdef MWC
  1691. extern char **environ;
  1692. #else
  1693. typedef struct
  1694.     {
  1695.     char    *p_lowtpa;
  1696.     char    *p_hitpa;
  1697.     char    *p_tbase;
  1698.     long    p_tlen;
  1699.     char    *p_dbase;
  1700.     long    p_dlen;
  1701.     char    *p_bbase;
  1702.     long    p_blen;
  1703.     char    *p_dta;
  1704.     char    *p_parent;
  1705.     char    *p_reserved;
  1706.     char    *p_env;
  1707.     long    p_undefined[20];
  1708.     char    p_cmdlin[128];
  1709.     }
  1710.     BASEPAGE;
  1711.  
  1712. extern BASEPAGE *_base;
  1713. #endif /* MWC */
  1714.  
  1715.  
  1716. /*
  1717.  * The environment code here is borrowed from Dale Schumacher.
  1718.  */
  1719.  
  1720. static char *findenv(var)
  1721.     register char *var;
  1722. /*
  1723.  *    INTERNAL FUNCTION.  This functions attempts to locate <var> in
  1724.  *    the environment.  If <var> is not found, NULL is returned.  If
  1725.  *    the environment is NULL, NULL is returned.  If <var> is found,
  1726.  *    a pointer to the beginning of <var> in the environment is returned.
  1727.  *    BOTH MS-DOS AND TOS ENVIRONMENT FORMATS ARE ACCOMODATED.
  1728.  */
  1729.     {
  1730.     register char *p;
  1731.     register int len;
  1732.  
  1733. #ifdef MWC
  1734.     if((p = *environ) == NULL)
  1735. #else
  1736.     if((p = _base->p_env) == NULL)
  1737. #endif /* MWC */
  1738.         return(NULL);
  1739.     len = strlen(var);
  1740.     while(*p)
  1741.         {
  1742.         if(!strncmp(p, var, len) && (p[len] == '='))
  1743.             return(p);
  1744.         while(*p++)        /* move to next arg */
  1745.             ;
  1746.         }
  1747.     return(NULL);
  1748.     }
  1749.  
  1750.  
  1751. char *getenv(var)
  1752.     register char *var;
  1753. /*
  1754.  *    Search for <var> in the environment.  If <var> is found, a pointer
  1755.  *    to it's value is returned.  NULL is returned if <var> is not found.
  1756.  *    WARNING:  The returned pointer points into the environment and
  1757.  *    must not be modified!
  1758.  */
  1759.     {
  1760.     register char *p, *q;
  1761.     register int len;
  1762.  
  1763.     len = strlen(var);
  1764.     if(p = findenv(var))
  1765.         {
  1766.         p += (len + 1);
  1767.         if(*p == '\0')        /* TOS env format or empty value */
  1768.             {
  1769.             q = p+1;
  1770.             if(*q == '\0')        /* empty value + end of env */
  1771.                 return(p);
  1772.             while(*q && (*q != '='))
  1773.                 ++q;
  1774.             if(*q)            /* empty value */
  1775.                 return(p);
  1776.             else            /* TOS env format */
  1777.                 return(p+1);
  1778.             }
  1779.         }
  1780.     return(p);
  1781.     }
  1782.  
  1783.  
  1784. /* Spawn a command.  You can run anything from this; it prompts you for
  1785.  *    the command to run.
  1786.  * I check for the two most common problems with Pexec:  not finding the
  1787.  *    file, and not having enough memory.  Otherwise, I assume bad status
  1788.  *    codes were the fault of the program, not Pexec, and that the program
  1789.  *    would have told the user what is wrong.
  1790.  */
  1791.  
  1792. spawncli(f, n)
  1793. {   register int s;
  1794.     char fname[NFILEN];
  1795.     char tail[NFILEN];
  1796.     char *shell = getenv("SHELL");
  1797.     extern VOID splitcmd();
  1798.    
  1799.     if (shell && *shell) {
  1800.         (VOID) strcpy(fname, shell);
  1801.         goto tryit;
  1802.     }
  1803.     else
  1804.         shell = NULL;
  1805.     
  1806. askfor:
  1807.     if ((s = ereply("Run program: ", fname, NFILEN)) != TRUE)
  1808.         return (s);
  1809. tryit:
  1810.     ttcolor (CTEXT);
  1811.     ttmove (nrow-1, 0);
  1812.     tteeol ();
  1813.     splitcmd (fname, tail);
  1814.     ttclose ();
  1815.     s = Pexec(0, fname, tail, 0L);
  1816.     ttopen ();
  1817.     if (s == -33) {
  1818.         if (shell) {
  1819.         shell = NULL;
  1820.             ewprintf ("Could not find shell.");
  1821.             sleep(1);
  1822.             goto askfor;
  1823.         }
  1824.         ewprintf ("Could not find file.");
  1825.         return (FALSE);
  1826.     }
  1827.     else if (s == -39) {
  1828.         if (shell) {
  1829.         shell = NULL;
  1830.             ewprintf ("Not enough memory to run shell!");
  1831.             sleep(1);
  1832.             goto askfor;
  1833.         }
  1834.         ewprintf ("Not enough memory to run this program!");
  1835.         return (FALSE);
  1836.     }
  1837.     else {
  1838.         sgarbf = TRUE;          /* Force repaint */
  1839.         Cconws ("Hit any key to return to MG:");
  1840.         (VOID) Crawcin ();
  1841.         return (TRUE);
  1842.         }
  1843. }
  1844.  
  1845.  
  1846. /* Pexec wants the command tail to have a byte count as the first
  1847.  *    character.  This function separates the program name from the command
  1848.  *    tail and adds the byte count.
  1849.  */
  1850.  
  1851. static VOID splitcmd (cmd, tail)
  1852.     char* cmd;
  1853.     char* tail;
  1854. {   int i, j;
  1855.     i = 0;
  1856.     j = 0;
  1857.     while (cmd[i] != '\0') {
  1858.         if (j != 0)  { 
  1859.         tail[j] = cmd[i]; 
  1860.         j++;
  1861.             }
  1862.         else if (cmd[i] == ' ')  {
  1863.             cmd[i] = '\0';
  1864.             tail[1] = ' ';
  1865.             j = 2;
  1866.         }
  1867.         i++;
  1868.         }
  1869.     if (j == 0)  {
  1870.         tail[0] = (char) 1;
  1871.         tail[1] = ' ';
  1872.         tail[2] = '\0';
  1873.         }
  1874.     else {
  1875.         tail[j+1] = '\0';
  1876.         tail[0] = (char) (j-1);
  1877.         }
  1878.     }
  1879.  
  1880.  
  1881.  
  1882.  
  1883. /*
  1884.  * copy 'count' bytes from 'src' to 'dst'. (optimized)
  1885.  */
  1886. VOID bcopy(src, dst, count)
  1887. register char *src, *dst;
  1888. register count;
  1889. {
  1890.     register c1;
  1891.  
  1892.     /*
  1893.     ** The magic number 8 comes from:
  1894.     **   1   max. bytes before a word boundary
  1895.     **   4   min. bytes in a block of long-words
  1896.     **   3   max. bytes after the last long-word in the block
  1897.     */
  1898.     if (count >= 8) {
  1899.         /*
  1900.         ** Advance dst pointer to word boundary.
  1901.         */
  1902.         if (1 & (short)dst) {
  1903.             *dst++ = *src++;
  1904.                 count--;
  1905.     }
  1906.         /*
  1907.         ** If src pointer is (also) aligned, use long-word copy.
  1908.         */
  1909.         if ((1 & (short)src) == 0) {
  1910.             c1 = ((unsigned)count >> 2);
  1911.             while (--c1 >= 0)
  1912.                 *((long *)dst)++ = *((long *)src)++;
  1913.             count &= 3;        /* There are 0,1,2, or 3 bytes left */
  1914.         }
  1915.     }
  1916.     /*
  1917.     ** Copy whatever is left.
  1918.     */
  1919.     while (--count >= 0)
  1920.     *dst++ = *src++;
  1921. }
  1922.  
  1923. /* Busy waiting to fake out sleep.  Thanks to Rich Sansom for the routine
  1924.  *    to poll the system clock.
  1925.  */
  1926.  
  1927. static long *hz_200 = (long *)0x000004ba;    /* system 200 hz clock        */
  1928.  
  1929. #ifdef NO_DPROMPT
  1930. static long read200hz()
  1931. #else
  1932. long read200hz()
  1933. #endif /* NO_DPROMPT */
  1934. {   return(*hz_200);
  1935.     }
  1936.  
  1937.  
  1938. /* Sleep (busily) for n seconds */
  1939.  
  1940. sleep (n)
  1941.     int n;
  1942. {   register long waitfor = (n * 200) + Supexec(read200hz);
  1943.  
  1944.     while (Supexec(read200hz) < waitfor);
  1945.     }
  1946.  
  1947. SHAR_EOF
  1948. cat << \SHAR_EOF > sys/atari/sysdef.h
  1949. /* sysdef.h --  MG header file for Atari ST
  1950.  *
  1951.  * author :  Sandra Loosemore
  1952.  * date   :  24 Oct 1987
  1953.  *
  1954.  */
  1955.  
  1956. #define    NULL    0L            /* So who needs stdio.h?    */
  1957. #include    <osbind.h>
  1958.  
  1959. /* This definition might be missing from your osbind.h */
  1960.  
  1961. #ifndef Supexec
  1962. #define Supexec(a)  xbios(38,a)
  1963. #endif
  1964.  
  1965.  
  1966. #define    KBLOCK        512        /* Kill grow.            */
  1967. #define    GOOD        0        /* Good exit status.        */
  1968. #define NO_VOID_TYPE    1        /* "void" is not a builtin type */
  1969. #ifdef MWC
  1970. #undef    NO_VOID_TYPE
  1971. #define    ZEROARRAY            /* See def.h            */
  1972.     /*
  1973.      * Using the MWC shell, ARGV is always the last environment entry
  1974.      * (if ARGV is not defined, the program was not started from the
  1975.      * MWC shell).  The last environment variable is followed by
  1976.      * the string pointed to by argv[0], then argv[1], etc.  This
  1977.      * means that the non-MWC getenv() in misc.c will take command line
  1978.      * args as environment variables.  It also means that if spawn()
  1979.      * (misc.c) runs the MWC shell, the shell takes this program's args
  1980.      * as its own.  So here we truncate the environment by zeroing out
  1981.      * the first character of argv[0], thus working around both problems.
  1982.      */
  1983. #define SYSINIT (*(argv[0]) = 0)    /* run in main()         */
  1984. #endif /* MWC */
  1985.  
  1986. #define MALLOCROUND(m) ((m)+=1,(m)&=~1)    /* 2-byte blocks (see alloc.c)    */
  1987. #define LOCAL_VARARGS    1        /* For echo.c            */
  1988. #define RSIZE long            /* Type for file/region sizes   */
  1989. #define KCHAR int                       /* 16 bits for keystrokes       */
  1990.  
  1991.  
  1992. /* Enable various things */
  1993.  
  1994. #define DO_METAKEY    1        /* Meta key code */
  1995. #define METABIT        0x200
  1996. #define FKEYS        1        /* Enable fkey code */
  1997. #define GOSMACS     1        /* Goslings compatibility functions */
  1998. #define PREFIXREGION    1        /* Enable prefix-region function */
  1999. #define BSMAP        FALSE        /* BSMAP code, default to off */
  2000.  
  2001. /* Disable some features for now. */
  2002.  
  2003. #define NO_BACKUP    1
  2004.  
  2005.  
  2006. /* Alcyon thinks subtracting two pointers gives a long.  Cast it to int.
  2007.  */
  2008.  
  2009. #define OFFSET(type,member) ((int)((char *)&(((type *)0)->member)-(char *)((type *)0)))
  2010. #ifdef MWC
  2011. #undef    OFFSET
  2012. #endif /* MWC */
  2013.  
  2014. /*
  2015.  * Macros used by the buffer name making code.
  2016.  * Start at the end of the file name, scan to the left
  2017.  * until BDC1 (or BDC2, if defined) is reached. The buffer
  2018.  * name starts just to the right of that location, and
  2019.  * stops at end of string (or at the next BDC3 character,
  2020.  * if defined). BDC2 and BDC3 are mainly for VMS.
  2021.  */
  2022.  
  2023. #define    BDC1    '\\'            /* Buffer names.        */
  2024. #define    BDC2    ':'
  2025.  
  2026.  
  2027. #define fncmp strcmp            /* All filenames are lowercased */
  2028. extern char *strncpy();
  2029.  
  2030. SHAR_EOF
  2031. cat << \SHAR_EOF > sys/atari/term.c
  2032. /* term.c -- screen output code for Atari ST terminal
  2033.  *
  2034.  * author :  Sandra Loosemore (based on an earlier version by dec-rec!conroy)
  2035.  * date   :  24 Oct 1987
  2036.  * changes:  Marion Hakanson -- Jan 1988
  2037.  *
  2038.  * This code simulates scrolling regions by using the
  2039.  * insert line and delete line functions. Should display
  2040.  * handling be taught about this. Based on Rich's code
  2041.  * for the Heath H19.
  2042.  */
  2043.  
  2044. #include    "..\..\def.h"
  2045.  
  2046. #define    BEL    0x07            /* BEL character.        */
  2047. #define    ESC    0x1B            /* ESC character.        */
  2048. #define    LF    0x0A            /* Line feed.            */
  2049.  
  2050. extern int ttrow;
  2051. extern int ttcol;
  2052. extern int tttop;
  2053. extern int ttbot;
  2054. extern int tthue;
  2055.  
  2056. int    tceeol    =    2;        /* Costs.            */
  2057. int    tcinsl, tcdell;            /* Set in ttyio.c:ttopen()    */
  2058.  
  2059.  
  2060. /* Move the cursor to the specified origin 0 row and column position.  Try
  2061.  *    to optimize out extra moves; redisplay may have left the cursor in 
  2062.  *    the right location on the screen last time.
  2063.  */
  2064.  
  2065. VOID ttmove(row, col)
  2066. {   if (ttrow!=row || ttcol!=col) {
  2067.     if (row > nrow)
  2068.         row = nrow;
  2069.     if (col > ncol)
  2070.         col = ncol;
  2071.     ttputc(ESC);
  2072.     ttputc('Y');
  2073.     ttputc(row+' ');
  2074.     ttputc(col+' ');
  2075.     ttrow = row;
  2076.     ttcol = col;
  2077.     }
  2078.     }
  2079.  
  2080.  
  2081. /* Erase to end of line. */
  2082.  
  2083. VOID tteeol()
  2084. {   ttputc(ESC);
  2085.     ttputc('K');
  2086.     }
  2087.  
  2088.  
  2089. /* Erase to end of page. */
  2090.  
  2091. VOID tteeop()
  2092. {   ttputc(ESC);
  2093.     ttputc('J');
  2094.     }
  2095.  
  2096.  
  2097. /* Make a noise.  */
  2098.  
  2099. VOID ttbeep()
  2100. {   ttputc(BEL);
  2101.     ttflush();
  2102.     }
  2103.  
  2104.  
  2105. /* Insert nchunk blank line(s) onto the screen, scrolling the last line on
  2106.  *    the screen off the bottom. This is done with a cluster of clever 
  2107.  *    insert and delete commands, because there are no scroll regions.
  2108.  */
  2109.  
  2110. VOID ttinsl(row, bot, nchunk)
  2111. {   register int    i;
  2112.     if (row == bot) {
  2113.     ttmove(row, 0);
  2114.     tteeol();
  2115.     return;
  2116.     }
  2117.     ttmove(1+bot-nchunk, 0);
  2118.     for (i=0; i<nchunk; i++) {
  2119.     ttputc(ESC);
  2120.     ttputc('M');
  2121.     }
  2122.     ttmove(row, 0);
  2123.     for (i=0; i<nchunk; i++) {
  2124.     ttputc(ESC);
  2125.     ttputc('L');
  2126.     }
  2127.     ttrow = row;
  2128.     ttcol = 0;
  2129.     }
  2130.  
  2131.  
  2132. /* Delete nchunk line(s) at "row", replacing the bottom line on the screen
  2133.  *    with a blank line. This is done with a crafty sequences of insert 
  2134.  *    and delete line sequences since there is no scroll region.  The
  2135.  *     presence of the echo area makes a boundary condition go away.
  2136.  */
  2137.  
  2138. VOID ttdell(row, bot, nchunk)
  2139. {   register int    i;
  2140.     if (row == bot) {
  2141.     ttmove(row, 0);
  2142.     tteeol();
  2143.     return;
  2144.     }
  2145.     ttmove(row, 0);
  2146.     for (i=0; i<nchunk; i++) {
  2147.     ttputc(ESC);
  2148.     ttputc('M');
  2149.     }
  2150.     ttmove(1+bot-nchunk,0);
  2151.     for (i=0; i<nchunk; i++) {
  2152.     ttputc(ESC);
  2153.     ttputc('L');
  2154.     }
  2155.     ttrow = 1+bot-nchunk;
  2156.     ttcol = 0;
  2157.     }
  2158.  
  2159.  
  2160. /* Set display color.  Normal video is text color.  Reverse video is used
  2161.  *     for the mode line.
  2162.  */
  2163.  
  2164. VOID ttcolor(color)
  2165.     register int color;
  2166. {   if (color != tthue) {
  2167.     if (color == CTEXT) {        /* Normal video.    */
  2168.         ttputc(ESC);
  2169.         ttputc('q');
  2170.         } 
  2171.     else if (color == CMODE) {    /* Reverse video.    */
  2172.         ttputc(ESC);
  2173.         ttputc('p');
  2174.         }
  2175.     tthue = color;
  2176.     }
  2177.     }
  2178. SHAR_EOF
  2179. cat << \SHAR_EOF > sys/atari/ttydef.h
  2180. /*
  2181.  * Name:    MicroEMACS
  2182.  *        Atari 520ST header file.
  2183.  * Version:    30
  2184.  * Last edit:    22-Feb-86
  2185.  * By:        rex::conroy
  2186.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  2187.  */
  2188. #define    GOSLING    1            /* Use fancy redisplay.        */
  2189.  
  2190. #define    NROW    50            /* The "50" is big enough to    */
  2191. #define    NCOL    80            /* deal with the "hi50" screen.    */
  2192.  
  2193. /*
  2194.  * Special keys.
  2195.  */
  2196.  
  2197. #define KFIRST    256
  2198. #define KLAST   284
  2199.  
  2200.  
  2201. /* These i/o functions are NOP's or direct equivalents of BIOS calls.
  2202.  *    Make them #define's so we don't have to go through a useless
  2203.  *    level of indirection.
  2204.  */
  2205.  
  2206. #define ttinit()
  2207. #define tttidy()
  2208. #define ttwindow(top,bot) (top, bot)
  2209. #define ttresize()
  2210. #define ttnowindow()
  2211. #define ttputc(c) Bconout(2, c)        /* Primitive output function    */
  2212. #define ttflush()                    /* A NOP            */
  2213. #define typeahead() ((int)Bconstat(2))    /* Check if there is input    */
  2214. SHAR_EOF
  2215. cat << \SHAR_EOF > sys/atari/ttyio.c
  2216. /* ttyio.c -- Low-level Atari ST terminal input/output handling
  2217.  *
  2218.  * author :  Sandra Loosemore (from an earlier version by dec-rex!conroy)
  2219.  * date   :  24 Oct 1987
  2220.  * changes:  Marion Hakanson -- Jan 1988
  2221.  *
  2222.  */
  2223.  
  2224. #include    "..\..\def.h"
  2225.  
  2226. int    nrow;                /* Terminal size, rows.        */
  2227. int    ncol;                /* Terminal size, columns.    */
  2228.  
  2229. #ifdef DO_METAKEY
  2230. #define RSHIFT   (0x01)
  2231. #define LSHIFT     (0x02)
  2232. #define CTRL     (0x04)
  2233. #define ALTKEY     (0x08)
  2234. #define CAPSLOCK (0x10)
  2235.  
  2236. static struct keytab {
  2237.     char *unshift;
  2238.     char *shift;
  2239.     char *capslock;
  2240.     } *keytable;
  2241.  
  2242.  
  2243. /* Mess with the bit that controls whether we get back all the shift keys
  2244.  *    on each keystroke.
  2245.  */
  2246.  
  2247. static unsigned char oldconterm;
  2248. static unsigned char *conterm = (char *)0x00000484;
  2249.  
  2250. static savect ()
  2251. {   oldconterm = *conterm;
  2252.     *conterm = (oldconterm | 0x8);
  2253.     }
  2254.  
  2255. static restct ()
  2256. {   *conterm = oldconterm;
  2257.     }
  2258. #endif /* DO_METAKEY */
  2259.  
  2260.  
  2261. /* Setup routines.  "getnrow" and "getncol" are assembly language routines.
  2262.  */
  2263.  
  2264. VOID ttopen()
  2265. {   nrow = getnrow();
  2266.     if (nrow > NROW)
  2267.     nrow = NROW;
  2268.     ncol = getncol();
  2269.     if (ncol > NCOL)
  2270.     ncol = NCOL;
  2271.     tcinsl = tcdell = (nrow * 2) + (ncol / 10);
  2272. #ifdef DO_METAKEY
  2273.     (VOID) Supexec(savect);
  2274.     keytable = (struct keytab *)Keytbl(-1L,-1L,-1L);
  2275. #endif /* DO_METAKEY */
  2276.     }
  2277.  
  2278. VOID ttclose()
  2279. {
  2280. #ifdef DO_METAKEY
  2281.     (VOID) Supexec(restct);
  2282. #endif /* DO_METAKEY */
  2283.     }
  2284.  
  2285.  
  2286. /* Keystrokes are returned as 10-bit quantities.
  2287.  *
  2288.  * Codes 0-255 are used for the usual character set.
  2289.  * Codes 256-511 are used for function keys.
  2290.  * Bit 10 (0x200) is the meta bit.
  2291.  *
  2292.  */
  2293. #ifdef FKEYS
  2294.  
  2295. static int keycodes[] = {
  2296.     0x00,    /* dummy for F0 entry */
  2297.     0x3b,    0x3c,    0x3d,    0x3e,    0x3f,
  2298.     0x40,    0x41,    0x42,    0x43,    0x44,
  2299.     0x54,    0x55,    0x56,    0x57,    0x58,
  2300.     0x59,    0x5a,    0x5b,    0x5c,    0x5d,
  2301.     0x62,    0x61,    0x52,    0x48,    0x47,
  2302.     0x4b,    0x50,    0x4d
  2303.         };
  2304.  
  2305. char *keystrings[] = {
  2306. "",        /* dummy for F0 entry */
  2307. "F1",        "F2",        "F3",        "F4",        "F5",
  2308. "F6",        "F7",        "F8",        "F9",        "F10",
  2309. "F11",        "F12",        "F13",        "F14",        "F15",
  2310. "F16",        "F17",        "F18",        "F19",        "F20",
  2311. "Help",        "Undo",        "Insert",    "Up",        "Clr/Home",
  2312. "Left",        "Down",        "Right"
  2313. };
  2314. #endif /* FKEYS */
  2315.  
  2316. /* Use the ALT key as a meta key.  The problem with this is that it
  2317.  *    appears to trash the ascii key code in the low order byte.
  2318.  *    Therefore, we have to resort to looking up the key in the
  2319.  *    system keystroke translation table.
  2320.  * Some non-US keyboards apparently use some ALT combinations to
  2321.  *    get real, printing characters.  If you've got one of these
  2322.  *    beasts you can use meta-key-mode to turn off recognition
  2323.  *    of the ALT key, in which case this routine just returns
  2324.  *    whatever BIOS gave as the key value.  If that approach is
  2325.  *    distasteful, you can also bind a function key to return
  2326.  *    the ALT characters usurped by the meta key mode.
  2327.  */
  2328.  
  2329. KCHAR getkbd()
  2330. {   register int code, bchar;
  2331. #ifdef FKEYS
  2332.     register int i;
  2333. #endif /* FKEYS */
  2334. #ifdef DO_METAKEY
  2335.     register int shifts;
  2336.     extern int use_metakey;        /* set in the generic kbd.c */
  2337. #endif /* DO_METAKEY */
  2338.     union {
  2339.         unsigned long k_rawkey;
  2340.         struct {
  2341.             unsigned char kb_shifts;    /* shift bits */
  2342.             unsigned char kb_code;    /* scan code */
  2343.             unsigned char kb_notused;
  2344.             unsigned char kb_bchar;    /* bios char */
  2345.         } k_break;
  2346.     } keyval;
  2347.  
  2348.     keyval.k_rawkey = Bconin(2);
  2349.     code   = keyval.k_break.kb_code;
  2350.  
  2351. #ifdef FKEYS
  2352.     for (i=KFIRST; i<=KLAST; i++)            /* Was it an Fkey? */
  2353.         if (code == keycodes[i-KFIRST])
  2354.         return((KCHAR)i);
  2355. #endif /* FKEYS */
  2356.  
  2357.     bchar  = keyval.k_break.kb_bchar;
  2358. #ifdef DO_METAKEY
  2359.     shifts = keyval.k_break.kb_shifts;
  2360.  
  2361.     /*
  2362.      * Rule out the case where some shift bit other than what
  2363.      * we're interested in is set (if such a beast ever exists).
  2364.      * If otherwise, just forget about any special handling here.
  2365.      */
  2366.     if (use_metakey == TRUE &&
  2367.             (shifts & ~(CTRL|LSHIFT|RSHIFT|CAPSLOCK)) == ALTKEY)
  2368.         if ((shifts & (CTRL|LSHIFT|RSHIFT|CAPSLOCK)) == 0) /* ALTKEY only */
  2369.         return ((KCHAR)(keytable->unshift[code] | METABIT));
  2370.         else if (shifts & CTRL)
  2371.         return ((KCHAR)(bchar | METABIT));
  2372.         else if (shifts & (LSHIFT|RSHIFT))
  2373.         return ((KCHAR)(keytable->shift[code] | METABIT));
  2374.         else /* (shifts & CAPSLOCK) */
  2375.         return ((KCHAR)(keytable->capslock[code] | METABIT));
  2376.     else
  2377.         return ((KCHAR)bchar);
  2378. #else
  2379.     return ((KCHAR)bchar);
  2380. #endif
  2381.     }
  2382.  
  2383. /* Establish default keypad bindings.  I've only done the arrow keys
  2384.  *    here.
  2385.  */
  2386.  
  2387.  
  2388. VOID ttykeymapinit() { 
  2389. /*  excline("global-set-key f13 previous-line"); */    /* Up arrow */
  2390. /*  excline("global-set-key f15 backward-char"); */     /* Left arrow */  
  2391. /*  excline("global-set-key f16 next-line"); */        /* Down arrow */
  2392. /*  excline("global-set-key f17 forward-char"); */        /* Right arrow */
  2393.     }
  2394.  
  2395.  
  2396. #ifndef NO_DPROMPT
  2397. /*
  2398.  * Return TRUE if we busy-wait for 2 seconds without any keystrokes;
  2399.  * otherwise return FALSE.  See sleep() in misc.c for details.
  2400.  */
  2401.  
  2402. ttwait() {
  2403.     extern long read200hz();
  2404.     register keyhit;
  2405.     register long waitfor = 400L + Supexec(read200hz);
  2406.  
  2407.     while ((keyhit = typeahead()) == 0 && Supexec(read200hz) < waitfor);
  2408.     if (keyhit)
  2409.         return FALSE;
  2410.  
  2411.     return TRUE;
  2412.     }
  2413. #endif /* NO_DPROMPT */
  2414.  
  2415.  
  2416. SHAR_EOF
  2417. cat << \SHAR_EOF > sys/atari/varargs.h
  2418. /*
  2419.  * Varargs, for use on Atari ST (works with MWC, probably others).
  2420.  *    Came from AmigaDOS version, which was borrowed from 4BSD.
  2421.  */
  2422.  
  2423. typedef char        *va_list;
  2424. #define va_dcl        int va_alist;
  2425. #define va_start(pv)    pv = (char *) &va_alist
  2426. #define va_end(pv)    /* Naught to do... */
  2427. #define va_arg(pv, t)    ((t *) (pv += sizeof(t)))[-1]
  2428. SHAR_EOF
  2429. #    End of shell archive
  2430. exit 0
  2431. -------
  2432.