How-To's for the message library incl. access method #2.

How to...
1. Create binary message libraries (catalogue files) for method #2?
2. Create _global_ catalogue files for method #2?
3. Create a program using MSGLIB access method #2?
4. Use the HP-style catalogue functions?
5. Create catalogues with more than one message group?

Typesets:
+ "#>" (without the quotes) indicates the shell command line
+ "%FDLIB%" (without the quotes) represents the globally shared FreeDOS
	library directory for your current compiler, e.g.
	D:\FDOS\SOURCE\LIB\BC5
+ "%FDINC%" (without the quotes) stands for the globally shared FreeDOS 
	include directory, e.g. D:\FREEDOS\SRC\INLCUDE

===

1. Create binary message libraries (catalogue files)?

#> msgcomp2 /f=2 %FDINC% english yerror.h

"english" is the name of the corresponding "english.MSG" message file
you want to be compiled, "yerror.h" is the local message include file.

The message compiler should display something like this:

#> msgcomp2 /f=2 ..\..\include english yerror.h
MSGCOMP2: Use default symbolic message ID mapper file: msglib.id
MSGCOMP2: Scanning message ID mapper file.
MSGCOMP2: Read internally used names out of the global message file
MSGCOMP2: Processing message file "english.MSG"
MSGCOMP2: Creating binary message library file: 'english.MS2'
MSGCOMP2: Create feature list into 'english.FTR'
#>

===

2. Create _global_ catalogue files for method #2?

Just pass the "/!" option along, e.g.:

#> msgcomp2 /! /f=2 %FDINC% english yerror.h

Strictly speaking, you would need to pass "/g=8", but currently the "/!"
is better.

===

3. Create a program using MSGLIB access method #2?


STEP 1)	-- Source code
Include your local message declaration file into every source file you
are using any of the functions of MSGLIB, don't include <msglib.h>!

The local message declaration file is the one you passed as the third
argument to the message compiler.

You'll find a template for this file within the source directory of
MSGLIB with the name "TEMPLATE.H".

Insert the following line right before #include'ing <msglib.h>:

#define MSG_METHOD 2


Within the main() function do this:

Insert the following line right after the variable declarations:

msgInit();

This will initialize the functions of MSGLIB, without it the funniest
things might occure.

Now you can use any of the MSGLIB functions, such as error() and hlpScreen(),
buf msgLock() and msgUnlock() as well.


STEP 2)	-- message file / catalogue
Create your local message file and save it into "<lng>.MSG", where <lng>
stands for something the message library has already be pre-built, look
into the directory %FDLIB% for a file named "?_<lng>.LIB".

If you doesn't find such files, you'll need to create the message library
for your compiler/language first.
NOTE: The name of the libraries will change in the near future, because
this concept does not honor some primary basics, such as character sets.

Now compile the message file into the catalogue file "<lng>.MS2".


STEP 3)	-- executable

Now compile and link your program. Note: You must perform step 2) each
time when the message file changes (e.g. you add/remove/modify messages)
and before compiling the program, because the message compiler will
generate two files that are included by your local message header file,
called "yerror.h" within this document.


STEP 4) -- adding messages

If you try to invoke your program, you will see various default messages,
depending on how noisy your program is.

That is so because your program has no access to the catalogue files
to read the message string from.

To make the catalogues known to your program you have two options:
1. <for testing/development only>
	right after the msgInit(); line add a number of the following lines:

	msgCatalogue("<lng>.MS2");

	Replace <lng> by your created language.

	Note: You'll have to add _two_ lines per language, because there is
	a global "<lng>.MS2" in the %FDINC% directory and the local one,
	you've created in step 2).

	Your main() could now look like this:

		msgInit();		// Initialize MSGLIB
		msgCatalogue("d:/freedos/src/include/english.ms2");	// global cat
		msgCatalogue("english.ms2");	// join in local catalogue

	This has the advantage that your program is ready to be executed
	right after step 3); but also the big disadvantages that a) the
	files are externally and b) the paths are absolute and c) to add
	more catalogues you'll need to modify your program.

2. <recommended variant>
	Just append both catalogues to your executable using the
	message management tool:

		#> msg2mgt <prg>.EXE + <lng>.MS2 + %FDINC%\<lng>.MS2

	Now the catalogues became an integral part of your program's
	executable. You have only a single file, no path names no longer,
	and, when you've translated the message file of another human's
	tongue, you can simply add it with the same line to the program.
	Your program can then spek two languages.

	The management tool might output something like this:

	#> Msg2mgt msgcomp2.exe + english.ms2 + \freedos\src\include\english.ms2
	MSG2MGT: Processing binary message library "msgcomp2.exe"
	MSG2MGT: 0 language definitions found in the binary message library
	MSG2MGT: One language definition added
	MSG2MGT: One language definition added
	MSG2MGT: 2 language definitions found in the binary message library
	#>

	First the tool identified that the executable did not have any
	language information attached, then the local and the global ones
	are added.

	The message compiler would speak the English tongue now, well my
	vision of it actually.

	So I invoke the management tool a second time, as I've already
	compiled the german variants of the global and local message files:

	#> Msg2mgt msgcomp2.exe + deutsch.ms2 + \freedos\src\include\deutsch.ms2
	MSG2MGT: Processing binary message library "msgcomp2.exe"
	MSG2MGT: 2 language definitions found in the binary message library
	MSG2MGT: One language definition added
	MSG2MGT: One language definition added
	MSG2MGT: 4 language definitions found in the binary message library
	#>

	And now the message compiler interacts in the German tongue with me,
	because my NLS tells MSGLIB that German suits the NLS better than
	English. If I would pass the 4-language MSGCOMP2 to you, the program
	would, most likely, pick the English tongue.

===

4. Use the HP-style catalogue functions?

Well, first decide, if it's enough for you open _one_ catalogue or
catalogues that do not contain the same set number (MSGLIB: message
group) twice.
If so, comment out the macro definition of MSG_MULTIPLE_CATALOGUES
in the configuration file MSG2_CFG.H; otherwise, uncomment the line.

Re-compile MSGLIB for your compiler.

The prototypes of the HP-style catalogue functions are located within
the header "NL_TYPES.H". You just have to import it into every source file,
you invoke a catalogue function.

Create and compile your mesage file with the message compiler.
Note: It's the same message compiler and the same message file as with
the other functions. If you want to use multiple sets, pass the
"/g=<set_number>" switch to the message compiler.

The message compiler generates the file MSGLIB.ID that assigns numbers
to the symbolic message IDs used within the message files. Print it or
write them down or just use this file as a reference. Note: As long as
you keep this file in the same directory as your local message file is
located in, these numbers won't change.

Create and compile your program. For the "catgets()" function you'll
need the numbers from the MSGLIB.ID file. Break down the hexa-decimal
number into the last three digits and the first one. The first one (the
highest four bits) represents the set number, the lower three are the
message number.

E.g. if the MSGLIB.ID contains:
	E_hlpScreen 0x0001
	I_glbMsgFile 0x8001
	I_languagecodes 0x8002

You'll use set:"0x0" msg:0x001 to get the message "E_hlpScreen", and
set:"0x8" msg:"0x002" for "I_languagecodes".

The next program code will display the message string "I_glbMsgFile":


#include <stdio.h>
#include "nl_types.h"

main(void)
{	nl_catd catd;

	if((catd = catopen("english.ms2", 0)) == (nl_catd)-1) {
		puts("catopen() error");
		return 1;
	}

	fputs("catgets(): ", stdout);
	puts(catgets(catd, 8, 1, ">>Failed<<"));
	catclose(catd);
	return 0;
}

Note: The message compiler will _never_ assign a message numnber of 0 (zero).
Although one could easily overcome the problem within catgets(), it would
lead to confusion between MSGCOMP2 (what is required to actually produce
the catalogue) and the user. This condition is considered a "Known Bug".

===

5. Create catalogues with more than one message group?

The message compiler is designed to translate a message file for just
_one_ message group.

You have to create one message file for each message group indivisually
and translate them individually, however, you must pass the "/g="
switch to the message compiler. The switch has one argument, a
decimal number that represents the message group in the range 0..15.
MSGLIB reserves the groups 8..15 for internal purpose, however, if
you stick to the HP-style interface, you can use all.

Also pass the "/t=" switch to the message compiler to let it know
which global language to use. Otherwise it would look for "GRP1.MSG"
in the %FDINC% directory.

Also pass a fourth argument to it specifying where the message declaration
information is to be dumped to. If you wouldn't do so, MSGCOMP2 would
pick a file on its own and would overwrite it all four times.

E.g. do this:
#> msgcomp2 /g=1 /f=2 /t=english \freedos\src\include grp1 yerror.h grp1.inc
#> msgcomp2 /g=2 /f=2 /t=english \freedos\src\include grp2 yerror.h grp2.inc
#> msgcomp2 /g=3 /f=2 /t=english \freedos\src\include grp3 yerror.h grp3.inc
#> msgcomp2 /g=4 /f=2 /t=english \freedos\src\include grp4 yerror.h grp4.inc

Now you have four files: GRP1.MS2, GRP2.MS2, GRP3.MS2,& GRP4.MS2.

If you want to use the normal MSGLIB functions rather than the
HP-style interface, you must include all four files: GRP1.INC,
GRP2.INC, GRP3.INC,& GRP4.INC into the local message header "yerror.h".
Otherwise the symbolic message IDs wouldn't be present.

Now you have two choices to join the four message groups into
one catalogue:
1. <simple>
	#> copy /b grp1.ms2 + grp2.ms2 + grp3.ms2 + grp4.ms2 allgrps.ms2

2. <using the message mnagement tool>
	#> msg2mgt /o=none allgrps.ms2 + grp1.ms2 + grp2.ms2 + grp3.ms2 + grp4.ms2

Both calls are absolutely identical. However, the resulting catalogue
misses a status information header that does allow it to "autodetect"
this catalogue as a part of an executable.

However, the resulting catalogue is totally equal (in the view of MSGLIB)
to the four individual files.
