home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / probs / probs.txt
Encoding:
Text File  |  1992-04-10  |  42.5 KB  |  1,401 lines

  1. ================================================================
  2.  
  3. Subject: Stream Manager
  4.  
  5. Location: TV
  6.  
  7. Item: #00001
  8.  
  9. Submitted by: Ken Vogel [74007,564]
  10.  
  11. Problem:  The stream manager does not follow documentation in the Turbo
  12. Vision User's Guide.  The following does not work as documented on page 176.
  13.  
  14.        1) Create an object.
  15.        2) Have two pointers point to the object.
  16.        3) Write out both pointers to the stream.
  17.        4) Read the object back into memory via the two pointers.
  18.  
  19. The book states that the pointers should be pointing to the same object, but
  20. they do not.  The following code demonstrates the problem.
  21.  
  22. Attach information:
  23. ------------------------ Cut Here ------------------------
  24. #include <stdio.h>
  25.  
  26. #define Uses_Tobject
  27. #define Uses_TStreamable
  28. #define Uses_TStreamableClass
  29. #define Uses_ofpstream
  30. #define Uses_ifpstream
  31. #include <tv.h>
  32.  
  33. // Two classes of different sizes
  34. class FirstClass : public TStreamable
  35.   {
  36.     public:
  37.         int Dummy;
  38.         FirstClass() { Dummy = 1; }
  39.  
  40.     // Stream Stuff
  41.     public:
  42.         static const char * const near ClassNameP;
  43.         static TStreamable *build();
  44.     private:
  45.         virtual const char *streamableName() const
  46.             { return ClassNameP; }
  47.     protected:
  48.         FirstClass (StreamableInit);
  49.         virtual void *read( ipstream& );
  50.         virtual void write( opstream& );
  51.   };
  52.  
  53. inline opstream& operator << ( opstream& os, FirstClass* cl )
  54.     { return os << (TStreamable *)cl; }
  55. inline ipstream& operator >> ( ipstream& is, FirstClass*& cl )
  56.     { return is >> (void *&)cl; }
  57.  
  58. const char * const near FirstClass::ClassNameP  = "FirstClass";
  59.  
  60. TStreamableClass RFirstClass( FirstClass::ClassNameP,
  61.                          FirstClass::build,
  62.                              __DELTA(FirstClass)
  63.                            );
  64.  
  65. TStreamable *FirstClass::build()
  66. {
  67.     return new FirstClass( streamableInit );
  68. }
  69.  
  70.  
  71. FirstClass::FirstClass( StreamableInit )
  72. {
  73. }
  74.  
  75. void FirstClass::write( opstream& os )
  76. {
  77.     os << Dummy;
  78. }
  79.  
  80. void *FirstClass::read( ipstream& is )
  81. {
  82.     is >> Dummy;
  83.     return this;
  84. }
  85.  
  86. class SecondClass : public TStreamable
  87.   {
  88.     public:
  89.         int Dummy1, Dummy2;
  90.         SecondClass() { Dummy1 = Dummy2 = 1; }
  91.  
  92.     // Stream Stuff
  93.     public:
  94.         static const char * const near ClassNameP;
  95.         static TStreamable *build();
  96.     private:
  97.         virtual const char *streamableName() const
  98.             { return ClassNameP; }
  99.     protected:
  100.         SecondClass (StreamableInit);
  101.         virtual void *read( ipstream& );
  102.         virtual void write( opstream& );
  103.   };
  104.  
  105. inline opstream& operator << ( opstream& os, SecondClass* cl )
  106.     { return os << (TStreamable *)cl; }
  107. inline ipstream& operator >> ( ipstream& is, SecondClass*& cl )
  108.     { return is >> (void *&)cl; }
  109.  
  110. const char * const near SecondClass::ClassNameP  = "SecondClass";
  111.  
  112. TStreamableClass RSecondClass( SecondClass::ClassNameP,
  113.                          SecondClass::build,
  114.                              __DELTA(SecondClass)
  115.                            );
  116.  
  117. TStreamable *SecondClass::build()
  118. {
  119.     return new SecondClass( streamableInit );
  120. }
  121.  
  122.  
  123. SecondClass::SecondClass( StreamableInit )
  124. {
  125. }
  126.  
  127. void SecondClass::write( opstream& os )
  128. {
  129.     os << Dummy1 << Dummy2;
  130. }
  131.  
  132. void *SecondClass::read( ipstream& is )
  133. {
  134.     is >> Dummy1 >> Dummy2;
  135.     return this;
  136. }
  137.  
  138. void main (void)
  139. {
  140.     FirstClass *Common1AP = new FirstClass();
  141.     FirstClass *Common1BP = Common1AP;
  142.     SecondClass *Common2AP = new SecondClass();
  143.     SecondClass *Common2BP = Common2AP;
  144.  
  145.     printf ("1.  Should be the same:  A = %p   B = %p\n", Common1AP,
  146. Common1BP);
  147.     printf ("2.  Should be the same:  A = %p   B = %p\n", Common2AP,
  148. Common2BP);
  149.  
  150.     ofpstream *OutP = new ofpstream ("TEMP.OUT", ios::out | ios::trunc);
  151.     if (OutP)
  152.       {
  153.         *OutP << Common1AP << Common2AP << Common1BP << Common2BP;
  154.         delete OutP;
  155.       }
  156.  
  157.     Common1AP = Common1BP = 0;
  158.     Common2AP = Common2BP = 0;
  159.  
  160.     // Read back
  161.     ifpstream *InP = new ifpstream ("TEMP.OUT");
  162.     if (InP)
  163.       {
  164.         *InP >> Common1AP >> Common2AP >> Common1BP >> Common2BP;
  165.         delete InP;
  166.       }
  167.  
  168.     printf ("1.  Should be the same:  A = %p   B = %p\n", Common1AP,
  169. Common1BP);
  170.     printf ("2.  Should be the same:  A = %p   B = %p\n", Common2AP,
  171. Common2BP);
  172. }
  173. ------------------------ Cut Here ------------------------
  174.  
  175.  
  176. Borland Response:  This is a problem with the documentation or the stream
  177. manager.
  178.  
  179.        Workarounds: None.
  180.  
  181.        Additional Information: None.
  182.  
  183. ================================================================
  184.  
  185. Subject: Help Compiler
  186.  
  187. Location: TV
  188.  
  189. Item: #00002
  190.  
  191. Submitted by: Doug Amaral [75300,2010]
  192.  
  193. Problem: The help compiler gets a divide by 0 message when compiling a file
  194. with many references. The following file demonstrates the problem.
  195.  
  196. Attach Information:
  197. ------------------------ Cut Here ------------------------
  198. Builder Command Reference
  199.  
  200. {Adaptor:Adaptor}
  201. {And:And}
  202. {BCFAdd:BCFAdd}
  203. {BCFCopy:BCFCopy}
  204. {BCFDelete:BCFDelete}
  205. {Beep:Beep}
  206. {BLDAttrib:BLDAttrib}
  207. {BLDChDir:BLDChDir}
  208. {BLDCopy:BLDCopy}
  209. {BLDDel:BLDDel}
  210. {BLDMkDir:BLDMkDir}
  211. {Box:Box}
  212. {CALL:CALL}
  213. {Canceled:Canceled}
  214. {CapsLockOff:CapsLockOff}
  215. {CapsLockOn:CapsLockOn}
  216. {CapsLockStatus:CapsLockStatus}
  217. {Case:Case}
  218. {CharToNum:CharToNum}
  219. {ClearLineTo:ClearLineTo}
  220. {Clock:Clock}
  221. {ClockOff:ClockOff}
  222. {Close:Close}
  223. {CloseAllFiles:CloseAllFiles}
  224. {CLS:CLS}
  225. {CLS On:CLS_On}
  226. {Contains:Contains}
  227. {CoprocessorInstalled:CoprocessorInstalled}
  228. {CPU:CPU}
  229. {CurrentDir:CurrentDir}
  230. {CurrentDrive:CurrentDrive}
  231. {DayoftheWeek:DayoftheWeek}
  232. {DirExists:DirExists}
  233. {DiskFree:DiskFree}
  234. {DiskLabel:DiskLabel}
  235. {DiskReady:DiskReady}
  236. {DiskSize:DiskSize}
  237. {DOSErrorLevel:DOSErrorLevel}
  238. {DOSInstalled:DOSInstalled}
  239. {DOSRAM:DOSRAM}
  240. {DriveSize:DriveSize}
  241. {DropDown:DropDown}
  242. {ECHO:ECHO}
  243. {EMSAvail:EMSAvail}
  244. {EMSInstalled:EMSInstalled}
  245. {EMSMajor:EMSMajor}
  246. {EMSMinor:EMSMinor}
  247. {EMSTotal:EMSTotal}
  248. {EMSVersion:EMSVersion}
  249. {ENVAvail:ENVAvail}
  250. {ENVTotal:ENVTotal}
  251. {EOF:EOF}
  252. {Exit:Exit}
  253. {External:External}
  254. {File:File}
  255. {FileChangedDateToLong:FileChangedDateToLong}
  256. {FileChangedTimeToLong:FileChangedTimeToLong}
  257. {FileSize:FileSize}
  258. {FlushKeyboard:FlushKeyboard}
  259. {FOR:FOR}
  260. {FillArea:FillArea}
  261. {FreeArray:FreeArray}
  262. {GetFilePos:GetFilePos}
  263. {GetKey:GetKey}
  264. {GetYN:GetYN}
  265. {GOTO:GOTO}
  266. {GoToXY:GoToXY}
  267. {HasExtension:HasExtension}
  268. {Help:Help}
  269. {IF:IF}
  270. {Input:Input}
  271. {Input @:Input_@}
  272. {Integer:Integer}
  273. {IntegerArray:IntegerArray}
  274. {IntToStr:IntToStr}
  275. {Item:Item}
  276. {Keypressed:Keypressed}
  277. {LastKey:LastKey}
  278. {Length:Length}
  279. {LightBar:LightBar}
  280. {Location:Location}
  281. {LongInt:LongInt}
  282. {LongIntArray:LongIntArray}
  283. {LongToDateStr:LongToDateStr}
  284. {LongToStr:LongToStr}
  285. {LongToTimeStr:LongToTimeStr}
  286. {LowerCase:LowerCase}
  287. {LTrim:LTrim}
  288. {MaxCols:MaxCols}
  289. {MaxRows:MaxRows}
  290. {Menu Style:Menu_Style}
  291. {MidStr:MidStr}
  292. {MouseHideCursor:MouseHideCursor}
  293. {MouseInstalled:MouseInstalled}
  294. {MouseShowCursor:MouseShowCursor}
  295. {Move:Move}
  296. {NestedItem:NestedItem}
  297. {NOT:NOT}
  298. {NumLockOff:NumLockOff}
  299. {NumLockOn:NumLockOn}
  300. {NumLockStatus:NumLockStatus}
  301. {NumofDrives:NumofDrives}
  302. {NumToChar:NumToChar}
  303. {OnPath:OnPath}
  304. {Open:Open}
  305. {Or:Or}
  306. {OSMajor:OSMajor}
  307. {OSMinor:OSMinor}
  308. {OSVersion:OSVersion}
  309. {ParamCount:ParamCount}
  310. {Password:Password}
  311. {Pause:Pause}
  312. {PickFile:PickFile}
  313. {PickList:PickList}
  314. {PopUp:PopUp}
  315. {PrinterReady:PrinterReady}
  316. {Put:Put}
  317. {Read:Read}
  318. {ReadLine:ReadLine}
  319. {ReadScrLine:ReadScrLine}
  320. {Reboot:Reboot}
  321. {REM:REM}
  322. {RenSub:RenSub}
  323. {Repeat:Repeat}
  324. {RestoreScreen:RestoreScreen}
  325. {Rewind:Rewind}
  326. {RowCol:RowCol}
  327. {RTrim:RTrim}
  328. {Run:Run}
  329. {RunString:RunString}
  330. {RunSwap:RunSwap}
  331. {SaveScreen:SaveScreen}
  332. {Say:Say}
  333. {ScreenBlank:ScreenBlank}
  334. {ScrollLockOff:ScrollLockOff}
  335. {ScrollLockOn:ScrollLockOn}
  336. {ScrollLockStatus:ScrollLockStatus}
  337. {Set:Set}
  338. {SetFilePos:SetFilePos}
  339. {SHIFT:SHIFT}
  340. {Sleep:Sleep}
  341. {SleepUntil:SleepUntil}
  342. {StrDateToLong:StrDateToLong}
  343. {String:String}
  344. {StringArray:StringArray}
  345. {StrTimeToLong:StrTimeToLong}
  346. {StrToNum:StrToNum}
  347. {Stuff:Stuff}
  348. {Sub:Sub}
  349. {SysDateToLong:SysDateToLong}
  350. {System:System}
  351. {SysTimeToLong:SysTimeToLong}
  352. {Text On:Text_On}
  353. {Trim:Trim}
  354. {Unshift:Unshift}
  355. {UpperCase:UpperCase}
  356. {BIOS:BIOS}
  357. {Dont Use BrightColors:Dont_Use_BrightColors}
  358. {Dont Use Commas:Dont_Use_Commas}
  359. {Dont Use CtrlBreak:Dont_Use_CtrlBreak}
  360. {Dont Use Cursor:Dont_Use_Cursor}
  361. {Direct:Direct}
  362. {DOS:DOS}
  363. {Dont Use Encryption:Dont_Use_Encryption}
  364. {Use ExtendedKeyboardBuffer:Use_ExtendedKeyboardBuffer}
  365. {VideoMode:VideoMode}
  366. {Wait:Wait}
  367. {WaitUntil:WaitUntil}
  368. {WhereX:WhereX}
  369. {WhereY:WhereY}
  370. {While:While}
  371. {Write:Write}
  372. {WriteLine:WriteLine}
  373. {XMSAvail:XMSAvail}
  374. {XMSInstalled:XMSInstalled}
  375. {XMSMajor:XMSMajor}
  376. {XMSMinor:XMSMinor}
  377. {XMSTotal:XMSTotal}
  378. {XMSVersion:XMSVersion}
  379. ------------------------ Cut Here ------------------------
  380.  
  381. Borland Response: This a problem with the help compiler.
  382.  
  383.        Workarounds: None.
  384.  
  385.        Additional information: None.
  386.  
  387. ================================================================
  388.  
  389. Subject: TVFORMS and memory leaks
  390.  
  391. Location: TV
  392.  
  393. Item: # 00003
  394.  
  395. Submitted by: Jens Kjaerby [70742,433]
  396.  
  397. Problem: There is some kind memory leak at an unconfirmed location within
  398. TVFORMS.  When there more information I will add it.
  399.  
  400. The following are comments on a TurboVision memory leak (heap). All the
  401. files contained in the zip-file should be copied to:
  402.  
  403.    \borlandc\tvision\demos
  404.  
  405. or or copy of this, because the replace some of the original files.
  406.  
  407.  
  408. The following is written by a client of mine, Allan Henson.
  409.  
  410. ****************************************************************************
  411.  
  412.         Comments on modifications to the code:
  413.  
  414. - first the minimum to add the
  415. indication of heap - this is in the TVForms.cpp/.h and clearly marked with
  416. /*********** new additions *****/.
  417. new code.......
  418. /*********** end new additions *****/.
  419. These additions are as follows:-
  420. 1. Taken from TVDEMO3.cpp - the idle override section - patched into
  421. TVForms.cpp - This required adjustments for declarations and so on.
  422. 2. The addition of gadgets.cpp in the TVFORMS.PRJ.
  423. 3. A polish to the about box to indicate what for !!.
  424.  
  425. I refer to this later as the unmodified code because functionally the code
  426. is the same but for the addition of the heap and clock indication. If the
  427. compiler does its job, only a small overhead should be expected and the
  428. functional .EXE. Code at run time should exhibit the same effects as before
  429. the additions. TV will however function a little differently as the void
  430. *idle is overridden in the new version. This again should only effect the
  431. dynamic properties and not the function.
  432.  
  433. - second the addition of a pre-compiler switch in the listdlg.cpp to switch
  434. in and out the modified effective code. The switch is de-active as sent to
  435. you and can be activated by taking out the comment mark // before the
  436. #define _TVERRERRED at the top of the definition and declaration table in
  437. listdlg.cpp. These modifications are clearly marked in listdlg.cpp with
  438.  
  439. /************* heap loss reduction *********/
  440. code changes with #ifdef and #ifndef
  441. /************** end heap loss reduction ************/
  442.  
  443. Effectively the modifications consist of moving the local declaration TForm
  444. *f; from the TListDialog constructor to the class declaration then allowing
  445. it to be destroyed in the TListDialog destructor.
  446.  
  447. The heap values indicated below are for my setup and will depend on DOS
  448. setups and compiler type used. I have DOS 5.0 all allocated HI, BorlandC++
  449. kernel and IDE.
  450.  
  451. In the unmodified version the following can be seen:-
  452.  
  453. 1. From the IDE compile and RUN the TVERRORS.PRJ.
  454. 2. With the about box up on the screen.
  455.    HEAP 63760.
  456. 3. Press return and release the about box.
  457.    HEAP 65232.
  458.  
  459. ************
  460. Note 1:- I will call this BASE HEAP.
  461. ************
  462.  
  463. 4. Select file - open - PARTS.TVF.
  464.    HEAP 58368.
  465. 5. Select item 1.
  466.     HEAP 54512.
  467. 6. Release item 1.
  468.    HEAP 58352.
  469.  
  470. ************
  471. Note 2:- From 4.-58368 to 6. 58352 a loss of 16 Bytes.
  472. This has been found to be due to the overhead of the Streamable TFORMS.CPP
  473. class which is not released. Under the scope rules for C++ de-allocation for
  474. classes and there internal objects, when a class/object goes out of scope it
  475. should be de-allocated. If this is not done in a systematic manner then HEAP
  476. fragmentation eventually causes a CRASH. Graceful exits can be arranged by
  477. careful HEAP and stack checks but should not be required for normal exits
  478. from an object.
  479. ************
  480.  
  481. 7. Now repeat with item 2 on the list
  482.    HEAP 54512.
  483. 8. Now release item 2.
  484.    HEAP 58352.
  485.  
  486. ************
  487. Note 3:- The heap is now as 6. - The streamable 16 Bytes was a one time
  488. loss.
  489. ************
  490.  
  491. 9. Release the list box with AltF3.
  492.    HEAP 63632.
  493.  
  494. ************
  495. Note 4:- A total loss from Base heap  65232-63632 = 1600 bytes. Take 16 for
  496. the streamable that was never released and we have 1584 loss.
  497. ************
  498.  
  499.  
  500. Repeat the process above from 4. to prove stability in the numbers - call
  501. the HEAP at this point New base heap.
  502.  
  503.  
  504. 4. HEAP 65864.
  505. 5. HEAP 53024.
  506. 6. HEAP 56864.
  507.  
  508. *************
  509. Note 5:- No further loss of 16 bytes streamable. Once declared and the loss
  510. undertaken it is active , even after it went out of scope when the calling
  511. class - listdlg.cpp went out of scope. listdlg went out of scope when the
  512. list box was released. All memory at that point declared in listdlg and its
  513. subclasses (including child processes) should have been released.
  514. **************
  515.  
  516. 7. HEAP 53024.
  517. 8. HEAP 56864.
  518.  
  519. **************
  520. Note 6:- No further loss of 16 bytes.
  521. **************
  522.  
  523. 9. HEAP 62144.
  524.  
  525. **************
  526. Note 7:- A loss from New base heap of 1488 bytes This does not match the
  527. first loss of 1584 lost in the first run.
  528. **************
  529.  
  530. repeat the process and you will find that there has been another permanent
  531. loss of 1488 bytes.
  532.  
  533. **************
  534. Note 8:-
  535. As can be seen these losses can be broken up into three groups from the
  536. experiment so far.
  537.   1. The one time 16 bytes streamable - lost when the TForms is
  538.      selected from the list box    by way of listdlg.cpp.
  539.   2. A one time loss of 96 Bytes - the difference of the loss in
  540.      run 1 and run 2. 1584-1488 = 96.
  541.   3. A repeated loss of 1488 bytes each time the form is selected.
  542. ***************
  543.  
  544. Repeating the procedure with PHONENUM:TVF exhibits the same pattern. loss
  545. type three is the only difference.
  546.  
  547. This lead me to the conclusion that there were a minimum of three possible
  548. areas of concern.
  549.  
  550. 1. Nonrecoverable heap due to streamable and as noted before this can lead
  551. to fragmented heap.
  552.  
  553. 2. A nonrecoverable 96 bytes that is systematic irrespective of the size of
  554. the Resource file of element size.  However 96 was devisable by 16 !! -
  555. perhaps TV uses 6 none recoverable streams also being used. If so this
  556. could be difficult to trace as the heap is not directly accessible.
  557. Further investigations show that there are indeed several streamable
  558. objects being used - Resource files- streamable disk access -          collections
  559. just to name three.
  560.  
  561. 3. What is causing the collection size dependent loss.
  562.  
  563. Now re-compile this time removing the comment // from the #define
  564.  
  565. This is now the pattern:-
  566.  
  567. 2. HEAP 63712.
  568. 3. HEAP 55184.
  569. 4. HEAP 58304.
  570. 5. HEAP 54448.
  571. 6. HEAP 58288.
  572. 7. HEAP 54448.
  573. 8. HEAP 58288.
  574. 9. HEAP 64960.
  575.  
  576. **************
  577. Note 9:- Note loss of 224 - 16 streamable = 208.
  578. **************
  579.  
  580. Now repeat as before:-
  581. 3. HEAP 64960.
  582. 4. HEAP 58176.
  583. 5. HEAP 54336.
  584. 6. HEAP 58176.
  585. 7. HEAP 54336.
  586. 8. HEAP 58176.
  587. 9. HEAP 64848.
  588.  
  589. **************
  590. Note 10:- Note loss of 112 bytes. Differance of 96 bytes.
  591. **************
  592.  
  593. **************
  594. Note 11:- Now we have some data to go on. 112 is also devisable by 16. But
  595. so is a long int !!.
  596. **************
  597.  
  598. repeat the process with the other file TPHONENUM.TVF
  599.  
  600. This gives the following:-
  601.  
  602. The memory regained after the modification is 1376 Bytes for each access to
  603. the listdlg.cpp.
  604.  
  605. The modification made was to take a declaration pointer to an object in the
  606. constructor and move it to the public area where it can be released
  607. 'manually' by the Destructor.
  608.  
  609. Again scope rules demand that local declarations are destroyed when an
  610. object goes out of scope. In deed but for the list box in TV all other items
  611. do destroy themselves - after all that was the intention. There is a clear
  612. declaration in the manuals that states that 'release Element;' is not good
  613. enough but that destroy(Element); shall be used in order to ensure that the
  614. objects are released in order and the memory recovered. For the list box it
  615. states that the users list shall be disposed of prior to releasing the box
  616. to ensure full recovery. It is the users responsibility to ensure this.
  617.  
  618. Any attempt to dispose of the list by making new = 0 collection as
  619. recommended, only leads to heap corruption.
  620.  
  621. Conclusion
  622. -----------
  623. The streamable objects can leave a heap fragmented with pointers hiding
  624. lower access - initializing the streamables at the front of the program can
  625. avoid this but requires that all are global and defeats the object of C++
  626. encapsulation and protection. In out test case only 16 bytes were lost to
  627. the declared streamable outside TV and this at a point before the real use
  628. of the heap begins.
  629.  
  630. TV seems to suffer the same kind of problem with streamables that a user
  631. streamable has. TV seems to use streams for the majority of its
  632. communication channels. Some are declared for extern use such as the
  633. streamable collections other are for internal use. In our test case 96 bytes
  634. were allocated to the TV streamables.
  635.  
  636. The permanent loss due to the destructor not de-allocating the pointer *f
  637. but rather only the pointer can be traced to the structure and nature of TV.
  638. As TV is a context program structure any allocation cannot be allowed to be
  639. automatically destroyed when the calling element goes out of scope. The desk
  640. top contents may be required by other objects. However when the owning
  641. object (in our case listdlg.cpp) goes out of scope it can be eliminated
  642. safely as it is the only object that can initiate and safely destroy objects
  643. owned by it. TV does not apparently release the memory allocation when the
  644. pointer to an object is de-allocated. This means that ALL objects shall be
  645. destroyed explicitly before the pointer is released. Some mention of this is
  646. made in the manuals but Borland did not take there own advice in this demo.
  647.  
  648. The remaining permanent loss each time the list box is accessed still
  649. remains a mystery. There seems to be no decernable relation to the
  650. collection size or elements of the collection. However the only thing that
  651. can be said is that it has been found to grow with increased size of each
  652. record of the collection. This is also related to the complexity of the
  653. window. The other related fact is that the loss is always devisable by 16 no
  654. matter what the contents if the record are.
  655.  
  656. I have built up a system with float, long, short, int signed and unsigned,
  657. matrix elements and so on ( fields.cpp ). No matter which type is used the
  658. same number of bytes are lost.
  659.  
  660. Whether this is a mater of a problem with the memory manager inside TV I do
  661. not know. The TV memory manager is stable and repeatable results can be
  662. obtained. There is a de-allocation problem somewhere in the system be it TV
  663. or the C++ memory functions.
  664.  
  665. I can only say that until I have found the answers I cannot to my customer
  666. that he uses the TV for his tool box yet. The tool box is to check safety
  667. software and MUST be itself error free.
  668.  
  669. Borland Response: There is a problem of a memory leak with TVFORMS, but I
  670. am unable to find the source of the problem.
  671.  
  672.        Workaround: None.
  673.  
  674.        Additional Information: None.
  675.  
  676. ================================================================
  677.  
  678. Subject: Low memory condition and TFILLIST.
  679.  
  680. Location: TV
  681.  
  682. Item: # 00004
  683.  
  684. Submitted by: Ken Vogel [74007,564]
  685.  
  686. Problem:   Your application will crash with an abnormal program termination
  687.            if you try to do a file Dialog in a directory with too many
  688.            files.
  689.  
  690. Proposed Solution:
  691.  
  692. Interestingly enough, TFILLIST has code to handle too many files. The loop
  693. to read a file diligently checks if the pointer (allocated via new) is NULL,
  694. and will terminate the loop. However, NEW.CPP provided with TurboVision will
  695. *terminate* when no more memory is available (after dipping into the safety
  696. pool).  TFILLIST should check the Safety Pool (via lowMemory) while it is
  697. looping, NOT the pointer itself.
  698.  
  699. In TFileList::readDirectory, change lines 167 and 179 as follows:
  700. **** FROM *****
  701. while( p != 0 && res == 0)
  702. ***** TO *****
  703. while( p != 0 && res == 0 && !lowMemory())
  704. ***** END *****
  705.  
  706. Also, change line 214:
  707. **** FROM 4*****
  708. if( p == 0 )
  709.     messageBox( tooManyFiles, mfOKButton | mfWarning );
  710. ***** TO *****
  711. if( p == 0  || lowMemory())
  712.     messageBox( tooManyFiles, mfOKButton | mfWarning );
  713. ***** END *****
  714.  
  715. Borland Response:  This seems to be a problem.  I have made a report and
  716. sent it to the Quality Assurance Group.
  717.  
  718.        Workaround: To following proposed solution.
  719.  
  720.        Additional Information: None.
  721.  
  722. ================================================================
  723.  
  724. Subject: TV and DOS less than 3.31
  725.  
  726. Location: TV
  727.  
  728. Item #: 0005
  729.  
  730. Submitted by: Nancy Enright [72230,1443]
  731.  
  732. Problem:  Will you add the TSystemError bug to your list - see the "Print
  733. via System call" thread. The only clarification I need to add to the
  734. documentation which I have already provided is that the machines which
  735. displayed the error message and hung were NOT all running DOS 3.21, 2 were,
  736. and 3 were running DOS 5.0. Let me know if I can supply any additional
  737. information which will help you track down this problem.
  738.  
  739. Borland Response:  I have made an information request concerning this
  740. problem.
  741.  
  742.        Workaround: None.
  743.  
  744.        Additional Information: Work on reproducing the problem.
  745.  
  746. ================================================================
  747.  
  748. Subject: ofTopSelect flags vs firstMatch.
  749.  
  750. Location: TV
  751.  
  752. Item #: 0006
  753.  
  754. Submitted by: John L. Swartzentruber [76646,1430]
  755.  
  756. Problem: This program is intended to demonstrate the bug in
  757. TGroup::firstMatch(). It also shows some other areas that appear to be
  758. problems.  It is created from a modified version of the TVGUID04 demo
  759. program.  For simplicity, the new fields do not have associated palettes, so
  760. the input fields are flashing red on white.
  761.  
  762. The main bug is seen by attempting to click the mouse on one of the non-
  763. current fields.  The selection does not change.  The problem can be seen by
  764. tracing from the TView::select() of the field that you click on.  This will
  765. eventually call firstMatch() which will return the wrong field. because of
  766. this, setCurrent() does nothing.
  767.  
  768. Other potential problems (marked with !!) are:
  769.  
  770. 1)  buffering does not work for embedded windows.  Writes seem to go to the
  771. parent window, but the current buffer containing garbage is what is painted.
  772.  
  773. 2)  TGroup::draw() does not call TView::draw().  This means that if the
  774. group is not completely covered by subviews, the rest of the group is
  775. covered with garbage.
  776.  
  777. Attached information:
  778. ------------------------ Cut Here ------------------------
  779. #define Uses_TEvent
  780. #define Uses_TApplication
  781. #define Uses_TKeys
  782. #define Uses_TRect
  783. #define Uses_TMenuBar
  784. #define Uses_TSubMenu
  785. #define Uses_TMenuItem
  786. #define Uses_TStatusLine
  787. #define Uses_TStatusItem
  788. #define Uses_TStatusDef
  789. #define Uses_TDeskTop
  790. #define Uses_TWindow
  791. #define Uses_TInputLine
  792. #include <tv.h>
  793.  
  794. const int cmMyNewWin   = 201;
  795.  
  796. class TMyApp : public TApplication
  797. {
  798.  
  799. public:
  800.     TMyApp();
  801.     static TStatusLine *initStatusLine( TRect r );
  802.     static TMenuBar *initMenuBar( TRect r );
  803.     virtual void handleEvent( TEvent& event);
  804.     void myNewWindow();
  805. };
  806.  
  807.  
  808. static short winNumber = 0;          // initialize window number
  809.  
  810. class TDemoWindow : public TWindow   // define a new window class
  811. {
  812.  
  813. public:
  814.  
  815.    TDemoWindow( const TRect& r, const char *aTitle, short aNumber );
  816. };
  817.  
  818.  
  819. class TInnerWindow : public TGroup
  820. {
  821. public:
  822.     TInnerWindow( const TRect& r );
  823.     virtual void draw();
  824. }
  825.  
  826.  
  827. TMyApp::TMyApp() :
  828.     TProgInit( &TMyApp::initStatusLine,
  829.                &TMyApp::initMenuBar,
  830.                &TMyApp::initDeskTop
  831.              )
  832. {
  833.     TEvent event;
  834.  
  835.     // Put up the demo window
  836.     event.what = evCommand;
  837.     event.message.command = cmMyNewWin;
  838.     putEvent(event);
  839. }
  840.  
  841. TStatusLine *TMyApp::initStatusLine(TRect r)
  842. {
  843.     r.a.y = r.b.y - 1;     // move top to 1 line above bottom
  844.     return new TStatusLine( r,
  845.         *new TStatusDef( 0, 0xFFFF ) +
  846.         // set range of help contexts
  847.             *new TStatusItem( 0, kbF10, cmMenu ) +
  848.             // define an item
  849.             *new TStatusItem( "~Alt-X~ Exit", kbAltX, cmQuit ) +
  850.             // define an item
  851.             *new TStatusItem( "~Alt-F3~ Close", kbAltF3, cmClose )
  852.             // and another one
  853.         );
  854. }
  855.  
  856. TMenuBar *TMyApp::initMenuBar( TRect r )
  857. {
  858.  
  859.     r.b.y = r.a.y + 1;    // set bottom line 1 line below top line
  860.     return new TMenuBar( r,
  861.         *new TSubMenu( "~F~ile", kbAltF )+
  862.             *new TMenuItem( "~N~ew",  cmMyNewWin,   kbF4, hcNoContext, "F4" )+
  863.             newLine()+
  864.             *new TMenuItem( "E~x~it", cmQuit, cmQuit, hcNoContext, "Alt-X" )+
  865.         *new TSubMenu( "~W~indow", kbAltW )+
  866.             *new TMenuItem( "~N~ext", cmNext,     kbF6, hcNoContext, "F6" )+
  867.             *new TMenuItem( "~Z~oom", cmZoom,     kbF5, hcNoContext, "F5" )
  868.         );
  869. }
  870.  
  871. void TMyApp::handleEvent(TEvent& event)
  872. {
  873.     TApplication::handleEvent(event); // act like base!
  874.     if( event.what == evCommand )
  875.         {
  876.         switch( event.message.command )
  877.             {
  878.             case cmMyNewWin:       // but respond to additional commands
  879.                 myNewWindow();     // define action for cmMyNewWin
  880.                 break;
  881.             default:
  882.                 return;
  883.             }
  884.         clearEvent( event );       // clear event after handling
  885.         }
  886. }
  887.  
  888. void TMyApp::myNewWindow()
  889. {
  890.     TRect r( 0, 0, 65, 18 );           // set initial size and position
  891.     r.move(winNumber*3, winNumber*3);
  892.     TDemoWindow *window = new TDemoWindow ( r, "Bug Demo Window", ++winNumber);
  893.     deskTop->insert(window); // put window into desktop and draw it
  894. }
  895.  
  896.  
  897. TDemoWindow::TDemoWindow( const TRect& r, const char *aTitle, short aNumber):
  898.                           TWindow( r, aTitle, aNumber),
  899.                           TWindowInit( &TDemoWindow::initFrame
  900.                         )
  901.  
  902. {
  903.     // Create and insert the inside group.  It is used so that nothing
  904.     // overwrites the frame.
  905.     TRect b = getExtent();
  906.     b.grow(-1,-1);
  907.     TView* inside = new TInnerWindow(b);
  908.     insert(inside);
  909. }
  910.  
  911.  
  912. TInnerWindow::TInnerWindow( const TRect& r ) : TGroup(r)
  913. {
  914.     options &= ~ofBuffered; // Buffering doesn't work in embedded windows !!
  915.  
  916.     TView* views[3];
  917.  
  918.     // Insert three input fields
  919.     for (int i=0; i < 3; ++i) {
  920.         TRect bounds(i * 17 + (i+1)*3, 1, (i+1) * 20, 2);
  921.         views[i] = new TInputLine(bounds, 16);
  922.         views[i]->options |= ofTopSelect;   // This is what causes problem to
  923.                                             // happen !!
  924.         insert(views[i]);
  925.     }
  926. }
  927.  
  928. void TInnerWindow::draw()
  929. {
  930.     // This is needed because the TGroup::draw() function never
  931.     // calls TView::draw() !!
  932.     TView::draw();
  933.     TGroup::draw();
  934.  
  935.     // Put instructions under the input fields
  936.     int color = 1;
  937.     writeStr(1, 3, "This demonstrates the bug in TGroup::firstMatch()", color);
  938.     writeStr(1, 5, "Click the mouse in the second or third field.", color);
  939.     writeStr(1, 6, "Observe that nothing happens.", color);
  940.     writeStr(1, 8, "The problem is that select() calls makeFirst()", color);
  941.     writeStr(5, 9, "which calls putInFrontOf()", color);
  942.     writeStr(5, 10, "which calls resetCurrent()", color);
  943.     writeStr(5, 11, "which calls firstMatch()", color);
  944.     writeStr(5, 12, "which has a bug and returns the last view, not the first",
  945.              color);
  946. }
  947.  
  948. int main()
  949. {
  950.     TMyApp myApp;
  951.     myApp.run();
  952.     return 0;
  953. }
  954. ------------------------ Cut Here ------------------------
  955.  
  956. Borland Response: I was able to reproduce the describe behavior.  I am
  957. not sure why it does not work for this case, but works for TWindow. There
  958. is some limitation to the use of ofTopSelect. I will let the designers
  959. decide the issue. I am not sure what the issues are for other
  960. problems.   When I get more information I will attach.
  961.  
  962.        Workarounds: None.
  963.  
  964.        Additional information: None.
  965.  
  966. ================================================================
  967.  
  968. Subject: Invalid cmReceivedFocus and cmReleasedFocus problems
  969.  
  970. Location: TV
  971.  
  972. Item #: 0007
  973.  
  974. Submitted by: Bill Morrison [70403,3224]
  975.  
  976.  
  977. Problem: I mentioned that the cmReleasedFocus and cmReceivedFocus messages
  978. (R&R msgs) were being broadcast numerous times for no valid reason.
  979. Yesterday, I discovered some if not all of the bugs that cause this. Realize
  980. that it is these invalid broadcasts that make processing these events
  981. unreliable at best.
  982.  
  983. Invalid R&R's are sent each time TView::setState is called to change the
  984. focus when in fact the focus state is already set to the desired value. In
  985. other words, a call to set the focus to True on a view whose focus is
  986. already True; and to False when already False. Again, pause a moment and
  987. realize: 1) the overhead of routing the message, 2) a handleEvent trying to
  988. discriminate a valid R&R from an invalid one. Maybe we can live with the
  989. overhead, and the modified TView::select is a valid alternative to R&R's.
  990. Personally, I prefer to have my cake and eat it too, so I will fix the bugs
  991. and modify select.
  992.  
  993. In fixing the bugs, I saw and weighed several alternative solutions. The
  994. following are the ones I'm using today.  They are all in the TGROUP module.
  995.  
  996. Bug 1:
  997.  
  998. void TGroup::focusView( TView* p, Boolean enable )
  999. {
  1000.     if( (state & sfFocused) != 0 && p != 0 )
  1001.         p->setState( sfFocused, enable );
  1002. }
  1003.  
  1004. My Fix to Bug 1:
  1005.  
  1006. void TGroup::focusView( TView* p, Boolean enable )
  1007. {
  1008.   if ( (p != 0)
  1009.   &&   ((state & sfFocused) != 0)
  1010.      )
  1011.   {
  1012.      Boolean isFocused=(Boolean) (p->state & sfFocused);
  1013.      if (isFocused != enable)
  1014.         p->setState(sfFocused,enable);
  1015.   }
  1016. }
  1017.  
  1018. The original TGroup::focusView says: if the group's present state is focused
  1019. and p is a pointer to a subview, then set the focus state of p to enable,
  1020. which can be True or False.
  1021.  
  1022. The corrected TGroup::focusView applys the additional requirement that p's
  1023. present focus state be different than enable.  This prevents invalid R&R's.
  1024.  
  1025. Bug 2:  within TGroup::setState method you'll find:
  1026.  
  1027. if( (aState & sfFocused) != 0 )
  1028.     {
  1029.     if( current != 0 )
  1030.         current->setState( sfFocused, enable );
  1031.     }
  1032.  
  1033. My fix to Bug 2:
  1034.  
  1035. if ((aState & sfFocused) != 0 )
  1036. {
  1037.    if (current !=0)
  1038.    {  Boolean isFocused = (Boolean) (current->state & sfFocused);
  1039.       if (isFocused != enable)
  1040.          current->setState(sfFocused,enable);
  1041.    }
  1042. }
  1043.  
  1044. Here again, I require the present focus state to be different than the
  1045. requested focus state.
  1046.  
  1047. Bug 3: within TGroup::setCurrent method you'll find:
  1048.  
  1049. if( (state & sfFocused) != 0 && p != 0 )
  1050.     p->setState( sfFocused, True );
  1051.  
  1052. My fix to Bug 3:
  1053.  
  1054. if ( (p!=0)
  1055. &&   ((state & sfFocused) !=0)
  1056. &&   ((p->state & sfFocused) == 0)
  1057.    )
  1058. {
  1059.      if (current!=0)
  1060.      {
  1061.         if ((current->state & sfFocused) == 0)
  1062.            p->setState(sfFocused,True);
  1063.      }
  1064.      else
  1065.         p->setState(sfFocused,True);
  1066. }
  1067.  
  1068. Again, the original does require p to be a subview of the focused group.
  1069.  
  1070. The fix also requires that the present focus state of p to be False prior to
  1071. setting it to True.  In addition, if current is a pointer to another
  1072. subview, that subview's focus state must also be False prior to setting p's
  1073. focus to True.
  1074.  
  1075. From page 105 of the User's Guide: "Within each group of views, one and only
  1076. one subview is selected at any given moment.", and a little later: "Within
  1077. the active window, the selected subview is called the focused view.".
  1078.  
  1079. Notice also, that TGroup::setCurrent is also responsible for maintaining the
  1080. sfSelected status for both the current and p subviews. It is likely that
  1081. this logic needs a little fix as well. Perhaps more on that later.
  1082.  
  1083. With the above fixes applied, you can recognize legitimate R&R messages
  1084. within you subview's handleEvent.  The approach that I have taken is to
  1085. optionally have the subview handleEvent place a command in the event queue
  1086. via putEvent.  That command can tell the group's handleEvent to select a
  1087. particular subview (previous, next, this, or whatever). For example:
  1088.  
  1089. void MyField1::handleEvent(TEvent& event)
  1090. {
  1091.   TInputLine::handleEvent(event);
  1092.  
  1093.   if ( ((event.what & evBroadcast)!=0)
  1094.   &&   (event.message.command==cmReleasedFocus)
  1095.   &&   (event.message.infoPtr==this)
  1096.   &&   ((state & sfExposed)!=0)
  1097.      )
  1098.   {
  1099.       if (valid(cmLeaving)!=True)
  1100.       {  event.what=evCommand;
  1101.          event.message.command=cmSelectThis;
  1102.          event.message.infoPtr=this;
  1103.          putEvent(event);
  1104.          clearEvent(event);  // important! and not on page 401
  1105.       }
  1106.   }
  1107. }
  1108.  
  1109. void MyDialog::handleEvent(TEvent& event)
  1110. {
  1111.   TDialog::handleEvent(event);
  1112.   if ((event.what & evCommand)!=0)
  1113.      switch (event.message.command)
  1114.      {  case cmSelectNext:
  1115.           clearEvent(event);
  1116.           selectNext(False);
  1117.         break;
  1118.  
  1119.         case cmSelectThis:
  1120.           setCurrent((TView *)event.message.infoPtr, normalSelect);
  1121.           clearEvent(event);
  1122.         break;
  1123.      }
  1124.  
  1125. }
  1126.  
  1127. Note, that for this to work with the mouse, I have set ofFirstClick for
  1128. MyField1 to False.  The reason that this is necessary is that the
  1129. TView::mouseEvent method will dispose of the queued command while waiting
  1130. for the evMouseUp.  I think I could have ofFirstClick set to True if
  1131. MyField1 handleEvent was smart enough.
  1132.  
  1133. Borland Response:  I have made a report that documents the problems with
  1134. cmReleaseFocus & cmReceivedFocus.  I have tried to supplied fixes and they
  1135. seem to be a possible workaround.
  1136.  
  1137.        Workarounds: Apply the above fixes.
  1138.  
  1139.        Additional information: None.
  1140.  
  1141. ================================================================
  1142.  
  1143. Subject: MSGBOX.CPP & MessageBoxRect
  1144.  
  1145. Location: TV
  1146.  
  1147. Item #: 0008
  1148.  
  1149. Submitted by: John L. Swartzentruber [76646,1430]
  1150.  
  1151. Problem: Replaced variable argument list MessageBoxRect(...) to make it
  1152. work. The output string was created with vsprintf(), then the fixed
  1153. parameter version of MessageBoxRect() was called.
  1154.  
  1155. Fixed a memory leak in the first messageBoxRect() function by calling
  1156. shutDown() for the dialog.
  1157.  
  1158. Borland Response:  I have made a report that documents the fixes purpose for
  1159. MessageBoxRect(...) and MessageBoxRect().  I have tried the supplied fixes
  1160. and they seem to be a possible workaround.
  1161.  
  1162.        Workarounds: None.
  1163.  
  1164.        Additional information: None.
  1165.  
  1166. ================================================================
  1167.  
  1168. Subject: SYSERR and critical error reporter
  1169.  
  1170. Location: TV
  1171.  
  1172. Item #: 0009
  1173.  
  1174. Submitted by: John L. Swartzentruber [76646,1430]
  1175.  
  1176.  
  1177. Problem: The sysErr() critical error reporting function assumed that the
  1178. output screen was 80 columns wide.  If it is wider, garbage will appear at
  1179. the end of the line, and the text will not be justified properly. Since the
  1180. width of the screen is known, and is stored in TScreen::screenWidth, I used
  1181. the actual screen width value.  This was fixed by replacing the hardcoded
  1182. numbers (80 and 79) with TScreen::screenWidth and TScreen::screenWidth-1.
  1183.  
  1184. Borland Response:  I have made a report that documents the fixes purpose for
  1185. critical error handler.  I have tried the supplied fixes and seem to be a
  1186. possible workaround.
  1187.  
  1188.        Workarounds: None.
  1189.  
  1190.        Additional information: None.
  1191.  
  1192. ================================================================
  1193.  
  1194. Subject: KeyBufOrg and KeyBufEnd
  1195.  
  1196. Location: TV
  1197.  
  1198. Item #: 0010
  1199.  
  1200. Submitted by: John L. Swartzentruber [76646,1430]
  1201.  
  1202. Problem: The keyboard interrupt handler was assuming that everyone's
  1203. keyboard buffer was at the default location. The handler can reset some of
  1204. the BIOS pointers to incorrect locations because of this.  Since the BIOS
  1205. data area contains fields that point to the real keyboard buffer, I used
  1206. those fields.  Again, it was a very simple fix.  The EQU's for KeyBufOrg and
  1207. KeyBufEnd were changed to 80H and 82H respectively. These are the locations
  1208. in the BIOS data area of words that point to the beginning and end of the
  1209. keyboard buffer. Everywhere in the code where these EQU's were used, was
  1210. changed to use the segment override (DS contains the BIOS data segment). For
  1211. example:
  1212.  
  1213.           MOV     AX,OFFSET KeyBufOrg
  1214.  
  1215.      was changed to
  1216.  
  1217.           MOV     AX,DS:KeyBufOrg
  1218.  
  1219. Borland Response:  I have made a report that documents the problems with
  1220. cmReleaseFocus & cmReceivedFocus.  I have tried to supplied fixes and they
  1221. seem to be a good workaround.
  1222.  
  1223.        Workarounds: None.
  1224.  
  1225.        Additional information: None.
  1226.  
  1227. ================================================================
  1228.  
  1229. Subject: iSqr and TDesktop.
  1230.  
  1231. Location: TV
  1232.  
  1233. Item #: 0011
  1234.  
  1235. Submitted by: John L. Swartzentruber [76646,1430]
  1236.  
  1237. Problem: The iSqr() function found a floating point square root, and then
  1238. cast it to an integer.  This works fine, except that it pulls in the
  1239. floating point code, even if it isn't used anywhere else (15 - 20K worth I
  1240. think).  I rewrote the iSqr() function using Pascal code posted by J.W.
  1241. Rider as its base, but making it fit the existing iSqr() interface.
  1242.  
  1243. Borland Response:  I have made a report that documents the problems with
  1244. iSqr.  I have tried to supplied fixes and they seem to be a good workaround.
  1245.  
  1246.        Workarounds: None.
  1247.  
  1248.        Additional information: None.
  1249.  
  1250. ================================================================
  1251.  
  1252. Subject: setBufSize and Tfiledtr
  1253.  
  1254. Location: TV
  1255.  
  1256. Item #: 0012
  1257.  
  1258. Submitted by: John L. Swartzentruber [76646,1430]
  1259.  
  1260. Problem: When the buffer size was being decreased, the setBufSize() function
  1261. was losing data that was located after the gap.  Also, when the buffer size
  1262. increased, the gap was the wrong size, and data was lost and garbage was
  1263. gained.  The solution was to require that all setBufSize() functions should
  1264. resize the gap when the buffer size is changed. To avoid duplication of
  1265. effort in the future, I wrote a new function in the TEditor class to handle
  1266. the changes.  This new function is in module TEDITOR3.CPP.
  1267.  
  1268. Borland Response:  I have made a report that documents the problems with
  1269. setBufSize.  I have tried to supplied fixes and they seem to be a good
  1270. workaround.
  1271.  
  1272.        Workarounds: None.
  1273.  
  1274.        Additional information: None.
  1275.  
  1276. ================================================================
  1277.  
  1278. Subject: TEditor, TFiledtr, and setBufSize.
  1279.  
  1280. Location: TV
  1281.  
  1282. Item #: 0013
  1283.  
  1284. Submitted by: John L. Swartzentruber [76646,1430]
  1285.  
  1286. Problem: This is a new module that I wrote to solve the problem in
  1287. TFilEdtr.cpp.  Since I did not want to have all the code duplicated in every
  1288. class that overrides setBufSize(), I wrote this helper function and put it
  1289. in the base class.  I also added the proper declaration for this function in
  1290. EDITORS.H.  The new function declaration looks like this:
  1291.  
  1292.           int TEditor::normalizeBuffer(ushort newSize);
  1293.  
  1294. The name isn't the best, but "setBufSize()" was already being used. This
  1295. function's purpose is the make sure that all the internal pointers are set
  1296. correctly and that the gap is the proper size for the new buffer size. This
  1297. function should only be called from a setBufSize() function in a class
  1298. derived from TEditor.  If the buffer is growing (i.e., newSize is greater
  1299. than bufSize), this function should be called after the new buffer is
  1300. allocated and the old data is copied to the buffer. If the new size is less
  1301. than the old size, this function should be called before allocating the new
  1302. buffer.  See the setBufSize() function in TFileEditor for an example.
  1303.  
  1304. Borland Response:  I have place this suggestion in the data base.
  1305.  
  1306.        Workarounds: None.
  1307.  
  1308.        Additional information: A this unofficial improvement to TEditor
  1309.        class.
  1310.  
  1311. ================================================================
  1312.  
  1313. Subject: Memory Leak in fpstream.
  1314.  
  1315. Location: TV
  1316.  
  1317. Item #: 0014
  1318.  
  1319. Submitted by: Ken Vogel [74004,564]
  1320.  
  1321. Problem:
  1322.  A descendent of TNSCollection which sets the shouldDelete
  1323.  member to false will leave one unfreed pointer if it is
  1324.  destroyed when items are contained within it.
  1325.  
  1326.  The TOBJSTRM module creates just such a collection during
  1327.  a read of a stream containing TStreamable *.
  1328.  
  1329. Proposed Solution:
  1330.  The problem appears to be as follows.  The shutDown function
  1331.  of TNSCollection calls the member function setLimit(0) to
  1332.  free all object pointers.  setLimit *never* lets limit fall
  1333.  below count.  Thus, if you destroy a TNSCollection with
  1334.  count > 0, the items member of TNSCollection will never be
  1335.  freed. (Note that I'm not talking about the contained pointers,
  1336.  which are obviously the responsibility of the caller in a
  1337.  shouldDelete = False situation).
  1338.  
  1339.  To fix the problem, change line 57 of TCOLLECT.CPP:
  1340. **** FROM *****
  1341. void TNSCollection::shutDown()
  1342. {
  1343.     if( shouldDelete )
  1344.         freeAll();
  1345.     setLimit(0);
  1346.     TObject::shutDown();
  1347. }
  1348. ***** TO *****
  1349. void TNSCollection::shutDown()
  1350. {
  1351.     if( shouldDelete )
  1352.         freeAll();
  1353.     else
  1354.         count = 0;
  1355.     setLimit(0);
  1356.     TObject::shutDown();
  1357. }
  1358. ***** END *****
  1359.  
  1360. Borland Response:  I have place this suggestion in the data base.
  1361.  
  1362.        Workarounds: None.
  1363.  
  1364.        Additional information: A this unofficial improvement to TEditor
  1365.        class.
  1366.  
  1367. ================================================================
  1368.  
  1369. Subject: TFILEDTR.CPP and cmCancel
  1370.  
  1371. Location: TV
  1372.  
  1373. Item #: 0015
  1374.  
  1375. Submitted by: Steve Goulet [72421,2733]
  1376.  
  1377. Problem:
  1378.   This is causing windows to be shut down or programs to be terminated when a
  1379. user presses Cancel on a mfYesNoCancel dialog box when an editor window is
  1380. being closed.
  1381.  
  1382. **** FROM ****
  1383. Line number 267 of file TFILEDTR.CPP reads:
  1384.  
  1385.   cmCancel:
  1386.  
  1387. when it should read
  1388.  
  1389.   case cmCancel:
  1390. **** END ****
  1391.  
  1392. Borland Response:  I have made a report that documents the problems with
  1393. TFILEDTR.  I have tried the supplied fix and it seem to be a good
  1394. workaround.
  1395.  
  1396.        Workarounds: Apply above workaround.
  1397.  
  1398.        Additional information: None.
  1399.  
  1400. ================================================================
  1401.