!
! bquote.h
!
! Synopsis
!
! Extension for writing block quotes, i.e. indented
! paragraphs, in Version 5 games. The effect is similar to
! the <blockquote> tag in HTML, but it always uses a fixed
! width font.
!
! Inclusion
!
! Include the file "bquote.h" at the beginning of your
! game file. For z-code, this extension is stand-alone.
!
! For Glulx, it relies on using the standard Inform
! library. Glulx compability is provided for the case that
! you decide to flip the -G switch during development. If
! you're going for Glulx from the start, you might be
! better off using the block quote style as produced by
! glk($0086, 7);
!
! How to print block quotes
!
! First, the block quote must be opened with
!
! bq_open(margin, padding, maxwidth);
!
! This will start a block quote with the specified margin
! left and right. If you specify a padding, the block
! quote is printed in a special style, usually reverse,
! with the padding from the left and right borders.
!
! Usually, the width of the quote is determined by the
! width of the screen and the margins and paddings. If you
! specify maxwidth, the width will still be adjusted to
! the screen width, but if the inner width of the box is
! greater than maxwidth, maxwidth is used.
!
! If you specify a negative maxwidth, the margin will be
! calculated so that the quote will be centered and
! -maxwidth characters wide. If the calculated margin is
! less than the specified margin, the width will be
! adjusted.
!
! For printing the text, use the routines
!
! bq_text(str, a1, a2, a3);
! bq_newline();
!
! where str may be the reference to a static string or a
! routine which can take up to three arguments a#.
!
! The output text must not contain the newline character ^
! - that's what the bq_newline() function is for - and it
! must not be longer than BQ_MAX_LENGTH characters. The
! complete text may be of any length, but it must be
! defined in chunks of less than BQ_MAX_LENGTH characters.
!
! If the text is longer, a warning is issued, which
! should tell you to either break down your text into
! smaller chunks or to define a larger value for the
! constant BQ_MAX_LENGTH (default is 512) before including
! "bqoute.h".
!
! Between two chunks of text, a space is inserted
! automatically.
!
! Finally, close your quote to return to normal printing
! by calling
!
! bq_close();
!
! Before opening and after closing a quote, a newline is
! printed. You might want to end the text before the quote
! and begin the text after it with an extra newline:
!
! description [;
! text "One section in particular catches
! your attention:^";
! bq_open(4);
! bq_text("The security system ...");
! bq_newline();
! bq_newline();
! bq_text("The password is ~Halifax~.");
! bq_close();
! "^Now that's interesting.";
! ];
!
! Examples of quote styles:
!
! Regular blockquote, four spaces left and right:
!
! bq_open(4);
!
! Reverse box across the whole screen with a padding of
! four:
!
! bq_open(0, 4);
!
! Zero margin boxes work on many interpreters, but on
! some terps they might cause extra blank lines, so better
! use a safty margin:
!
! bq_open(1, 3);
!
! Narrow box 30 spaces wide, aligned to left margin (4):
!
! bq_open(4, 1, 30);
!
! Same, but centered. The text is always left flushed:
!
! bq_open(4, 1, -30);
!
! Customization
!
! The style for quotes with a positive margin is reverse
! per default, making such block quotes inline box quotes.
!
! You can change the style of these quotes by specifying
! your own routines bq_style_on and bq_style_off, e.g. to
! use coloured blocks and a "mail quote" effect:
!
! Replace bq_style_on;
! Replace bq_style_off;
!
! [bq_style_on;
! if ((0->1) & 1 ~= 0) @set_colour 3 9;
! else style reverse;
! print">";
! ];
!
! [bq_style_off;
! if ((0->1) & 1 ~= 0) @set_colour 1 1;
! else style roman;
! ];
!
! Include "bquote";
!
! Words that run longer than a line are printed over the
! right margin. Buffering is off in bq mode, so that the
! layout is usually not very much affected. You can change
! this behaviour by defining the constant BQ_TRIM_LINES
! which causes long words to be pruned. A tilde is then
! printed and the word continues on the next line. This
! might be tidier for reverse boxes.
!
! Versions and History
!
! 18-May-2005 Version 1.0
!
! Author
!
! Martin Oehm (martin.oehm at gmx.de)
!
!---------------------------------------------------------------
System_file;
Default BQ_MAX_LENGTH 512;
Global bq_width = -1;
Global bq_margin;
Global bq_padding;
Global bq_pos;
Array bq_buffer -> BQ_MAX_LENGTH + 2;
[bq_getwidth;
#ifdef TARGET_ZCODE;
! read the z-code header byte
return 0->$21;
#ifnot;
! use the width of the status window if possible
if (gg_statuswin)
glk($0025, gg_statuswin, gg_arguments, gg_arguments + WORDSIZE);
else
glk($0025, gg_mainwin, gg_arguments, gg_arguments + WORDSIZE);
return gg_arguments-->0;
#endif;
];
[bq_open marg padd max;
if (bq_width > 0) print "[*** Waring: bq already open. ***]";
bq_width = bq_getwidth();
bq_padding = padd;
if (max < 0) {
! margins are determined by width
bq_margin = (bq_width + max)/2 - bq_padding;
if (bq_margin < marg) bq_margin = marg;
max = 0;
} else {
! width is determined by margins
bq_margin = marg;
}
bq_width = bq_width - 2*bq_margin - 2*bq_padding;
if (max && bq_width > max) bq_width = max;
font off;
bq_newline(1);
#ifdef TARGET_ZCODE;
#ifndef BQ_TRIM_LINES;
! no buffering for words that run over the right margin
@buffer_mode 0;
#endif;
#endif;
];
[bq_print a l;
if (l < 0 || l > BQ_MAX_LENGTH) "***", l, " ***";
while (l--) {
if (a->0 == 13 or 10) print "@@94";
else print (char) a->0;
a++; bq_pos++;
}
];
[bq_text s a1 a2 a3 a l ll sep;
if (bq_width < 0) "[*** Error: bq not opened! ***]";
#ifdef TARGET_ZCODE;
@output_stream 3 bq_buffer;
if (s ofclass String) s.print();
if (s ofclass Routine) s.call(a1, a2, a3);
@output_stream -3;
l = bq_buffer-->0;
a = bq_buffer + 2;
#ifnot;
l = PrintAnyToArray(bq_buffer, BQ_MAX_LENGTH, s, a1, a2, a3);
a = bq_buffer;
#endif;
if (l > BQ_MAX_LENGTH) "[*** Error: String chunk too long! ***]";
while (bq_pos + l > bq_width) {
ll = bq_width - bq_pos - 1;
while (ll > 0 && a->ll ~= ' ') ll--;
#ifdef BQ_TRIM_LINES;
if (ll <= 0 && bq_pos == 0) {
! trim overlong words
ll = bq_width - bq_pos -1;
sep = true;
}
#ifnot;
if (ll <= 0 && bq_pos == 0) {
! find next space
ll = bq_width - bq_pos;
while (ll < l && a->ll ~= ' ') ll++;
}
#endif;
if (ll > 0) {
bq_print(a, ll);
a = a + ll + 1;
l = l -ll - 1;
if (sep) {
print "@@126"; bq_pos++;
a--; l++; sep = false;
}
if (l < 0) { a = a + l; l = 0; }
}
bq_newline();
}
bq_print(a, l);
if (bq_pos < bq_width) {
print " "; bq_pos++;
}
];