home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff285.lzh / 'Liner / Source / 'Liner.c < prev    next >
C/C++ Source or Header  |  1989-11-28  |  35KB  |  1,156 lines

  1.  
  2. /*'Liner Version 1.32.  Written by Dave Schreiber                        */
  3. /*©1988, 1989 Dave Schreiber.  All Rights Reserved.                      */
  4. /*1.32 completed Monday, October 31, 1989                                */
  5. /*1.31 completed Friday, October 6, 1989                                 */
  6. /*1.3 completed Saturday, February 25, 1989                              */
  7. /*1.2 completed Friday, November 11, 1988                                */
  8. /*1.1 completed Friday, October 14, 1988                                 */
  9. /*1.0 completed Friday, September 9, 1988                                */
  10.  
  11. /*Compiled with Lattice C V5.02                                          */
  12. /*To compile:  1> lc -cw -j30 -L+YAFR:YAFR.o 'Liner                      */
  13. /*You must assign YAFR: to the directory where YAFR.o is stored.         */
  14. /*You must also assign LINER: to the directory where the 'Liner source   */
  15. /*is located.                                                            */
  16.  
  17. /*'Liner is an outliner, with up to six levels of depth, and up to       */
  18. /*26 items per level (each isolated section).  It has both clipboard and */
  19. /*non-clipboard support of CUT, COPY, and PASTE.  It can output files    */
  20. /*in its own format, or in ASCII (to disk or printer).  It can read files*/
  21. /*in its own format only.  It uses dynamic memory allocation to allow    */
  22. /*an infinite number of items (memory providing).*/
  23.  
  24. /*Amiga features of note that are used:                                  */
  25. /*console device, disk i/o, printer i/o, clipboard i/o                   */
  26.  
  27. /*Intuition objects (screen, windows, gadgets, menus, etc.) generated by */
  28. /*PowerWindows Version 2.0*/
  29.  
  30. /*V1.1 corrects some bugs, doubles the number of characters available    */
  31. /*for filenames, and improves PrintItemList() so that it doesn't always  */
  32. /*print the entire item list*/
  33.  
  34. /*1.2 allows the toggling between 640x200 & 640x400 screens and the      */
  35. /*choice of the order that levels appear in, has a completely reworked   */
  36. /*About... window, lets the user change the level of all the items       */
  37. /*in a highlighted block, and now displays the current filename          */
  38. /*in the title bar.*/
  39.  
  40. /*1.3 adds support for user-selected keymaps, and now prints an asterisk */
  41. /*in the title bar if an outline has been edited but not saved.  It also */
  42. /*includes my very own file requester, YAFR (Yet Another File Requester) */
  43. /*based in principal upon Charlie Heath's, but with a lot more buttons.  */
  44.  
  45. /*1.31 changes the default device where files are located from DF0: to   */
  46. /*the current directory                                                  */
  47.  
  48. /*1.32 fixed a bug that kept the screen from updating properly after a   */
  49. /*paste.  Also uses YAFR V1.1                                            */
  50.  
  51. #include <exec/types.h>
  52. #include <exec/exec.h>
  53. #include <intuition/intuition.h>
  54. #include <devices/console.h>
  55. #include <devices/clipboard.h>
  56. #include <libraries/dos.h>
  57. #include <libraries/dosextens.h>
  58. #include <devices/inputevent.h>
  59. #include <devices/keymap.h>
  60. #include <math.h>
  61.  
  62. struct IntuitionBase *IntuitionBase;
  63. struct GfxBase *GfxBase;
  64. ULONG DosBase;
  65.  
  66. struct IOStdReq *consoleWriteMsg,*consoleReadMsg;
  67. struct Port *consoleWritePort,*consoleReadPort;
  68. struct IOClipReq ClipboardIO;
  69. struct MsgPort clipboardMsgPort;
  70. struct Process *ThisProc;
  71.  
  72. struct LineItem               /*'Liner structure definition*/
  73.    {
  74.    struct LineItem *NextItem,*PrevItem;
  75.    UBYTE Level,ItemNumber;
  76.    char Text[80];
  77.    };
  78.  
  79. extern struct LineItem *InsertItem(),*FindNext(),*FindPrev();
  80.  
  81.  
  82. struct Screen *Screen;
  83. struct Window *Window,*AboutWindow;
  84. struct KeyMap keymap;
  85. #define Rp Window->RPort;
  86. #define CSI  0x09b
  87. #define SEMI 0x03b
  88. #define NEWPAGE 0x0c
  89. #define CLOSECHAR 0x05c
  90. #define SCRNHEIGHT RowsInScreen
  91. #define REQUESTERCHARS 57
  92. APTR ConsoleDevice;
  93. struct LineItem *CharItem,*StartIItem,*EndIItem,*ClipStart,*ClipEnd;
  94. int ButtonState,PtrX,PtrY,LastX,LastY,InvsMode,StartChar,EndChar,InvY,EndIY;
  95. int BLastX,BLastY,ClipMode,ErrorInTitle=FALSE;
  96. UBYTE Laced,RowsInScreen,StartingLevel,Modified;
  97. char Indent=0;
  98. char DoubleSpc=FALSE;
  99. char FileName[150+33],SDirName[150],SFileName[33],SExt[18];
  100. char PDName[150+33],PDirName[150],PFileName[33],PExt[18];
  101.  
  102. char ScreenTitle[] = {" 'Liner V1.32:  "};
  103.  
  104. #define UP 0
  105. #define DOWN 1
  106. #define NOINV 0
  107. #define LINE_PENDING 1
  108. #define LINE_FWD 2
  109. #define LINE_BACK 3
  110.  
  111. #define BLOCK_PENDING -1
  112. #define BLOCK_DOWN -2
  113. #define BLOCK_UP -3
  114.  
  115. UBYTE OLCPos[6][6]=
  116. {
  117.    {9,13,17,21,25,29},
  118.    {6,10,14,18,22,26},
  119.    {6,10,14,18,22,26},
  120.    {6,10,14,18,22,26},
  121.    {6,10,14,18,22,26},
  122.    {6,10,14,18,22,26}
  123. };
  124.  
  125. /*Some macros*/
  126. #define PERPOS(x) OLCPos[StartingLevel][x]-3
  127. #define MinX(LI)  OLCPos[StartingLevel][(LI->Level)-1]
  128. #define MaxX(LI)  OLCPos[StartingLevel][(LI->Level)-1]+strlen(LI->Text)
  129. #define MaxLen(Level) 79-OLCPos[StartingLevel][Level-1]
  130. #define PosInText(Level) CurX-OLCPos[StartingLevel][Level-1]
  131. #define RealLevel(LI) (LI->Level+StartingLevel > 6) ? (LI->Level+StartingLevel-7) : (LI->Level+StartingLevel)
  132.     /* ^^^ == get level when StartingLevel != 0 */
  133. /*Pointers to various LineItems*/
  134. struct LineItem *FirstItem,*LastItem,*CurrentItem,*FirstScrnItem,*ScrnBtm;
  135. int CurX,CurY,DispRows;
  136.  
  137. /*Outline characters*/
  138. char *OutLineChars[6][26]=
  139.    {
  140.       {
  141.       {"I."},{"II."},{"III."},{"IV."},{"V."},{"VI."},{"VII."},{"VIII."},
  142.       {"IX."},{"X."},{"XI."},{"XII."},{"XIII."},{"XIV."},{"XV."},{"XVI."},
  143.       {"XVII."},{"XVIII."},{"XIX."},{"XX."},{"XXI."},{"XXII."},{"XXIII."},
  144.       {"XXIV."},{"XXV."},{"XXVI."}
  145.       },
  146.  
  147.       {
  148.       {"A."},{"B."},{"C."},{"D."},{"E."},{"F."},{"G."},{"H."},{"I."},
  149.       {"J."},{"K."},{"L."},{"M."},{"N."},{"O."},{"P."},{"Q."},{"R."},
  150.       {"S."},{"T."},{"U."},{"V."},{"W."},{"X."},{"Y."},{"Z."}
  151.       },
  152.  
  153.       {
  154.       {"1."},{"2."},{"3."},{"4."},{"5."},{"6."},{"7."},{"8."},{"9."},
  155.       {"10."},{"11."},{"12."},{"13."},{"14."},{"15."},{"16."},{"17."},
  156.       {"18."},{"19."},{"20."},{"21."},{"22."},{"23."},{"24."},{"25."},
  157.       {"26."}
  158.       },
  159.  
  160.       {
  161.       {"a."},{"b."},{"c."},{"d."},{"e."},{"f."},{"g."},{"h."},{"i."},
  162.       {"j."},{"k."},{"l."},{"m."},{"n."},{"o."},{"p."},{"q."},{"r."},
  163.       {"s."},{"t."},{"u."},{"v."},{"w."},{"x."},{"y."},{"z."}
  164.       },
  165.  
  166.       {
  167.       {"1)"},{"2)"},{"3)"},{"4)"},{"5)"},{"6)"},{"7)"},{"8)"},{"9)"},
  168.       {"10)"},{"11)"},{"12)"},{"13)"},{"14)"},{"15)"},{"16)"},{"17)"},
  169.       {"18)"},{"19)"},{"20)"},{"21)"},{"22)"},{"23)"},{"24)"},{"25)"},
  170.       {"26)"}
  171.       },
  172.  
  173.       {
  174.       {"a)"},{"b)"},{"c)"},{"d)"},{"e)"},{"f)"},{"g)"},{"h)"},{"i)"},
  175.       {"j)"},{"k)"},{"l)"},{"m)"},{"n)"},{"o)"},{"p)"},{"q)"},{"r)"},
  176.       {"s)"},{"t)"},{"u)"},{"v)"},{"w)"},{"x)"},{"y)"},{"z)"}
  177.       },
  178.    };
  179.  
  180. /*The position of each special character in the array below*/
  181. int SCPos[]=
  182.    {0,1,4,5,9,13,14,16,17,18,19,20,21,23,25,27,29};
  183.  
  184. /*Special characters (TAB, RETURN, etc.)*/
  185. char SpecChars[]=
  186.    {
  187.    32,
  188.    8,CSI,'P',
  189.    0,
  190.    0x0D,0x0A,CSI,'L',
  191.    0x0D,0x0A,CSI,'L',
  192.    0,
  193.    CSI,'P',
  194.    0,
  195.    0,
  196.    0,
  197.    0,
  198.    0,
  199.    CSI,'A',
  200.    CSI,'B',
  201.    CSI,'C',
  202.    CSI,'D'
  203.    };
  204.  
  205. /*All the other little components of 'Liner*/
  206. #include <liner:mouse.h>
  207. #include <liner:Windows.h>
  208. #include <liner:menu.h>
  209. #include <liner:disk.h>
  210. #include <liner:sure.h>
  211. #include <liner:clip.h>
  212.  
  213. _main()
  214. {
  215.    ULONG Class;
  216.    USHORT Code,Qualifier;
  217.    APTR IAddress;
  218.    SHORT MouseX,MouseY;
  219.    int Seconds,Micros;
  220.    struct IntuiMessage *Message;
  221.  
  222.    char Buffer[200];
  223.    Buffer[0]=NULL;
  224.    FileName[0]=SFileName[0]=SExt[0]=NULL;
  225.    strcpy(SDirName,"");
  226.    strcpy(PDirName,"");
  227.    PDName[0]=PFileName[0]=PExt[0]=NULL;
  228.    Laced=FALSE;   /*Not interlaced*/
  229.    Modified=FALSE;  /*No modifications, yet*/
  230.    StartingLevel=0;
  231.  
  232.    /*Open all the libraries*/
  233.    IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",1);
  234.    if(IntuitionBase==NULL)
  235.       exit(10);
  236.  
  237.    GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",1);
  238.    if(GfxBase==NULL)
  239.       exit(20);
  240.  
  241.    DosBase=OpenLibrary("dos.library",1);
  242.    if(DosBase==NULL)
  243.       exit(30);
  244.  
  245.    RowsInScreen=23;
  246.    ThisProc=(struct Process *)FindTask(NULL);  /*Get 'Liner's process structure*/
  247.    OpenGraphics();   /*Open screen, window, etc.*/
  248.    SetupClipboard(); /*Open the clipboard*/
  249.  
  250.    /*Setup various system variable*/
  251.    DispRows=1;
  252.    PtrX=PtrY=LastX=LastY=1;
  253.    ButtonState=UP;
  254.    InvsMode=ClipMode=NOINV;
  255.    FirstItem=LastItem=FirstScrnItem=CurrentItem=(struct LineItem *)
  256.          InsertItem(NULL,NULL);
  257.    FirstItem->Level=1;
  258.    FirstItem->ItemNumber=0;
  259.    PrintItemList(FirstItem,1);
  260.    PlotCursor(MinX(CurrentItem),1);
  261.    FileName[0]=PDName[0]=NULL;
  262.  
  263.    for(;;)    /*The main loop!*/
  264.       {
  265.       Wait(1<<Window->UserPort->mp_SigBit);  /*Wait for an event*/
  266.       while((Message=(struct IntuiMessage *) /*Get the message*/
  267.             GetMsg(Window->UserPort))!=NULL)
  268.          {        /*Get the message's information*/
  269.          Class=Message->Class;
  270.          Code=Message->Code;
  271.          Qualifier=Message->Qualifier;
  272.          MouseX=Message->MouseX;
  273.          MouseY=Message->MouseY;
  274.          Seconds=Message->Seconds;
  275.          Micros=Message->Micros;
  276.  
  277.          IAddress=(APTR)Message->IAddress;
  278.  
  279.          ReplyMsg(Message);   /*Reply to the message*/
  280.  
  281.             /*Decode the message*/
  282.          if(HandleIDCMP(Class,Code,Qualifier,MouseX,MouseY,IAddress,
  283.                Buffer,Seconds,Micros))
  284.             {     /*If the message was a keypress*/
  285.             InsertChar(CurrentItem->Text,Buffer[2],   /*Print the letter*/
  286.                   PosInText(CurrentItem->Level));     /*onto the screen*/
  287.             CurX++;
  288.             WriteConsole(Buffer,-1);
  289.             }
  290.          }
  291.       }
  292. }
  293.  
  294. WriteConsole(Buffer,Length)   /*Write a string to the console*/
  295. char *Buffer;
  296. int Length;
  297. {
  298.    consoleWriteMsg->io_Command=CMD_WRITE;
  299.    consoleWriteMsg->io_Data=(char *)Buffer;
  300.    consoleWriteMsg->io_Length=Length;
  301.    DoIO(consoleWriteMsg);
  302. }
  303.  
  304. /*Decode an IDCMP message*/
  305. HandleIDCMP(Class,Code,Qualifier,MouseX,MouseY,IAddress,Buffer,Secs,Micros)
  306. ULONG Class;
  307. USHORT Code,Qualifier;
  308. APTR IAddress;
  309. SHORT MouseX,MouseY;
  310. int Secs,Micros;
  311. char *Buffer;
  312. {
  313.    struct MenuItem *item;
  314.    struct InputEvent KeyEvent;
  315.    struct LineItem *WorkingItem;
  316.    int TempX,TempY;
  317.    Buffer[0]=CSI;
  318.    Buffer[1]=0x40;
  319.    Buffer[2]=NULL;
  320.    switch(Class)
  321.       {
  322.       case MENUPICK: /*There was a menu selection*/
  323.          if(ErrorInTitle)
  324.             TitleErrorCancel();
  325.          while(Code != MENUNULL)
  326.             {
  327.             item=(struct MenuItem *)ItemAddress(&Menu1,Code);
  328.             HandleEvent(item);
  329.             Code=item->NextSelect;
  330.             }
  331.       case MOUSEBUTTONS:   /*The left mouse button was pushed*/
  332.          if(Code==SELECTDOWN)
  333.             HandleButton(Secs,Micros);
  334.          break;
  335.       case MOUSEMOVE:      /*The mouse was moved*/
  336.          MovedMouse(MouseX,MouseY);
  337.          break;
  338.       /*A key was pressed*/
  339.       case RAWKEY:         /*By using IDCMP RAWKEY as input, and the*/
  340.          if(Code & 0x80)   /*console for output, we can both get input*/
  341.             return(FALSE);  /*and IDCMP messsages without having to try*/
  342.          if(ErrorInTitle)   /*and decode ASCII console messages*/
  343.             TitleErrorCancel(); /*(IDCMP structures are MUCH easier)*/
  344.          if((Code < 0x41) || (0x5a <= Code && Code <= 0x5e) ||
  345.                (Code==0x4a))
  346.             {    /*^^^==All the RAWKEY codes that represent ASCII symbols*/
  347.             CheckModified();
  348.             KeyEvent.ie_NextEvent=NULL;     /*Create a fake input event*/
  349.             KeyEvent.ie_Class=IECLASS_RAWKEY; /*for RawKeyConvert() to */
  350.             KeyEvent.ie_SubClass=NULL; /*munch on.  Using RawKeyConvert()*/
  351.             KeyEvent.ie_Code=Code;   /*insures that the current keymap*/
  352.             KeyEvent.ie_Qualifier=Qualifier; /*is used*/
  353.             RawKeyConvert(&KeyEvent,&Buffer[2],200,&keymap),ConsoleDevice;
  354.             Buffer[3]=NULL;   /* ^^^ == RAWKEY to ASCII*/
  355.  
  356.             if(InvsMode < NOINV) /*If a block of lines was highlighted*/
  357.                {                 /*when a key was pressed, cancel the*/
  358.                EndBlockInvs();   /*highlight*/
  359.                return(FALSE);
  360.                }
  361.                                  /*If a key was pressed when TEXT was*/
  362.             if(InvsMode)         /*highlighted, delete the text & replace*/
  363.                DelTextBlock();   /*it with the letter pressed*/
  364.  
  365.             /*If the current line isn't full*/
  366.             if(strlen(CurrentItem->Text)<MaxLen(CurrentItem->Level))
  367.                return(TRUE);  /*OK to print the character*/
  368.             else
  369.                return(FALSE); /*Otherwise not*/
  370.             }
  371.          else
  372.             switch(Code)   /*Handle all the "special" characters*/
  373.                {
  374.                case 0x4d:        /*Move cursor down one*/
  375.                   CancelInvs();
  376.                   if(Qualifier & 3) /*Handle SHIFT-DOWN*/
  377.                      WholeScreenDown();
  378.                   else if(Qualifier & 8) /*Handle CTRL-DOWN*/
  379.                      JumpToBottom();
  380.                   else
  381.                      CursorDown();
  382.                   break;
  383.                case 0x4c:        /*Move cursor up one*/
  384.                   CancelInvs();
  385.                   if(Qualifier & 3)     /*Check for shift*/
  386.                      WholeScreenUp();
  387.                   else if(Qualifier & 8) /*Check for control*/
  388.                      JumpToTop();
  389.                   else
  390.                      CursorUp();
  391.                   break;
  392.                case 0x4e:        /*Move cursor one to the right*/
  393.                   CancelInvs();
  394.                   if(CurX >= MaxX(CurrentItem))
  395.                      {
  396.                      TempX=CurX;
  397.                      CurX=1;
  398.                      if(!CursorDown())
  399.                         CurX=TempX;
  400.                      }
  401.                   else
  402.                      if(Qualifier & 3) /*Handle SHIFT-cursor-right*/
  403.                         PlotCursor(MaxX(CurrentItem),CurY);
  404.                      else
  405.                         PlotCursor(CurX+1,CurY);
  406.                   break;
  407.                case 0x4f:        /*Move cursor one to the left*/
  408.                   CancelInvs();
  409.                   if(CurX <= MinX(CurrentItem))
  410.                      {
  411.                      TempX=CurX;
  412.                      CurX=100;
  413.                      if(!CursorUp())
  414.                         CurX=TempX;
  415.                      }
  416.                   else
  417.                      if(Qualifier & 3) /*Handle SHIFT-cursor-left*/
  418.                         PlotCursor(MinX(CurrentItem),CurY);
  419.                      else
  420.                         PlotCursor(CurX-1,CurY);
  421.                   break;
  422.                case 0x41:        /*Backspace over a character*/
  423.                   CheckModified();
  424.                   if(DelInvs())  /*If something is highlighted*/
  425.                      break;      /*delete it*/
  426.  
  427.          /*Delete the character, if not at the beginning of the line...*/
  428.                   if(CurX>MinX(CurrentItem))
  429.                      {
  430.                      strcpy(Buffer,&SpecChars[SCPos[1]]);
  431.                      Buffer[SCPos[2]-SCPos[1]]=NULL;
  432.                      DeleteChar(CurrentItem->Text,
  433.                            PosInText(CurrentItem->Level)-1);
  434.                      WriteConsole(Buffer,-1);
  435.                      CurX--;
  436.                      }
  437.                   else  /*otherwise, delete the line*/
  438.                      if(CurrentItem->PrevItem != NULL &&
  439.                            strlen(CurrentItem->Text)==0)
  440.                         {
  441.                         DelBlock(CurrentItem,CurrentItem,CurY,CurY);
  442.                         if(CurrentItem != LastItem)
  443.                            CursorUp();
  444.                         PlotCursor(MaxX(CurrentItem),CurY);
  445.                         }
  446.                   break;
  447.                case 0x46:        /*Delete a character*/
  448.                   CheckModified();
  449.                   if(DelInvs())
  450.                      break;
  451.  
  452.                   if(CurX<MaxX(CurrentItem))
  453.                      {
  454.                      strcpy(Buffer,&SpecChars[SCPos[6]]);
  455.                      Buffer[SCPos[7]-SCPos[6]]=NULL;
  456.                      DeleteChar(CurrentItem->Text,
  457.                            PosInText(CurrentItem->Level));
  458.                      WriteConsole(Buffer,-1);
  459.                      }
  460.                   break;
  461.                case 0x42:           /*TAB (in or out)*/
  462.                   CheckModified();
  463.                   if(InvsMode < NOINV)  /*Block highlighted*/
  464.                      if(Qualifier & 3)
  465.                         if(InvsMode==BLOCK_DOWN)
  466.                            PullOutBlock(StartIItem,EndIItem,InvY);
  467.                         else
  468.                            PullOutBlock(EndIItem,StartIItem,EndIY);
  469.                      else
  470.                         if(InvsMode==BLOCK_DOWN)
  471.                            PushInBlock(StartIItem,EndIItem,InvY);
  472.                         else
  473.                            PushInBlock(EndIItem,StartIItem,EndIY);
  474.                   else
  475.                      {
  476.                      if(CancelInvs())
  477.                         return(FALSE);
  478.                      TempY=CurY;
  479.                      PlotCursor(1,TempY);
  480.                      if(Qualifier & 3)    /*TAB out (shift pressed)*/
  481.                         PullOut(CurrentItem);
  482.                      else
  483.                         PushIn(CurrentItem); /*TAB in*/
  484.                      PlotCursor(MinX(CurrentItem),TempY);
  485.                      }
  486.                   break;
  487.                case 0x43:  /*Return & Enter */
  488.                case 0x44:  /*Insert a line*/
  489.                   CheckModified();
  490.                   if(CancelInvs())
  491.                      return(FALSE);
  492.                   if(CurX < MaxX(CurrentItem))
  493.                      if(!CursorUp())
  494.                         {
  495.                         InsertLineAtTop();
  496.                         return(FALSE);
  497.                         }
  498.                   strcpy(Buffer,&SpecChars[SCPos[4]]);
  499.                   WriteConsole(Buffer,4);
  500.                   WorkingItem=(struct LineItem *)
  501.                         InsertItem(CurrentItem->NextItem,CurrentItem);
  502.                   WorkingItem->Level=CurrentItem->Level;
  503.                   if(CurrentItem->ItemNumber==25)
  504.                      WorkingItem->ItemNumber=0;
  505.                   else
  506.                      WorkingItem->ItemNumber=CurrentItem->ItemNumber+1;
  507.                   if(CurY==SCRNHEIGHT)
  508.                      {
  509.                      ScrnBtm=(struct LineItem *)WorkingItem;
  510.                      FirstScrnItem=(struct LineItem *)
  511.                            FirstScrnItem->NextItem;
  512.                      }
  513.                   else
  514.                      {
  515.                      CurY++;
  516.                      if(DispRows==SCRNHEIGHT)
  517.                         ScrnBtm=(struct LineItem *)ScrnBtm->PrevItem;
  518.                      else
  519.                         ++DispRows;
  520.                      }
  521.                   if(WorkingItem->NextItem==NULL)
  522.                      ScrnBtm=LastItem=(struct LineItem *)
  523.                            WorkingItem;
  524.                   AddItem(WorkingItem);
  525.                   TempY=CurY;
  526.                   RedrawOutlineChars(WorkingItem,WorkingItem->Level,0);
  527.                   CurrentItem=(struct LineItem *)WorkingItem;
  528.                   PlotCursor(MinX(CurrentItem),TempY);
  529.                   break;
  530.                }
  531.             return(FALSE);
  532.       }
  533.    return(FALSE);
  534.  
  535. }
  536.  
  537. /*Close everything*/
  538. CloseStuff()
  539. {
  540.    FreeListMem(FirstItem,LastItem);
  541.    if(ClipMode < NOINV)
  542.       FreeListMem(ClipStart,ClipEnd);
  543.  
  544.    ShutDownClipboard();
  545.    CloseGraphics();
  546.  
  547.    CloseLibrary(DosBase);
  548.    CloseLibrary(GfxBase);
  549.    CloseLibrary(IntuitionBase);
  550.    exit(0);
  551. }
  552.  
  553. Leave(err,why) /*If an error occured, tell user, close window & screen*/
  554. int err;          /*& exit*/
  555. char *why;
  556. {
  557.    TitleError(why);
  558.    Delay(500);          /*Give user 5 seconds to read error message*/
  559.    exit(err);
  560. }
  561.  
  562. PushIn(Item)   /*Increase and redraw the level of an item*/
  563. struct LineItem *Item;
  564. {
  565.    if(Push(Item))
  566.       {
  567.       RedrawOutlineChars(Item,Item->Level-1,Item->Level);
  568.       return(TRUE);
  569.       }
  570.    else
  571.       return(FALSE);
  572. }
  573.  
  574. Push(Item)   /*Increase the level of an item (I. to A., etc.)*/
  575. struct LineItem *Item;
  576. {
  577.    if(Item->Level==6)
  578.       return(FALSE);
  579.  
  580.    RemItem(Item);
  581.    Item->Level++; /*Increase the level and chop off excess text if it*/
  582.    Item->Text[MaxLen(Item->Level)]=NULL; /*would go off the line*/
  583.    AddItem(Item);
  584.    PrintItem(Item);
  585.  
  586.    return(TRUE);
  587. }
  588.  
  589. PullOut(Item)  /*Decrease the level of an item and redraw*/
  590. struct LineItem *Item;
  591. {
  592.    if(Pull(Item))
  593.       {
  594.       RedrawOutlineChars(Item,Item->Level+1,Item->Level);
  595.       return(TRUE);
  596.       }
  597.    else
  598.       return(FALSE);
  599. }
  600.  
  601. Pull(Item)  /*Decrease the level of an item (a. to 1., etc.)*/
  602. struct LineItem *Item;
  603. {
  604.    if(Item->Level==1)
  605.       return(FALSE);
  606.  
  607.    RemItem(Item);
  608.    Item->Level--;
  609.    AddItem(Item);
  610.    AddItem(Item->NextItem);
  611.    PrintItem(Item);
  612.  
  613.    return(TRUE);
  614. }
  615.  
  616. PushInBlock(Start,End,YStart) /*Indent a reversed block*/
  617. struct LineItem *Start,*End;
  618. UBYTE YStart;
  619. {
  620.    struct LineItem *Item;
  621.    UBYTE OldX=CurX;
  622.    UBYTE OldY=CurY;
  623.    UBYTE Y=YStart;
  624.  
  625.    Item=(struct LineItem *)Start; /*Check to see if any items are as*/
  626.    while(Item != End)             /*pushed in as possible*/
  627.       {
  628.       if(Item->Level == 6)
  629.          return(FALSE);
  630.       Item=(struct LineItem *)Item->NextItem;
  631.       }
  632.  
  633.    PlotCursor(1,Y);
  634.    Item=(struct LineItem *)Start; /*Do first one*/
  635.    Push(Item);
  636.  
  637.    while(Item != End)  /*Loop until all pushed in*/
  638.       {
  639.       Item=(struct LineItem *)Item->NextItem;
  640.       PlotCursor(1,++Y);
  641.       Push(Item);
  642.       }
  643.  
  644.    PlotCursor(1,++Y);      /*Redraw outline characters*/
  645.    RedrawOutlineChars(End->NextItem,6,5);
  646.    PlotCursor(1,Y);
  647.    RedrawOutlineChars(End->NextItem,4,3);
  648.    PlotCursor(1,Y);
  649.    RedrawOutlineChars(End->NextItem,2,1);
  650.  
  651.    PlotCursor(1,YStart);
  652.    RvsBlock(Start,End);
  653.    if(OldX < MinX(CurrentItem)) /*OldX might no longer be possible if*/
  654.       PlotCursor(MinX(CurrentItem),OldY); /*CurrentItem was one pushed in*/
  655.    else
  656.       PlotCursor(OldX,OldY);
  657. }
  658.  
  659. PullOutBlock(Start,End,YStart) /*Indent a reversed block*/
  660. struct LineItem *Start,*End;
  661. UBYTE YStart;
  662. {
  663.    struct LineItem *Item;
  664.    UBYTE OldX=CurX;
  665.    UBYTE OldY=CurY;
  666.    UBYTE Y=YStart;
  667.  
  668.    Item=(struct LineItem *)Start; /*Check to see if any items are as*/
  669.    while(Item != End)             /*pushed in as possible*/
  670.       {
  671.       if(Item->Level == 1)
  672.          return(FALSE);
  673.       Item=(struct LineItem *)Item->NextItem;
  674.       }
  675.  
  676.    PlotCursor(1,Y);
  677.    Item=(struct LineItem *)Start; /*Do first one*/
  678.    Pull(Item);
  679.  
  680.    while(Item != End)  /*Loop until all pushed in*/
  681.       {
  682.       Item=(struct LineItem *)Item->NextItem;
  683.       PlotCursor(1,++Y);
  684.       Pull(Item);
  685.       }
  686.    PlotCursor(1,++Y);      /*Redraw outline characters*/
  687.    RedrawOutlineChars(End->NextItem,6,5);
  688.    PlotCursor(1,Y);
  689.    RedrawOutlineChars(End->NextItem,4,3);
  690.    PlotCursor(1,Y);
  691.    RedrawOutlineChars(End->NextItem,2,1);
  692.  
  693.    PlotCursor(1,YStart);
  694.    RvsBlock(Start,End);
  695.    if(OldX > MaxX(CurrentItem)) /*OldX might no longer be possible if*/
  696.       PlotCursor(MaxX(CurrentItem),OldY); /*CurrentItem was one pushed in*/
  697.    else
  698.       PlotCursor(OldX,OldY);
  699. }
  700.  
  701. JumpToTop() /*Jump to top of outline*/
  702. {
  703.    FirstScrnItem=CurrentItem=(struct LineItem *)FirstItem;
  704.    PrintItemList(CurrentItem,1);
  705.    PlotCursor(MinX(CurrentItem),1);
  706. }
  707.  
  708. JumpToBottom() /*Jump to bottom of outline*/
  709. {
  710.    struct LineItem *Item;
  711.    int c;
  712.  
  713.    CurrentItem=(struct LineItem *)LastItem;
  714.    for(c=0,Item=(struct LineItem *)LastItem;Item!=FirstItem && 
  715.          c < SCRNHEIGHT-1;Item=(struct LineItem *)Item->PrevItem,c++);
  716.    FirstScrnItem=(struct LineItem *)Item;
  717.    PrintItemList(FirstScrnItem,1);
  718.    PlotCursor(MinX(CurrentItem),DispRows);
  719. }
  720.  
  721. PrintItemList(FrstItem,StartY) /*Prints a specified number of items*/
  722. struct LineItem *FrstItem;
  723. int StartY;
  724. {
  725.    struct LineItem *CrntItem;
  726.    int y;
  727.    char Buffer[3];
  728.  
  729.    PlotCursor(1,StartY);
  730.    CrntItem=(struct LineItem *)FrstItem;
  731.    Buffer[0]=0x9b;
  732.    Buffer[1]=0x4a;
  733.    WriteConsole(Buffer,2);
  734.  
  735.    for(y=StartY;y<=SCRNHEIGHT && CrntItem!=NULL;y++)
  736.       {
  737.       PlotCursor(1,y);
  738.       PrintItem(CrntItem);
  739.       ScrnBtm=(struct LineItem *)CrntItem;
  740.       CrntItem=(struct LineItem *)CrntItem->NextItem;
  741.       }
  742.    DispRows=y-1;
  743. }
  744.  
  745. PrintItem(Item)   /*Print an item at the current Y location*/
  746. struct LineItem *Item;
  747. {
  748.    char ConsoleBuffer[100];
  749.  
  750.    ConsoleBuffer[0]=CSI;
  751.    ConsoleBuffer[1]=0x4b;
  752.    ConsoleBuffer[2]=NULL;
  753.  
  754.    GetOutlineChars(Item,ConsoleBuffer);
  755.    strcat(ConsoleBuffer,"  ");
  756.    strcat(ConsoleBuffer,Item->Text);
  757.    WriteConsole(ConsoleBuffer,-1);
  758. }
  759.  
  760. GetOutlineChars(Item,ConsoleBuffer) /*Get the outline chars (IX.,B.,etc.)*/
  761. struct LineItem *Item;     /*for an item*/
  762. char *ConsoleBuffer;
  763. {
  764.    int Level,StrLen,InsLen,c;
  765.  
  766.    Level=RealLevel(Item)-1;
  767.    StrLen=strlen(OutLineChars[Level][(Item->ItemNumber)]);
  768.    InsLen=PERPOS((Item->Level)-1)-StrLen;
  769.    for(c=0;c<InsLen;c++)
  770.       strcat(ConsoleBuffer," ");
  771.  
  772.    strcat(ConsoleBuffer,OutLineChars[Level][(Item->ItemNumber)]);
  773. }
  774.  
  775. RedrawOutlineChars(Item,Hi,Lo)   /*Redraw the outline characters */
  776. struct LineItem *Item;  /*(Lo <= Changed level <= Hi)*/
  777. int Hi,Lo;
  778. {
  779.    char Buffer[60];
  780.    int x=1;
  781.    int y,Level;
  782.  
  783.    Level=Item->Level;
  784.  
  785.    for(y=CurY;y<=SCRNHEIGHT & Item != NULL ;y++)
  786.       {
  787.       if(Lo == Item->Level || Hi == Item->Level)
  788.          {
  789.          PlotCursor(x,y);
  790.          strcpy(Buffer,"");
  791.          GetOutlineChars(Item,Buffer);
  792.          WriteConsole(Buffer,-1);
  793.          }
  794.       Item=(struct LineItem *)Item->NextItem;
  795.       }
  796. }
  797.  
  798. PlotCursor(x,y)      /*Plot the console cursor on the screen*/
  799. int x,y;
  800. {
  801.    char Buffer[10];
  802.    int len=1;
  803.  
  804.    Buffer[0]=CSI;
  805.    len+=stci_d(&Buffer[1],y,9);
  806.    Buffer[len]=0x3b;
  807.    len+=stci_d(&Buffer[len+1],x,6);
  808.    Buffer[len+1]=0x48;
  809.    Buffer[len+2]=NULL;
  810.    WriteConsole(Buffer,-1);
  811.    CurX=x;
  812.    CurY=y;
  813. }
  814.  
  815. CursorUp()  /*Move the cursor up (scroll screen, etc.)*/
  816. {
  817.    char Buffer[20];
  818.    int TempX;
  819.  
  820.    if(CurrentItem->PrevItem !=NULL)
  821.       {
  822.       if(CurrentItem==FirstScrnItem && CurrentItem != FirstItem)
  823.          {
  824.          strcpy(Buffer,&SpecChars[SCPos[0x0c]]);
  825.          WriteConsole(Buffer,2);
  826.          TempX=CurX;
  827.          PlotCursor(1,1);
  828.          PrintItem(CurrentItem->PrevItem);
  829.          ++CurY;
  830.          if(ScrnBtm==LastItem && DispRows < SCRNHEIGHT)
  831.             ++DispRows;
  832.          else
  833.             ScrnBtm=(struct LineItem *)ScrnBtm->PrevItem;
  834.          FirstScrnItem=(struct LineItem *)FirstScrnItem->PrevItem;
  835.          CurX=TempX;
  836.          InvY++;
  837.          }
  838.  
  839.       if(CurX < MinX(CurrentItem->PrevItem))
  840.          CurX=MinX(CurrentItem->PrevItem);
  841.       else
  842.          if(CurX > MaxX(CurrentItem->PrevItem))
  843.             CurX=MaxX(CurrentItem->PrevItem);
  844.       PlotCursor(CurX,CurY-1);
  845.       CurrentItem=(struct LineItem *) CurrentItem->PrevItem;
  846.       return(TRUE);
  847.       }
  848.    return(FALSE);
  849. }
  850.  
  851. CursorDown()      /*Move the cursor down (scroll screen, etc.)*/
  852. {
  853.    char Buffer[20];
  854.    int TempX;
  855.  
  856.    if(CurrentItem->NextItem != NULL)
  857.       {
  858.       if(CurrentItem==ScrnBtm && (CurrentItem->NextItem != NULL))
  859.          {
  860.          strcpy(Buffer,&SpecChars[SCPos[0x0d]]);
  861.          WriteConsole(Buffer,2);
  862.          TempX=CurX;
  863.          PlotCursor(1,CurY);
  864.          PrintItem(CurrentItem->NextItem);
  865.          PlotCursor(TempX,CurY-1);
  866.          ScrnBtm=(struct LineItem *)ScrnBtm->NextItem;
  867.          FirstScrnItem=(struct LineItem *)FirstScrnItem->NextItem;
  868.          InvY--;
  869.          }
  870.  
  871.       if(CurX < MinX(CurrentItem->NextItem))
  872.          CurX=MinX(CurrentItem->NextItem);
  873.       else
  874.          if(CurX > MaxX(CurrentItem->NextItem))
  875.             CurX=MaxX(CurrentItem->NextItem);
  876.       PlotCursor(CurX,CurY+1);
  877.       CurrentItem=(struct LineItem *)CurrentItem->NextItem;
  878.       return(TRUE);
  879.       }
  880.    return(FALSE);
  881. }
  882.  
  883. InsertChar(Text,Character,Pos)   /*Insert a char into an item*/
  884. char *Text,Character;
  885. int Pos;
  886. {
  887.    int c;
  888.  
  889.    for(c=strlen(Text);c>=Pos;c--)
  890.       Text[c+1]=Text[c];
  891.    Text[Pos]=Character;
  892. }
  893.  
  894. DeleteChar(Text,Pos)    /*Delete a char in an item*/
  895. char *Text;
  896. int Pos;
  897. {
  898.    int lim;
  899.  
  900.    for(lim=strlen(Text);Pos<lim;Pos++)
  901.       Text[Pos]=Text[Pos+1];
  902. }
  903.  
  904. /*Insert an item into the item list*/
  905. extern struct LineItem *InsertItem(NextItem,PrevItem)
  906. struct LineItem *NextItem,*PrevItem;
  907. {
  908.    struct LineItem *Item;
  909.  
  910.    Item=(struct LineItem *)AllocMem(sizeof(struct LineItem),MEMF_CLEAR);
  911.    if(Item==NULL)
  912.       return(NULL);
  913.  
  914.    if(NextItem != NULL)
  915.       {
  916.       NextItem->PrevItem=(struct LineItem *)Item;
  917.       Item->NextItem=(struct LineItem *)NextItem;
  918.       }
  919.  
  920.    if(PrevItem != NULL)
  921.       {
  922.       PrevItem->NextItem=(struct LineItem *)Item;
  923.       Item->PrevItem=(struct LineItem *)PrevItem;
  924.       }
  925.  
  926.    return(Item);
  927. }
  928.  
  929. RemItem(Item)  /*Adjust the ItemNumbers for items after one is removed*/
  930. struct LineItem *Item;
  931. {
  932.    int ItemNumber;
  933.    struct LineItem *WorkingItem;
  934.  
  935.    if(Item==NULL)
  936.       return(FALSE);
  937.    if((WorkingItem=(struct LineItem *)FindPrev(Item))==NULL)
  938.       ItemNumber=0;
  939.    else
  940.       ItemNumber=Item->ItemNumber;
  941.  
  942.    while((Item=(struct LineItem *)FindNext(Item))!=NULL)
  943.       {
  944.       if(ItemNumber==25)
  945.          ItemNumber=0;
  946.       Item->ItemNumber=ItemNumber++;
  947.       }
  948. }
  949.  
  950. AddItem(Item)  /*Adjust the ItemNumbers after adding an item*/
  951. struct LineItem *Item;
  952. {
  953.    int ItemNumber;
  954.    struct LineItem *CrntItem;
  955.  
  956.    if((CrntItem=(struct LineItem *)FindPrev(Item))==NULL)
  957.       ItemNumber=0;
  958.    else
  959.       ItemNumber=CrntItem->ItemNumber+1;
  960.  
  961.    do
  962.       {
  963.       if(ItemNumber==25)
  964.          ItemNumber=0;
  965.       Item->ItemNumber=ItemNumber++;
  966.       Item=(struct LineItem *)FindNext(Item);
  967.       }
  968.    while(Item != NULL && Item->PrevItem->Level >= Item->Level);
  969. }
  970.  
  971. extern struct LineItem *FindPrev(Item) /*Find the previous item of*/
  972. struct LineItem *Item;  /*the same Level as Item*/
  973. {
  974.    int Level;
  975.  
  976.    Level=Item->Level;
  977.    Item=(struct LineItem *)Item->PrevItem;
  978.  
  979.    while(Item->Level > Level && Item !=NULL)
  980.       Item=(struct LineItem *)Item->PrevItem;
  981.  
  982.    if(Item->Level < Level || Item == NULL)
  983.       return(NULL);
  984.    else
  985.       return(Item);
  986. }
  987.  
  988. extern struct LineItem *FindNext(Item) /*Find the next item of the same*/
  989. struct LineItem *Item;     /*Level as Item*/
  990. {
  991.    int Level;
  992.  
  993.    Level=Item->Level;
  994.    Item=(struct LineItem *)Item->NextItem;
  995.  
  996.    while(Item->Level > Level && Item != NULL)
  997.       Item=(struct LineItem *)Item->NextItem;
  998.  
  999.    if(Item->Level < Level)
  1000.       return(NULL);
  1001.    else
  1002.       return(Item);
  1003. }
  1004.  
  1005. InsertLineAtTop() /*Insert a line at the top of the list*/
  1006. {
  1007.    struct LineItem *WorkingItem;
  1008.  
  1009.    WorkingItem=(struct LineItem *)
  1010.       InsertItem(FirstItem,NULL);
  1011.    WorkingItem->Level=1;
  1012.  
  1013.    FirstItem=(struct LineItem *)WorkingItem;
  1014.    AddItem(FirstItem);
  1015.    PlotCursor(1,1);
  1016.    RedrawOutlineChars(WorkingItem->NextItem,1,1);
  1017.    PlotCursor(MinX(CurrentItem),1);
  1018.    CursorUp();
  1019. }
  1020.  
  1021. WholeScreenDown() /*Scrolls down by an entire screen*/
  1022. {
  1023.    struct LineItem *item;
  1024.    UBYTE c,X,Y;
  1025.  
  1026.    item=(struct LineItem *)ScrnBtm;
  1027.    if(item->NextItem == NULL)   /*No lines after screen bottom?*/
  1028.       {  /*Move to last line*/
  1029.       CurrentItem=(struct LineItem *)LastItem;
  1030.       PlotCursor(MinX(CurrentItem),DispRows);
  1031.       return(FALSE);
  1032.       }
  1033.    /*Get the first screen item*/
  1034.    item=FirstScrnItem=(struct LineItem *)item->NextItem;
  1035.    for(c=1;(c < CurY) && (item->NextItem != NULL);c++)
  1036.       item=(struct LineItem *)item->NextItem; /*Get item at old Y*/
  1037.  
  1038.    CurrentItem=(struct LineItem *)item;  /*It is now the CurrentItem*/
  1039.    Y=c;     /*In case CurY is no longer possible (23 lines down)*/
  1040.    /*If CurX's old position is no longer possible*/
  1041.    /*move the cursor to the nearest possible position*/
  1042.    if(CurX < MinX(CurrentItem))
  1043.       X=MinX(CurrentItem);
  1044.    else
  1045.       if(CurX > MaxX(CurrentItem))
  1046.          X=MaxX(CurrentItem);
  1047.       else
  1048.          X=CurX;
  1049.  
  1050.    for(c=1;(c < SCRNHEIGHT-CurY) && (item->NextItem != NULL);c++)
  1051.       item=(struct LineItem *)item->NextItem; /*Find screen bottom*/
  1052.    ScrnBtm=(struct LineItem *)item;  /*Got it!*/
  1053.    DispRows=c; /*Get the number of lines*/
  1054.    PrintItemList(FirstScrnItem,1); /*Refresh the display*/
  1055.    PlotCursor(X,Y);
  1056.    return(TRUE);     /*Done!*/
  1057. }
  1058.  
  1059.  
  1060. WholeScreenUp() /*Move up one screenfull of lines*/
  1061. {
  1062.    struct LineItem *item;
  1063.    UBYTE c,X,Y;
  1064.  
  1065.    Y=CurY;
  1066.    item=(struct LineItem *)FirstScrnItem;
  1067.    if(item->PrevItem == NULL) /*At the top?*/
  1068.       {  /*Move cursor to first line*/
  1069.       CurrentItem=(struct LineItem *)FirstItem;
  1070.       PlotCursor(MinX(CurrentItem),1);
  1071.       return(FALSE);
  1072.       }
  1073.    for(c=0;(c<SCRNHEIGHT) & (item->PrevItem != NULL);c++)
  1074.       item=(struct LineItem *)item->PrevItem;
  1075.    FirstScrnItem=(struct LineItem *)item;
  1076.    for(c=1;(c<CurY) && (item->NextItem != NULL);c++) /*Get new CurrentItem*/
  1077.       item=(struct LineItem *)item->NextItem;
  1078.    CurrentItem=(struct LineItem *)item;
  1079.  
  1080.    if(CurX < MinX(CurrentItem))  /*If CurX is no longer possible*/
  1081.       X=MinX(CurrentItem);    /*get closest possible X*/
  1082.    else
  1083.       if(CurX > MaxX(CurrentItem))
  1084.          X=MaxX(CurrentItem);
  1085.       else
  1086.          X=CurX;
  1087.    for(;(c<SCRNHEIGHT) & (item->NextItem != NULL);c++)
  1088.       item=(struct LineItem *)item->NextItem; /*Get ScrnBtm*/
  1089.    ScrnBtm=(struct LineItem *)item;
  1090.    DispRows=c;    /*Number of lines*/
  1091.    PrintItemList(FirstScrnItem,1); /*Refresh display*/
  1092.    PlotCursor(X,Y);
  1093.    return(TRUE); /*Done!*/
  1094. }
  1095.  
  1096. OpenGraphics() /*Open screen, window, etc.*/
  1097. {
  1098.    /*Open screen (640x200x2)*/
  1099.    NewWindow.Screen=Screen=(struct Screen *)OpenScreen(&NewScreen);
  1100.    if(Screen==NULL)
  1101.       exit(40);
  1102.  
  1103.    /*Open backdrop window & make requestors open onto it*/
  1104.    if((ThisProc->pr_WindowPtr=Window=
  1105.          (struct Window *)OpenWindow(&NewWindow))==NULL)
  1106.       {
  1107.       CloseScreen(Screen);
  1108.       exit(50);
  1109.       }
  1110.    /*Install menus*/
  1111.    SetMenuStrip(Window,&Menu1);
  1112.  
  1113.    /*Setup the console.device*/
  1114.    consoleWritePort=(struct Port *)CreatePort("mycon.write",0);
  1115.    if(consoleWritePort==NULL)
  1116.       Leave(60,"Couldn't open console.device!");
  1117.  
  1118.    consoleWriteMsg=(struct IOStdReq *)CreateStdIO(consoleWritePort);
  1119.    if(consoleWriteMsg==NULL)
  1120.       Leave(70,"Couldn't open console.device!");
  1121.  
  1122.    consoleReadPort=(struct Port *)CreatePort("mycon.read",0);
  1123.    if(consoleReadPort==NULL)
  1124.       exit(60);
  1125.  
  1126.    consoleReadMsg=(struct IOStdReq *)CreateStdIO(consoleReadPort);
  1127.    if(consoleReadMsg==NULL)
  1128.       exit(70);
  1129.  
  1130.    consoleWriteMsg->io_Data=(struct Window *)Window;  /*Attach console*/
  1131.    consoleWriteMsg->io_Length=sizeof(struct Window);  /*device to window...*/
  1132.    OpenDevice("console.device",0,consoleWriteMsg,0); /*& open it*/
  1133.  
  1134.    ConsoleDevice=consoleReadMsg->io_Device=(APTR)consoleWriteMsg->io_Device;
  1135.    consoleReadMsg->io_Unit=consoleWriteMsg->io_Unit;
  1136.    consoleReadMsg->io_Command=CD_ASKKEYMAP;
  1137.    consoleReadMsg->io_Length=sizeof(struct KeyMap);
  1138.    consoleReadMsg->io_Data=&keymap;
  1139.    DoIO(consoleReadMsg);
  1140.    TitleErrorCancel();
  1141. }
  1142.  
  1143. CloseGraphics()   /*Close the window, screen, etc.*/
  1144. {
  1145.    CloseDevice(consoleWriteMsg);
  1146.    DeleteStdIO(consoleWriteMsg);
  1147.    DeleteStdIO(consoleReadMsg);
  1148.    DeletePort(consoleWritePort);
  1149.    DeletePort(consoleReadPort);
  1150.  
  1151.    ClearMenuStrip(Window);
  1152.    CloseWindow(Window);
  1153.    CloseScreen(Screen);
  1154. }
  1155.  
  1156.