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

on open (f, adr=nil, flHidden=false, adrButtonTable=nil, windowTitle=nil) {
		<<7/2/05; 11:43:21 AM by DW
			<<Comment window.update call, avoid unnecessary flash.
		<<6/13/05; 3:19:06 AM by DW
			<<Add optional title that allows the caller to set the window title.
		<<6/10/05; 12:55:40 PM by DW
			<<Add optional parameter that allows a button bar to be provided.
		<<5/24/02; 4:52:44 PM by JES
			<<When preserving comments at the top of the file, don't save the "OPML generated by" comment. Prevents it from being added again when the file is saved.
		<<10/11/01; 3:04:49 AM by JES
			<<If the file is already opened, bring its window to the front, instead of opening a new window.
		<<8/9/01; 1:15:13 AM by JES
			<<Replace line ending characters with CR's. Prevents UNIX (MacOS X) files from opening on a single outline headline.
	bundle { //if the window is already open, bring it to the front
		local (t); new (tableType, @t);
		local (adrtype = parentOf (this^));
		t.type = "outlinerFile";
		t.f = f;
		local (adrwindow);
		if (@t, @adrwindow) {
			local (title, flReadOnly = false);
			window.attributes.getOne ("title", @title, adrwindow);
			window.attributes.getOne ("flReadOnly", @flReadOnly, adrwindow);
			if not flHidden {
				edit (adrwindow, title, flReadOnly, adrButtonTable);
				return (true)}}};
	local (outlinerSuffixes = {"xml", "opml", "txt", "html", "htm", "py"});
	on isOutlinerFile () {
		if string.lower (file.type (f)) == "opml" { //PBS 09/26/00: might be lower on Windows, upper on Macs
			return (true)};
		local (lowerSuffix = string.lower (string.nthField (f, ".", string.countFields (f, "."))));
		if outlinerSuffixes contains lowerSuffix {
			return (true)};
		if system.environment.isMac { //all text files on Macs
			if file.type (f) == 'TEXT' {
				local (objectSuffixes = {"fat", "2clk", "card", "fatp", "ftds", "ftmb", "ftop", "ftsc", "fttb", "ftwp", "osas", "osax", "rsrc", "stak", "ucmd"});
				if not (objectSuffixes contains lowerSuffix) {
					return (true)}}};
		return (false)};
	on isOPML (s) { //is this an OPML file?
		if string.lower (f) endsWith ".opml" and s == "" { //05/15/2001 JES: empty files are empty OPML documents, if the extension is .opml
			return (true)};
		s = string.replaceAll (s, "\r\n", "\r");
		s = string.replaceAll (s, "\n", "\r"); //support unix text files
		s = string.trimWhiteSpace (s); //05/15/2001 JES
		if s beginsWith "<?xml " {
			local (startByte = sizeOf (s) - 200);
			if startByte < 1 {
				startByte = 1};
			local (last200bytes = string.mid (s, startByte, infinity));
			last200bytes = string.lower (string.trimWhiteSpace (last200bytes));
			if last200bytes endsWith "</outlinedocument>" {
				return (true)};
			if last200bytes endsWith "</opml>" {
				return (true)}};
		if s beginsWith "<opml " or s beginsWith "<outlineDocument " {
			return (true)};
		return (false)};
	if isOutlinerFile () { //we get to handle it
		if adr == nil { //it's a new window -- get one
			adr = ("outlinerFile", true)};
		local (title = file.fileFromPath (f));
		if windowTitle != nil { //6/13/05; 3:20:47 AM by DW
			title = windowTitle};
		local (timeCreated = file.created (f));
		local (timeModified = file.modified (f));
		local (s = file.readWholeFile (f));
		bundle { //set attributes
			local (t); new (tableType, @t);
			t.f = f;
			t.timeCreated = timeCreated;
			t.lastSaved = timeModified;
			t.title = title;
			if system.environment.isMac { //remember the type and creator
				t.fileType = file.type (f);
				t.fileCreator = file.creator (f)};
			bundle { //determine line-ending, convert text
				local (ix = 1);
				while ix < sizeOf (s) { //find the first line ending and determine whether it's Windows, Mac, or UNIX
					case s[ix] {
						'\n' {
							t.lineEnding = "\n";
						'\r' {
							if s[ix+1] == '\n' {
								t.lineEnding = "\r\n"}
							else {
								t.lineEnding = "\r"};
				if defined (t.lineEnding) {
					s = string.replaceAll (s, t.lineEnding, "\r")}};
			window.attributes.addGroup (@t, adr)};
		if isOPML (s) {
			if system.environment.isMac { //12/31/00 JES: convert to Mac text.
				s = string.latinToMac (s)};
			s = string.replaceAll (s, "\r\n", "\r");
			s = string.replaceAll (s, "\n", "\r"); //support unix text files
			bundle { //01/23/01 JES: support style sheet declarations
				local (xmlHeaders = "");
				for i = 2 to 100 { // allow for up to 99 lines between <xml> and <outlineDocument>
					local (aLine = string.nthField (s, "\r", i));
					local (lowerLine = string.trimWhiteSpace (string.lower (aLine)));
					if lowerLine beginsWith "<opml " {
					if lowerLine beginsWith "<outlinedocument " {
					if string.trimWhiteSpace (aLine) != "" { //05/15/2001 JES: don't add lines which are plain whitespace
						if not (string.lower (string.trimWhiteSpace (aLine)) beginsWith "<!-- opml generated by ") { //05/24/02 JES: skip "generated by" comments so they don't get doubled-up by op.outlineToXml
							xmlHeaders = xmlHeaders + aLine + "\r"}}};
				if sizeOf (string.trimWhiteSpace (xmlHeaders)) > 0 { //05/24/02 JES: only add headers if they actually exist
					window.attributes.setOne ("xmlHeaders", xmlHeaders, adr)}};
			if not (string.trimWhiteSpace (s) == "") { //don't error on empty files -- treat as empty outlines
				op.xmlToOutline (s, adr)};
			window.attributes.setOne ("flOutlineDocument", true, adr)}
		else { //open in outliner as raw XML
			op.newOutlineObject (s, adr);
			local (oldTarget = target.set (adr));
			op.firstSummit ();
			op.fullExpand ();
			try {target.set (oldTarget)};
			window.attributes.setOne ("flOutlineDocument", false, adr)};
		if not flHidden {
			edit (adr, adrButtonTable:adrButtonTable)};
		window.setTitle (adr, title);
		<<window.update (adr) //commented -- 7/2/05; 11:43:13 AM by DW
		setTimeCreated (adr, timeCreated); //03/05/2001 JES: preserve timeCreated for the OPML header
		setTimeModified (adr, timeModified); //03/05/2001 JES: preserve timeCreated for the OPML header
		return (true)};
	return (false)} //we didn't handle the file

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.