{ Testing the wMessages2.pp unit.
  This is a very important unit in the GAP Library.
  I already tested it in tEx026.pp,  but I want more.

  My goal is that if we give a name to a main Window or a dialog box,
  Its position (and size) are saved in a file, and each time they are
  reopened, they come to the place they where last time.

  To do this, I want to associate to a string another string, or
  4 or 5 numbers, stroring information associated with this string.

  I want to :
  - Set the information associated to the string :
    SetStringData(str:ShortString; wD1,wD2,wD3,wD4,wD5:Word32);

  - Get the information associated to the string :
    GetStringData(str:ShortString; var wD1,wD2,wD3,wD4,wD5:Word32);

  - Get the number of strings having an association,
    In order to save them all.
    GetNumberStrings:Word32;

  - Get the strings and data from a number between 1 and  GetNumberStrings
    In order to save them all.
    GetStringNumber(var strS:ShortString; var wD1,wD2,wD3,wD4,wD5:Word32);

  - Deleting a string and its data will come later, maybe.

  See tEx040.pp  for the continuation.
  This was a first test.

  --------------------------------------------}
program tEx039;

// To tell FreePascal that the application is a Graphical User Interface
// i.e. is running in windows, not in text mode.
{$APPTYPE GUI}

Uses
  wApplication0
 ,wWindow0
 ,wDialog0
 ,wComboBox0
 ,wParamApplic2
 ,wDialogCreatorLOW2
 ,wVariableNumLink2
 ,wWindowBase0
 ,wMessages2
 ,wErrors0
 ,wUtiles0
 ,wDebug0
 ,wGlobals2
 ,Windows;

type
  PMyWindow = ^TMyWindow;
  TMyWindow = object(TWindow)
  //"""""""""""""""""""""""""

  strPathName : ShortString;
  // Pathname of the file containing the strings - Data link information

  wSubPlace : word;
  // To see the content of the strings in the "_Prm.msg" file

  strMsgTextLine : ShortString;
  // The text line being at message number 4000000000,
  // wSubPlace lines bellow.

  constructor Init(strWinTitlePrm:ShortString);

  procedure WinCreate(strWinClass:ShortString); virtual;

  procedure Test1; virtual;

  procedure Test2; virtual;

  procedure InitDialogEnd(poDlg:PWindowBase0); virtual;
  // When a dialog box has been filled with its
  // Control windows, and is ready to be shown.
  // the dialog calls this method with a pointer on itself. (it's his parent method)
  // Is destinated to be overriden, does nothing by default.

  procedure CtrlVarUpdate(poCtrl:PWindowBase0; pVar:pointer); virtual;
  // When a control changed its value and it is linked to a variable and
  // it belongs to a dialog belonging to a window, then
  // the control calls this method with a pointer on itself and
  // a pointer on the associated variable.
  // Either you know the type, or you can get it with
  // pControl(poCtrl)^.rVarLinkInfo.wVarType

  function WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT; virtual;
  // Handles the menu messages

//  function WindowProc(hWindow:HWND; wMsg:UINT; wPar:WPARAM; lPar:LPARAM):LRESULT; virtual;
    // Not Used
  end; // TMyWindow = object(TWindow0)

// var nNotUsed : integer; // only to avoid an error message while compliling in DevPascal 1.9

//******************************************************************
// TMyWindow = object(TWindow0)
//******************************************************************

constructor TMyWindow.Init(strWinTitlePrm:ShortString);
//=====================================================
begin
inherited Init(strWinTitlePrm);
end;  // TMyWindow.Init

procedure TMyWindow.WinCreate(strWinClass:ShortString);
//=====================================================
// Create the window, and insert an edit box and a status line in it.
var
  wError      // if the file does not exist, it will not open.
              : Word32;
  strEXEDir   : ShortString;  // with the '\' at the end
  strEXEName  : String[80];
  strEXEExt   : String[12]; // 12 is quite arbitrary.

begin
// here strWinClass=''.
inherited WinCreate(strWinClass);

wSubPlace :=1;
strMsgTextLine :='';
WordField(1001, wSubPlace);
StrField( 2001, strMsgTextLine, SizeOf(strMsgTextLine));

// Same name as the parameter's file name, but with the  .msg extension
FileSplit(gglpoPrm^.strParamPath, strEXEDir,strEXEName,strEXEExt);
strPathName:=strEXEDir + strEXEName + '_TEST.msg';

// Opens the parameter message file, at the bottom
// (100 files down, if 100 .msg files are opened)  (1=> read/write)
OpenMsgPlaced( strPathName, 100, 0, wError); // 0 => read only

//if (wError <> 0) then DBW0(1, 'Small Warning=' + ITS(wError));

// We want that line 4'000'000'000 exist in the message file.
if (wError <> 0) or (Copy(GetMsg(4000000000),1,3) = '???') then begin
   // The file doesn't exist or the number doesn't exist,
   // thus create it.
   // Append a line beggining with the wanted number (4'000'000'000)
   // The 0 means that we know that the file cannot be opened as a .msg file
   AppendLine(0, 4000000000, strPathName, 'This is a starting list of texts.', wError);
   if (wError <> 0) then DBW0(1, 'Error=' + ITS(wError));
   end;

end;  // TMyWindow.WinCreate

procedure TMyWindow.Test1;
//========================
var
  strS        : ShortString;
  wError,
  wRep        : Word32;

begin
strS:='';
StrField(111, strS, SizeOf(strS));
wRep:=DialogExecMSG(11199, @Self);

if (wRep = IDOK) then begin
   // To have a long line, which can be modified later :
   strS:=Copy(strS +
     ' #--------------------------------------------------------------------------',
        1, 80);
   // Append a line beggining with the wanted number
   // 4000000000 is an existing number in the file.
   // 0 is the number which will be added.
   AppendLine(4000000000, 0, strPathName, strS, wError);
if (wError <> 0) then DBW0(1, 'Error=' + ITS(wError));
   end;
end;  // TMyWindow.Test1

procedure TMyWindow.Test2;
//=========================
// This test allows to modify the content of an existing line.
const wPlace : word = 1;

var
  strS        : ShortString;
  wError,
  wRep        : Word32;

begin
strS:='';
WordField(101, wPlace);
StrField(111, strS, SizeOf(strS));
wRep:=DialogExecMSG(11299, @Self);

if (wRep = IDOK) then begin
   // To have a long line, which can be modified later :
   strS:=Copy(strS +
     ' #--------------------------------------------------------------------------',
        1, 80);

   // Append a line beggining with the wanted number
   ReplaceLineMsg(4000000000, wPlace+1, strS, wError);

   if (wError <> 0) then
      DBW0(1, 'wError =' + IntToStr(wError,3) + ' probably a place number to big');

   end; // if (nRep = IDOK) then begin

end;  // TMyWindow.Test2

procedure TMyWindow.InitDialogEnd(poDlg:PWindowBase0);
//====================================================
// When a dialog box has been filled with its
// Control windows, and is ready to be shown.
// the dialog calls this method with a pointer on itself. (it's his parent method)
// Is destinated to be overriden, does nothing by default.
var
  nMax,       // To count how many lines are after line 4'000'000'000 in the .msg file
  nn          : Word32;
  poDlgL      : PDialog;
  poCombo     : PComboBox;
  strS        : ShortString;

Begin
// The dialog just created its child window, thus we can fill
// the combo box with choices.
poDlgL:=PDialog(poDlg); // We know that it is a pointer on a dialog

if (poDlgL^.wMsgDescriptor = 11399) then begin
   // We now that we associated the variable  wSubPlace
   // to a combo box in dialog 11399
   poCombo:=PComboBox(poDlgL^.GetControlFromVar(wSubPlace));

   // Count how many lines are after the number 4'000'000'000
   strS:=GetMsg(4000000000);
   nMax:=0;
   while (Copy(strS,1,3) <> '???') do begin
      inc(nMax);
      strS:=GetMsg(msgNext);
      end;

   // fill the choices of the combo
   for nn:=0 to nMax-1 do poCombo^.AddString(IntToStr(nn,0));

   poCombo^.SetCurrentSelection(1)
   end;
end;  // TMyWindow.InitDialogEnd

procedure TMyWindow.CtrlVarUpdate(poCtrl:PWindowBase0; pVar:pointer);
//===================================================================
// a variable has changed in a dialog box.
// poVar = pointer on the variable
// poCtrl = pointer on the control linked to this variable
// poCtrl^.poParent = pointer on the dialog box
// PDialog(poCtrl^.poParent)^.wMsgDescriptor =
// = msg which generated the dialog box
begin
poCtrl:=poCtrl;  // to avoid a hint.

if (pVar = @wSubPlace) then begin
   // It is useless to do anything if another variable changed
   // Will show immediatly the string stored
   // wSubPlace line bellow place 4'000'000'000
   strMsgTextLine :=GetMsgSub(4000000000, wSubPlace);
   UpdateFromVar;
   end;

end;  // TMyWindow.CtrlVarUpdate

function TMyWindow.WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT;
//=============================================================
// Handles the menu messages
Var
  wNrMenu     : word;
begin
WMCommand := 0; // Default return value when processing a message

if (lPar <> 0) then begin
   // call the parent WMCommand method.
   WMCommand:=inherited WMCommand(wPar, lPar);
   exit;
   end; // if (lPar <> 0) then begin

// for the menus,  lPar = 0
//=========================
wNrMenu   := LoWord(wPar);
Case wNrMenu Of
   100 : DBW0(0, '');  // just open the debugging window
   101 : Test1;
   102 : Test2;
   103 : begin
         strMsgTextLine :=GetMsgSub(4000000000, wSubPlace);
         DialogExecMSG(11399, @Self);
         end;

   else WMCommand:=inherited WMCommand(wPar, lPar);
   end;  // Case NrMenu Of
end;  // TMyWindow.WMCommand

var
  oApp        : TApplication;
  poMyMainWin : PMyWindow;

Begin // MAIN ******
// Name under which the main window is registered. Spaces are not allowed
oApp.Init('Example039');

// Creation of the main window
new(poMyMainWin, Init('tEx039. Test the wMessages2.pp unit.'));

oApp.Run;
oApp.Done;  // The main window object is disposed here.
End.

