home *** CD-ROM | disk | FTP | other *** search
/ Power CD-ROM!! 7 / POWERCD7.ISO / prgmming / inter43 / int2whlp / int2whlp.inc < prev    next >
Text File  |  1994-11-04  |  26KB  |  715 lines

  1. (* INT2WHLP Pascal Program Include File *)
  2.  
  3. (*
  4.   Interrupt List -> WinHelp converter (c) 1994 by Christian Müller-Planitz
  5.   ------------------------------------------------------------------------
  6. *)
  7.  
  8. (* v. 1.12 *)
  9.  
  10. type
  11.   stringPtr = ^string;
  12.   categoryStringPtrArr = array['!'..#126] of stringPtr;
  13.   titleStringPtrArr = array[byte] of stringPtr;
  14.   stringListPtr = ^stringList;
  15.   stringList = record next: stringListPtr; s: string; end;
  16.     (* NB! The program relies on "next" being the first field *)
  17.   stringListPtrPtr = ^stringListPtr;
  18.   aliasStringType = string[119];
  19.  
  20. var
  21.   flagStrings,categoryStrings,categoryKeyStrings: categoryStringPtrArr;
  22.   INTtitles: titleStringPtrArr;
  23.  
  24.   CONST InPath  : dirStr = '';
  25.     OutPath : dirStr = '';
  26.     OutFileCounter : Word = 0;
  27.     TopicNo : Word = 0;
  28.     LastSection : String[3] = '';    { stores number of last processed int }
  29.     IntTopicStr : String[7] = '';    { stores handle to page with subfunctions of the int's}
  30.     filterFileName: pathStr = '';
  31.     filtered: boolean = false;
  32.     compression: string[19] = 'NO';
  33.     emptyString: string[1] = '';
  34.     noteString: string[5] = 'note';
  35.     noneString: string[7] = '(none)';
  36.     buildExpr: string = '';
  37.     equStr: string[7] = ' Ax = ';
  38.     equBlanks: byte = 2;
  39.       (* These two variables can be changed to ' Ax=' and 0 by
  40.          program parameter -Q-. They control the format of search
  41.          strings as "INT nn AX = ahal" or "INT nn AX=ahal".
  42.          equStr[3] is assigned 'L', 'H', or 'X' by the program.
  43.       *)
  44.     tables: boolean = true; (* enables table cross referencing *)
  45.     backRef: boolean = false; (* disables the very first backward xref *)
  46.     missingTableCounter: word = 0;
  47.     missingTableLimit = 5; (* wait for user response when reached *)
  48.     indexColumns: integer = 1;
  49.     queuedEntry: string[127] = '';
  50.       (* stores an entry for the index, inserted by a call to insertQueued *)
  51.     notesCount: word = 0;    (* counts "Notes" entries in index *)
  52.     title: string[127] = ''; (* current "Notes" or "INT nn ... " *)
  53.     lastINTno: integer = -1;
  54.     firstAliasP: stringListPtr = NIL; (* aliases to be written to HPJ *)
  55. {
  56.     firstINTWINconfigP: stringListPtr = NIL; (* ditto CONFIG *)
  57. }
  58.     nl: string[5] = '\par '; (* global NewLine string for AddTopic *)
  59.     indentIndex: string[7] = '\par   '; (* or '\par ' *)
  60.  
  61. const
  62.   (* The following typed constants controls some program behaviors. They
  63.      can all be set under configuration file and program parameter control.
  64.      The configuration section [OPTIONS] uses keys with the same names as
  65.      the typed constants, and the program parameters are listed for each
  66.      constant.
  67.   *)
  68.   singlesInMain: boolean = false;
  69.     (* There are two levels in the Interrupts index: A main index
  70.        with an entry for each interrupt, and a page for each interrupt
  71.        number. If "singlesInMain" is true, the entry in the main index
  72.        refers directly to the interrupt text if there is only one entry
  73.        in the table for that interrupt, if  "singlesInMain" is false, the
  74.        entry in the main index refers to a page with only one field.
  75.        Controlled by program parameter -1.
  76.     *)
  77.   twoIndexes: boolean = true;
  78.     (* If "twoIndexes" is true, the program mantains two indexes,
  79.        "Interrupt Index" with all the topics in the Interrupt List, and
  80.        "Interrupts" as described above. If the flag is false, only the
  81.        latter index is created.
  82.        Controlled by program parameter -2.
  83.     *)
  84.   errorLog: boolean = false;
  85.     (* controles whether HCxx error messages are written to a log file,
  86.        or to the screen only.
  87.        Controlled by program parameter -E.
  88.     *)
  89.   indexHeaders: boolean = true;
  90.     (* controles whether or not a heading "INT nn" is inserted for every
  91.        new interrupt number in the "Interrupt Index". Ignored if
  92.        "twoIndexes" is false.
  93.        Controlled by program parameter -H.
  94.     *)
  95.   markKeys: boolean = true;
  96.     (* If true, keywords (like "See also:", "Notes:") are bolded, if
  97.        false, they are not.
  98.        Controlled by program parameter -M.
  99.     *)
  100.   releaseNo: integer = 41;
  101.     (* This variable can be used to control program behavior and thus
  102.        facilitate compilation of older releases of the Interrupt List.
  103.        Currently it is used to:
  104.        Inhibit table as separate topics and table cross references if
  105.          releaseNo<41.
  106.        Controlled by program parameter -R.
  107.     *)
  108.   scrollIndexTitle: boolean = true;
  109.     (* Windows have a non-scroll area with the window title. Index
  110.        windows have an initial title part describing List release
  111.        number and help file compile date (inserted by specifying
  112.        "specialClassification" in the call to procedure "NewHlpPage").
  113.        If "scrollIndexTitle" is true, only the general part of the
  114.        title is in the non-scroll region, thus opening more space for
  115.        the scrolling part. If the flag is false, the whole title field
  116.        is made non-scrolable.
  117.        Controlled by program parameter -S.
  118.     *)
  119.   tableWindow: boolean = true;
  120.     (* If true, tables activated from a "#nnnn" hotspot appear in a
  121.        secondary window, if fase, in the main window.
  122.        Controlled by program parameter -T.
  123.     *)
  124.   expandedIndex: boolean = true;
  125.     (* controls whether the Interrupt Index initialy pops up in expanded
  126.        or compressed format.
  127.        Controlled by program parameter -X.
  128.     *)
  129.  
  130. (* Help windows topic titles and identifiers: *)
  131.     (* The following text describes windows titles as defined by the "$"
  132.        footnotes and topic identifiers (context strings) as defined by
  133.        the "#" footnotes. The identifiers can be used to open the List
  134.        at a given position by an external call to WINHELP.
  135.  
  136. window title        identifier    text
  137.  
  138. Contents:        CONTENTS    Main index.
  139. Interrupt Index        idIndex        Total list, only if "twoIndexes" is true.
  140. Interrupts            idInterrupts    Main interrupt index.
  141. INT NN List        nn_0        Index for INT NN, nn are two hex digits.
  142. INT NN AHAL - <header>    nn_1        First entry about INT NN, the following
  143.                     entries have consecutive identifiers
  144.                     ... nn_9, nn_10, ... . Aliases for
  145.                     Interrupt List topics can be compiled
  146.                     and written to the Help Project file.
  147.                     These aliases can be used to identify
  148.                     any (unique) topic.
  149. Tables            idTables    Table index.
  150. NN AHAL <table title>    tnnnn        Table No. nnnn, nnnn are the four
  151.                     decimal digits from the List. Aliases
  152.                     can be compiled based on table position
  153.                     and title.
  154.                     NN and AHAL in the title are the
  155.                     interrupt number and the register
  156.                     contents (sub function) where the table
  157.                     is defined.
  158. FILELIST        1        The initial part of the Interrrupt List.
  159. <notes>            n        Other notes have consecutive numbers as
  160.                     identifiers.
  161. INTERRUP.1ST File    id1st        INTERRUP.1ST file window.
  162. none            idPartComp    Partial compilation popup window if
  163.                     parameter -f<name>.
  164. Filter Method        idFlt_meth    Filter Method if parameter -f<name>.
  165. Filter File        idFlt_file    Filter File if parameter -f<name>.
  166. Credits            idCredits    The Credits window.
  167. none        Compressed_Index    This identifier is used as a marker.
  168.  
  169. The identifiers mentioned above are reserved for program use. Titles and
  170. identifiers for other windows are defined in the configuration file.
  171.  
  172. The program maintains 6 browse chains, as defined by the "+" footnotes:
  173.  
  174. The "main" chain:
  175.     m:1    the Credits window.
  176.     m:2    the Contents window.
  177.     m:3    the Interrupt Index window provided "twoIndexes" is true.
  178.     m:4    the Interrupts window.
  179.     m:5    the Tables window provided "releaseNo" >= 41.
  180.     m:9    index windows included as window type 2.
  181.  
  182. The "list" chain:
  183.     l:0    the interrupt list sub index windows.
  184.  
  185. The "interrupt" chain:
  186.     i:0    the interrupt windows.
  187.  
  188. The "file" chain:
  189.     f:0    files included by the program or as window type 1.
  190.  
  191. The "table" chain:
  192.     t:0    the table windows provided "releaseNo" >= 41.
  193.  
  194. The "ports" chain:
  195.     p:0    the sub windows compiled from window type 2 inclusion.
  196.  
  197. Window type 3 inclusions can link onto these chains or maintain their own
  198. chains under user control.
  199.  
  200. *)
  201.  
  202. (* Constants defining windows setup etc.
  203.    All the typed constants can be changed by the configuration file, and
  204.    some of them also by program parameters.
  205. *)
  206.  
  207. (* definitions for the *.HPJ file: *)
  208.     windowsTitle =     '"Ralf Brown''s Interrupt List"';
  209.     secWindowsTitle =  '"Interrupt List Tables"';
  210.     secWindow = 'ITW'; (* the name of the secondary window *)
  211.     mainW: string[5] = '>main'; (* or '' *)
  212.     tableW: string[((length(secWindow)+3) AND $FE) - 1] = '>'+secWindow;
  213.     windowsPosSize: string[21]   =   '';
  214.       (* or: '(xpos,ypos,width,heigth)' *)
  215.     secWindowsPosSize: string[21] =  '(43,0,980,1023)';
  216.       (* values must be defined for a secondary window *)
  217.     windowsMaximized = '0';      (* '0': no; '1': yes (overrides size) *)
  218.     windowsBackgr: string[19]    = ''; (* or: '(red,green,blue)' *)
  219.     windowsHdrBackgr: string[19] = ''; (* or: '(red,green,blue)' *)
  220.  
  221. (* definitions for fonts, attributes, and size: *)
  222.     headerFont: string[31]       = 'roman Times New Roman';
  223.       (* or 'swiss Arial' *)
  224.     textFont: string[31]         = 'modern Courier New';
  225.     deciPoints: word             = 90;
  226.       (* 10 times point size *)
  227.     headerDeciPoints: word       = 140;
  228.     header2ndDeciPoints: word    = 120;
  229.     headerAttrib =     '';       (*
  230.         \b   = bold
  231.         \i   = italics
  232.       *)
  233.     highlightInt =     '';       (* this attribute highlights specificly
  234.                        the "INT nn" part of the header *)
  235.     indent =           '1060';   (* left indent of header after line one *)
  236.       (* (in twips, whatever that is?) *)
  237.     dateSep =  '-';        (* for compile time YYYY-MM-DD string *)
  238.     timeSep =  ':';        (* for compile time H:MM string *)
  239.     (*.$define m_dd_yy *)  (* defines date format, default is yyyy-mm-dd *)
  240.     (*.$define d_mm_yy *)  (* defines date format if m_dd_yy is undefined *)
  241.     (*.$define yy_mm_dd *) (* defines date format to yy-mm-dd instead of
  242.                   yyyy-mm-dd if both m_dd_yy and d_mm_yy
  243.                   are undefined *)
  244.  
  245.   Var
  246.       ProcessTime    : Longint;
  247.       IndexFile      : Text;                    { stores *all* section names }
  248.       IntFile        : Text;                    { stores one entry per int-number }
  249.       SubIntFile     : Text;                    { stores all subfunctions of an int per page }
  250.       TableFile      : Text;                    { stores tables references (index) }
  251.       HPJ            : Text;                    { hlep compiler project file }
  252.       indexHeader    : string;                  { index and subindex header string }
  253.       compilationStr : string[159];             { compilation information }
  254.       TopicStr   : String[15];            { used in CheckKeyWords and ProcessList }
  255.       indexPages,indexRows: integer;
  256.       dateString: string[19];
  257.       fontSize, headerSize, header2ndSize: string[7];
  258.       aliasP,tableAliasP: stringListPtr;
  259.     (* aliases read from configuration file *)
  260.       aliasId,tableAliasId: string[19];
  261.       aliasString,tableAliasString: aliasStringType;
  262.       nextAliasPP: stringListPtrPtr;
  263.     (* stored aliases, to be written to the HPJ file *)
  264.       INTcounts: array[byte] of word;
  265.       currentDir,homeDir: dirStr;
  266.       currentTable: string[5];
  267.       lineCount  : word; (* for error report *)
  268.  
  269.   Const
  270.     (* classification characters < '!' do not insert a classification string as
  271.        a keyword.
  272.     *)
  273.     InvalidClassification = '-'; (* don't insert classification string as keyword *)
  274.     nullClassification = #0;     (* no title as keyword *)
  275.     specialClassification = #1;  (* use indexHeader in header *)
  276.     tableClassification = #2;    (* insert '#' + currentTable as keyword *)
  277.  
  278. function readKeyWd: word;
  279. (* Calls BIOS to read the keyboard, returns scan code in hi and char. in lo *)
  280.   inline($B4/$00/ {mov ah,0}  $CD/$16 {int $16});
  281.  
  282. procedure wl(s: string);
  283. (* a substitute for single-string "writeln" to screen (or "output") (saves
  284.    20 bytes of code per call).
  285. *)
  286.   begin writeln(s) end;
  287.  
  288. procedure errorExit(msg: string; err: byte);
  289. (* prints "msg" to screen and halts with errorlevel "err" *)
  290.   begin wl(msg); halt(err); end;
  291.  
  292. function exist(filename: pathStr): boolean;
  293. (* check the existance of "filename" *)
  294.   var b: boolean; t: text;
  295.   begin
  296. (*$I-*)
  297.     assign(t,filename);
  298.     reset(t);
  299.     b:=IOresult=0;
  300.     if b then close(t);
  301.     exist:=b;
  302. (*$I+*)
  303.   end; (* function exist *)
  304.  
  305. procedure defaultDir(var fileName: pathStr; var default: dirStr);
  306. (* if fileName has no drive, root, or current specification, then insert the
  307.    default directory.
  308. *)
  309.   begin
  310.     if (fileName[2]<>':') AND (fileName[1]<>'\') AND (fileName[1]<>'.') then
  311.       insert(default,filename,1);
  312.     fileName:=fExpand(fileName);
  313.   end; (* procedure defaultDir *)
  314.  
  315. (* Some of the following procedures are Windows getPrivateProfileXxx-like
  316.    routines to search the configuration file. If INT2WHLP.CFG is not found
  317.    in the current directory or in INT2WHLP.EXE's home directory, or if
  318.    the section or entry is not found in the file, the "value" parameter is
  319.    unchanged, otherwise the section/entry value is assigned to "value". A
  320.    boolean value is considered false if it is 0, and true otherwise.
  321. *)
  322.  
  323. function findProfile(var configFile: text; var section: dirStr): boolean;
  324. (* opens INT2WHLP.CFG on configFile and reads up to the specified section.
  325.    findProfile returns true if the configuration file was located, false
  326.    otherwise. If eof(configFile) returns true after a successful call
  327.    to findProfile this indicates that the section was not found, or it was
  328.    empty and last.
  329. *)
  330.   var i,l: integer; s: string;
  331.   begin
  332. (*$I-*)
  333.     findProfile:=false; (* suggest configuration file absent *)
  334.     if exist(progName+'.CFG') then assign(configFile,progName+'.CFG')
  335.     else assign(configFile,homeDir+progName+'.CFG');
  336.     reset(configFile);
  337.     if IOresult<>0 then exit;
  338.     findProfile:=true;
  339.     i:=1;
  340.     l:=length(section);
  341.     if l=0 then exit; (* we will interpret section='' as "open only" *)
  342.     while (i<=l) AND NOT eof(configFile) do begin
  343.       readln(configFile,s);
  344.       i:=1;
  345.       if (length(s)>=l+2) AND (s[1]='[') AND (s[l+2]=']') then
  346.     while (i<=l) AND (upcase(section[i])=upcase(s[succ(i)])) do inc(i);
  347.     end; (* while i<=l ... *)
  348. (*$I+*)
  349.   end; (* procedure findProfile *)
  350.  
  351. procedure profileList(section: dirStr; var listP: stringListPtr);
  352. (* reads all the entries in the specified section to a linked list and
  353.    assigns the beginning of the list to listP. Empty lines and lines
  354.    starting with a semicolon (;) are ignored.
  355. *)
  356.   label done,doneNC;
  357.   var listPP: ^stringListPtr; s: string; configFile: text;
  358.   begin
  359.     listPP:=@listP;
  360.     if NOT findProfile(configFile,section) then goto doneNC;
  361.       (* no configuration file *)
  362.     while NOT eof(configFile) do begin
  363.       readln(configFile,s);
  364.       if (s<>'') AND (s[1]<>';') then begin
  365.     if s[1]='[' then goto done;
  366.     getMem(listPP^,length(s)+1+sizeOf(pointer));
  367.     listPP^^.s:=s;
  368.     listPP:=@listPP^^.next;
  369.       end; (* if (s<>'')... *)
  370.     end; (* while NOT eof() *)
  371.   done:
  372.     close(configFile);
  373.   doneNC:
  374.     listPP^:=NIL;
  375.   end; (* procedure profileList *)
  376.  
  377. procedure freeStringRec(var p: stringListPtr);
  378. (* updates p to point to the next record, and frees the current one *)
  379.   var p1: stringListPtr;
  380.   begin
  381.     if p=NIL then exit;
  382.     p1:=p;
  383.     p:=p1^.next;
  384.     freeMem(p1,length(p1^.s)+1+sizeOf(pointer));
  385.   end; (* procedure freeStringRec *)
  386.  
  387. procedure profileString(section, entry: dirStr; var value: string;
  388.   bufferLen: integer);
  389.   label done;
  390.   var i,l: integer; s: string; configFile: text;
  391.   begin
  392. (*$I-*)
  393.     if (section='') OR (entry='') then exit;
  394.     if NOT findProfile(configFile,section) then exit;
  395.       (* no configuration file *)
  396.     i:=1;
  397.     l:=length(entry);
  398.     while (i<=l) AND NOT eof(configFile) do begin
  399.       readln(configFile,s);
  400.       if (s<>'') AND (s[1]='[') then goto done;
  401.       i:=1;
  402.       if (length(s)>l) AND (s[succ(l)]='=') then
  403.     while (i<=l) AND (upcase(entry[i])=upcase(s[i])) do inc(i);
  404.     end; (* while i<=l ... *)
  405.     if i>l then value:=copy(s,succ(i),bufferLen);
  406.   done:
  407.     close(configFile);
  408. (*$I+*)
  409.   end; (* procedure profileString *)
  410.  
  411. procedure profileInt(section, entry: dirStr; var value: integer);
  412.   var i,j: integer; s: string[19];
  413.   begin
  414.     s:='';
  415.     profileString(section,entry,s,pred(sizeOf(s)));
  416.     if s='' then exit;
  417.     val(s,i,j);
  418.     if j=0 then value:=i;
  419.   end; (* procedure profileInt *)
  420.  
  421. procedure profileBoolean(section, entry: dirStr; var value: boolean);
  422.   var i: integer;
  423.   begin
  424.     i:=ord(value);
  425.     profileInt(section,entry,i);
  426.     value:=i<>0;
  427.   end; (* procedure profileBoolean *)
  428.  
  429. procedure scan(line: string; var spa: categoryStringPtrArr);
  430. (* scans lines with format "xxx a - definition a, A - definition A" and
  431.    allocates memory and stores the definitions at appropriate index in spa.
  432. *)
  433.   var
  434.     p: integer;
  435.     c: char;
  436.     ok: boolean;
  437.   begin
  438.     repeat
  439.       p:=pos(' - ',line);
  440.       if p=0 then exit;
  441.       if p>1 then c:=line[p-1];
  442.       ok:=((p=2) OR ((p>2) AND (line[p-2]<=' '))) AND (c>' ') AND (c<#127);
  443.       delete(line,1,p+2);
  444.       if ok then begin
  445.     p:=pos(' - ',line);
  446.     if p=0 then p:=length(line)+1 else dec(p,2);
  447.     while line[p-1]<=' ' do dec(p);
  448.     if line[p-1]=',' then dec(p);
  449.     getmem(spa[c],p);
  450.     spa[c]^:=copy(line,1,p-1);
  451.     delete(line,1,p);
  452.       end; (* if ok *)
  453.     until false; (* terminated by exit *)
  454.   end; (* procedure scan *)
  455.  
  456. procedure check1st(var s: string);
  457. (* scans s for the occurence of 'INTERRUP.1ST' and inserts xref to id1st.
  458.    Letter case is ignored.
  459. *)
  460.   var p: byte; s1: string[119];
  461.   begin
  462.     s1[0]:=s[0];
  463.     for p:=1 to length(s) do s1[p]:=upcase(s[p]);
  464.     p:=pos('INTERRUP.1ST',s1);
  465.     if p<>0 then begin
  466.       insert('}{\v id1st}',s,p+12);
  467.       insert('{\uldb ',s,p);
  468.     end; (* if p<>0 *)
  469.   end; (* procedure check1st *)
  470.  
  471. procedure getINTtitle(var line: string; var titles: titleStringPtrArr);
  472. (* allocates memory and copies a line starting with "INT nn " to titles[nn]^ *)
  473.   type (* for type casts *)
  474.     lineRec = record l: byte; INT: longint; nn: word; spc: char; end;
  475.     hexRec = record l: byte; dollar: char; nn: word; end;
  476.   const
  477.     intC = ord('I')+ord('N')*$100+ord('T')*$10000+ord(' ')*$1000000;
  478.     intNumber: string[3] = '$nn'; (* preset length to 3 and [1] to '$' *)
  479.   var
  480.     lineR: lineRec absolute line; (* for typecast *)
  481.     intR: hexRec absolute intNumber; (* for typecast *)
  482.     n,j: integer;
  483.   begin
  484.     if (length(line)<8) OR (lineR.spc<>' ') OR (lineR.INT<>intC) then exit;
  485.     intR.nn:=lineR.nn; (* two characters typecasted to a word *)
  486.     val(intNumber,n,j);
  487.     if j<>0 then exit;
  488.     getmem(titles[n],succ(length(line)));
  489.     titles[n]^:=line;
  490.   end; (* procedure getINTtitle *)
  491.  
  492. procedure getNextAlias(var aliasP: stringListPtr;
  493.    var aliasId, aliasString: string);
  494. (* extract an alias string from the heap and free the heap memory *)
  495.   var n: integer;
  496.   begin
  497.     aliasString:='';
  498.     if aliasP=NIL then exit;
  499.     aliasString:=aliasP^.s;
  500.     freeStringRec(aliasP); (* free memory and update aliasP *)
  501.     n:=pos('=',aliasString);
  502.     if n<2 then errorExit('Missing alias Id in '+aliasString,1);
  503.     if n>pred(sizeOf(aliasId)) then errorExit('Alias Id too long in '+aliasString,1);
  504.     aliasId:=copy(aliasString,1,n);
  505.     delete(aliasString,1,n);
  506.   end; (* procedure getNextAlias *)
  507.  
  508. procedure saveAlias(var aPP: stringListPtrPtr; s: dirStr);
  509. (* allocates memory on the heap, stores information, and updates aPP *)
  510.   begin
  511.     getmem(aPP^,length(s)+1+sizeOf(pointer));
  512.     aPP^^.next:=NIL;
  513.     aPP^^.s:=s;
  514.     aPP:=@aPP^^.next
  515.   end; (* procedure saveAlias *)
  516.  
  517. procedure processAliasList(aP: stringListPtr);
  518.   begin
  519.     while aP<>NIL do begin
  520.       writeln(HPJ,aP^.s);
  521.       aP:=aP^.next;
  522.     end; (* while aP<>NIL *)
  523.   end; (* procedure processAliasList *)
  524.  
  525. procedure setTabs(var f: text; spaces, deciPoints, tabs: word);
  526. (* writes tab settings to file f, tabspacing approximately "spaces" character
  527.    columns width New Courier font with size 1/10*"deciPoints". Number of tab
  528.    settings = "tabs".
  529.    The tabs are valid until the next "\pard".
  530. *)
  531.   var i: integer; s: string[11];
  532.   begin
  533.     for i:=1 to tabs do begin
  534.       str(longint(i*spaces*deciPoints)*1170 DIV 1000,s);
  535.       (* tab spacing = (point size)*(column width)*11.70 *)
  536.     (* at least, this seems to fit pretty well *)
  537.       write(f,'\tx',s);
  538.     end; (* for i:=1 *)
  539.     writeln(f);
  540.   end; (* procedure setTabs *)
  541.  
  542. procedure writeIndex(s: string);
  543.   begin writeln(indexFile, s); end;
  544.  
  545.   procedure CreateHPJ;
  546.     var i,n: integer; bP: stringListPtr; s: dirStr;
  547.     begin
  548.       assign(HPJ, OutPath + hfName+'.HPJ');
  549.       rewrite(HPJ);
  550.       n:=0;
  551.       profileList('BUILDTAGS',bP);
  552.       if bP<>NIL then begin (* write [BuildTags] section *)
  553.     writeln(HPJ,'[BUILDTAGS]');
  554.     while bP<>NIL do begin
  555.       writeln(HPJ,bP^.s);
  556.       freeStringRec(bP); (* free memory and update bP *)
  557.     end; (* while bP<>NIL *)
  558.     writeln(HPJ);
  559.       end; (* if i>0 *)
  560.       s:=fExpand(OutPath);
  561.       if length(s)>3 then dec(s[0]); (* delete terminating '\' if not root *)
  562.       writeln(HPJ, '[OPTIONS]'#13#10'CONTENTS=CONTENTS'#13#10'COMPRESS=',compression);
  563.       writeln(HPJ,'REPORT=ON'#13#10'WARNING=2'#13#10'ROOT=',s);
  564.     (* warning=2 avoids the "Using old *.ph file" warning *)
  565.       if errorLog then writeln(HPJ,'ERRORLOG='+hfName+'.ERR');
  566.       if buildExpr<>'' then writeln(HPJ,'BUILD=',buildExpr);
  567.       writeln(HPJ, 'CITATION=Copied from Ralf Brown''s Interrupt List');
  568.       writeln(HPJ, 'COPYRIGHT='+hfName+' Layout: Christian Müller-Planitz');
  569.       writeln(HPJ, #13#10'[CONFIG]'#13#10'CreateButton("id_print","&Print","Print()")');
  570.       writeln(HPJ, 'CreateButton("id_copy","C&opy","CopyTopic()")'#13#10'BrowseButtons()');
  571.       writeln(HPJ, 'CreateButton("id_exit","E&xit","Exit()")');
  572.       if twoindexes AND NOT expandedIndex then
  573.     writeln(HPJ, 'SaveMark("Compressed_Index")');
  574.       profileList('INTWINCONFIG',bP);
  575.       while bP<>NIL do begin (* copy [INTWINCONFIG] entries *)
  576.     writeln(HPJ,bP^.s);
  577.     freeStringRec(bP); (* free memory and update bP *)
  578.       end; (* while bP<>NIL *)
  579.       writeln(HPJ, #13#10'[WINDOWS]'#13#10'main='+windowsTitle+',',windowsPosSize,
  580.     ','+windowsMaximized+',',windowsBackgr,',',windowsHdrBackgr);
  581.       if tableWindow then writeln(HPJ, secWindow+'='+secWindowsTitle+',',
  582.     secWindowsPosSize,','+windowsMaximized+',',windowsBackgr,',',
  583.     windowsHdrBackgr);
  584.       writeln(HPJ, #13#10'[FILES]');
  585.     end;
  586.  
  587.   Procedure OpenRTF(VAR F: Text; Name: String);
  588.     begin
  589.      {$I-}
  590.       assign(F, OutPath + Name);
  591.       rewrite(F);
  592.      {$I+}
  593.       if IOResult <> 0 then errorExit('Error craeting '+ OutPath + Name, 1);
  594.  
  595.       writeln(HPJ, Name);
  596.  
  597.       writeln(F, '{\rtf1\pc \deff1{\fonttbl{\f0\f',headerFont,';}');
  598.       writeln(F, '{\f1\f',textFont,';}}');
  599.       writeln(F, '{\colortbl \red255\green0\blue0;\red0\green0\blue0;');
  600.       writeln(F, '\red0\green0\blue255;\red255\green255\blue255;}');
  601.       writeln(F, '\plain',fontSize,'\pard\keep');
  602.     end;
  603.  
  604.  
  605.   Procedure CloseRTF(VAR F: Text);
  606.     begin
  607.       writeln(F, '}');
  608.       close(F);
  609.     end;
  610.  
  611.  
  612.   Procedure OpenOutFile(VAR FData: Text);
  613.       VAR Name : String;
  614.  
  615.       begin
  616.     STR(OutFileCounter, Name);
  617.     Name := hfName + Name + '.RTF';
  618.  
  619.     OpenRTF(FData, Name);
  620.     Inc(OutFileCounter);
  621.       end;
  622.  
  623.   Function HEX(b:byte):string;
  624.     Const h : array [0..15] of char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
  625.     begin
  626.       Hex[0]:=#2; Hex[1]:=h[b shr 4]; Hex[2]:=h[b and 15];
  627.     end;
  628.  
  629.  
  630.   Procedure ReadLine(VAR F: Text; VAR S: String);
  631.     label again, keep;
  632.     VAR q: Word;
  633.     S1: String;
  634.     failed: Boolean;
  635.  
  636.     begin
  637.       readln(F, S1);
  638.       failed:=false;
  639.  
  640.     again:
  641.       S := S1;
  642.       q:= 1;
  643.       while q <= Length(s) do    { duplicate all '\' etc. }
  644.     begin
  645.       case s[q] of
  646.         '\', '{', '}': begin insert('\', s, q); inc(q); end;
  647.         #196: if failed then s[q]:='-' else goto keep;
  648.         #205: if failed then s[q]:='=' else goto keep;
  649.           (* horizontal single and double frame *)
  650.         #128..#255: begin
  651.       keep:
  652.           insert(#39+HEX(ord(s[q])), s, q+1);
  653.           s[q] := '\';
  654.           Inc(q,3);
  655.         end; (* case #128..#255 *)
  656.       end; (* case s[q] of *)
  657.       if q>255 then begin
  658.         failed:= NOT failed;
  659.         if failed then goto again
  660.         else begin
  661.           writeln('Too many graphic characters in line ', lineCount,
  662.         ':'#13#10, s1);
  663.           ErrorExit('Please correct the file and try again', 1);
  664.         end; (* else *)
  665.       end; (* if q>255 *)
  666.       Inc(q);
  667.     end; (* while q>=length(s) *)
  668.  
  669.     end;
  670.  
  671.  
  672.  
  673.   Procedure OutLN(VAR F: Text; S : String);
  674.     begin
  675.       writeln(F, '\par ', S);
  676.     end;
  677.  
  678.  
  679.   Procedure Intro;
  680.     begin
  681.       wl(#10'Interrupt List-WinHelp preprocessor '+progname+' version '+progvers);
  682.       wl(copyright);
  683.       wl(e_mail+#13#10);
  684.       wl('Use "'+progname+' ?" for help.'#13#10);
  685.     end;
  686.  
  687.   Procedure Explain;
  688.     begin
  689.       wl('This program converts the Interrupt List written by Ralf Brown to a RTF-Format');
  690.       wl('that is used as an input format by the Microsoft WinHelp compiler.'#10);
  691.  
  692.       wl('In order to generate a Windows 3.1 helpfile you need the WinHelp compiler');
  693.       wl('"HC31.EXE", which is distributed with almost all Windows compilers and which');
  694.       wl('is also available on many Internet sites and FIDO BBS systems.'#10);
  695.  
  696.       wl('Please note that you also need a fast computer and a *lot* of free space on');
  697.       wl('your harddrive, see the file I2W-HINT.TXT. If you want to find out whether you');
  698.       wl('are able to compile a RTF file, I recommend that you experiment with the files');
  699.       wl('in the I2W-TEST.ZIP subpackage.'#10);
  700.  
  701.       wl('After this program finishes, you have to invoke the WinHelp compiler with');
  702.       writeln('the command "HC31 ',hfName,'.HPJ".'#10);
  703.  
  704.       wl('For more information about '+progName+' program options and configuration file,');
  705.       wl('read the I2W-OPT.TXT and I2W-CFG.TXT files.'#10);
  706.  
  707.       wl('Have fun ! --CMP'#10);
  708.  
  709.       wl('P.S. If you have problems building the helpfile or if you simply want to write');
  710.       wl('     an e-mail to me, please write to:');
  711.       wl('     '+e_mail);
  712.       halt(0);
  713.     end;
  714.  
  715.