home *** CD-ROM | disk | FTP | other *** search
- >Thanks, modifications to tvdemos programs would be fine. If you can, please
- >package up the whole program; a "diff" file would be hard to apply since I
- >have a different version of the files than you do. It'll also make it clearer
- >which bugs have been addressed in the June 91 release.
- Now I'm ready. Since there is one program being very similar to TVEDIT.PAS
- I just gave the additions to that file. Including the whole file would be
- a waste of space.
-
- >> >bugs@borland.com). Have you already done that?
- >> No.
- >I'll wait for you demonstration code then, and send it myself.
- Meanwhile I got the address of Sydney Markowitz (sydney@borland.com)
- and sent him the list. You can send it to bugs@borland.com anyway.
- And now the list:
-
- Bugs in TurboVision and TurboPascal 6.0
- This file contains a collection of bugs found in Borland's
- TurboPascal 6.0 compiler and the TurboVision units. Each
- bug is described in the following form:
-
- Bug: procedure/function name (Unit name)
- short description explaining the context and effect
- Example:
- sample Pascal text or name of file, with instructions
- how to see the bug in effect. CAUTION: some bugs will
- cause the system to hang, so be sure to save all your
- important data.
- Some of the sample programs are appended to this text,
- separated by lines like:
- --------- FILENAME.PAS -------------------
- One of them, EDIT.PAS, is derived from TVEDIT.PAS
- and TVDEMO.PAS (both by Borland). So I added a
- description how to generate it, instead of the
- whole file.
- Fix:
- Replacement/addition for the buggy routine
-
- Some improvements are added, in a similar form.
-
-
- Bug: procedure TFileEditor.InitBuffer (Unit Editors)
- TFileEditor.NewBuffer allocates 0 bytes, but does not set BufSize
- to 0. Now, if TFileEditor.Load loads a TFileEditor from a stream,
- BufSize is read from the stream, too, and has its old value.
- InitBuffer (called by TEditor.Load) ignores it, so the content
- of the editor is loaded into memory, which was never allocated
- -> the program will crash. So you can't use TFileEditors, if you
- store and load the desktop.
- Example:
- Compile the file EDIT.PAS to disk and start it. Open two edit
- windows via File!New, type in some text and save them. Do not
- close the windows! Save the desktop with Windows!Save desktop,
- then reload it with Windows!Retrieve and type a single key:
- The actual edit window will show some weird chars in the
- beginning of the first line. Edit the text in one window and
- then select the other one; watch the effects. If you exit the
- program, sometimes your system hangs because of corrupted
- memory control blocks.
- Fix:
- procedure TFileEditor.InitBuffer;
- begin
- NewBuffer(Pointer(Buffer));
- (* Bugfix 13.05.91 JS: consider BufSize! TEditor.InitBuffer
- allocates BufSize bytes, this routine allocates 0 Bytes,
- but does not set BufSize to the correct value. If BufSize
- is <>0 (e.g. after TEditor.Load from a stream), the pro-
- gram will crash. *)
- BufSize:=0;
- end;
-
-
- Bug: function IScan (Unit Editors)
- In this assembly-routine the programmer forgot, that MOV does
- not set the flags. If the search string nearly matches the last
- chars in the text, the routine runs over the end of the text --
- eventually replacing text! Here is an example:
- Let '123456' be the text, and search for '45z'.
- The routine scans the text '1234' for the '4' and finds it:
- 123456
- 45z
- Then it compares the rest, finds the difference and skips
- this occurence. CX (number the chars left in the text) is
- now 0, but the routine just MOVs it back from DX, jumping
- then with JNE. Now it is behind the end of text!
- Example:
- TVDEMO\TVEDIT.PAS. Open a new edit window and type "123456"
- without the quote marks. Do not terminate the line with
- Enter! Press the Home key, then Ctrl-Q F to invoke the Find
- dialog. Enter "45z" as search text (without the quote marks)
- and press Enter (Case sensitivity is unselected by default):
- Your system hangs (sometimes wrong occurences are shown, or
- the search wraps around).
- Fix:
- (* Comment: The only change needed is the line marked with ***.
- But for better use of TEditor objects outside the USA and
- GB, it's better to use the DOS codepage (MSDOS3.X or higher
- required) for case conversion. *)
-
- { Improvement JS: UpperCase uses DOS codepage }
- procedure DOSUpCase; assembler;
- { a dummy to get a pointer in the codesegment }
- asm
- DD 0
- end;
-
- function UpperCase:Char ; assembler ;
- { changes lower case to upper case letters, using DOS codepage.
- does not need DS to point to Turbo's global data segment.
- input : AL char
- output: AL upper case of it }
- asm
- CMP AL,'a' { normal lower case chars.. }
- JB @@1
- CMP AL,'z'
- JBE @@4 { .. get normal treatment. }
- DB $2E,$FF,$1E { this is a CALLF [cs:] }
- DW DOSUpCase { all others are converted using }
- JMP @@1 { the DOS codepage }
- @@4:
- SUB AL,20H
- @@1:
- end ;
-
- function UpCase(c:Char): Char; assembler;
- { should be exported, i.e. included in interface }
- asm
- MOV AL,c
- CALL UpperCase
- end;
-
- function IScan(var Block; Size: Word; Str: String): Word; assembler;
- var
- S: String;
- asm
- PUSH DS
- MOV AX,SS { copy the Str to S, converting it.. }
- MOV ES,AX { to upper case }
- LEA DI,S
- LDS SI,Str
- XOR AH,AH
- LODSB { copy string length }
- STOSB
- MOV CX,AX
- MOV BX,AX
- JCXZ @@9
- @@1: LODSB { load each char from Str.. }
- CALL UpperCase { get upper case of it.. }
- STOSB { and store it to S }
- LOOP @@1
- SUB DI,BX { goto beginning of S (without length byte) }
- LDS SI,Block
- MOV CX,Size
- JCXZ @@8
- CLD
- SUB CX,BX { no need to examine the last chars in..}
- JB @@8 { Block, the search string won't fit }
- INC CX
- @@4: MOV AH,ES:[DI] { search for the first char of search string }
- @@5: LODSB
- CALL UpperCase
- CMP AL,AH { compare chars from Block with first char.. }
- LOOPNE @@5 { of search string until found }
- JNE @@8 { no occurence -> goto end }
- DEC SI { compare the whole search string }
- MOV DX,CX { save number of remaining bytes in Block }
- MOV CX,BX { get search string length }
- @@6: REPE CMPSB { exact match.. }
- JE @@10 { up to end of search string -> success }
- MOV AL,DS:[SI-1] { else: }
- CALL UpperCase { compare upper case }
- CMP AL,ES:[DI-1]
- JE @@6 { matches -> continue }
- SUB CX,BX { else compare failed; restore pointers.. }
- ADD SI,CX { in Block.. }
- ADD DI,CX { and search string }
- INC SI
- MOV CX,DX { restore number of remaining bytes in Block }
- OR CX,CX { *** MOV does not modify the flags! }
- JNE @@4 { zero remaining bytes -> end }
- @@8: XOR AX,AX { end without success: return 0 }
- JMP @@11
- @@9: MOV AX, 1 { end with empty search string:.. }
- JMP @@11 { pointer to next char }
- @@10: SUB SI,BX { end with success: return pointer to.. }
- MOV AX,SI { found occurence }
- SUB AX,WORD PTR Block
- INC AX
- @@11: DEC AX { set correct range of AX for BOOLEAN }
- POP DS
- end;
-
- { an init routine, replacing the END. at the end of EDITORS.PAS: }
- const RetFar:Byte=$CB ;
- var i: Integer;
- begin
- { Improvement JS: UpperCase uses DOS codePage }
- asm
- push ds
- mov ds,PrefixSeg
- mov dx,$D0 { DS:DX = 32 bytes scratch area in the PSP }
- mov ax,$3800 { get extended country information }
- int 21h
- mov bx,dx
- mov ax,[bx+$12] { Pointer to case conversion routine.. }
- mov bx,[bx+$14] { for chars >80h }
- pop ds
- jnc @@ok { if DOS reports error, set it to RETF }
- mov ax,Offset RetFar
- mov bx,ds
- @@ok:
- mov word ptr cs:DOSUpCase,ax
- mov word ptr cs:DOSUpCase+2,bx
- end ;
- end.
-
-
- Bug: procedure TEditor.HandleEvent (Unit Editors)
- This routine consumes all cmScrollBarChanged-events, without
- testing the sender. With TEditor, everything is ok, but with
- TMemo, there is a problem: this object cannot coexist in a
- TDialog with other objects having scrollbars. The test, whe-
- ther a cmScrollBarChanged-event is from one of its own scroll
- bars is done in the local procedure CheckScrollBar, but the
- HandleEvent routine clears the event in any case.
- Example:
- TESTMEMO. Start it and press F1 to get a MemoDialog, where a
- TMemo field is together with a TListviewer, both having scroll-
- bars. Try to position the focus in the TListbox with the scroll-
- bar or with the cursor keys (they are translated by the scroll-
- bar as well): it won't work. On the contrary, the TMemo works
- fine.
- Fix:
- TEditor.HandleEvent(var Event: TEvent);
-
- (* ... several lines skipped ... *)
-
- { Bugfix JS: function CheckScrollBar:Boolean returns False, if
- the sending scrollbar was not the scrollbar in question. }
- function CheckScrollBar(P: PScrollBar; var D: Integer): Boolean;
- begin
- if (Event.InfoPtr = P) and (P^.Value <> D) then
- begin
- D := P^.Value;
- Update(ufView);
- CheckScrollBar := True;
- end
- else CheckScrollBar := False;
- end;
-
- begin
- TView.HandleEvent(Event);
- ConvertEvent(Event);
-
- (* ... several lines skipped ... *)
-
- evBroadcast:
- case Event.Command of
- cmScrollBarChanged:
- { Bugfix JS: function CheckScrollBar():Boolean returns False,
- if the sending scrollbar was not the scrollbar in question.
- The EXIT prevents the Event from being cleared. }
- if not(CheckScrollBar(HScrollBar, Delta.X) or
- CheckScrollBar(VScrollBar, Delta.Y)) then Exit;
- else Exit;
- end;
- end;
- ClearEvent(Event);
- end;
-
-
- Bug: function TEditor.InsertBuffer (Unit Editors)
- Overwriting chars in an TEditor object is done in TEditor.Handle-
- Event by marking the next char as block and calling InsertBuffer
- via InsertText. This routine checks, whether there is enough
- memory and complains (edOutOfMemory), but does not reset the
- block marker. If you now press backspace, the block is deleted
- (i.e. the char under the cursor), not the char on the left side
- of the cursor.
- Example:
- Be sure to compile TVDEMOS\TVEDIT.PAS without the Range Check
- option; there seems to be another minor bug concerning Integer
- and Word types. Start TVEDIT.EXE, open a new edit window and
- start typing until the messagebox 'Not enough memory for this
- operation' comes up. Press Enter to close the messagebox, move
- the cursor in the middle of a line and type until the messagebox
- comes up again. Press Enter to close it again and then press
- Backspace. Not the char on the left side of the cursor will be
- deleted, but the char at cursor position.
- Fix:
- function TEditor.InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
- AllowUndo, SelectText: Boolean): Boolean;
- var
- SelLen, DelLen, SelLines, Lines: Word;
- NewSize: Longint;
- begin
- InsertBuffer := True;
- Selecting := False;
- SelLen := SelEnd - SelStart;
- if (SelLen = 0) and (Length = 0) then Exit;
- DelLen := 0;
- if AllowUndo then
- if CurPtr = SelStart then DelLen := SelLen else
- if SelLen > InsCount then DelLen := SelLen - InsCount;
- NewSize := Longint(BufLen + DelCount - SelLen + DelLen) + Length;
- if NewSize > BufLen + DelCount then
- if (NewSize > $FFF0) or not SetBufSize(NewSize) then
- begin
- EditorDialog(edOutOfMemory, nil);
- { Bugfix JS: reset block markers to avoid abnormal behaviour
- of a following BackSpace: }
- SelEnd := SelStart;
- InsertBuffer := False;
- Exit;
- end;
-
- (* ... several lines skipped ... *)
-
- SetBufSize(BufLen + DelCount);
- if (SelLines = 0) and (Lines = 0) then Update(ufLine) else Update(ufView);
- end;
-
- Bug: function NoWildChars (Unit StdDlg)
- This routine is used by TFileDialog-objects to delete wildcards
- in filenames. If called with an empty argument, it overwrites
- the stack. Try it: just give first '*' as mask, then a name with
- no extension in a TFileDialog.
- Example:
- TVDEMOS\TVDEMO.PAS. Create the file TEST (no extension!), then
- start TVDEMO.EXE. Press F3 to invoke the FileOpen dialog. Type
- "*" without the quote marks, press Enter, choose TEST from the
- file list and press Enter again: The system hangs.
- Fix:
- function NoWildChars(S: String): String; assembler;
- asm
- PUSH DS
- LDS SI,S { pointer to argument string }
- LES DI,@Result { same to result string }
- XOR AX,AX
- LODSB { get length of argument string }
- { Bugfix JS: test for empty argument string }
- OR AL,AL { length=0 ? }
- JE @@3 { -> result = '' }
- XCHG AX,CX { else: }
- INC DI { skip result length byte }
- @@1: LODSB { get char from argument string }
- CMP AL,'?' { '?' or '*' ? }
- JE @@2 { then skip it.. }
- CMP AL,'*'
- JE @@2
- STOSB { else copy it into result string }
- @@2: LOOP @@1
- XCHG AX,DI { calculate length of result string.. }
- MOV DI,WORD PTR @Result
- SUB AX,DI { as Endoffset+1 - Startoffset }
- DEC AX { don't count the length byte }
- @@3:
- STOSB { set length of result string }
- POP DS
- end;
-
- Bug: procedure THelpTopic.AddCrossRef (Unit HelpFile)
- In this routine the programmer allocates memory and then
- forgets to use the pointer to it. He just forgot a line.
- Example:
- No example. 'The code is obvious.'
- Fix:
- procedure THelpTopic.AddCrossRef(Ref: TCrossRef);
- var
- P: PCrossRefs;
- begin
- GetMem(P, (NumRefs+1) * SizeOf(TCrossRef));
- if NumRefs > 0 then
- begin
- Move(CrossRefs^, P^, NumRefs * SizeOf(TCrossRef));
- FreeMem(CrossRefs, NumRefs * SizeOf(TCrossRef));
- end;
- { Bugfix JS: the following line is missing in the original }
- CrossRefs := P;
- CrossRefs^[NumRefs] := Ref;
- Inc(NumRefs);
- end;
-
- Bug: function THelpIndex.Position (Unit HelpFile)
- If called with a negative argument, it returns random values,
- since it checks only for the upper bound, not for the lower
- one. The help compiler TVHC uses -1 for unknown topics, so
- this doesn't work.
- Example:
- Compile TVDEMOS\TVDEMO.PAS to disk. Then add the
- line
- {abc}
- to the first topic in TVDEMOS\DEMOHELP.TXT and
- compile it with
- TVHC DEMOHELP.TXT
- This will produce DEMOHELP.HLP and DEMOHELP.PAS.
- Start TVDEMO.EXE, press F1 to see the general help
- and then Enter to follow the cross reference 'abc'.
- You will not see the text 'No help available in this
- context.', as intended by HELPFILE.PAS, but get a
- runtime error (if you compiled TVDEMO with Range Check
- option) or a randomly chosen help text if any (without
- Range checking).
- Fix:
- function THelpIndex.Position(I: Integer): Longint;
- begin
- if (-1 < I) and (I < Size) then Position := Index^[I]
- else Position := -1;
- end;
-
- Bug: procedure AddToBuffer (Programm TVHC)
- No range checking is done in this routine. If a paragraph is
- longer than specified in the constant BufferSize (default:1024),
- memory behind the buffer is overwritten, resulting in crash.
- Example:
- Create a file TESTHELP.TXT with this content:
- .topic TestContext
- The following paragraph is too long to fit into the
- standard-sized buffer of TVHC.PAS:
- 1234567890123456789012345678901234567890
- 1234567890123456789012345678901234567890
-
- .. another 100 lines likes these ..
-
- 1234567890123456789012345678901234567890
- 1234567890123456789012345678901234567890
- Now start TVHC on it:
- TVHC TESTHELP.TXT
- Your system will hang, if you haven't compiled TVHC with Range
- Check option, otherwise you will get a runtime error 204.
- Fix:
- procedure AddToBuffer(var Line: String; Wrapping: Boolean); assembler;
- asm
- PUSH DS
- CLD
- PUSH DS
- POP ES
- MOV DI,OFFSET Buffer
- ADD DI,Ofs
- LDS SI,Line
- LODSB
- XOR AH,AH
- { Bugfix JS: the following test is missing in the original
- version. Causes crashes on buffer overflow }
- MOV BX,BufferSize { BufferSize-Ofs is the space left in Buffer }
- SUB BX,ES:Ofs
- CMP BX,AX { AX holds the needed amount of space }
- JAE @@0 { enough -> ok }
- MOV AX,BX { else just fill the Buffer up }
- @@0:
- ADD ES:Ofs,AX
- XCHG AX,CX
- JCXZ @@3 { don't copy 64K if there is nothing to do }
- REP MOVSB
- CMP ES:Ofs,BufferSize
- JE @@3 { don't append ' '/#13 if there is no room }
- XOR AL,AL
- INC ES:Ofs
- TEST Wrapping,1 { Only add a #13, line terminator, if not }
- JE @@1 { currently wrapping the text. Otherwise }
- MOV AL,' '-13 { add a ' '. }
- @@1: ADD AL,13
- @@2: STOSB
- @@3:
- POP DS
- end;
-
- Bug: procedure THistory.Draw (Unit Dialogs)
- For the history button sides, the chars ASCII 221 and 222 are
- used. These chars are _not_ included in codepages other than
- 437 (e.g. codepage 850, recommended by IBM for europe). So,
- the button looks somewhat awful in europe.
- Example:
- To use codepage 850 with your display, include the lines
- (with correct paths, of course)
- nlsfunc.exe country.sys
- mode con cp prepare=((850)ega.cpi)
- in your AUTOEXEC.BAT and type CHCP 850 at the DOS prompt after
- startup. DOS will complain, because you haven't prepared this
- codepage for all devices, but this doesn't matter. Start
- TVDEMOS\TVDEMO and press F3 to invoke a TFileDialog with a
- history button on the left side of the 'Name' input line.
- Look at the System-menu symbol for another example of such
- incompatibly written software.
- Fix:
- No fix.
-
- Bug: integrated assembler
- The integrated assembler doesn't generate the correct code for
- lines like this:
-
- MOV AX,[WORD PTR BX]
-
- The alternative form
-
- MOV AX,WORD PTR [BX]
-
- is handled properly. This is especially bad, since the first form
- is TASM syntax in Ideal mode, while the latter is MASM syntax.
- Example:
- Compile TESTASM.PAS to disk. Then start DEBUG with TESTASM.EXE
- and type 'u' to unassemble the code. You will see
- MOV BX,0038
- MOV AX,[0000]
- MOV AX,[BX]
- Fix:
- No fix.
-
-
- Some improvements:
- Behaviour: ^T in TVEdit sometimes deletes more than the next word.
- Explanation:
- ^T deletes _up to the next_ word, to be exact: up to the next
- char out of
- WordChars: set of Char = ['0'..'9', 'A'..'Z', '_', 'a'..'z']
- This will usually be just the next word, but can be more. The
- IDE editor first skips the current word if the cursor is in one.
- Then it skips blanks and tabs up to the next non-blank/non-tab.
- Example:
- EDIT.PAS. Open a new edit window and type this line:
- abc[[[[123]
- Press Home to position the cursor on the 'a'. Press ^T; this
- will delete 'abc[[[['. The TurboPascal Editor would delete 'abc'.
- Fix:
- function TEditor.NextWord(P: Word): Word;
- begin
- if BufChar(P) in WordChars then
- while (P < BufLen) and (BufChar(P) in WordChars) do
- P := NextChar(P)
- else
- P := NextChar(P);
- while (P < BufLen) and ((BufChar(P) = ' ') or (BufChar(P) = #9)) do
- P := NextChar(P);
- NextWord := P;
- end ;
-
- Behaviour: ^QF followed by ^L followed by Space deletes words in TVEdit.
- Explanation:
- If you mark a block manually and type a key, the block will be
- replaced by the key. Because occurences of the search string
- are marked as block, the described effect is seen. If you
- really want to avoid it, you have to change TEditor.HandleEvent
- to clear the blockmarkers before inserting a normal char.
- Example:
- EDIT.PAS. Open a new edit window and type this:
- 1234567890
- Move the cursor to the '3', hold down a Shift key and move the
- cursor to the '8' to mark the string '34567'. Press the space
- bar; this will replace '34567' by ' '.
- Fix:
- TEditor.HandleEvent(var Event: TEvent);
-
- (* ... several lines skipped ... *)
-
- begin
-
- (* ... several lines skipped ... *)
-
- evKeyDown:
- case Event.CharCode of
- #9,#32..#255:
- begin
- Lock;
- { Improvement JS: reset blockmarkers if not overwriting }
- if Overwrite then
- begin
- if CurPtr <> LineEnd(CurPtr) then SelEnd := NextChar(CurPtr)
- end
- else
- SelEnd := SelStart;
- InsertText(@Event.CharCode, 1, False);
- TrackCursor(CenterCursor);
- Unlock;
- end;
- else
- Exit;
- end;
-
- (* ... several lines skipped ... *)
-
- end;
-
-
- What I thought to be a bug, but was not:
- Bug: local assembly-procedures in assembly-procedures
- Here the compiler seems to have problems with the parameter
- sizes. Look at this:
-
- function FnTruncSet(Pattern:String):Boolean ; assembler ;
- procedure Number ; assembler ;
- asm
- [....]
- end ;
- asm
- [....]
- call Number
- [....]
- end ;
-
- For the procedure Number, the compiler generates a RET 2 instead
- of RET. I have no idea, why it wants to pop 2 bytes while having
- no argument; in this form, it will crash.
- Explanation:
- In the Programmer's reference, nested procedures are described.
- TurboPascal always pushes BP onto the stack to allow local pro-
- cedures to access the arguments of the enclosing routine. So, it
- has to pop 2 Bytes at the end.
- Fix:
- RTFM. Or, TurboPascal should not do this, because the same manual
- states that ASSEMBLER routines do not get a stack frame, if they
- have no arguments and local variables. So BP doesn't have to be
- pushed, it already has its correct value inside the local routine.
-
- --------------------------- EDIT.PAS ------------------------------
- { This text describes changes to be applied to the program TVEDIT.PAS
- from Borland. The changes will extend it to allow storing and reloa-
- ding the desktop with routines from TVDEMO.PAS. All changes are
- described in the form
- (* TVEDIT.PAS original <place/routine name> *)
- ... program text from TVEDIT.PAS ...
- (* EDIT.PAS replacement *)
- ... some other program text ...
- Just replace (or better: add) as described, and you will get EDIT.PAS
- }
-
- (* TVEDIT.PAS original, at the top: *)
- const
- cmOpen = 100;
- cmNew = 101;
- cmChangeDir = 102;
- cmDosShell = 103;
- cmCalculator = 104;
- cmShowClip = 105;
-
- (* EDIT.PAS replacement *)
- const
- cmOpen = 100;
- cmNew = 101;
- cmChangeDir = 102;
- cmDosShell = 103;
- cmCalculator = 104;
- cmShowClip = 105;
- cmSaveDesktop =1000;
- cmRetrieveDesktop =1001;
-
-
- (* TVEDIT.PAS original, at the top *)
- type
- PEditorApp = ^TEditorApp;
- TEditorApp = object(TApplication)
- constructor Init;
- destructor Done; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure InitMenuBar; virtual;
- procedure InitStatusLine; virtual;
- procedure OutOfMemory; virtual;
- end;
-
- (* EDIT.PAS replacement *)
- type
- PEditorApp = ^TEditorApp;
- TEditorApp = object(TApplication)
- constructor Init;
- destructor Done; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure InitMenuBar; virtual;
- procedure InitStatusLine; virtual;
- procedure LoadDesktop(var S: TStream);
- procedure StoreDesktop(var S: TStream);
- procedure OutOfMemory; virtual;
- end;
-
- (* TVEDIT.PAS original, TEditorApp.Init *)
- if H > HeapSize then BufHeapSize := H - HeapSize else BufHeapSize := 0;
- InitBuffers;
- TApplication.Init;
- DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
- cmUndo, cmFind, cmReplace, cmSearchAgain]);
-
- (* EDIT.PAS replacement
- if H > HeapSize then BufHeapSize := H - HeapSize else BufHeapSize := 0;
- InitBuffers;
- RegisterObjects;
- RegisterViews;
- RegisterMenus;
- RegisterDialogs;
- RegisterApp;
- RegisterEditors;
- RegisterCalc;
- TApplication.Init;
- DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
- cmUndo, cmFind, cmReplace, cmSearchAgain]);
-
-
- (* TVEDIT.PAS, original does not include the following routines: *)
- (* EDIT.PAS addition *)
- { copied from TVDEMO.PAS and modified TTVDemo to TEditorApp }
- { Since the safety pool is only large enough to guarantee that allocating
- a window will not run out of memory, loading the entire desktop without
- checking LowMemory could cause a heap error. This means that each
- window should be read individually, instead of using Desktop's Load.
- }
-
- procedure TEditorApp.LoadDesktop(var S: TStream);
- var
- P: PView;
-
- procedure CloseView(P: PView); far;
- begin
- Message(P, evCommand, cmClose, nil);
- end;
-
- begin
- if Desktop^.Valid(cmClose) then
- begin
- Desktop^.ForEach(@CloseView); { Clear the desktop }
- repeat
- P := PView(S.Get);
- Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
- until P = nil;
- end;
- end;
-
- procedure TEditorApp.StoreDesktop(var S: TStream);
-
- procedure WriteView(P: PView); far;
- begin
- if P <> Desktop^.Last then S.Put(P);
- end;
-
- begin
- Desktop^.ForEach(@WriteView);
- S.Put(nil);
- end;
-
-
- (* TVEDIT.PAS original, TEditorApp.HandleEvent does not include the
- following local routines: *)
- (* EDIT.PAS addition *)
- { copied from TVDEMO.PAS and modified filenames }
- procedure RetrieveDesktop;
- var
- S: PStream;
- begin
- S := New(PBufStream, Init('TVEDIT.DSK', stOpenRead, 1024));
- if LowMemory then OutOfMemory
- else if S^.Status <> stOk then
- MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
- else
- begin
- LoadDesktop(S^);
- if S^.Status <> stOk then
- MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
- end;
- Dispose(S, Done);
- end;
-
- procedure SaveDesktop;
- var
- S: PStream;
- F: File;
- begin
- S := New(PBufStream, Init('TVEDIT.DSK', stCreate, 1024));
- if not LowMemory and (S^.Status = stOk) then
- begin
- StoreDesktop(S^);
- if S^.Status <> stOk then
- begin
- MessageBox('Could not create TVEDIT.DSK.', nil, mfOkButton + mfError);
- {$I-}
- Dispose(S, Done);
- Assign(F, 'TVEDIT.DSK');
- Erase(F);
- Exit;
- end;
- end;
- Dispose(S, Done);
- end;
-
-
- (* TVEDIT.PAS original, TEditorApp.HandleEvent *)
- cmCalculator: Calculator;
- cmShowClip: ShowClip;
- cmTile: Tile;
- cmCascade: Cascade;
- else
- Exit;
-
- (* EDIT.PAS replacement *)
- cmCalculator: Calculator;
- cmShowClip: ShowClip;
- cmTile: Tile;
- cmCascade: Cascade;
- cmSaveDesktop: SaveDesktop;
- cmRetrieveDesktop: RetrieveDesktop;
- else
- Exit;
-
-
- (* TVEDIT.PAS original, TEditorApp.InitMenuBar *)
- NewItem('~P~revious', 'Shift-F6', kbShiftF6, cmPrev, hcNoContext,
- NewItem('~C~lose', 'Alt-F3', kbAltF3, cmClose, hcNoContext,
- NewLine(
- NewItem('Ca~l~culator', '', kbNoKey, cmCalculator, hcNoContext,
- nil)))))))))),
- nil)))))));
- end;
-
- (* EDIT.PAS replacement *)
- NewItem('~P~revious', 'Shift-F6', kbShiftF6, cmPrev, hcNoContext,
- NewItem('~C~lose', 'Alt-F3', kbAltF3, cmClose, hcNoContext,
- NewLine(
- NewItem('Ca~l~culator', '', kbNoKey, cmCalculator, hcNoContext,
- NewLine(
- NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcNoContex
- NewItem('Sa~v~e desktop', '', kbNoKey, cmSaveDesktop, hcNoContext,
- nil)))))))))))))
- nil)))))));
- end;
-
- --------------------------- TESTASM.PAS ---------------------------
- program TestAsm;
- begin
- asm
- MOV BX,OFFSET PrefixSeg
- MOV AX,[WORD PTR BX]
- MOV AX,WORD PTR [BX]
- end;
- end.
- --------------------------- TESTMEMO.PAS --------------------------
- program TestMemos ;
- uses Objects,Drivers,Views,Menus,Dialogs,Editors,App;
-
- const
- cmMemo = 1000;
-
- type
- PDemoListViewer = ^TDemoListViewer;
- TDemoListViewer = object(TListViewer)
- function GetText(Item: Integer; MaxLen: Integer): String; virtual;
- end;
-
- type
- TMemoApp=object(TApplication)
- procedure InitStatusLine; virtual;
- procedure HandleEvent(var Event:TEvent); virtual;
- end;
-
- function TDemoListViewer.GetText(Item: Integer; MaxLen: Integer): String;
- var
- S: String[5];
- begin
- Str(Item, S);
- GetText := copy('Item '+S,1,MaxLen);
- end;
-
- procedure TMemoApp.InitStatusLine;
- var
- R: TRect;
- begin
- GetExtent(R);
- R.A.Y := R.B.Y - 1;
- New(StatusLine, Init(R,
- NewStatusDef(0, $FFFF,
- NewStatusKey('~Alt-X~ Exit', kbALtX, cmQuit,
- NewStatusKey('~F1~ MemoDialog', kbF1, cmMemo,
- nil)),
- nil)));
- end;
-
- procedure TMemoApp.HandleEvent(var Event:TEvent);
- var
- R: TRect;
- D: PDialog;
- V,W: PView;
- begin
- TApplication.HandleEvent(Event);
- if (Event.What = evCommand) and (Event.Command = cmMemo) then
- begin
- R.Assign(22, 3, 58, 19);
- D := New(PDialog,Init(R, 'MemoDialog'));
- with D^ do
- begin
- R.Assign(12, 2, 13, 14);
- V := New(PScrollBar, Init(R));
- Insert(V);
- R.Assign(2, 2, 12, 14);
- V := New(PDemoListViewer, Init(R, 1, nil, PScrollBar(V)));
- PDemoListViewer(V)^.SetRange(20);
- Insert(V);
-
- R.Assign(33, 2, 34, 13);
- V := New(PScrollBar, Init(R));
- Insert(V);
- R.Assign(14, 13, 33, 14);
- W := New(PScrollBar, Init(R));
- Insert(W);
- R.Assign(14, 2, 33, 13);
- V := New(PMemo, Init(R, PScrollBar(W), PScrollBar(V), nil, 1024));
- Insert(V);
- end;
- DeskTop^.ExecView(D);
- D^.Done;
- end;
- end;
-
- var MemoApp:TMemoApp;
- begin
- MemoApp.Init;
- MemoApp.Run;
- MemoApp.Done;
- end.
- -------------------- End of bugs! ---------------------------------
- I got an update to TP6.01, but they haven't change anything.
- - J"urgen Schlegelmilch
-
-