{ HELP.INC: Online Help System Routines }

{==========================================================================}
{ (c) Copyright Waterline Software Developent V.O.F. 1990-1994             }
{                                                                          }
{    Waterline Software Development V.O.F.                                 }
{    Wouter Sluislaan 12                                                   }
{    1461 AC  Zuidoostbeemster                                             }
{    The Netherlands                                                       }
{                                                                          }
{ It not allowed to use this user interface in any program not owned by    }
{ the Waterline Software Development V.O.F.                                }
{ Special conditions apply to programs distributed by the Waterline        }
{ Software Development V.O.F. If the source code of any of these programs  }
{ is distributed as well, it is NOT allowed to use the user interface in   }
{ your own programs. Violators may be prosecuted!                          }
{                                                                          }
{ Please contact the Waterline Software Development V.O.F. at the above    }
{ address for your licence to use the "Ramon" user interface. You will get }
{ the most recent copy of the "Ramon" user interface and the "Ramon" user  }
{ interface expert for free. This program helps you design your user       }
{ interfaces at an instance.                                               }
{                                                                          }
{ This copyright notice should remain in this file and all files that are  }
{ part of the user interface "Ramon".                                      }
{==========================================================================}


{ History:

    17-10-93 Eerste versie van deze online help geschreven. Inclusief de
             compiler.
MD  30-10-93 Kleine aanpassing '@@' wordt vertaald in een '@'
                              '##' wordt vertaald in een '#'
RWI 26-10-94 Dijk's aanpassing uit de HELP.PAS van WtrGate Ramon unit
             overgenomen. Zenx man!

Future extension wishes:

De hele index header in een keer inlezen (bij 1000 handles is ie nog pas
6000 bytes) en dan daarin gaan zoeken. Zou het geheel wat sneller maken.
Als het echt traag wordt dan snel invoeren!

}


{--------------------------------------------------------------------------}
{ AssignHelpFile                                                           }
{                                                                          }
{ Met deze routine kan een helpfile toegekend worden aan het systeem. Op   }
{ die manier is het mogelijk meerdere helpfiles te hebben. Bij het         }
{ opvragen van help worden de gegevens uit deze file gehaald.              }
{ Het bestaan van de helpfile wordt hier niet gecontroleerd. Als je hem    }
{ niet wilt hebben, omdat je de online help toch niet gebruikt, dan moet   }
{ ie bij het opstarten van een applicatie niet meteen gaan zeuren.         }
{                                                                          }
PROCEDURE AssignHelpFile (Filename : STRING);
BEGIN
     HelpFilename:=Filename;
END;


{--------------------------------------------------------------------------}
{ HandleHelpRequest                                                        }
{                                                                          }
{ Met deze routine kan help opgevraagd worden over een bepaalde topic. Dit }
{ is toepasbaar als in een routine waarin zelf de toetsen afgehandeld      }
{ worden, op een help-opvraag toets (F1 ofzo) gedrukt wordt. Het help      }
{ scherm wordt getoond, eventueel kan naar een volgende/vorige help pagina }
{ gebladerd worden. Met Escape kan worden teruggekeerd naar het systeem.   }
{ Bij het aanroepen van de help wordt de cursor stand bewaard en uitgezet. }
{ Ook de kleur wordt onthouden. Bij het verlaten van de help worden de     }
{ kleur en cursor terug gezet.                                             }
{ Deze routine geeft TRUE terug als het scherm er staat. In geval van een  }
{ probleem wordt FALSE terug gegeven. Dit is speciaal voor                 }
{ HelpRequestDontWait.                                                     }
{                                                                          }
FUNCTION HandleHelpRequest (HelpHandle : HelpHandleType; GoBack : BOOLEAN) : BOOLEAN;

TYPE DataBufferPtr  = ^DataBufferType;
     DataBufferType = ARRAY[1..65000] OF CHAR;

VAR IORes  : BYTE;
    Header : STRING[3];
    Index  : HelpIndexRecord;
    Quit   : BOOLEAN;

    LinkKeysCount : BYTE;
    LinkKeysArray : ARRAY[1..MaxLinkKeys] OF LinkKeyRecord;
    LinkLp        : 1..MaxLinkKeys;

    DataPtr    : WORD;
    DataLength : WORD;
    DataBuffer : DataBufferPtr;

    Lp          : BYTE;
    ThisXl,
    Xb,Yb,Xl,Yl : XYType;
    HulpString  : STRING;

    OldCursor   : BOOLEAN;
    OldColor    : ColorSet;

    HekjePos,
    AapjePos    : BYTE;
    BackLink    : HelpHandleType; { 960822 }

BEGIN
     HandleHelpRequest:=FALSE; { assume error }

     OldColor:=GetColor;
     OldCursor:=CursorIsOn;
     CursorOff;

     { helpfile openen }
     IF (HelpFilename = '') THEN
     BEGIN
          IF (NOT GoBack) THEN
             Error ('Helpfile not assigned!');

          SetColor (OldColor);
          IF OldCursor THEN CursorOn;
          Exit;
     END;

     Assign (HelpFile,HelpFilename);
     {$I-} Reset (HelpFile,1); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
     BEGIN
          IF (NOT GoBack) THEN
             Error ('ERROR: Cannot find helpfile '+HelpFilename);

          SetColor (OldColor);
          IF OldCursor THEN CursorOn;
          Exit;
     END;

     { header controleren }
     Seek (HelpFile,17);
     BlockRead (HelpFile,Header[1],3);
     Header[0]:=#3;

     IF (Header = 'RH1') THEN
     BEGIN
          { hierbinnen kan met pgup/pgdn gebladerd worden. Dan wordt gewoon }
          { HelpHandle aangepast en Quit FALSE gelaten.                     }
          Quit:=FALSE;
          REPEAT
                { zoek in de index naar de HelpHandle }
                Seek (HelpFile,20); { begin van de index }
                REPEAT
                      BlockRead (HelpFile,Index,SizeOf (HelpIndexRecord));
                UNTIL (Index.Handle = HelpHandle) OR (Index.Handle = 0);

                IF (Index.Handle = 0) THEN
                BEGIN
                     IF (NOT GoBack) THEN
                        Error ('Help not found in helpfile '+HelpFilename);
                     Quit:=TRUE;
                END ELSE
                BEGIN
                     { help tekst data block inlezen }
                     Seek (HelpFile,Index.Offset);
                     BlockRead (HelpFile,DataLength,2);

                     GetMem (DataBuffer,DataLength);
                     BlockRead (HelpFile,DataBuffer^,DataLength);

                     { buffer doorlopen: aantal tekst regels en maximale }
                     { breedte bepalen en link toetsen eruit opmaken en  }
                     { in het array stoppen.                             }
                     LinkKeysCount:=0;
                     IF (HelpHandle <> 65432) THEN
                     BEGIN
                          Inc (LinkKeysCount);
                          LinkKeysArray[1].Key:=kF1;
                          LinkKeysArray[1].Handle:=65432; { Help on Help link }
                          BackLink:=HelpHandle; { voor kEsc afhandeling }
                     END;

                     Yl:=2; { 2 ivm de kader }
                     Xl:=0;

                     DataPtr:=1;
                     REPEAT
                           { regel definitie }
                           IF (DataBuffer^[DataPtr] = #13) THEN
                           BEGIN
                                ThisXl:=XYType (DataBuffer^[DataPtr+1]);
                                FOR Lp:=1 TO ThisXl DO
{ --- Aanpassing MD }
                                BEGIN
                                     IF ((DataBuffer^[DataPtr+1+Lp] = '@') AND (DataBuffer^[DataPtr+2+Lp] <> '@')) THEN
                                        Dec(ThisXl);
                                     IF ((DataBuffer^[DataPtr+1+Lp] = '#') AND (DataBuffer^[DataPtr+2+Lp] <> '#')) THEN
                                        Dec(ThisXl);
                                END; { for }
{ --- Aanpassing MD }
                                IF (ThisXl > Xl) THEN
                                   Xl:=ThisXl;
                                Inc (Yl);

                                { naar volgende veld }
                                Inc (DataPtr,XYType (DataBuffer^[DataPtr+1])+2);
                           END;

                           { link key definitie }
                           IF (DataBuffer^[DataPtr] = #1) THEN
                           BEGIN
                                IF (LinkKeysCount < MaxLinkKeys) THEN
                                BEGIN
                                     Inc (LinkKeysCount);

                                     { BP is picky about line length, even }
                                     { for $IFDEF disabled code???         }
                                     {$IFDEF PLATFORM_WIN32}
                                     {## want to keep these casts seperate, until we know they work right}
                                     LinkKeysArray[LinkKeysCount].Key:=KeyType (BYTE (DataBuffer^[DataPtr+1]));
                                     LinkKeysArray[LinkKeysCount].Handle:=HelpHandleType
                                                                 ((WORD (BYTE (DataBuffer^[DataPtr+3]) SHL 8))
                                                                 OR Byte (DataBuffer^[DataPtr+2]));
                                     {$ELSE}
                                     LinkKeysArray[LinkKeysCount].Key:=KeyType (DataBuffer^[DataPtr+1]);
                                     LinkKeysArray[LinkKeysCount].Handle:=HelpHandleType
                                                       ((WORD (DataBuffer^[DataPtr+3]) SHL 8)
                                                       OR Byte (DataBuffer^[DataPtr+2]));
                                     {$ENDIF}
                                END;

                                Inc (DataPtr,4);
                           END;
                     UNTIL (DataPtr > DataLength);

                     { link keys zijn nu bekend en de lengte en aantal }
                     { regels van het help scherm zitten in Xl en Yl   }
                     Inc (Xl,4); { 2 ivm de kaders en 2 voor ruimte tot kaders }
                     Xb:=(Video.Cols DIV 2)-(Xl DIV 2);
                     Yb:=(Video.Rows DIV 2)-(Yl DIV 2);

                     { window deel pushen, box tekenen en tekst erin zetten }
                     IF (NOT GoBack) THEN
                     BEGIN
                          PushKeysLine;
                          WriteKeysLine (HelpKeysLine);
                     END;

                     HandleHelpRequest:=TRUE; { scherm komt er nu aan }
                     WindowPush (Xb,Yb,Xl,Yl);
                     BoxDrawC (cHelp,Double,Xb,Yb,Xl,Yl);

                     DataPtr:=1;
                     Inc (Yb); { afdruk regel (kader verder) }
                     Inc (Xb,2); { afdruk positie (kader en spatie verder) }
                     REPEAT
                           IF (DataBuffer^[DataPtr] = #13) THEN
                           BEGIN
                                { regel afdrukken }
                                Move (DataBuffer^[DataPtr+1],HulpString,Byte (DataBuffer^[DataPtr+1])+1);

                                RGotoXY (Xb,Yb);
                                REPEAT
                                      HekjePos:=Pos ('#',HulpString);
                                      AapjePos:=Pos ('@',HulpString);

                                      SetColor (cHelp);

{ ------------------- Aanpassing MD }
                                      IF (AapjePos > 0) AND (HulpString[AapjePos+1] = '@') THEN
                                      BEGIN
                                           RWrite (Copy (HulpString,1,AapjePos));
                                           HulpString:=Copy (HulpString,AapjePos+2,255);
                                           Continue;
                                      END;

                                      IF (HekjePos > 0) AND (HulpString[HekjePos+1] = '#') THEN
                                      BEGIN
                                           RWrite (Copy (HulpString,1,HekjePos));
                                           HulpString:=Copy (HulpString,HekjePos+2,255);
                                           Continue;
                                      END;
{ ------------------- Aanpassing MD }

                                      IF (HekjePos = 0) AND (AapjePos = 0) THEN
                                      BEGIN
                                           RWrite (HulpString);
                                           HulpString:='';
                                      END ELSE
                                          IF (HekjePos > 0) AND ((AapjePos = 0) OR (HekjePos < AapjePos)) THEN
                                          BEGIN
                                               { tot # in cHelp }
                                               IF (HekjePos > 1) THEN
                                                  RWrite (Copy (HulpString,1,HekjePos-1));
                                               Delete (HulpString,1,HekjePos);

                                               SetColor (cHelpLink);

                                               HekjePos:=Pos ('#',HulpString);
                                               IF (HekjePos = 0) THEN
                                               BEGIN
                                                    { rest in cHelpLink }
                                                    RWrite (HulpString);
                                                    HulpString:='';
                                               END ELSE
                                               BEGIN
                                                    RWrite (Copy (HulpString,1,HekjePos-1));
                                                    Delete (HulpString,1,HekjePos);
                                               END;
                                          END ELSE
                                              IF (AapjePos > 0) AND ((HekjePos = 0) OR (AapjePos < HekjePos)) THEN
                                              BEGIN
                                                   { tot @ in cHelp }
                                                   IF (AapjePos > 1) THEN
                                                      RWrite (Copy (HulpString,1,AapjePos-1));

                                                   Delete (HulpString,1,AapjePos);

                                                   SetColor (cHelpBright);

                                                   AapjePos:=Pos ('@',HulpString);
                                                   IF (AapjePos = 0) THEN
                                                   BEGIN
                                                        { rest in cHelpBright }
                                                        RWrite (HulpString);
                                                        HulpString:='';
                                                   END ELSE
                                                   BEGIN
                                                        { stukje tot volgende @ in cHelpBright }
                                                        RWrite (Copy (HulpString,1,AapjePos-1));
                                                        Delete (HulpString,1,AapjePos);
                                                   END;
                                              END;

                                UNTIL (HulpString = '');

                                Inc (DataPtr,XYType (DataBuffer^[DataPtr+1])+2);

                                Inc (Yb); { naar volgende regel }
                           END;

                           IF (DataBuffer^[DataPtr] = #1) THEN
                              Inc (DataPtr,4);

                     UNTIL (DataPtr > DataLength);

                     { scherm staat nu in beeld, wacht op een toetsdruk }
                     { en reageer daarop.                               }
                     IF (NOT GoBack) THEN
                     REPEAT
                           Key:=ReadKey;
                           IF (Key = kUnknown) THEN
                              AsciiKey:=UpCase (AsciiKey);

                           IF (Key = kEsc) THEN
                           BEGIN
                                IF (HelpHandle = 65432) THEN
                                BEGIN
                                     HelpHandle:=BackLink;
                                     Key:=mOpt01;
                                END ELSE
                                    Quit:=TRUE;
                           END ELSE
                           BEGIN
                                { detectie link keys }
                                IF (LinkKeysCount > 0) THEN
                                   FOR LinkLp:=1 TO LinkKeysCount DO
                                       IF (LinkKeysArray[LinkLp].Key = Key) OR
                                          ((Key = kUnknown) AND
                                           ((Byte (LinkKeysArray[LinkLp].Key) AND 128) > 0) AND
                                           ((Byte (LinkKeysArray[LinkLp].Key) AND 127) = Byte (AsciiKey))) THEN
                                       BEGIN
                                            HelpHandle:=LinkKeysArray[LinkLp].Handle;
                                            Quit:=TRUE;
                                            Key:=mOpt01; { zorg voor <> kUnknown }
                                            Break;
                                       END;

                                IF (NOT Quit) THEN
                                   Key:=kUnknown
                                ELSE
                                    Quit:=FALSE;
                           END;
                     UNTIL (Key <> kUnknown);

                     { window weer van het scherm verwijderen }
                     IF (NOT GoBack) THEN
                     BEGIN
                          WindowPop;
                          PopKeysLine;
                     END;

                     { data buffer weer vrijgeven }
                     FreeMem (DataBuffer,DataLength);
                END;
          UNTIL Quit OR GoBack;
     END ELSE
         IF (NOT GoBack) THEN
            Error ('ERROR: Invalid helpfile structure in '+HelpFilename);

     { helpfile weer sluiten }
     Close (HelpFile);

     SetColor (OldColor);
     IF OldCursor THEN
     BEGIN
          CursorGotoXY (CursorX,CursorY);
          CursorOn;
     END;
END;


{--------------------------------------------------------------------------}
{ RequestHelp                                                              }
{                                                                          }
{ Deze routine roept de help routines aan waarbij er wel met allerlei      }
{ toetsen doorheen gewandeld kan worden.                                   }
{                                                                          }
PROCEDURE RequestHelp (HelpHandle : HelpHandleType);
BEGIN
     HandleHelpRequest (HelpHandle,FALSE{niet meteen terug});
END;


{--------------------------------------------------------------------------}
{ RequestHelpDontWait                                                      }
{                                                                          }
{ Deze routine tekent het opgegeven help scherm, maar gaat daarna niet op  }
{ een toets staan wachten. Als het window niet opgebouwd kan worden om de  }
{ een of andere reden, dan wordt FALSE terug gegeven. Anders TRUE.         }
{                                                                          }
FUNCTION RequestHelpDontWait (HelpHandle : HelpHandleType) : BOOLEAN; { TRUE -> window is visible }
BEGIN
     RequestHelpDontWait:=HandleHelpRequest (HelpHandle,TRUE{wel meteen terug});
END;
