Footnotesupport include
From 40tude Dialog Wiki
Contents |
Footnote-Support (Include-File)
The following script brings footnote-support into 40tude Dialog. This enhanced version of the script corrects many bugs and brings up a lot of new features. Its based on a early version from Mirko D. Walter (mwalter@2via.de) and currently was modified by homas Barghahn.
Little docu
Please read this extensive documentation for more details on making footnotes.
- Note that you have to leave a blank after #fn# (ConstStartupFootnote).
Otherwise your article gets possibly wrapped in a wrong way. - Be sure you don't forget the ## (ConstEndFootnote).
Otherwise footnotes will be not interpreted and you will get an error-message. - Please note, that you will see the result not inside the editor-window but only in the transmitted article!
In short:
Enter the following text inside your editor window:
This is a test #fn# With a very stupid footnote.## with blank. This is another test#fn# With a very intelligent footnote.## without blank.
And you will get this output:
This is a test [1] with blank. This is another test[2] without blank. Footnotes: ========== [1] With a very stupid footnote. [2] With a very intelligent footnote.
Specials
- If you put %% somewhere inside the footnote-markers, it will expand to a blank line.
- If you use Footnotes inside text which will be boxquoted (using the Boxquote script), you have to put an << (ConstRewrapToLine) at the end of your text inside the boxquote. Otherwise, your boxquote will be destroyed.
Questions, Bugs & Comments
If you have questions, comments or found a bug please post to de.comm.software.40tude-dialog.
Install & Setup the script
Please note that this script is an include-file!. You have to copy the following script inside a new custom script (for example "Footnote_include") and safe it. Please don't compile this custom script! After that you have to add the following lines to your OnBeforeSending-Script:
{$I Footnote_include.ds}
and
result := doFootNoteNew ( Message );
This may look like this:
program OnBeforeSendingMessage;
{$I Footnote_include.ds}
function OnBeforeSendingMessage(var Message: TStringlist; Servername: string; IsEmail: boolean):boolean;
begin
result:=true;
result := doFootNoteNew ( Message );
//possibly some other calls to scripts
end;
begin
end.
Just compile this OnBeforeSending-Script now to get your include-file to work. The setup of the script is shown inside the script. Please take a look at this to customize the script to your own fits. Please note that whenever you reconfigure the footnote custom script, you have to recompile the OnBeforeSending-Script to apply the changes.
Setup in the script:
If you want to change the setup for the footnotes, you have to edit the lines below inside the script.
// // Configuration Options: // // Set this to true, if you want a footnote-header like this: // // Footnotes: // ========== ConstFootnoteHead = true; // Define the text, you want to see in your footnote-header. ConstFootnoteHeadTxt = 'Footnotes:'; // Here you can define the character which one should underline the // footnote-header. If there should be no underline, just set // "ConstFootnoteHeadUnderline = '';" (without double quotes). ConstFootnoteHeadUnderline = '='; // If there should be a blank line between footnote-header and // footnotes, set this to true. Otherwhise (false) there will be // no empty line between them. ConstEmptyLine = false; // Defines start tag for footnote recognition. // Everything after that (and between end tag) is recogniced as footnote. ConstStartupFootnote = '#fn#'; // Defines end tag of footnote recognation. // Please be sure to use chars, you will not put in normal (footnote) text. ConstEndFootnote = '##'; // For longer footnotes its important to reformat their line length. // The number below is the column number where the line break will // occur at the latest (should always be 1 char more than inside Dialog; // You will find this option in Settings -> General settings ... -> // Posting -> Wrap lines after xx chars) ConstReWrapEdge = 73; // Defines a control character which expands to a blank line in the // footnote. Change it as you like - but be aware: same warning as // for the ConstEndFootnote applies. ConstMultiLine = '%%'; // Defines char(s) until this the paragraph will be reformatted by the // footnote-logic. Its very important to put this at the end of your // footnote (or at least at the end of the text to be boxquoted) if you // want to use footnotes inside boxquotes! ConstRewrapToLine = '<<'; // Useful if you want to talk about this footnote-skript inside 40tude // Dialog: Just comment them out. Note that the comment-chars will not // be deleted in the article. ConstComments = '//'; // By default this script adds a blank line before the footnote block. // Set this to false if you don't want the blank line. ConstEmptyLineBeforeFootnote = true;
The Script
//
// program Footnotes - Date: 2004/11/05
//
procedure Init_doFootNoteNew ( var ConstFootnoteHead : boolean;
var ConstFootnoteHeadTxt : String;
var ConstFootnoteHeadUnderline : String;
var ConstEmptyLine : Boolean;
var ConstEmptyLineBeforeFootnote : Boolean;
var ConstStartupFootnote : String;
var ConstEndFootnote : String;
var ConstReWrapEdge : Integer;
var ConstMultiLine : String;
var ConstRewrapToLine : String;
var ConstComments : String
);
begin
// ----------------------------------------------------
// Configuration settings
// ----------------------------------------------------
// Footnote-Support:
// configure your settings here:
//
// Set this to true, if you want a footnote-header like this:
// Footnotes:
// ==========
ConstFootnoteHead := true;
// Define the text, you want to see in your footnote-header.
ConstFootnoteHeadTxt := 'Footnotes:';
// Here you can define the character which should underline the
// footnote-header. If there should be no underline, just set
// "ConstFootnoteHeadUnderline = '';" (without double quotes).
ConstFootnoteHeadUnderline := '=';
// If there should be a blank line between footnote-header
// and footnotes,set this to "true". Otherwhise (false) there
// is no empty line between.
ConstEmptyLine := false;
// By default this script adds a blank line before the footnote block.
// Set this to false if you do not want the blank line.
ConstEmptyLineBeforeFootnote := true;
// Defines start-tag for footnote recognition.
// Everything after that (and between end-tag) is recogniced as footnote.
ConstStartupFootnote := '#fn#';
// Defines end-tag of footnote recognation.
// Please use chars, you normaly not type inside your text.
ConstEndFootnote := '##';
// For longer footnotes its important to reformat the footnote.
// This number defines the column-number (should always be 1 char higher
// than inside Dialog). You will find this option in Settings -> General
// settings... -> Posting -> Wrap lines after xx chars
ConstReWrapEdge := 73;
// Defines a control character to expand the footnote to a blank line.
// Change it as your own wish.
ConstMultiLine := '%%';
// Define char(s) till which the paragraph will be reformated by the
// footnote-logic. Its very important if you want to use footnotes
// inside boxquotes, to put this at the end of your footnote!
ConstRewrapToLine := '<<';
// Useful if you want to talk about this footnote-skript inside 40tude
// Dialog, just comment them out. Note that the comment-chars will not
// be deleted in the article.
ConstComments := '//';
// ----------------------------------------------------
// End of configuration settings
// ----------------------------------------------------
end;
// --------------------------------------------------------------- //
// ---- No user maintainable parts below this line -------------- //
// --------------------------------------------------------------- //
//
// Flags to indicate the buttons contained in the message box:
//
// MB_OK = 0; // 1 button: OK.
// MB_OKCancel = 1; // 2 buttons: OK and Cancel.
// MB_AbortRetryIgnore = 2; // 3 buttons: Abort, Retry, and Ignore.
// MB_VbYesNoCancel = 3; // 3 buttons: Yes, No, and Cancel.
// MB_YesNo = 4; // 2 buttons: Yes and No.
// MB_RetryCancel = 5; // 2 buttons: Retry and Cancel.
//
// Flags to display an icon in the message box:
//
// MB_IconCritical = 16; // stop sign
// MB_IconQuestion = 32; // question mark
// MB_IconExclamation = 48; // exclamation point
// MB_IconInformation = 64; // lowercase i in a circle
function MessageBox( hWnd : Cardinal; lpText, lpCaption : PChar; uType : longword ) : Integer;
external 'MessageBoxA@user32.dll stdcall';
function GetText(
var Txt : TStringlist;
var FoundLine : Integer;
var FoundPosi : Integer;
var CurrLine : Integer;
var CurrPosi : Integer;
var ConstMultiL : String
) : String; // Function by Mirko D. Walter
var
res : String;
i : Integer;
bposi : Integer;
MaxInt : Integer;
begin
MaxInt := 2147483647;
result :='';
res := '';
if FoundLine = CurrLine then begin
res := Copy( txt.strings[foundline], FoundPosi, CurrPosi - FoundPosi );
end
else begin
BPosi := FoundPosi;
for i := FoundLine to CurrLine do begin
if i < CurrLine then begin
res := Res + Trim( Copy(txt.strings[i], BPosi, MaxInt) ) + ' ';
BPosi := 0;
end
else begin
res := res + Copy( txt.strings[i], 1, CurrPosi-1 );
end;
end;
end;
//
// Multine-Special-Character?
//
BPosi := AnsiPos( ConstMultiL, res );
if BPosi > 0 then begin
repeat
//
// if the following characters are #13#10
// then do no linebreak, simply remove
// 1234567890123
// ABCDEF%%gaga#
//
if Copy( res, BPosi + Length(ConstMultiL), 2 ) = #13#10
then res := Copy( res, 1, BPosi - 1 )
+ #13#10
+ Trim( Copy(res, BPosi + Length(ConstMultiL), MaxInt) )
else res := Copy( res, 1, BPosi - 1 )
+ #13#10
+ #13#10
+ Trim( Copy(res, BPosi + Length(ConstMultiL), MaxInt) );
BPosi := AnsiPos( ConstMultiL, res );
until BPosi <= 0;
res := Trim( res );
end;
result := Trim( res );
end; // function GetText()
function Rewrap_Str(
StrL : String;
WEdge : Integer;
FootNote : Boolean;
ConstRewrap : String
) : String;
var
Space_Old : Integer;
Space_New : Integer;
i : Integer;
Space_Pos : Integer;
Break_L : Boolean;
begin
Space_Old := 1;
Space_New := 1;
Space_Pos := WEdge;
if Copy( StrL, Length(StrL), 1 ) <> ' '
then StrL := StrL + ' ';
if AnsiPos( ConstRewrap, StrL ) > 0
then Delete( StrL, AnsiPos(ConstRewrap, StrL), 2 );
for i:=1 to Length( StrL ) do begin
if (StrL[i] = ' ') and (i > 1) and (i < Length(StrL)) then begin
if StrL[i+1] = ' ' then begin // found double blank
if (StrL[i-1] <> '.') // it's perfectly fine to
and (StrL[i-1] <> '?') // have double blanks after
and (StrL[i-1] <> '!') // punctuation marks (at
and (StrL[i-1] <> ':') // least beyond sentence
and (StrL[i-1] <> ';') // delimiters).
then begin // but otherwise not!
Delete( StrL, i, 1 );
end;
end;
end;
end;
i := 0;
while i <= Length( StrL ) do begin
i := i + 1;
if (Copy(StrL, i, 1) = ' ')
or (Copy(StrL, i, 4) = (#13#10 + #13#10))
then begin
Break_L := false;
Space_Old := Space_New;
Space_New := i;
if Copy( StrL, i , 4 ) = (#13#10 + #13#10) then begin
Insert( ' ', StrL, i + 4 );
Break_L := true;
if Space_New < Space_Pos then begin
Space_Pos := i + 4 + WEdge;
Space_Old := i + 4;
Space_New := i + 4;
i := i + 4;
end;
end;
if (Space_New >= Space_Pos)
and (Space_old <= Space_Pos)
then begin
if (Space_New = Space_Pos)
and (Length(StrL) > Space_Pos)
then begin
if Footnote = false then begin
Delete( StrL, Space_New, 1 );
Insert( #13#10, StrL, Space_New );
Space_Pos := Space_New + WEdge + 1;
end
else begin
Insert( #13#10 + ' ', StrL, Space_New );
if Break_L then begin
Space_Pos := i + 4 + WEdge;
Space_Old := i + 4;
Space_New := i + 4;
i := i + 4;
end
else Space_Pos := Space_New + WEdge + 1;
i := i + 3;
end;
end
else begin
if Footnote = false then begin
if Length( StrL ) > Space_Pos then begin
Delete( StrL, Space_Old, 1 );
Insert( #13#10, StrL, Space_Old );
end;
Space_Pos := Space_Old + WEdge + 1;
if (Space_New >= Space_Pos)
and (Length(StrL) > Space_Pos)
then begin
Delete( StrL, Space_New + 1, 1 );
Insert( #13#10, StrL, Space_New + 1 );
Space_Pos := Space_New + WEdge + 2;
i := i + 1;
end;
end
else begin
if Space_Old > 5 then begin
if Length( StrL ) > Space_Pos
then Insert( #13#10 + ' ', StrL, Space_Old );
if Break_L then begin
Space_Pos := i + 4 + WEdge;
Space_Old := i + 4;
Space_New := i + 4;
i := i + 4;
end
else begin
Space_Pos := Space_Old + WEdge + 1;
if Space_New >= Space_Pos then begin
Insert( #13#10 + ' ', StrL, Space_New + 5 );
Space_Pos := Space_New + WEdge + 6;
end;
end;
i := i + 3;
end
else begin
Insert( #13#10 + ' ', StrL, Space_New );
Space_Pos := Space_New + WEdge + 1;
i := i + 3;
end;
end;
end;
i := i + 1;
end;
end;
end; // while
result := TrimRight( StrL );
end; // function Rewrap_Str()
function doFootNoteNew(
var Message : TStringlist
) : Boolean; // is message ok?
var
ConstFootnoteHead : boolean;
ConstFootnoteHeadTxt : String;
ConstFootnoteHeadUnderline : String;
ConstEmptyLine : boolean;
ConstEmptyLineBeforeFootnote : Boolean;
ConstStartupFootnote : String;
ConstEndFootnote : String;
ConstReWrapEdge : Integer;
ConstMultiLine : String;
ConstRewrapToLine : String;
ConstComments : String;
i : Integer;
Posi : Integer;
Mult_Posi : Integer;
FoundLine : Integer;
FoundPosi : Integer;
OLength : Integer;
RFoundPosi : Integer;
Rest : String;
FN_Temp : String;
FN : String;
FNR : Integer;
Skip : Boolean;
Sig : Boolean;
txt2 : String;
txt3 : String;
Temp_Str : String;
Add_txt3 : Boolean;
FootnoteStr : String;
zw : Integer;
MB_OK : LongWord;
MB_IconExclamation : LongWord;
MaxInt : Integer;
begin
Init_doFootNoteNew ( ConstFootnoteHead, ConstFootnoteHeadTxt, ConstFootnoteHeadUnderline,
ConstEmptyLine, ConstEmptyLineBeforeFootnote, ConstStartupFootnote,
ConstEndFootnote, ConstReWrapEdge, ConstMultiLine, ConstRewrapToLine,
ConstComments );
result := false;
if ConstFootnoteHead then begin
if Length( ConstFootnoteHeadUnderline ) = 1 then begin
for i := 1 to Length( ConstFootnoteHeadTxt ) do begin
FootnoteStr := FootnoteStr + ConstFootnoteHeadUnderline;
end;
end
else FootnoteStr := '';
end
else FootnoteStr := '';
i := -1;
posi := -1;
foundposi := -1;
rest := '';
fn := '';
sig := false;
fnr := 0;
txt2 := '';
txt3 := '';
Mult_Posi := -1;
Add_Txt3 := false;
FN_Temp := '';
Temp_Str := '';
MB_OK := 0;
MB_IconExclamation := 48;
MaxInt := 2147483647;
while (i <= message.count-1) and (sig = false) do begin
if Rest = '' then begin
i := i + 1;
// ignore quotes and empty lines
Skip := true;
while Skip and (i <= message.count - 1) do begin
Skip := false;
if Sig then begin
txt2 := txt2 + message.strings[i] + #13#10;
i := i + 1;
Skip := true;
end
else begin
if Length( message.strings[i] ) > 0 then begin
if Copy( message.strings[i], 1, 1 ) = '>' then begin
txt2 := txt2 + message.strings[i] + #13#10;
i := i + 1;
Skip := true;
end;
if Length( message.strings[i] ) > 2 then begin
if Copy( message.strings[i], 1, 3 ) = '-- ' then begin
if Length( FN ) > 0 then begin
WriteToLog('FN: >' + FN + '<', 7);
if ConstEmptyLineBeforeFootnote = true then begin
txt2 := txt2 + #13#10 + FN;
end
else begin
txt2 := txt2 + FN;
end;
end;
Sig := true;
Skip := true;
end;
end;
end
else begin
txt2 := txt2 + message.strings[i] + #13#10;
i := i + 1;
Skip := true;
end;
end;
end;
if i > message.count-1 then break; // fix added by MM (Oct. 30th, 2003)
Rest := message.strings[i];
OLength := Length(Rest);
end;
if not Sig then begin
if FoundPosi > 0 then begin
Posi := AnsiPos( ConstEndFootNote, Rest );
if Posi > 0 then begin
Mult_Posi := AnsiPos( ConstStartupFootnote, Rest );
if (i + 1) = message.count
then Temp_Str := ''
else Temp_Str := message.strings[i + 1];
if (AnsiPos(ConstRewrapToLine, Rest) > 0)
or (Temp_Str = '')
or (Temp_Str = '-- ')
then begin
Add_Txt3 := false;
if Mult_Posi = 0 then begin
if AnsiPos( ConstRewrapToLine, Rest ) > 0
then txt3 := txt3
+ Copy( Rest, posi+Length(ConstEndFootnote),
AnsiPos(ConstRewrapToLine, Rest)+1 )
else txt3 := txt3
+ Copy( Rest, posi+Length(ConstEndFootnote), MaxInt );
end;
end
else Add_Txt3 := true;
zw := posi + olength - Length( rest );
FN_Temp := '[' + IntToStr(FNR) + '] '
+ GetText( message, FoundLine, FoundPosi, i, zw, ConstMultiLine);
FN_Temp := Rewrap_Str( FN_Temp, ConstReWrapEdge, true, ConstRewrapToLine );
if (FN = '')
and (FN_Temp <> '')
and (ConstFootnoteHead = true)
then begin
if FootnoteStr <> ''
then FN := ConstFootnoteHeadTxt + #13#10 + FootnoteStr + #13#10
else FN := ConstFootnoteHeadTxt + #13#10;
if ConstEmptyLine = true then FN := FN + #13#10;
end;
FN := FN + FN_Temp + #13#10;
// FN := FN
// + '[' + IntToStr(FNR) + '] '
// + GetText(message, FoundLine, FoundPosi, i, zw) + #13#10;
Rest := Copy( Rest,posi+Length(ConstEndFootnote), MaxInt );
If Rest = '' then Rest := ' '; //08.10.2004 !!
FoundPosi := -1;
Mult_Posi := -1;
end
else begin
Rest:='';
end;
end
else begin
// WriteToLog('R: ' + Rest, 7);
// 1. char = #, ignore this, could be a control character
if Copy( Rest + ' ', 1, Length(ConstComments) ) <> ConstComments then begin
Posi := AnsiPos(ConstStartupFootnote, Rest);
if Posi > 0 then begin
// WriteToLog('FN: ' + IntToStr(Posi), 7);
RFoundPosi := Posi + Length( ConstStartupFootnote );
FoundPosi := RFoundPosi + OLength - Length( Rest );
FoundLine := i;
FNR := FNR + 1;
// txt2 := txt2 + Copy( Rest, 1, Posi - 1 ) + '[' + IntToStr(FNR) + ']';
txt3 := txt3 + Copy( Rest, 1, Posi - 1 ) + '[' + IntToStr(FNR) + ']';
Rest := Copy( Rest, RFoundPosi, MaxInt ); // 08.10.2004 Trim entfernt
end
else begin
if FoundPosi = -1 then begin
if Add_Txt3 then txt3 := txt3 + Rest + ' ';
if (i + 1) = message.count
then Temp_Str := ''
else Temp_Str := message.strings[i + 1];
if ( (AnsiPos(ConstRewrapToLine, Rest) > 0)
or (Temp_Str = '') or (Temp_Str = '-- '))
and (txt3 <> '')
then begin
Add_Txt3 := false;
txt3 := Rewrap_Str( txt3, ConstReWrapEdge, false, ConstRewrapToLine );
txt2 := txt2 + txt3;
txt3 := '';
Rest := '';
end;
if Add_Txt3 = false then txt2 := txt2 + Rest + #13#10;
Rest := '';
end;
end;
end
else begin
txt2 := txt2 + Rest + #13#10;
Rest := '';
end;
end;
end;
end;
if txt3 = '' then begin
result := true;
if Sig = false then begin
if Length( FN ) > 0 then begin
message.text := txt2 + #13#10 + FN;
end;
end
else message.text := txt2;
end
else begin
message.text := message.text;
result := false;
MessageBox( 0, 'End-Tag ''' + ConstEndFootnote + ''' of footnote not found!',
'Abort sending!', MB_OK or MB_IconExclamation );
end;
end; // function doFootNoteNew()
René Fischer