/*'Liner Version 1.32. Written by Dave Schreiber */ /*©1988, 1989 Dave Schreiber. All Rights Reserved. */ /*1.32 completed Monday, October 31, 1989 */ /*1.31 completed Friday, October 6, 1989 */ /*1.3 completed Saturday, February 25, 1989 */ /*1.2 completed Friday, November 11, 1988 */ /*1.1 completed Friday, October 14, 1988 */ /*1.0 completed Friday, September 9, 1988 */ /*Compiled with Lattice C V5.02 */ /*To compile: 1> lc -cw -j30 -L+YAFR:YAFR.o 'Liner */ /*You must assign YAFR: to the directory where YAFR.o is stored. */ /*You must also assign LINER: to the directory where the 'Liner source */ /*is located. */ /*'Liner is an outliner, with up to six levels of depth, and up to */ /*26 items per level (each isolated section). It has both clipboard and */ /*non-clipboard support of CUT, COPY, and PASTE. It can output files */ /*in its own format, or in ASCII (to disk or printer). It can read files*/ /*in its own format only. It uses dynamic memory allocation to allow */ /*an infinite number of items (memory providing).*/ /*Amiga features of note that are used: */ /*console device, disk i/o, printer i/o, clipboard i/o */ /*Intuition objects (screen, windows, gadgets, menus, etc.) generated by */ /*PowerWindows Version 2.0*/ /*V1.1 corrects some bugs, doubles the number of characters available */ /*for filenames, and improves PrintItemList() so that it doesn't always */ /*print the entire item list*/ /*1.2 allows the toggling between 640x200 & 640x400 screens and the */ /*choice of the order that levels appear in, has a completely reworked */ /*About... window, lets the user change the level of all the items */ /*in a highlighted block, and now displays the current filename */ /*in the title bar.*/ /*1.3 adds support for user-selected keymaps, and now prints an asterisk */ /*in the title bar if an outline has been edited but not saved. It also */ /*includes my very own file requester, YAFR (Yet Another File Requester) */ /*based in principal upon Charlie Heath's, but with a lot more buttons. */ /*1.31 changes the default device where files are located from DF0: to */ /*the current directory */ /*1.32 fixed a bug that kept the screen from updating properly after a */ /*paste. Also uses YAFR V1.1 */ #include #include #include #include #include #include #include #include #include #include struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; ULONG DosBase; struct IOStdReq *consoleWriteMsg,*consoleReadMsg; struct Port *consoleWritePort,*consoleReadPort; struct IOClipReq ClipboardIO; struct MsgPort clipboardMsgPort; struct Process *ThisProc; struct LineItem /*'Liner structure definition*/ { struct LineItem *NextItem,*PrevItem; UBYTE Level,ItemNumber; char Text[80]; }; extern struct LineItem *InsertItem(),*FindNext(),*FindPrev(); struct Screen *Screen; struct Window *Window,*AboutWindow; struct KeyMap keymap; #define Rp Window->RPort; #define CSI 0x09b #define SEMI 0x03b #define NEWPAGE 0x0c #define CLOSECHAR 0x05c #define SCRNHEIGHT RowsInScreen #define REQUESTERCHARS 57 APTR ConsoleDevice; struct LineItem *CharItem,*StartIItem,*EndIItem,*ClipStart,*ClipEnd; int ButtonState,PtrX,PtrY,LastX,LastY,InvsMode,StartChar,EndChar,InvY,EndIY; int BLastX,BLastY,ClipMode,ErrorInTitle=FALSE; UBYTE Laced,RowsInScreen,StartingLevel,Modified; char Indent=0; char DoubleSpc=FALSE; char FileName[150+33],SDirName[150],SFileName[33],SExt[18]; char PDName[150+33],PDirName[150],PFileName[33],PExt[18]; char ScreenTitle[] = {" 'Liner V1.32: "}; #define UP 0 #define DOWN 1 #define NOINV 0 #define LINE_PENDING 1 #define LINE_FWD 2 #define LINE_BACK 3 #define BLOCK_PENDING -1 #define BLOCK_DOWN -2 #define BLOCK_UP -3 UBYTE OLCPos[6][6]= { {9,13,17,21,25,29}, {6,10,14,18,22,26}, {6,10,14,18,22,26}, {6,10,14,18,22,26}, {6,10,14,18,22,26}, {6,10,14,18,22,26} }; /*Some macros*/ #define PERPOS(x) OLCPos[StartingLevel][x]-3 #define MinX(LI) OLCPos[StartingLevel][(LI->Level)-1] #define MaxX(LI) OLCPos[StartingLevel][(LI->Level)-1]+strlen(LI->Text) #define MaxLen(Level) 79-OLCPos[StartingLevel][Level-1] #define PosInText(Level) CurX-OLCPos[StartingLevel][Level-1] #define RealLevel(LI) (LI->Level+StartingLevel > 6) ? (LI->Level+StartingLevel-7) : (LI->Level+StartingLevel) /* ^^^ == get level when StartingLevel != 0 */ /*Pointers to various LineItems*/ struct LineItem *FirstItem,*LastItem,*CurrentItem,*FirstScrnItem,*ScrnBtm; int CurX,CurY,DispRows; /*Outline characters*/ char *OutLineChars[6][26]= { { {"I."},{"II."},{"III."},{"IV."},{"V."},{"VI."},{"VII."},{"VIII."}, {"IX."},{"X."},{"XI."},{"XII."},{"XIII."},{"XIV."},{"XV."},{"XVI."}, {"XVII."},{"XVIII."},{"XIX."},{"XX."},{"XXI."},{"XXII."},{"XXIII."}, {"XXIV."},{"XXV."},{"XXVI."} }, { {"A."},{"B."},{"C."},{"D."},{"E."},{"F."},{"G."},{"H."},{"I."}, {"J."},{"K."},{"L."},{"M."},{"N."},{"O."},{"P."},{"Q."},{"R."}, {"S."},{"T."},{"U."},{"V."},{"W."},{"X."},{"Y."},{"Z."} }, { {"1."},{"2."},{"3."},{"4."},{"5."},{"6."},{"7."},{"8."},{"9."}, {"10."},{"11."},{"12."},{"13."},{"14."},{"15."},{"16."},{"17."}, {"18."},{"19."},{"20."},{"21."},{"22."},{"23."},{"24."},{"25."}, {"26."} }, { {"a."},{"b."},{"c."},{"d."},{"e."},{"f."},{"g."},{"h."},{"i."}, {"j."},{"k."},{"l."},{"m."},{"n."},{"o."},{"p."},{"q."},{"r."}, {"s."},{"t."},{"u."},{"v."},{"w."},{"x."},{"y."},{"z."} }, { {"1)"},{"2)"},{"3)"},{"4)"},{"5)"},{"6)"},{"7)"},{"8)"},{"9)"}, {"10)"},{"11)"},{"12)"},{"13)"},{"14)"},{"15)"},{"16)"},{"17)"}, {"18)"},{"19)"},{"20)"},{"21)"},{"22)"},{"23)"},{"24)"},{"25)"}, {"26)"} }, { {"a)"},{"b)"},{"c)"},{"d)"},{"e)"},{"f)"},{"g)"},{"h)"},{"i)"}, {"j)"},{"k)"},{"l)"},{"m)"},{"n)"},{"o)"},{"p)"},{"q)"},{"r)"}, {"s)"},{"t)"},{"u)"},{"v)"},{"w)"},{"x)"},{"y)"},{"z)"} }, }; /*The position of each special character in the array below*/ int SCPos[]= {0,1,4,5,9,13,14,16,17,18,19,20,21,23,25,27,29}; /*Special characters (TAB, RETURN, etc.)*/ char SpecChars[]= { 32, 8,CSI,'P', 0, 0x0D,0x0A,CSI,'L', 0x0D,0x0A,CSI,'L', 0, CSI,'P', 0, 0, 0, 0, 0, CSI,'A', CSI,'B', CSI,'C', CSI,'D' }; /*All the other little components of 'Liner*/ #include #include #include #include #include #include _main() { ULONG Class; USHORT Code,Qualifier; APTR IAddress; SHORT MouseX,MouseY; int Seconds,Micros; struct IntuiMessage *Message; char Buffer[200]; Buffer[0]=NULL; FileName[0]=SFileName[0]=SExt[0]=NULL; strcpy(SDirName,""); strcpy(PDirName,""); PDName[0]=PFileName[0]=PExt[0]=NULL; Laced=FALSE; /*Not interlaced*/ Modified=FALSE; /*No modifications, yet*/ StartingLevel=0; /*Open all the libraries*/ IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",1); if(IntuitionBase==NULL) exit(10); GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",1); if(GfxBase==NULL) exit(20); DosBase=OpenLibrary("dos.library",1); if(DosBase==NULL) exit(30); RowsInScreen=23; ThisProc=(struct Process *)FindTask(NULL); /*Get 'Liner's process structure*/ OpenGraphics(); /*Open screen, window, etc.*/ SetupClipboard(); /*Open the clipboard*/ /*Setup various system variable*/ DispRows=1; PtrX=PtrY=LastX=LastY=1; ButtonState=UP; InvsMode=ClipMode=NOINV; FirstItem=LastItem=FirstScrnItem=CurrentItem=(struct LineItem *) InsertItem(NULL,NULL); FirstItem->Level=1; FirstItem->ItemNumber=0; PrintItemList(FirstItem,1); PlotCursor(MinX(CurrentItem),1); FileName[0]=PDName[0]=NULL; for(;;) /*The main loop!*/ { Wait(1<UserPort->mp_SigBit); /*Wait for an event*/ while((Message=(struct IntuiMessage *) /*Get the message*/ GetMsg(Window->UserPort))!=NULL) { /*Get the message's information*/ Class=Message->Class; Code=Message->Code; Qualifier=Message->Qualifier; MouseX=Message->MouseX; MouseY=Message->MouseY; Seconds=Message->Seconds; Micros=Message->Micros; IAddress=(APTR)Message->IAddress; ReplyMsg(Message); /*Reply to the message*/ /*Decode the message*/ if(HandleIDCMP(Class,Code,Qualifier,MouseX,MouseY,IAddress, Buffer,Seconds,Micros)) { /*If the message was a keypress*/ InsertChar(CurrentItem->Text,Buffer[2], /*Print the letter*/ PosInText(CurrentItem->Level)); /*onto the screen*/ CurX++; WriteConsole(Buffer,-1); } } } } WriteConsole(Buffer,Length) /*Write a string to the console*/ char *Buffer; int Length; { consoleWriteMsg->io_Command=CMD_WRITE; consoleWriteMsg->io_Data=(char *)Buffer; consoleWriteMsg->io_Length=Length; DoIO(consoleWriteMsg); } /*Decode an IDCMP message*/ HandleIDCMP(Class,Code,Qualifier,MouseX,MouseY,IAddress,Buffer,Secs,Micros) ULONG Class; USHORT Code,Qualifier; APTR IAddress; SHORT MouseX,MouseY; int Secs,Micros; char *Buffer; { struct MenuItem *item; struct InputEvent KeyEvent; struct LineItem *WorkingItem; int TempX,TempY; Buffer[0]=CSI; Buffer[1]=0x40; Buffer[2]=NULL; switch(Class) { case MENUPICK: /*There was a menu selection*/ if(ErrorInTitle) TitleErrorCancel(); while(Code != MENUNULL) { item=(struct MenuItem *)ItemAddress(&Menu1,Code); HandleEvent(item); Code=item->NextSelect; } case MOUSEBUTTONS: /*The left mouse button was pushed*/ if(Code==SELECTDOWN) HandleButton(Secs,Micros); break; case MOUSEMOVE: /*The mouse was moved*/ MovedMouse(MouseX,MouseY); break; /*A key was pressed*/ case RAWKEY: /*By using IDCMP RAWKEY as input, and the*/ if(Code & 0x80) /*console for output, we can both get input*/ return(FALSE); /*and IDCMP messsages without having to try*/ if(ErrorInTitle) /*and decode ASCII console messages*/ TitleErrorCancel(); /*(IDCMP structures are MUCH easier)*/ if((Code < 0x41) || (0x5a <= Code && Code <= 0x5e) || (Code==0x4a)) { /*^^^==All the RAWKEY codes that represent ASCII symbols*/ CheckModified(); KeyEvent.ie_NextEvent=NULL; /*Create a fake input event*/ KeyEvent.ie_Class=IECLASS_RAWKEY; /*for RawKeyConvert() to */ KeyEvent.ie_SubClass=NULL; /*munch on. Using RawKeyConvert()*/ KeyEvent.ie_Code=Code; /*insures that the current keymap*/ KeyEvent.ie_Qualifier=Qualifier; /*is used*/ RawKeyConvert(&KeyEvent,&Buffer[2],200,&keymap),ConsoleDevice; Buffer[3]=NULL; /* ^^^ == RAWKEY to ASCII*/ if(InvsMode < NOINV) /*If a block of lines was highlighted*/ { /*when a key was pressed, cancel the*/ EndBlockInvs(); /*highlight*/ return(FALSE); } /*If a key was pressed when TEXT was*/ if(InvsMode) /*highlighted, delete the text & replace*/ DelTextBlock(); /*it with the letter pressed*/ /*If the current line isn't full*/ if(strlen(CurrentItem->Text)Level)) return(TRUE); /*OK to print the character*/ else return(FALSE); /*Otherwise not*/ } else switch(Code) /*Handle all the "special" characters*/ { case 0x4d: /*Move cursor down one*/ CancelInvs(); if(Qualifier & 3) /*Handle SHIFT-DOWN*/ WholeScreenDown(); else if(Qualifier & 8) /*Handle CTRL-DOWN*/ JumpToBottom(); else CursorDown(); break; case 0x4c: /*Move cursor up one*/ CancelInvs(); if(Qualifier & 3) /*Check for shift*/ WholeScreenUp(); else if(Qualifier & 8) /*Check for control*/ JumpToTop(); else CursorUp(); break; case 0x4e: /*Move cursor one to the right*/ CancelInvs(); if(CurX >= MaxX(CurrentItem)) { TempX=CurX; CurX=1; if(!CursorDown()) CurX=TempX; } else if(Qualifier & 3) /*Handle SHIFT-cursor-right*/ PlotCursor(MaxX(CurrentItem),CurY); else PlotCursor(CurX+1,CurY); break; case 0x4f: /*Move cursor one to the left*/ CancelInvs(); if(CurX <= MinX(CurrentItem)) { TempX=CurX; CurX=100; if(!CursorUp()) CurX=TempX; } else if(Qualifier & 3) /*Handle SHIFT-cursor-left*/ PlotCursor(MinX(CurrentItem),CurY); else PlotCursor(CurX-1,CurY); break; case 0x41: /*Backspace over a character*/ CheckModified(); if(DelInvs()) /*If something is highlighted*/ break; /*delete it*/ /*Delete the character, if not at the beginning of the line...*/ if(CurX>MinX(CurrentItem)) { strcpy(Buffer,&SpecChars[SCPos[1]]); Buffer[SCPos[2]-SCPos[1]]=NULL; DeleteChar(CurrentItem->Text, PosInText(CurrentItem->Level)-1); WriteConsole(Buffer,-1); CurX--; } else /*otherwise, delete the line*/ if(CurrentItem->PrevItem != NULL && strlen(CurrentItem->Text)==0) { DelBlock(CurrentItem,CurrentItem,CurY,CurY); if(CurrentItem != LastItem) CursorUp(); PlotCursor(MaxX(CurrentItem),CurY); } break; case 0x46: /*Delete a character*/ CheckModified(); if(DelInvs()) break; if(CurXText, PosInText(CurrentItem->Level)); WriteConsole(Buffer,-1); } break; case 0x42: /*TAB (in or out)*/ CheckModified(); if(InvsMode < NOINV) /*Block highlighted*/ if(Qualifier & 3) if(InvsMode==BLOCK_DOWN) PullOutBlock(StartIItem,EndIItem,InvY); else PullOutBlock(EndIItem,StartIItem,EndIY); else if(InvsMode==BLOCK_DOWN) PushInBlock(StartIItem,EndIItem,InvY); else PushInBlock(EndIItem,StartIItem,EndIY); else { if(CancelInvs()) return(FALSE); TempY=CurY; PlotCursor(1,TempY); if(Qualifier & 3) /*TAB out (shift pressed)*/ PullOut(CurrentItem); else PushIn(CurrentItem); /*TAB in*/ PlotCursor(MinX(CurrentItem),TempY); } break; case 0x43: /*Return & Enter */ case 0x44: /*Insert a line*/ CheckModified(); if(CancelInvs()) return(FALSE); if(CurX < MaxX(CurrentItem)) if(!CursorUp()) { InsertLineAtTop(); return(FALSE); } strcpy(Buffer,&SpecChars[SCPos[4]]); WriteConsole(Buffer,4); WorkingItem=(struct LineItem *) InsertItem(CurrentItem->NextItem,CurrentItem); WorkingItem->Level=CurrentItem->Level; if(CurrentItem->ItemNumber==25) WorkingItem->ItemNumber=0; else WorkingItem->ItemNumber=CurrentItem->ItemNumber+1; if(CurY==SCRNHEIGHT) { ScrnBtm=(struct LineItem *)WorkingItem; FirstScrnItem=(struct LineItem *) FirstScrnItem->NextItem; } else { CurY++; if(DispRows==SCRNHEIGHT) ScrnBtm=(struct LineItem *)ScrnBtm->PrevItem; else ++DispRows; } if(WorkingItem->NextItem==NULL) ScrnBtm=LastItem=(struct LineItem *) WorkingItem; AddItem(WorkingItem); TempY=CurY; RedrawOutlineChars(WorkingItem,WorkingItem->Level,0); CurrentItem=(struct LineItem *)WorkingItem; PlotCursor(MinX(CurrentItem),TempY); break; } return(FALSE); } return(FALSE); } /*Close everything*/ CloseStuff() { FreeListMem(FirstItem,LastItem); if(ClipMode < NOINV) FreeListMem(ClipStart,ClipEnd); ShutDownClipboard(); CloseGraphics(); CloseLibrary(DosBase); CloseLibrary(GfxBase); CloseLibrary(IntuitionBase); exit(0); } Leave(err,why) /*If an error occured, tell user, close window & screen*/ int err; /*& exit*/ char *why; { TitleError(why); Delay(500); /*Give user 5 seconds to read error message*/ exit(err); } PushIn(Item) /*Increase and redraw the level of an item*/ struct LineItem *Item; { if(Push(Item)) { RedrawOutlineChars(Item,Item->Level-1,Item->Level); return(TRUE); } else return(FALSE); } Push(Item) /*Increase the level of an item (I. to A., etc.)*/ struct LineItem *Item; { if(Item->Level==6) return(FALSE); RemItem(Item); Item->Level++; /*Increase the level and chop off excess text if it*/ Item->Text[MaxLen(Item->Level)]=NULL; /*would go off the line*/ AddItem(Item); PrintItem(Item); return(TRUE); } PullOut(Item) /*Decrease the level of an item and redraw*/ struct LineItem *Item; { if(Pull(Item)) { RedrawOutlineChars(Item,Item->Level+1,Item->Level); return(TRUE); } else return(FALSE); } Pull(Item) /*Decrease the level of an item (a. to 1., etc.)*/ struct LineItem *Item; { if(Item->Level==1) return(FALSE); RemItem(Item); Item->Level--; AddItem(Item); AddItem(Item->NextItem); PrintItem(Item); return(TRUE); } PushInBlock(Start,End,YStart) /*Indent a reversed block*/ struct LineItem *Start,*End; UBYTE YStart; { struct LineItem *Item; UBYTE OldX=CurX; UBYTE OldY=CurY; UBYTE Y=YStart; Item=(struct LineItem *)Start; /*Check to see if any items are as*/ while(Item != End) /*pushed in as possible*/ { if(Item->Level == 6) return(FALSE); Item=(struct LineItem *)Item->NextItem; } PlotCursor(1,Y); Item=(struct LineItem *)Start; /*Do first one*/ Push(Item); while(Item != End) /*Loop until all pushed in*/ { Item=(struct LineItem *)Item->NextItem; PlotCursor(1,++Y); Push(Item); } PlotCursor(1,++Y); /*Redraw outline characters*/ RedrawOutlineChars(End->NextItem,6,5); PlotCursor(1,Y); RedrawOutlineChars(End->NextItem,4,3); PlotCursor(1,Y); RedrawOutlineChars(End->NextItem,2,1); PlotCursor(1,YStart); RvsBlock(Start,End); if(OldX < MinX(CurrentItem)) /*OldX might no longer be possible if*/ PlotCursor(MinX(CurrentItem),OldY); /*CurrentItem was one pushed in*/ else PlotCursor(OldX,OldY); } PullOutBlock(Start,End,YStart) /*Indent a reversed block*/ struct LineItem *Start,*End; UBYTE YStart; { struct LineItem *Item; UBYTE OldX=CurX; UBYTE OldY=CurY; UBYTE Y=YStart; Item=(struct LineItem *)Start; /*Check to see if any items are as*/ while(Item != End) /*pushed in as possible*/ { if(Item->Level == 1) return(FALSE); Item=(struct LineItem *)Item->NextItem; } PlotCursor(1,Y); Item=(struct LineItem *)Start; /*Do first one*/ Pull(Item); while(Item != End) /*Loop until all pushed in*/ { Item=(struct LineItem *)Item->NextItem; PlotCursor(1,++Y); Pull(Item); } PlotCursor(1,++Y); /*Redraw outline characters*/ RedrawOutlineChars(End->NextItem,6,5); PlotCursor(1,Y); RedrawOutlineChars(End->NextItem,4,3); PlotCursor(1,Y); RedrawOutlineChars(End->NextItem,2,1); PlotCursor(1,YStart); RvsBlock(Start,End); if(OldX > MaxX(CurrentItem)) /*OldX might no longer be possible if*/ PlotCursor(MaxX(CurrentItem),OldY); /*CurrentItem was one pushed in*/ else PlotCursor(OldX,OldY); } JumpToTop() /*Jump to top of outline*/ { FirstScrnItem=CurrentItem=(struct LineItem *)FirstItem; PrintItemList(CurrentItem,1); PlotCursor(MinX(CurrentItem),1); } JumpToBottom() /*Jump to bottom of outline*/ { struct LineItem *Item; int c; CurrentItem=(struct LineItem *)LastItem; for(c=0,Item=(struct LineItem *)LastItem;Item!=FirstItem && c < SCRNHEIGHT-1;Item=(struct LineItem *)Item->PrevItem,c++); FirstScrnItem=(struct LineItem *)Item; PrintItemList(FirstScrnItem,1); PlotCursor(MinX(CurrentItem),DispRows); } PrintItemList(FrstItem,StartY) /*Prints a specified number of items*/ struct LineItem *FrstItem; int StartY; { struct LineItem *CrntItem; int y; char Buffer[3]; PlotCursor(1,StartY); CrntItem=(struct LineItem *)FrstItem; Buffer[0]=0x9b; Buffer[1]=0x4a; WriteConsole(Buffer,2); for(y=StartY;y<=SCRNHEIGHT && CrntItem!=NULL;y++) { PlotCursor(1,y); PrintItem(CrntItem); ScrnBtm=(struct LineItem *)CrntItem; CrntItem=(struct LineItem *)CrntItem->NextItem; } DispRows=y-1; } PrintItem(Item) /*Print an item at the current Y location*/ struct LineItem *Item; { char ConsoleBuffer[100]; ConsoleBuffer[0]=CSI; ConsoleBuffer[1]=0x4b; ConsoleBuffer[2]=NULL; GetOutlineChars(Item,ConsoleBuffer); strcat(ConsoleBuffer," "); strcat(ConsoleBuffer,Item->Text); WriteConsole(ConsoleBuffer,-1); } GetOutlineChars(Item,ConsoleBuffer) /*Get the outline chars (IX.,B.,etc.)*/ struct LineItem *Item; /*for an item*/ char *ConsoleBuffer; { int Level,StrLen,InsLen,c; Level=RealLevel(Item)-1; StrLen=strlen(OutLineChars[Level][(Item->ItemNumber)]); InsLen=PERPOS((Item->Level)-1)-StrLen; for(c=0;cItemNumber)]); } RedrawOutlineChars(Item,Hi,Lo) /*Redraw the outline characters */ struct LineItem *Item; /*(Lo <= Changed level <= Hi)*/ int Hi,Lo; { char Buffer[60]; int x=1; int y,Level; Level=Item->Level; for(y=CurY;y<=SCRNHEIGHT & Item != NULL ;y++) { if(Lo == Item->Level || Hi == Item->Level) { PlotCursor(x,y); strcpy(Buffer,""); GetOutlineChars(Item,Buffer); WriteConsole(Buffer,-1); } Item=(struct LineItem *)Item->NextItem; } } PlotCursor(x,y) /*Plot the console cursor on the screen*/ int x,y; { char Buffer[10]; int len=1; Buffer[0]=CSI; len+=stci_d(&Buffer[1],y,9); Buffer[len]=0x3b; len+=stci_d(&Buffer[len+1],x,6); Buffer[len+1]=0x48; Buffer[len+2]=NULL; WriteConsole(Buffer,-1); CurX=x; CurY=y; } CursorUp() /*Move the cursor up (scroll screen, etc.)*/ { char Buffer[20]; int TempX; if(CurrentItem->PrevItem !=NULL) { if(CurrentItem==FirstScrnItem && CurrentItem != FirstItem) { strcpy(Buffer,&SpecChars[SCPos[0x0c]]); WriteConsole(Buffer,2); TempX=CurX; PlotCursor(1,1); PrintItem(CurrentItem->PrevItem); ++CurY; if(ScrnBtm==LastItem && DispRows < SCRNHEIGHT) ++DispRows; else ScrnBtm=(struct LineItem *)ScrnBtm->PrevItem; FirstScrnItem=(struct LineItem *)FirstScrnItem->PrevItem; CurX=TempX; InvY++; } if(CurX < MinX(CurrentItem->PrevItem)) CurX=MinX(CurrentItem->PrevItem); else if(CurX > MaxX(CurrentItem->PrevItem)) CurX=MaxX(CurrentItem->PrevItem); PlotCursor(CurX,CurY-1); CurrentItem=(struct LineItem *) CurrentItem->PrevItem; return(TRUE); } return(FALSE); } CursorDown() /*Move the cursor down (scroll screen, etc.)*/ { char Buffer[20]; int TempX; if(CurrentItem->NextItem != NULL) { if(CurrentItem==ScrnBtm && (CurrentItem->NextItem != NULL)) { strcpy(Buffer,&SpecChars[SCPos[0x0d]]); WriteConsole(Buffer,2); TempX=CurX; PlotCursor(1,CurY); PrintItem(CurrentItem->NextItem); PlotCursor(TempX,CurY-1); ScrnBtm=(struct LineItem *)ScrnBtm->NextItem; FirstScrnItem=(struct LineItem *)FirstScrnItem->NextItem; InvY--; } if(CurX < MinX(CurrentItem->NextItem)) CurX=MinX(CurrentItem->NextItem); else if(CurX > MaxX(CurrentItem->NextItem)) CurX=MaxX(CurrentItem->NextItem); PlotCursor(CurX,CurY+1); CurrentItem=(struct LineItem *)CurrentItem->NextItem; return(TRUE); } return(FALSE); } InsertChar(Text,Character,Pos) /*Insert a char into an item*/ char *Text,Character; int Pos; { int c; for(c=strlen(Text);c>=Pos;c--) Text[c+1]=Text[c]; Text[Pos]=Character; } DeleteChar(Text,Pos) /*Delete a char in an item*/ char *Text; int Pos; { int lim; for(lim=strlen(Text);PosPrevItem=(struct LineItem *)Item; Item->NextItem=(struct LineItem *)NextItem; } if(PrevItem != NULL) { PrevItem->NextItem=(struct LineItem *)Item; Item->PrevItem=(struct LineItem *)PrevItem; } return(Item); } RemItem(Item) /*Adjust the ItemNumbers for items after one is removed*/ struct LineItem *Item; { int ItemNumber; struct LineItem *WorkingItem; if(Item==NULL) return(FALSE); if((WorkingItem=(struct LineItem *)FindPrev(Item))==NULL) ItemNumber=0; else ItemNumber=Item->ItemNumber; while((Item=(struct LineItem *)FindNext(Item))!=NULL) { if(ItemNumber==25) ItemNumber=0; Item->ItemNumber=ItemNumber++; } } AddItem(Item) /*Adjust the ItemNumbers after adding an item*/ struct LineItem *Item; { int ItemNumber; struct LineItem *CrntItem; if((CrntItem=(struct LineItem *)FindPrev(Item))==NULL) ItemNumber=0; else ItemNumber=CrntItem->ItemNumber+1; do { if(ItemNumber==25) ItemNumber=0; Item->ItemNumber=ItemNumber++; Item=(struct LineItem *)FindNext(Item); } while(Item != NULL && Item->PrevItem->Level >= Item->Level); } extern struct LineItem *FindPrev(Item) /*Find the previous item of*/ struct LineItem *Item; /*the same Level as Item*/ { int Level; Level=Item->Level; Item=(struct LineItem *)Item->PrevItem; while(Item->Level > Level && Item !=NULL) Item=(struct LineItem *)Item->PrevItem; if(Item->Level < Level || Item == NULL) return(NULL); else return(Item); } extern struct LineItem *FindNext(Item) /*Find the next item of the same*/ struct LineItem *Item; /*Level as Item*/ { int Level; Level=Item->Level; Item=(struct LineItem *)Item->NextItem; while(Item->Level > Level && Item != NULL) Item=(struct LineItem *)Item->NextItem; if(Item->Level < Level) return(NULL); else return(Item); } InsertLineAtTop() /*Insert a line at the top of the list*/ { struct LineItem *WorkingItem; WorkingItem=(struct LineItem *) InsertItem(FirstItem,NULL); WorkingItem->Level=1; FirstItem=(struct LineItem *)WorkingItem; AddItem(FirstItem); PlotCursor(1,1); RedrawOutlineChars(WorkingItem->NextItem,1,1); PlotCursor(MinX(CurrentItem),1); CursorUp(); } WholeScreenDown() /*Scrolls down by an entire screen*/ { struct LineItem *item; UBYTE c,X,Y; item=(struct LineItem *)ScrnBtm; if(item->NextItem == NULL) /*No lines after screen bottom?*/ { /*Move to last line*/ CurrentItem=(struct LineItem *)LastItem; PlotCursor(MinX(CurrentItem),DispRows); return(FALSE); } /*Get the first screen item*/ item=FirstScrnItem=(struct LineItem *)item->NextItem; for(c=1;(c < CurY) && (item->NextItem != NULL);c++) item=(struct LineItem *)item->NextItem; /*Get item at old Y*/ CurrentItem=(struct LineItem *)item; /*It is now the CurrentItem*/ Y=c; /*In case CurY is no longer possible (23 lines down)*/ /*If CurX's old position is no longer possible*/ /*move the cursor to the nearest possible position*/ if(CurX < MinX(CurrentItem)) X=MinX(CurrentItem); else if(CurX > MaxX(CurrentItem)) X=MaxX(CurrentItem); else X=CurX; for(c=1;(c < SCRNHEIGHT-CurY) && (item->NextItem != NULL);c++) item=(struct LineItem *)item->NextItem; /*Find screen bottom*/ ScrnBtm=(struct LineItem *)item; /*Got it!*/ DispRows=c; /*Get the number of lines*/ PrintItemList(FirstScrnItem,1); /*Refresh the display*/ PlotCursor(X,Y); return(TRUE); /*Done!*/ } WholeScreenUp() /*Move up one screenfull of lines*/ { struct LineItem *item; UBYTE c,X,Y; Y=CurY; item=(struct LineItem *)FirstScrnItem; if(item->PrevItem == NULL) /*At the top?*/ { /*Move cursor to first line*/ CurrentItem=(struct LineItem *)FirstItem; PlotCursor(MinX(CurrentItem),1); return(FALSE); } for(c=0;(cPrevItem != NULL);c++) item=(struct LineItem *)item->PrevItem; FirstScrnItem=(struct LineItem *)item; for(c=1;(cNextItem != NULL);c++) /*Get new CurrentItem*/ item=(struct LineItem *)item->NextItem; CurrentItem=(struct LineItem *)item; if(CurX < MinX(CurrentItem)) /*If CurX is no longer possible*/ X=MinX(CurrentItem); /*get closest possible X*/ else if(CurX > MaxX(CurrentItem)) X=MaxX(CurrentItem); else X=CurX; for(;(cNextItem != NULL);c++) item=(struct LineItem *)item->NextItem; /*Get ScrnBtm*/ ScrnBtm=(struct LineItem *)item; DispRows=c; /*Number of lines*/ PrintItemList(FirstScrnItem,1); /*Refresh display*/ PlotCursor(X,Y); return(TRUE); /*Done!*/ } OpenGraphics() /*Open screen, window, etc.*/ { /*Open screen (640x200x2)*/ NewWindow.Screen=Screen=(struct Screen *)OpenScreen(&NewScreen); if(Screen==NULL) exit(40); /*Open backdrop window & make requestors open onto it*/ if((ThisProc->pr_WindowPtr=Window= (struct Window *)OpenWindow(&NewWindow))==NULL) { CloseScreen(Screen); exit(50); } /*Install menus*/ SetMenuStrip(Window,&Menu1); /*Setup the console.device*/ consoleWritePort=(struct Port *)CreatePort("mycon.write",0); if(consoleWritePort==NULL) Leave(60,"Couldn't open console.device!"); consoleWriteMsg=(struct IOStdReq *)CreateStdIO(consoleWritePort); if(consoleWriteMsg==NULL) Leave(70,"Couldn't open console.device!"); consoleReadPort=(struct Port *)CreatePort("mycon.read",0); if(consoleReadPort==NULL) exit(60); consoleReadMsg=(struct IOStdReq *)CreateStdIO(consoleReadPort); if(consoleReadMsg==NULL) exit(70); consoleWriteMsg->io_Data=(struct Window *)Window; /*Attach console*/ consoleWriteMsg->io_Length=sizeof(struct Window); /*device to window...*/ OpenDevice("console.device",0,consoleWriteMsg,0); /*& open it*/ ConsoleDevice=consoleReadMsg->io_Device=(APTR)consoleWriteMsg->io_Device; consoleReadMsg->io_Unit=consoleWriteMsg->io_Unit; consoleReadMsg->io_Command=CD_ASKKEYMAP; consoleReadMsg->io_Length=sizeof(struct KeyMap); consoleReadMsg->io_Data=&keymap; DoIO(consoleReadMsg); TitleErrorCancel(); } CloseGraphics() /*Close the window, screen, etc.*/ { CloseDevice(consoleWriteMsg); DeleteStdIO(consoleWriteMsg); DeleteStdIO(consoleReadMsg); DeletePort(consoleWritePort); DeletePort(consoleReadPort); ClearMenuStrip(Window); CloseWindow(Window); CloseScreen(Screen); }