Document contents
-----------------
- Turbo Vision Conversion Notes
- Class Library Conversion Notes
- RTL Library notes
- Odds and ends

Turbo Vision Conversion notes for Borland C++ 4.0
--------------------------------------------------
Here are a couple of tips that may come in handy when converting
Turbo Vision to the so-called "new and improved" Borland C++ 4.0.
The notes apply to Turbo Vision 1.3 (the one that was supplied with
Borland C++ 3.1).

1. You have to make the changes described in COMPAT.TXT (in the DOC
subdirectory of BC4).  To those who want to know what they're doing,
here an explanation of the changes:

- change 1 is needed because C++ does not allow initialisation of
local variables to be skipped.  The reason this rule is present in C++
and not in C, is because declarations in C++ can occur anywhere, not just
at the beginning of the block (as in C).
Remember, a switch statement expands to a gigantic if/goto statement, where
by default the execution falls through to the next case, and you get a
similar situation.

- changes 2 and 3 (the explicit cast to char*) are also needed because in
C++, some functions like strchr have 2 declarations: one returning a const
value for a const parameter, and one returning a non-const value for a
non-const parameter.  For strchr, the declarations look like this in C++:

	const char *strchr(const char *s,int c)
	char *strchr(char *s,int c)

If the first parameter is a const char *, the first functions is chosen.
If the first parameter is just a char *, the second function is chosen.
BUT, that means trouble if, like in TV, the return value of the first
function is assigned to a char * instead of a const char *.  Therefore,
you need the cast as described.

- change 4 changes the makefile.  The -x- parameter added just turns of
exception handling.  The change to TLIB prevents it of stripping off
comment records (i.e. debug information) when generating a DEBUG version
of the library.  And finally, the last changes copy the pre-assembled
files, if you cannot assemble them, using that brand new Turbo
Assembler of theirs.

2. If you follow the instructions to the letter, you will find that your
Turbo Vision application consumes more memory than with Borland C++ 3.1,
despite 4.0's "improved optimisations".
Moreover, you will have generated a 80286 library, since 80286 code
generation is on by default.
You may decide that is not important, since as soon as DOS 7 comes out,
the entire WORLD will switch to it INSTANTLY.  Of course, since everyone
now is working with MS-DOS 6.20 or Windows NT, right?
For the more realistic among us, here are a couple of hints that attempt
to rectify the situation:

- Run-Time Type Information (RTTI) is turned ON by default.  This means
a substantial increase in lib size (about 40K, but I don't remember it
exactly).  What you want to add to the CFLAGS is:

			-RT-

to tell BC4 NOT to include RTTI.
Alas, things are not that simple.  The Run-Time library has been compiled
with RTTI.  Moreover, if any class inherits from another class having RTTI,
this class should have it too.
This concerns TV since there is a class TTextDevice inheriting from
streambuf.  Since streambuf is in the RTL, it has RTTI.  Therefore, all
classes that derive from TTextDevice should have RTTI too.  If not,
you get the message:

	Can't inherit non-RTTI class from RTTI base 'streambuf'

Oh, yes: don't bother looking this message up in the BC4 docs: it's not
there.  You can find it in ERRMSGS.TXT, which of course you read before
everything else.
It turns out that the .h file containing TTextDevice is used in geninc.cpp
and textview.cpp.  I added

geninc.obj : geninc.cpp
		$(BCC) -RT $&.cpp

textview.obj : textview.cpp
		$(BCC) -RT $&.cpp

in the makefile, just above the "geninc.exe : geninc.obj" line.  Since
command line options override options in TURBOC.CFG, these 2 files are
being compiled with RTTI.


- Turning on 8086 code generation is not that simple.  80286 code generation
is on by default.  According to the docs, the "lowest" BC4 can go is 80186
(using the -1 option, which is documented in the User's guide, not
documented in the "Command line options" online-help topic, but
mentioned in the #pragma online-help topic.  So much for consistency).
It would seem that the option -2- (i.e. "turn off 80286 code generation)
does the trick.  There is no way to make sure, however.
The only ways I found to check that was by looking at the generated code,
and running the program.  I'm happy to report that this seems to work,
but there is no way to examine ALL the generated code, or to make sure
the entire program got executed.
Of course, you can always use the profiler to test for coverage.
Profiler? Oops, no profiler.  So much for "leveraging your developement".
I must have misunderstood.  After all, english is my third language.


3. There are warnings displayed when compiling TV with BC++ 4.0.
You may encounter them in helpbase.cpp and tbkgrnd.cpp.
In helpbase.cpp, the compiler will complain about "suspicious pointer
conversions".  This is because functions returning a char * have
a char [] in their return statement.  The compiler correctly flags
this as a warning, since they are not (in the very strict sense) identical.
In tbkgrnd.cpp, the compiler warns "Temporary used", because a member
variable of type char is used on a function "<<" defined only for signed
chars and unsigned chars.
According to the new C++ standard, char, signed char and unsigned char are
3 distinct types, so the compiler complains about having to use a temporary 
variable.
The more permanent  solution for this last problem is to add a definition
for operator<<(char c) in opstream and operator>>(char c) in ipstream.

Hope this proves useful to the almost nonexisting TV users, according
to Borland.


ClassLib Conversion Notes
-------------------------
If you were using the old class library in your projects, get ready for
a surprise.  The semantics of some member functions have changed.

I used the following:

typedef BI_IArrayAsVector<TSomeType> TSomeTypeArray;

I wanted to insert an element e at index [0], moving all other elements up.
I don't know what mood I was in, but here's what I wrote:

TSomeArray array;

unsigned i=array.getItemsInContainer();
array.add(array[i-1]);
--i;
while(i>0) {
	array.addAt(array[i-1],i);
	--i;
	}
array[0]=e;

In Borland C++ 3.1, this works perfectly.  In Borland C++ 4.0, it generates
a "delayed crash" (i.e. a gradual memory corruption until the heap is
such a mess that the program goes UAE).
Why? Because Borland, in its infinite wisdom, changed the addAt(t,loc)
function from

	if( loc >= lim )
		resize( loc+1 );
	data[loc] = t;

to:

	if( loc > Count_ )
		Count_ = loc;
	for( unsigned cur = Count_; cur > loc; cur-- )
		Data[cur] = Data[cur-1];
	Data[loc] = t;
	Count_++;

Notice the for loop: it actually performs an insert operation by moving all
elements up.
The net result for some unsuspected user (like me) is that my code
inadvertently creates duplicate entries, which are then destroyed more than
once when the array gets deleted.
So much for compatibility.


RTL Library notes
-----------------
Ever written a program using _read and _write?  I did.  Now these functions
are called "obsolete", so I dutifully switched to _rtl_read and _rtl_write.
Surprise! _rtl_read is nowhere to be found.  I suspect the _read function
still exists in RTL module reada, and was forgotten to be renamed.
Since I don't have the run-time library source code, I cannot certify this.
Anyway, better stick with read, or _dos_read.  Or just use _read and
forget about the warning.


Odds and ends
-------------
- Don't trust the "data size", if you choose to display it in the project
manager.
For example, having a .CPP file with the definition:

char Strange[40000u];

.. and after your compile, the file will be listed as having a data size
of more than 4 billion!

- despite numerous efforts, I have been unable to make executable files
as small as Borland C++ 3.1.  This can be traced to the inclusion of the
class typeinfo (for RTTI), and appearently xmsg, even when you don't
use them.
There is nothing that can be done about this.  It may well be that
Borland C++ 4.0 generates smaller and faster code... but the run time
library is compiled with RTTI, so you will never see that potential
benefit.
This seems to be a general trend of Borland C++ 4.0: everything is
better, safer, faster, smaller, but somehow the combined effect of all
these qualities result in something inferior than was possible with the
previous version.

- Here is a "feature" that caused me endless grief, until I knew what
was going on.
It happens when you add a library to your target, to be linked in.
Use the SpeedMenu for the target, select Add Node, and type your
library.  So far so good.
Use the speedmenu of the just added .lib file, and select "Edit node
attributes".  You will correctly see the Translator set as BinInclude,
meaning the library has indeed to be included.
Since experts are there to help you, and you do want to give the impression
that you actually use all these experts, select the Target Expert for the
.lib file.  The Target Expert dialog box pops up.  Without changing
anything, click on OK.  Now rebuild your project.
Congratulations!  You have just destroyed the .lib file!  When you clicked
on OK in the Target Expert, the Translator changed from BinInclude to
LibCreate.  The next build creates an empty library (since there are no
dependent nodes) therefore destroying the .lib contents.
And they call that a "Target Expert". Ha!  I really would like to know
the reason behind THAT logic.




Vincent Van Den Berghe
(via Johnny Penet CSID 72377,3426)

