Footnotesupport
From 40tude Dialog Wiki
Contents |
Footnote-Support
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 Thomas 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
Of course the tags alone won't do much. You have to insert the script into the OnBeforeSendingMessage event of your scripting window.
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
Changelog
2004-10-30: += error messages if you forgot something.
2004-11-04: += leave double spaces beyond sentence delimiting punctuation marks unchanged
program OnBeforeSendingMessage;
const
ConstFootnoteHead = true;
ConstFootnoteHeadTxt = 'Footnotes:';
ConstFootnoteHeadUnderline = '=';
ConstEmptyLine = false;
ConstStartupFootnote = '#fn#';
ConstEndFootnote = '##';
ConstReWrapEdge = 73;
ConstMultiLine = '%%';
ConstRewrapToLine = '<<';
ConstComments = '//';
ConstEmptyLineBeforeFootnote = true;
// --------------------------------------------------------------- //
// ---- No user maintainable parts below this line -------------- //
// --------------------------------------------------------------- //
maxint = 2147483647;
//
// 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
//
// program Footnotes - Date: 2004/11/05
//
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
) : String; // Function by Mirko D. Walter
var
res : String;
i : Integer;
bposi : Integer;
begin
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( ConstMultiLine, 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(ConstMultiLine), 2 ) = #13#10
then res := Copy( res, 1, BPosi - 1 )
+ #13#10
+ Trim( Copy(res, BPosi + Length(ConstMultiLine), MaxInt) )
else res := Copy( res, 1, BPosi - 1 )
+ #13#10
+ #13#10
+ Trim( Copy(res, BPosi + Length(ConstMultiLine), MaxInt) );
BPosi := AnsiPos( ConstMultiLine, res );
until BPosi <= 0;
res := Trim( res );
end;
result := Trim( res );
end; // function GetText()
function Rewrap_Str(
StrL : String;
WEdge : Integer;
FootNote : Boolean
) : 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( ConstRewrapToLine, StrL ) > 0
then Delete( StrL, AnsiPos(ConstRewrapToLine, 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
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;
begin
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 := '';
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 );
FN_Temp := Rewrap_Str( FN_Temp, ConstReWrapEdge, true );
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 );
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()
//
// Our local main ;o)
//
function OnBeforeSendingMessage(
var Message : TStringlist;
const Servername : String;
const IsEmail : Boolean
) : Boolean;
begin
result := doFootNoteNew(message);
// boxquote(message);
end;
// ----------------------------------------------------------------------
begin
end.
René Fischer