Monday, November 08, 2010 at 12:05 AM.

	<<1/31/02; 6:17:06 PM by DW
		<<Manage the (new) Web Services folder. Tutorial coming soon.
	<<1/17/02; 5:31:44 PM by JES
		<<Check the text of the file to see if it's UTF-16 or UTF-8 encoded, and convert to ANSI text. Also, convert all non-breaking space characters to normal spaces, so that the script will compile.
	<<1/6/02; 5:00:26 PM by DW
		<<Instead of storing the macros at user.html.macros, store them at["#tools"]. Same effect, but stay out of user space. 
	<<1/5/02; 12:59:05 PM by DW
		<<Created. If the Macros folder doesn't exist, create it. It's a top-level sub-folder of the Radio UserLand folder. The goal is to get a bunch of compiled scripts to show up in user.html.macros so they can be called from any page in your www folder.

on manageFolder (foldername, adrtable) {
	local (folder = frontier.pathstring + foldername + file.getpathchar ());
	if not file.exists (folder) {
		file.newfolder (folder)};
	on callback (adr, f) {
		if typeof (adr^) == stringType { //convert to a script
			<<on stringToScript (s, adr) //old version, a parser
				<<local (dir = down)
				<<new (scripttype, adr)
				<<local (oldtarget = target.set (adr))
				<<bundle //do string replacements
					<<s = string.replaceall (s, "\t", "")
					<<s = string.replaceall (s, "\r\n", "\r")
				<<on insert (s, dir)
					<<if s != ""
						<<op.insert (s, dir)
					<<if sizeof (s) == 0
					<<local (ix = string.patternmatch ("\r", s), line)
					<<if ix == 0
						<<line = s
						<<s = ""
						<<line = string.trimwhitespace (string.commentdelete (string.mid (s, 1, ix - 1)))
						<<msg (line)
						<<s = string.delete (s, 1, ix)
					<<if line endswith "};" //pop the semi
						<<line = string.mid (line, 1, sizeof (line) - 1)
					<<bundle //insert the line
						<<local (s = string.mid (line, 1, sizeof (line) - 1))
						<<while s endswith "}"
							<<s = string.delete (s, sizeof (s), 1)
						<<op.insert (s, dir)
					<<if line endswith "{"
						<<dir = right
						<<while line endswith "}"
							<<op.go (left, 1)
							<<line = string.delete (line, sizeof (line), 1)
						<<dir = down
				<<op.firstsummit ()
				<<op.deleteline ()
				<<target.set (oldtarget)
			on stringToScript (s, adr) { //new version, use script.getcode
				new (scripttype, adr);
				local (oldtarget = target.set (adr));
				bundle { //convert utf-8 or utf-16 text to ansi, and replace non-breaking spaces with normal space chars
					on isUtf16 (s) {
						local (x = binary (string (s[1]) + s[2]));
						if number (x) == 0xFFFE {
							return (true)};
						if number (x) == 0xFEFF {
							return (true)};
						on checkEverySecondCharIsNull (s, ixstart) {
							local (i, ct = (sizeOf (s) / 2) - 1);
							for i = 0 to ct {
								if s[ (i * 2) + ixstart ] != 0 {
									return (false)}};
							return (true)};
						if checkEverySecondCharIsNull (s, 1) {
							return (true)};
						if checkEverySecondCharIsNull (s, 2) {
							return (true)};
						return (false)};
					if isUtf16 (s) {
						s = string.utf16ToAnsi (s)}
					else { //convert from utf-8 -- this is always safe for ansi strings because ansi is a subset of utf-8
						s = string.utf8ToAnsi (s)};
					s = string.replaceAll (s, char (160), " ")};
				op.setlinetext (s);
				target.set (oldtarget);
				script.getcode (adr, adr)};
			stringtoscript (string (adr^), adr)}};
	file.synchTableWithFolder (folder, adrtable, @callback)};
manageFolder ("Macros",["#tools"]);
manageFolder ("Web Services",;
manageFolder ("Web Services",

This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.