home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 26
/
CD_ASCQ_26_1295.iso
/
vrac
/
tvme30.zip
/
TVBC4BUG.DOC
< prev
next >
Wrap
Text File
|
1995-08-02
|
6KB
|
147 lines
To all Turbo Vision 1.03 users:
First, let me state that this is *NOT* a bug in the compiler, it is a
bug in Turbo Vision. It's just that a slightly different code sequence
generated by the compiler has uncovered it. Anyone still using BC++ 3.1
should also make the changes documented below but it isn't as mandatory as
it is for those of us using BC++ 4.0.
Problem:
========
I spent several hours trying to figure out why any call to
TProgram::setScreenMode() in my applications compiled under BC++ 4.0 would
leave the screen blank and only redraw views that had the focus (such as an
About Box or the status line). I had to dig down all the way into the
assembler code using Turbo Debugger to find out that there is an existing
bug in the Turbo Vision code for TVEXPOSD.ASM and TPROGRAM.CPP that causes
the problem.
How It Happens:
===============
The thing that causes the bug to show itself is in a code generation
change in TGroup::drawSubViews(). BC++ 4.0 switches the AX and DX registers
used for a while()-loop comparison. This alters what is in the AX register
when TView::exposed() is called during the redraw procedure.
Borland C++ 3.1 generates code for "while(p != bottom)" in the function
TGroup::drawSubViews() in TGROUP.CPP as follows:
@10@86:
mov ax,word ptr [bp+12]
mov dx,word ptr [bp+10]
cmp ax,word ptr [bp+16]
jne short @10@58
cmp dx,word ptr [bp+14]
jne short @10@58
Borland C++ 4.0 generates code for "while(p != bottom)" in the function
TGroup::drawSubViews() in TGROUP.CPP as follows:
@10@142:
mov dx,word ptr [bp+12] <<-- Note that it has switched
mov ax,word ptr [bp+10] <<-- the registers around. This
cmp dx,word ptr [bp+16] <<-- is what uncovers the bug in
jne short @10@114
cmp ax,word ptr [bp+14] <<-- TVEXPOSD.ASM and TPROGRAM.CPP.
jne short @10@114
The bad code in TPROGRAM.CPP for TProgram::setScreenMode():
setState(sfExposed, False); <<--- Screen exposure is disabled
redraw(); <<--- so redraw() does nothing under
setState(sfExposed, True); <<--- BC++ 4.0 because it sees that
the desktop isn't exposed.
The bad code in TVEXPOSD.ASM:
LES DI,[thisPtr]
TEST [WORD PTR ES:DI+TViewState],sfExposed
JE @@2 <<-- AX is cleared *AFTER* a test that can exit
XOR AX,AX <<-- the function instead of *BEFORE* it.
.
.
.
@@2:
MOV AL,0 <<-- The register is only half cleared if
JMP @@30 <<-- the above test fails. This causes
invalid True results to get returned
under BC++ 3.1.
Under BC++ 3.1 the AX register contains a segment value for a pointer
(i.e. 55AFh) and will therefore always return a non-zero value to its caller
because the AH register is not cleared when the first test for sfExposed
fails (it returns something like 5500h). This makes the caller think the
view is exposed whether it really is or not. Under BC++ 4.0, AX now
contains the offset value for a pointer (usually 0004h). Due to the way
TProgram::setScreenMode() performs its redraw, TView::exposed() now
correctly recognizes that no views are exposed and always returns False
(0000h).
To fix the bug do the following:
================================
In TVEXPOSD.ASM, change lines 37-40 to be:
XOR AX,AX ; Clear AX *BEFORE* the first test.
LES DI,[thisPtr]
TEST [WORD PTR ES:DI+TViewState],sfExposed
JE @@2
In TPROGRAM.CPP, in the function TProgram::setScreenMode(), change lines
257-259 from:
setState(sfExposed, False);
redraw();
setState(sfExposed, True);
To be:
setState(sfExposed, False); // sfExposed off to free display buffer.
setState(sfExposed, True); // Expose the screen so it will be seen!
redraw(); // Now redraw the whole desktop.
The call to setState(sfExposed, False) causes TGroup::setState() to
free the desktop screen buffer so that when the screen is exposed and
redrawn, it will be truly redrawn instead of just redisplayed from an
image buffer.
Once the above changes have been made, you can rebuild the library in
the normal manner. Because TVEXPOSD.ASM was fixed, you will need TASM to
recompile it or the equivalent fixed TVEXPOSD.OBJ file.
Optional modification to TVEXPOSD.ASM
=====================================
While fixing those two bugs, I spotted a minor change to TVEXPOSD.ASM
that will knock a few cycles off of its execution time and shorten it a byte
or two. It's not much, but I always say every little bit helps for screen
updates <g>.
Change lines 54-61 from:
CMP AX,[ES:DI+TViewSizeY]
JL @@1
@@2:
MOV AL,0
JMP @@30
@@3:
MOV AL,1
JMP @@30
To be:
CMP AX,[ES:DI+TViewSizeY]
JL @@1
MOV AL,0
@@2: ; AX is already zero if JE'd or JGE'd to.
RET ; JMP @@30 is redundant. Just RETurn.
@@3:
MOV AL,1
RET ; JMP @@30 is redundant. Just RETurn.
Then delete or comment out lines 149-150:
; @@30:
; RET ; Never referenced after the above change.
That's all.