#charset "us-ascii"
/*
** cquotes: a TADS 3 output filter for making single curly quotes
**
** To use, just add to your project. The PreinitObject at the end
** of this file automatically registers the curly quote output filter.
**
** You may use this module in your own game. You may distribute
** modified versions of this file, though I would prefer you contact
** me first at stephen@granades.com and see about having me add your
** changes to my source.
**
** Version: 0.2 (2 Feb 2004)
** Added in fixes for patIsHTMLTag and patIsFormatTag from
** Matt McGlone
** 0.1 (27 Aug 2002)
** Original release
**
** Copyright (c) 2002, 2004 by Stephen Granade. All Rights Reserved.
*/
#include <tadsgen.h>
#include <systype.h>
// A filter to change single quotes "'" to curly ones. Comes in two
// flavors:
//
// non-aggressive: will only change the single quotes that are part
// of English contractions (like "won't") into ‘
// aggressive: will change every single left quote it can find. Any
// single quote that is preceeded by a letter or punctuation is
// turned into ‘.
//
// To choose between them, set cquoteOutputFilter.aggressive to
// true (for aggressive changing) or nil (for non-aggressive matching).
//
// No translation is done to single quotes which a) fall within HTML
// tags (i.e. <font face='courier'>), or b) fall within
// formatting tags (i.e. {It's obj})
cquoteOutputFilter: OutputFilter
aggressive = nil
// Patterns for our searches
patIsHTMLTag = static new RexPattern('<langle><^rangle>+<squote><^rangle>*<rangle>')
patIsFormatTag = static new RexPattern('{[^}]+<squote>[^}]*}')
patAggressive = static new RexPattern('(<alphanum|punct>)<squote>')
patIsCont1Tag = static new RexPattern('(<alpha>)<squote>(s|m|d|ve|re|ll)')
patIsCont2Tag = static new RexPattern('(<alpha>)n<squote>t')
patIsPossTag = static new RexPattern('(<alpha>)s<squote>')
filterText(ostr, val) {
local ret;
// Look for an HTML tag. We only need to find the first one,
// because we'll be recursing through the string
ret = rexSearch(patIsHTMLTag, val);
if (ret == nil) {
// Look for a formatting tag
ret = rexSearch(patIsFormatTag, val);
}
// If we got a match either from the HTML or the formatting
// tag, ignore that match recursively; that is, run the output
// filter on the text before and after the match. This is
// assuming that the whole start wasn't prefixed by a backslash
// (since e.g. "\<font face='courier>" isn't really an HTML tag)
if (ret != nil && (ret[1] == 1 ||
val.substr(ret[1] - 1, 1) != '\\')) {
return filterText(ostr, val.substr(1, ret[1] - 1)) + ret[3] +
filterText(ostr, val.substr(ret[1] + ret[2],
val.length() - (ret[1]+ret[2])
+ 1));
}
// Do the appropriate replacements. First, aggressive
if (aggressive) {
val = rexReplace(patAggressive, val, '%1’',
ReplaceAll);
}
else {
// We recognize the contractions 's, 'm, 'd, 've, 're,
// 'll, and n't, as well as the plural possessive s'.
// (Possessive 's is handled by the contraction.) All
// must be preceeded by a letter.
val = rexReplace(patIsCont1Tag,
val, '%1’%2', ReplaceAll);
val = rexReplace(patIsCont2Tag, val, '%1n’t',
ReplaceAll);
val = rexReplace(patIsPossTag, val, '%1s’',
ReplaceAll);
}
return val;
}
;
// When we first start up, register us as an output filter
PreinitObject
execute() {
mainOutputStream.addOutputFilter(cquoteOutputFilter);
}
;
TADS 3 Library Manual
Generated on 1/21/2007 from TADS version 3.0.13