home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / vrac / ve2tv103.zip / TVBC4BUG.DOC < prev    next >
Text File  |  1994-07-28  |  6KB  |  147 lines

  1. To all Turbo Vision 1.03 users:
  2.     First, let me state that this is *NOT* a bug in the compiler, it is a
  3. bug in Turbo Vision.  It's just that a slightly different code sequence
  4. generated by the compiler has uncovered it.  Anyone still using BC++ 3.1
  5. should also make the changes documented below but it isn't as mandatory as
  6. it is for those of us using BC++ 4.0.
  7.  
  8. Problem:
  9. ========
  10.     I spent several hours trying to figure out why any call to
  11. TProgram::setScreenMode() in my applications compiled under BC++ 4.0 would
  12. leave the screen blank and only redraw views that had the focus (such as an
  13. About Box or the status line).  I had to dig down all the way into the
  14. assembler code using Turbo Debugger to find out that there is an existing
  15. bug in the Turbo Vision code for TVEXPOSD.ASM and TPROGRAM.CPP that causes
  16. the problem.
  17.  
  18. How It Happens:
  19. ===============
  20.     The thing that causes the bug to show itself is in a code generation
  21. change in TGroup::drawSubViews().  BC++ 4.0 switches the AX and DX registers
  22. used for a while()-loop comparison.  This alters what is in the AX register
  23. when TView::exposed() is called during the redraw procedure.
  24.  
  25. Borland C++ 3.1 generates code for "while(p != bottom)" in the function
  26. TGroup::drawSubViews() in TGROUP.CPP as follows:
  27.  
  28. @10@86:
  29.     mov    ax,word ptr [bp+12]
  30.     mov    dx,word ptr [bp+10]
  31.     cmp    ax,word ptr [bp+16]
  32.     jne    short @10@58
  33.     cmp    dx,word ptr [bp+14]
  34.     jne    short @10@58
  35.  
  36. Borland C++ 4.0 generates code for "while(p != bottom)" in the function
  37. TGroup::drawSubViews() in TGROUP.CPP as follows:
  38.  
  39. @10@142:
  40.     mov    dx,word ptr [bp+12]         <<-- Note that it has switched
  41.     mov    ax,word ptr [bp+10]         <<-- the registers around.  This
  42.     cmp    dx,word ptr [bp+16]         <<-- is what uncovers the bug in
  43.     jne    short @10@114
  44.     cmp    ax,word ptr [bp+14]         <<-- TVEXPOSD.ASM and TPROGRAM.CPP.
  45.     jne    short @10@114
  46.  
  47.  
  48. The bad code in TPROGRAM.CPP for TProgram::setScreenMode():
  49.  
  50.     setState(sfExposed, False);     <<--- Screen exposure is disabled
  51.     redraw();                       <<--- so redraw() does nothing under
  52.     setState(sfExposed, True);      <<--- BC++ 4.0 because it sees that
  53.                                           the desktop isn't exposed.
  54.  
  55. The bad code in TVEXPOSD.ASM:
  56.  
  57.         LES     DI,[thisPtr]
  58.         TEST    [WORD PTR ES:DI+TViewState],sfExposed
  59.         JE      @@2         <<-- AX is cleared *AFTER* a test that can exit
  60.         XOR     AX,AX       <<-- the function instead of *BEFORE* it.
  61.         .
  62.         .
  63.         .
  64. @@2:
  65.         MOV     AL,0        <<-- The register is only half cleared if
  66.         JMP     @@30        <<-- the above test fails.  This causes
  67.                                  invalid True results to get returned
  68.                                  under BC++ 3.1.
  69.  
  70.     Under BC++ 3.1 the AX register contains a segment value for a pointer
  71. (i.e. 55AFh) and will therefore always return a non-zero value to its caller
  72. because the AH register is not cleared when the first test for sfExposed
  73. fails (it returns something like 5500h).  This makes the caller think the
  74. view is exposed whether it really is or not.  Under BC++ 4.0, AX now
  75. contains the offset value for a pointer (usually 0004h).  Due to the way
  76. TProgram::setScreenMode() performs its redraw, TView::exposed() now
  77. correctly recognizes that no views are exposed and always returns False
  78. (0000h).
  79.  
  80.  
  81. To fix the bug do the following:
  82. ================================
  83.  
  84. In TVEXPOSD.ASM, change lines 37-40 to be:
  85.  
  86.         XOR     AX,AX               ; Clear AX *BEFORE* the first test.
  87.         LES     DI,[thisPtr]
  88.         TEST    [WORD PTR ES:DI+TViewState],sfExposed
  89.         JE      @@2
  90.  
  91. In TPROGRAM.CPP, in the function TProgram::setScreenMode(), change lines
  92. 257-259 from:
  93.  
  94.     setState(sfExposed, False);
  95.     redraw();
  96.     setState(sfExposed, True);
  97.  
  98. To be:
  99.  
  100.     setState(sfExposed, False);     // sfExposed off to free display buffer.
  101.     setState(sfExposed, True);      // Expose the screen so it will be seen!
  102.     redraw();                       // Now redraw the whole desktop.
  103.  
  104.     The call to setState(sfExposed, False) causes TGroup::setState() to
  105. free the desktop screen buffer so that when the screen is exposed and
  106. redrawn, it will be truly redrawn instead of just redisplayed from an
  107. image buffer.
  108.  
  109.     Once the above changes have been made, you can rebuild the library in
  110. the normal manner.  Because TVEXPOSD.ASM was fixed, you will need TASM to
  111. recompile it or the equivalent fixed TVEXPOSD.OBJ file.
  112.  
  113. Optional modification to TVEXPOSD.ASM
  114. =====================================
  115.     While fixing those two bugs, I spotted a minor change to TVEXPOSD.ASM
  116. that will knock a few cycles off of its execution time and shorten it a byte
  117. or two.  It's not much, but I always say every little bit helps for screen
  118. updates <g>.
  119.  
  120. Change lines 54-61 from:
  121.  
  122.         CMP     AX,[ES:DI+TViewSizeY]
  123.         JL      @@1
  124. @@2:
  125.         MOV     AL,0
  126.         JMP     @@30
  127. @@3:
  128.         MOV     AL,1
  129.         JMP     @@30
  130.  
  131. To be:
  132.         CMP     AX,[ES:DI+TViewSizeY]
  133.         JL      @@1
  134.         MOV     AL,0
  135. @@2:                            ; AX is already zero if JE'd or JGE'd to.
  136.         RET                     ; JMP @@30 is redundant.  Just RETurn.
  137. @@3:
  138.         MOV     AL,1
  139.         RET                     ; JMP @@30 is redundant.  Just RETurn.
  140.  
  141. Then delete or comment out lines 149-150:
  142.  
  143. ; @@30:
  144. ;        RET                     ; Never referenced after the above change.
  145.  
  146. That's all.
  147.