home *** CD-ROM | disk | FTP | other *** search
- /*
- 'Liner Version 2.00. Written by Dave Schreiber
- ©1988, 1989, 1990 by Dave Schreiber. All Rights Reserved.
-
- 2.00 completed Saturday, June 23, 1990
- 1.32 completed Monday, October 30, 1989
- 1.31 completed Friday, October 6, 1989
- 1.30 completed Saturday, February 25, 1989
- 1.20 completed Friday, November 11, 1988
- 1.10 completed Friday, October 14, 1988
- 1.00 completed Friday, September 9, 1988
-
- Length of source code: 5714 lines
-
- 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
- 52 items per level (each isolated section). It has both clipboard and
- non-clipboard support of CUT, COPY, and, for single lines of text, 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).
- It supports ARexx, Workbench icons, overscanned and interlaced screens
-
- *********************************
-
- 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
-
- ------------
-
- 2.00 added a number of things:
- -Two way ARexx support
- -Search/replace
- -Greater Clipboard support (a block of lines that are CUT or COPYed are
- now sent to the Clipboard
- -Truer WYSIWYG: double spacing is now shown on screen
- -Support for more than one line per number
- -Icon support: icons now can be created when a document is saved. When
- the icon is double clicked on, 'Liner will be run and the document
- loaded
- -Support for overscanned screens, allowing more rows of text on screen
- at once
- -Adjustable screen colors
- -An option to save various settings in a preferences file
- -A new, more compact file format that supports the new 'Liner's
- improvements
- -The limit of highlighting only one screenful of lines at a time has
- been removed. There is now no limit
- -Support for up to 52 lines per level, up from 26 in 1.32
- -Uses YAFR V1.20. See the file YAFR.c for more details.
- In addition, a bug that would cause 'Liner to crash if the user
- attempted to load a file that wasn't a 'Liner outline has been removed
-
- *********************************
-
- */
-
- #include "globals.h"
-
- /*Outline characters*/
- char *OutLineChars[6][99]=
- {
- {
- {"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."},{"XXVII."},{"XXVIII."},{"XXIX."},{"XXX."},
- {"XXXI."},{"XXXII."},{"XXXIII."},{"XXXIV."},{"XXXV."},{"XXXVI."},
- {"XXXVII."},{"XXXVIII."},{"IXL."},{"XL."},{"XLI."},{"XLII."},{"XLIII."},
- {"XLIV."},{"XLV."},{"XLVI."},{"XLVII."},{"XLVIII."},{"IL."},{"L."},
- {"LI."},{"LII."}
- },
-
- {
- {"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."},{"AA."},
- {"AB."},{"AC."},{"AD."},{"AE."},{"AF."},{"AG."},{"AH."},{"AI."},
- {"AJ."},{"AK."},{"AL."},{"AM."},{"AN."},{"AO."},{"AP."},{"AQ."},
- {"AR."},{"AS."},{"AT."},{"AU."},{"AV."},{"AW."},{"AX."},{"AY."},
- {"AZ."}
- },
-
- {
- {"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."},{"27."},{"28."},{"29."},{"30."},{"31."},{"32."},{"33."},
- {"34."},{"35."},{"36."},{"37."},{"38."},{"39."},{"40."},{"41."},
- {"42."},{"43."},{"44."},{"45."},{"46."},{"47."},{"48."},{"49."},
- {"50."},{"51."},{"52."}
- },
-
- {
- {"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."},{"aa."},
- {"ab."},{"ac."},{"ad."},{"ae."},{"af."},{"ag."},{"ah."},{"ai."},
- {"aj."},{"ak."},{"al."},{"am."},{"an."},{"ao."},{"ap."},{"aq."},
- {"ar."},{"as."},{"at."},{"au."},{"av."},{"aw."},{"ax."},{"ay."},
- {"az."}
- },
-
- {
- {"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)"},{"27)"},{"28)"},{"29)"},{"30)"},{"31)"},{"32)"},{"33)"},
- {"34)"},{"35)"},{"36)"},{"37)"},{"38)"},{"39)"},{"40)"},{"41)"},
- {"42)"},{"43)"},{"44)"},{"45)"},{"46)"},{"47)"},{"48)"},{"49)"},
- {"50)"},{"51)"},{"52)"}
- },
-
- {
- {"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)"},{"aa)"},
- {"ab)"},{"ac)"},{"ad)"},{"ae)"},{"af)"},{"ag)"},{"ah)"},{"ai)"},
- {"aj)"},{"ak)"},{"al)"},{"am)"},{"an)"},{"ao)"},{"ap)"},{"aq)"},
- {"ar)"},{"as)"},{"at)"},{"au)"},{"av)"},{"aw)"},{"ax)"},{"ay)"},
- {"az)"}
- },
- };
-
- /*The position of each special character in the array below*/
- extern int SCPos[]=
- {0,1,4,5,9,13,14,16,17,18,19,20,21,23,25,27,29};
-
- /*Special characters (TAB, RETURN, etc.)*/
- extern 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',
- NULL
- };
-
- char Inv[]=
- {CSI,'7',0x6d,NULL};
- char Norm[]=
- {CSI,'0',0x6d,NULL};
-
- _main() /*The main function*/
- {
- ULONG Class;
- USHORT Code,Qualifier;
- APTR IAddress;
- SHORT MouseX,MouseY;
- int Seconds,Micros;
- struct IntuiMessage *Message;
- char Buffer[200];
-
- Buffer[0]=NULL; /*Initialize various variables...*/
- FileName[0]=SFileName[0]=SExt[0]=NULL;
- strcpy(PDirName,"");
- PDName[0]=PFileName[0]=PExt[0]=NULL;
- Modified=FALSE; /*No modifications, yet*/
- StartingLevel=0;
-
- /*Open all the libraries*/
- IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",1);
- if(IntuitionBase==NULL) /*Intuition*/
- exit(10);
-
- GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",1);
- if(GfxBase==NULL) /*Graphics*/
- exit(20);
-
- DosBase=OpenLibrary("dos.library",1);
- if(DosBase==NULL) /*Dos*/
- Leave(30,"Can't open dos.library!");
-
- IconBase=OpenLibrary("icon.library",1);
- if(IconBase==NULL) /*Icon*/
- Leave(40,"Can't open icon.library!");
-
-
- OpenARexx(); /*Open the ARexx port*/
-
- ThisProc=(struct Process *)FindTask(NULL);/*Get 'Liner's process structure*/
-
- GetLinerPrefs("liner:liner.prefs"); /*Load the preferences*/
- InterpretPrefs(); /*Install the preferences*/
-
- 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);
- if(FirstItem==NULL)
- {
- CloseGraphics();
- CloseLibrary(IconBase);
- CloseLibrary(GfxBase);
- Leave(50,"Memory too fragmented to run 'Liner! Exiting.");
- }
- FirstItem->Level=1;
- FirstItem->ItemNumber=0;
- PrintItemList(FirstItem,1);
- PlotCursor(MinX(CurrentItem),1);
-
- if(WBenchMsg != 0) /*If called from the Workbench...*/
- if(WBenchMsg->sm_NumArgs > 1) /*Outline clicked on instead of 'Liner*/
- {
- CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
- /*Make outline's directory the current directory*/
-
- if(strcmp(WBenchMsg->sm_ArgList[1].wa_Name,"liner.prefs") != 0)
- { /*Make sure user didn't click on liner.prefs icon*/
- strcpy(FileName,WBenchMsg->sm_ArgList[1].wa_Name);
- strcpy(SFileName,FileName);
- /*Store the outline's filename*/
- ReadItemList(WBenchMsg->sm_ArgList[1].wa_Name);
- /*Load the outline*/
- TitleErrorCancel();
- }
- }
-
- for(;;) /*The main loop!*/
- {
- /*Wait for something to happen*/
- Wait((1<<Window->UserPort->mp_SigBit) | ARexxSigBit);
-
- CheckRexxPort(); /*Check the ARexx port for any messages*/
-
- while((Message=(struct IntuiMessage *) /*Get the message if IDCMP*/
- 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);
- }
- }
- }
- }
-
- /*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;
- 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 *)GetFirstItemAddress(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)) && !(Qualifier & 8))
- { /*^^^==All the RAWKEY codes for alphanumeric characters*/
- 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)<MaxLen(CurrentItem->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*/
- CancelLineInvs();
- if(Qualifier & 3) /*Handle SHIFT-DOWN*/
- WholeScreenDown();
- else if(Qualifier & 8) /*Handle CTRL-DOWN*/
- JumpToBottom();
- else
- CursorDown();
- break;
- case 0x4c: /*Move cursor up one*/
- CancelLineInvs();
- 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*/
- CursorRight(Qualifier);
- break;
- case 0x4f: /*Move cursor one to the left*/
- CursorLeft(Qualifier);
- break;
- case 0x41: /*Backspace over a character*/
- HandleBS();
- break;
- case 0x46: /*Delete a character*/
- CheckModified();
- if(DelInvs())
- break;
-
- if(CurX<MaxX(CurrentItem))
- {
- strcpy(Buffer,&SpecChars[SCPos[6]]);
- Buffer[SCPos[7]-SCPos[6]]=NULL;
- DeleteChar(CurrentItem->Text,
- PosInText(CurrentItem->Level));
- WriteConsole(Buffer,-1);
- }
- break;
- case 0x42: /*TAB (in or out)*/
- HandleTAB(Qualifier);
- break;
- case 0x43: /*Return & Enter */
- case 0x44: /*Insert a line*/
- HandleReturn(Qualifier);
- break;
- }
- return(FALSE);
- }
- return(FALSE);
-
- }
-
- /*Close everything*/
- void CloseStuff()
- {
- FreeListMem(FirstItem,LastItem); /*Free the outline's memory*/
- if(ClipMode < NOINV)
- FreeListMem(ClipStart,ClipEnd); /*Delete any clipped lines*/
- CloseARexx(); /*Close the ARexx port*/
-
- ShutDownClipboard();
- CloseGraphics(); /*Close the screen, etc...*/
- CloseLibrary(IconBase); /*Close the libraries*/
- CloseLibrary(DosBase);
- CloseLibrary(GfxBase);
- CloseLibrary(IntuitionBase);
- exit(0);
- }
-
- void HandleBS() /*Handle the pressing of the backspace key*/
- {
- char Buffer[20];
-
- CheckModified();
-
- if(DelInvs()) /*If something is highlighted*/
- return; /*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 &&
- !(CurrentItem->NextItem && !CurrentItem->cont &&
- CurrentItem->NextItem->cont))
- {
- DelBlock(CurrentItem,CurrentItem,CurY,CurY);
- if(CurrentItem != LastItem)
- CursorUp();
- PlotCursor(MaxX(CurrentItem),CurY);
- }
- }
-
- HandleReturn(Qualifier) /*The return key was pressed, so add a line...*/
- USHORT Qualifier;
- {
- BYTE TempX,TempY;
- char Buffer[20];
- struct LineItem *WorkingItem;
-
- CheckModified();
- if(CancelInvs())
- return(FALSE);
-
- if(CurX == MinX(CurrentItem) && strlen(CurrentItem->Text) > 0)
- if(!CursorUp())
- {
- InsertLineAtTop();
- return(FALSE);
- }
-
- /*If the next item is a continuation and SHIFT wasn't pressed*/
- if((CurrentItem->NextItem != NULL) && !(Qualifier & 3) &&
- (CurrentItem->NextItem->cont))
- return(FALSE); /*Don't do anything*/
-
- WorkingItem=(struct LineItem *) /*Create the line*/
- InsertItem(CurrentItem->NextItem,CurrentItem);
- if(WorkingItem==NULL)
- {
- Leave(0,"Memory too fragmented to add line!"); /*Ran out of memory*/
- return(FALSE);
- }
-
- if((DispRows==SCRNHEIGHT) && (CurY != SCRNHEIGHT))
- { /*If a full screen & cursor isn't at the bottom*/
- TempX=CurX; /*Delete the last line*/
- TempY=CurY;
- PlotCursor(1,SCRNHEIGHT);
- Buffer[0]=0x9b;
- Buffer[1]=0x4a;
- WriteConsole(Buffer,2);
- PlotCursor(TempX,TempY);
- }
-
- strcpy(Buffer,&SpecChars[SCPos[4]]); /*Make space for the line*/
- WriteConsole(Buffer,4); /*on the screen*/
-
- if(prefs.DS) /*If double spaced*/
- {
- WriteConsole(Buffer,4); /*Add an extra line*/
- if((CurrentItem==ScrnBtm) && (Odd))
- WriteConsole(Buffer,4);
- }
-
- WorkingItem->Level=CurrentItem->Level;
-
- if(Qualifier & 3) /*If a SHIFT-RETURN*/
- {
- WorkingItem->cont=TRUE; /*The line is a continuation of the previous*/
- WorkingItem->ItemNumber=CurrentItem->ItemNumber; /*line*/
- }
- else
- { /*Otherwise, it's an independent line*/
- WorkingItem->cont=FALSE;
- if(CurrentItem->ItemNumber==
- MaxNumOnLevel[CurrentItem->Level]-1)
- WorkingItem->ItemNumber=0;
- else
- WorkingItem->ItemNumber=CurrentItem->ItemNumber+1;
- }
-
- if(CurY==SCRNHEIGHT) /*If at the bottom of the screen*/
- {
- if(prefs.DS) /*If double spaced, open up more space*/
- WriteConsole(Buffer,4);
- 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) /*If it's at the end of the outline*/
- ScrnBtm=LastItem=(struct LineItem *) /*update appropriate pointers*/
- WorkingItem;
-
- AddItem(WorkingItem);
- TempY=CurY;
- RedrawOutlineChars(WorkingItem,WorkingItem->Level,0);
- CurrentItem=(struct LineItem *)WorkingItem; /*Make the new line current*/
- PlotCursor(MinX(CurrentItem),TempY); /*and put the cursor on it*/
- }
-
- void Leave(err,why) /*If an error occured, tell user, close window & screen*/
- int err; /*& exit*/
- char *why;
- {
- char whyindeed[256];
- SHORT x;
-
- /*Construct the string for DisplayAlert()*/
- x=8*(80-strlen(why))/2;
- whyindeed[1]=x;
- whyindeed[0]=x>>8;
- whyindeed[2]=14;
- strcpy(&whyindeed[3],why);
- whyindeed[strlen(&whyindeed[3])+4]=NULL;
- DisplayAlert(RECOVERY_ALERT,whyindeed,24); /*Display the alert*/
-
- if(err!=0)
- exit(err);
- }
-
- PushIn(Item) /*Increase and redraw the level of an item*/
- struct LineItem *Item;
- {
- struct LineItem *Start,*End,*work;
-
- for(work=(struct LineItem *)Item;(work->PrevItem!=NULL) && (work->cont);
- work=(struct LineItem *)work->PrevItem);
- Start=(struct LineItem *)work;
-
- for(work=(struct LineItem *)Item;(work->NextItem != NULL) &&
- (work->NextItem->cont);work=(struct LineItem *)work->NextItem);
- End=(struct LineItem *)work;
-
- if(Start != End)
- PushInBlock(Start,End,IsOnScreen(Start),FALSE);
- else
- 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);
-
- if(IsOnScreen(Item)) /*Print item if it is on screen*/
- PrintItem(Item);
- return(TRUE);
- }
-
- PullOut(Item) /*Decrease the level of an item and redraw*/
- struct LineItem *Item;
- {
- struct LineItem *Start,*End,*work;
-
- for(work=(struct LineItem *)Item;(work->PrevItem!=NULL) && (work->cont);
- work=(struct LineItem *)work->PrevItem);
- Start=(struct LineItem *)work;
-
- for(work=(struct LineItem *)Item;(work->NextItem != NULL) &&
- (work->NextItem->cont);work=(struct LineItem *)work->NextItem);
- End=(struct LineItem *)work;
-
- if(Start != End) /*If the line is a continuation or has continuing lines...*/
- PullOutBlock(Start,End,IsOnScreen(Start),FALSE); /*Pull 'em all out*/
- else
- 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;
- {
- struct LineItem *wrk;
- if(Item->Level==1)
- return(FALSE);
-
- for(wrk=(struct LineItem *)Item->NextItem;(wrk != NULL) && (wrk->cont);
- wrk=(struct LineItem *)wrk->NextItem);
-
- RemItem(Item);
- Item->Level--;
- AddItem(Item);
- AddItem(wrk);
- if(IsOnScreen(Item)) /*Print item if it is on screen*/
- PrintItem(Item);
-
- return(TRUE);
- }
-
- PushInBlock(TrueStart,TrueEnd,YStart,Inverse) /*Indent a reversed block*/
- struct LineItem *TrueStart,*TrueEnd;
- UBYTE YStart;
- BYTE Inverse;
- {
- struct LineItem *Item,*Start,*End;
- UBYTE OldX=CurX;
- UBYTE OldY=CurY;
- UBYTE Y=YStart;
-
- /*If Start or End is a continued item, find where the continued items end*/
-
- Start=(struct LineItem *)FindPrevNonCont(TrueStart);
- End=(struct LineItem *)FindNextNonCont(TrueEnd);
-
- 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;
- }
-
- if(Y=IsOnScreen(Start))
- 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;
- if(Y=IsOnScreen(Item)) /*If it's on the screen*/
- PlotCursor(1,Y);
- Push(Item);
- }
- RemItem(Start);
- AddItem(Start);
-
- if(IsOnScreen(Item->NextItem))
- {
- 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);
- }
- else
- if(IsBefore(Item,FirstScrnItem))
- {
- Y=1;
- PlotCursor(1,Y); /*Redraw outline characters*/
- RedrawOutlineChars(FirstScrnItem,6,5);
- PlotCursor(1,Y);
- RedrawOutlineChars(FirstScrnItem,4,3);
- PlotCursor(1,Y);
- RedrawOutlineChars(FirstScrnItem,2,1);
- }
-
-
- PlotCursor(1,YStart);
- if(Inverse)
- RvsBlock(TrueStart,TrueEnd);
- 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(TrueStart,TrueEnd,YStart,Inverse) /*Indent a reversed block*/
- struct LineItem *TrueStart,*TrueEnd;
- UBYTE YStart;
- BYTE Inverse;
- {
- struct LineItem *Item,*Start,*End;
- UBYTE OldX=CurX;
- UBYTE OldY=CurY;
- UBYTE Y;
-
- Start=(struct LineItem *)FindPrevNonCont(TrueStart);
- End=(struct LineItem *)FindNextNonCont(TrueEnd);
-
- 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;
- }
-
- if(Y=IsOnScreen(Start))
- 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;
- if(Y=IsOnScreen(Item))
- PlotCursor(1,Y);
- Pull(Item);
- }
-
- Item=(struct LineItem *)Item->NextItem;
- RemItem(Start);
- AddItem(Start);
- if(Y=IsOnScreen(Item))
- {
- PlotCursor(1,Y); /*Redraw outline characters*/
- RedrawOutlineChars(Item,6,5);
- PlotCursor(1,Y);
- RedrawOutlineChars(Item,4,3);
- PlotCursor(1,Y);
- RedrawOutlineChars(Item,2,1);
- }
- else
- if(IsBefore(Item,FirstScrnItem))
- {
- Y=1;
- PlotCursor(1,Y); /*Redraw outline characters*/
- RedrawOutlineChars(FirstScrnItem,6,5);
- PlotCursor(1,Y);
- RedrawOutlineChars(FirstScrnItem,4,3);
- PlotCursor(1,Y);
- RedrawOutlineChars(FirstScrnItem,2,1);
- }
-
-
- PlotCursor(1,YStart);
- if(Inverse)
- RvsBlock(TrueStart,TrueEnd);
-
- if(OldX > MaxX(CurrentItem)) /*OldX might no longer be possible if*/
- PlotCursor(MaxX(CurrentItem),OldY); /*CurrentItem was one pushed in*/
- else
- PlotCursor(OldX,OldY);
- }
-
- void PrintItemList(FrstItem,StartY) /*Prints a specified number of items*/
- struct LineItem *FrstItem;
- int StartY;
- {
- struct LineItem *CrntItem;
- int y;
- char Buffer[3];
-
- CancelLineInvs(); /*Cancel any highlighted text on a line*/
-
- if(InvsMode < NOINV ) /*If a block is highlighted somewhere...*/
- if( InvsMode == BLOCK_DOWN)
- { /*and if the line is in the block*/
- if( (IsAfter(FrstItem,StartIItem)) && (IsBefore(FrstItem,EndIItem)) )
- WriteConsole(Inv,-1);
- }
- else /*make sure it's highlighted*/
- if( (IsAfter(FrstItem,EndIItem)) && (IsBefore(FrstItem,StartIItem)) )
- WriteConsole(Inv,-1);
-
- PlotCursor(1,StartY); /*Start at the top...*/
- CrntItem=(struct LineItem *)FrstItem;
- Buffer[0]=0x9b;
- Buffer[1]=0x4a;
- WriteConsole(Buffer,2);
-
- for(y=StartY;y<=SCRNHEIGHT && CrntItem!=NULL;y++)
- {
- if(InvsMode < 0) /*If inversed at and the start of a block...*/
- if((CrntItem == StartIItem) &&
- ((InvsMode == BLOCK_DOWN) || (InvsMode == BLOCK_PENDING)) )
- WriteConsole(Inv,-1); /*Make sure the line is highlighted*/
- else
- if((CrntItem == EndIItem) && (InvsMode == BLOCK_UP))
- WriteConsole(Inv,-1); /*if it's in the block*/
-
- PlotCursor(1,y);
- PrintItem(CrntItem);
- ScrnBtm=(struct LineItem *)CrntItem;
-
- if(InvsMode < 0) /*If inversed and at the end of a block*/
- if((CrntItem == EndIItem) &&
- ( (InvsMode == BLOCK_DOWN) || (InvsMode==BLOCK_PENDING) ))
- WriteConsole(Norm,-1); /*Turn off highlighting*/
- else
- if((CrntItem == StartIItem) && (InvsMode == BLOCK_UP))
- WriteConsole(Norm,-1);
-
- CrntItem=(struct LineItem *)CrntItem->NextItem;
- }
- DispRows=y-1;
- WriteConsole(Norm,-1);
- }
-
- void 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;
- if(Item->cont)
- InsLen=MinX(Item)-3;
- else
- {
- StrLen=strlen(OutLineChars[Level][(Item->ItemNumber)]);
- InsLen=PERPOS((Item->Level)-1)-StrLen;
- }
- for(c=0;c<InsLen;c++)
- strcat(ConsoleBuffer," ");
-
- if(!(Item->cont))
- strcat(ConsoleBuffer,OutLineChars[Level][(Item->ItemNumber)]);
- }
-
- void 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;
- }
- }
-
- /*Insert an item into the item list*/
- extern struct LineItem *InsertItem(NextItem,PrevItem)
- struct LineItem *NextItem,*PrevItem;
- {
- struct LineItem *Item;
-
- Forbid(); /*Make sure that nobody grabs memory inbetween the*/
- /*AvailMem() and the AllocMem()*/
- if(AvailMem(MEMF_LARGEST)<MINMEMORY) /*If we're out of memory*/
- {
- Permit();
- return(NULL);
- }
- if((Item=(struct LineItem *)AllocMem(sizeof(struct LineItem),
- MEMF_CLEAR))==NULL)
- {
- Permit();
- return(NULL);
- }
- Permit();
-
- if(NextItem != NULL)
- {
- NextItem->PrevItem=(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->cont) || Item==NULL) /*If a continued line, or if there*/
- return(FALSE); /*is no item, just return*/
- if((WorkingItem=(struct LineItem *)FindPrev(Item))==NULL)
- ItemNumber=0;
- else
- ItemNumber=Item->ItemNumber;
-
- while((Item=(struct LineItem *)FindNext(Item))!=NULL)
- {
- if(ItemNumber==MaxNumOnLevel[Item->Level]-1)
- ItemNumber=0;
- Item->ItemNumber=ItemNumber++;
- }
- }
-
- void AddItem(Item) /*Adjust the ItemNumbers after adding an item*/
- struct LineItem *Item;
- {
- int ItemNumber;
- struct LineItem *CrntItem;
-
- if(Item->cont) /*If a continued line*/
- return; /*just return*/
- if((CrntItem=(struct LineItem *)FindPrev(Item))==NULL)
- ItemNumber=0;
- else
- ItemNumber=CrntItem->ItemNumber+1;
-
- do /*Go through the outline, updating ItemNumbers*/
- {
- if(ItemNumber==MaxNumOnLevel[Item->Level]-1)
- 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->cont) || (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->cont) || (Item->Level > Level) ) && (Item != NULL) )
- Item=(struct LineItem *)Item->NextItem;
-
- if((Item->Level < Level) || (Item->cont) )
- return(NULL);
- else
- return(Item);
- }
-
- void InsertLineAtTop() /*Insert a line at the top of the list*/
- {
- struct LineItem *WorkingItem;
-
- WorkingItem=(struct LineItem *)
- InsertItem(FirstItem,NULL);
- if(WorkingItem==NULL) /*Out of memory*/
- {
- Leave(0,"Memory too fragmented to add line!");
- return;
- }
- WorkingItem->Level=1;
-
- FirstItem=(struct LineItem *)WorkingItem;
- AddItem(FirstItem);
- PlotCursor(1,1);
- RedrawOutlineChars(WorkingItem->NextItem,1,1);
- PlotCursor(MinX(CurrentItem),1);
- CursorUp();
- }
-
- IsOnScreen(item) /*Test to see whether a LineItem is currently*/
- struct LineItem *item; /*on the screen, and if so, return its Y position*/
- {
- struct LineItem *wrk;
- int y;
-
- /*Search items on screen for a match*/
- for(y=1,wrk=(struct LineItem *)FirstScrnItem;(wrk!=item) && (wrk!=ScrnBtm);
- wrk=(struct LineItem *)wrk->NextItem,y++);
-
- if(wrk == item)
- return(y); /*It's on screen*/
- else
- return(FALSE);
- }
-
- IsBefore(item,start) /*Checks to see if 'item' if before 'start' in*/
- struct LineItem *start,*item; /*the linked list*/
- {
- for(;(start != item) && (start != NULL);
- start=(struct LineItem *)start->PrevItem);
- if(start==item)
- return(TRUE);
- else
- return(FALSE);
- }
-
- IsAfter(item,start) /*Checks to see if 'item' is after 'start' in the*/
- struct LineItem *start,*item; /*linked list*/
- {
- for(;(start != item) && (start != NULL);
- start=(struct LineItem *)start->NextItem);
- if(start==item)
- return(TRUE);
- else
- return(FALSE);
- }
-
- extern struct LineItem *FindPrevNonCont(Start)/*Find the first line before*/
- struct LineItem *Start; /*or at 'Start' that isn't a continuation*/
- {
- struct LineItem *Item;
-
- for(Item=(struct LineItem *)Start;(Item->PrevItem!=NULL)&&(Item->cont);
- Item=(struct LineItem *)Item->PrevItem);
-
- return(Item);
- }
-
- extern struct LineItem *FindNextNonCont(Start) /*Find the first non-*/
- struct LineItem *Start; /*continuation after 'Start'*/
- {
- struct LineItem *Item;
-
- for(Item=(struct LineItem *)Start;(Item->NextItem != NULL) &&
- (Item->NextItem->cont);Item=(struct LineItem *)Item->NextItem);
-
- return(Item);
- }
-
- CursorUp() /*Move the cursor up (scroll screen, etc.)*/
- {
- char Buffer[20];
- int TempX;
-
- CancelLineInvs();
- if(ErrorInTitle)
- TitleErrorCancel();
- if(CurrentItem->PrevItem !=NULL)
- {
- if(CurrentItem==FirstScrnItem && CurrentItem != FirstItem)
- {
- TempX=CurX; /*Delete the last line*/
- PlotCursor(1,SCRNHEIGHT);
- Buffer[0]=0x9b;
- Buffer[1]=0x4a;
- WriteConsole(Buffer,2);
- PlotCursor(TempX,1);
-
- strcpy(Buffer,&SpecChars[SCPos[0x0c]]);
- WriteConsole(Buffer,2);
-
- if(prefs.DS)
- WriteConsole(Buffer,2); /*If double spaced, scroll twice*/
-
- TempX=CurX;
- PlotCursor(1,1);
-
- if(InvsMode < NOINV) /*Block Invs is active somewhere*/
- switch(InvsMode)
- {
- case BLOCK_PENDING:
- if(CurrentItem->PrevItem == StartIItem)
- WriteConsole(Inv,-1); /*Inverse*/
- break;
- case BLOCK_DOWN:
- if(IsAfter(CurrentItem->PrevItem,StartIItem) && /*If it's in*/
- IsBefore(CurrentItem->PrevItem,EndIItem)) /*the block*/
- WriteConsole(Inv,-1); /*Inverse*/
- break;
- case BLOCK_UP:
- if(IsAfter(CurrentItem->PrevItem,EndIItem) && /*Same as*/
- IsBefore(CurrentItem->PrevItem,StartIItem)) /*above*/
- WriteConsole(Inv,-1);
- }
-
- PrintItem(CurrentItem->PrevItem);
- WriteConsole(Norm,-1); /*Make it normal again*/
- ++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)) /*If the cursor wouldn't be*/
- CurX=MinX(CurrentItem->PrevItem); /*in a legal place on the line*/
- else /*now, move it onto the line*/
- if(CurX > MaxX(CurrentItem->PrevItem))
- CurX=MaxX(CurrentItem->PrevItem);
-
- PlotCursor(CurX,CurY-1); /*Position the cursor*/
- CurrentItem=(struct LineItem *) CurrentItem->PrevItem;
- return(TRUE);
- }
- return(FALSE);
- }
-
- CursorDown() /*Move the cursor down (scroll screen, etc.)*/
- {
- char Buffer[20];
- int TempX;
-
- CancelLineInvs();
- if(ErrorInTitle)
- TitleErrorCancel();
- if(CurrentItem->NextItem != NULL)
- {
- if(CurrentItem==ScrnBtm)
- {
- strcpy(Buffer,&SpecChars[SCPos[0x0d]]);
- WriteConsole(Buffer,2);
-
- if(prefs.DS) /*If double spaced, scroll twice*/
- {
- WriteConsole(Buffer,2);
- WriteConsole(Buffer,2);
- if(Odd)
- WriteConsole(Buffer,2);
- }
-
- TempX=CurX;
- PlotCursor(1,CurY);
-
- if(InvsMode < NOINV) /*Block Invs is active somewhere*/
- switch(InvsMode)
- {
- case BLOCK_PENDING:
- if(CurrentItem->NextItem == StartIItem)
- WriteConsole(Inv,-1); /*Inverse*/
- break;
- case BLOCK_DOWN:
- if(IsAfter(CurrentItem->NextItem,StartIItem) && /*If it's in*/
- IsBefore(CurrentItem->NextItem,EndIItem)) /*the block*/
- WriteConsole(Inv,-1); /*Inverse*/
- break;
- case BLOCK_UP:
- if(IsAfter(CurrentItem->NextItem,EndIItem) && /*Same as*/
- IsBefore(CurrentItem->NextItem,StartIItem)) /*above*/
- WriteConsole(Inv,-1);
- }
-
- PrintItem(CurrentItem->NextItem);
- WriteConsole(Norm,-1);
- PlotCursor(TempX,CurY-1);
- ScrnBtm=(struct LineItem *)CurrentItem->NextItem;
- FirstScrnItem=(struct LineItem *)FirstScrnItem->NextItem;
- InvY--;
- }
- if(CurX < MinX(CurrentItem->NextItem)) /*If the cursor wouldn't be on*/
- CurX=MinX(CurrentItem->NextItem); /*the new line, move it*/
- else
- if(CurX > MaxX(CurrentItem->NextItem))
- CurX=MaxX(CurrentItem->NextItem);
- PlotCursor(CurX,CurY+1);
- CurrentItem=(struct LineItem *)CurrentItem->NextItem; /*Update the */
- return(TRUE); /*Current line pointer*/
- }
- return(FALSE);
- }
-
- /*End of liner.c*/
-