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

on install (f) {
		<<9/17/10; 11:30:03 PM by DW
			<<If is true, install the scheduled script in user.scheduler2 and delete the links in user.scheduler (so the scripts only run once).
		<<06/24/02; 3:05:44 PM by JES
			<<If a Tool's suite has a localization sub-table, register the languages in the appropriate localization sub-table(s).
		<<06/12/02; 12:13:04 AM by JES
			<<Install callbacks in the table, if the Tool has callbacks at, and is defined.
		<<03/07/02; 12:02:37 AM by JES
			<<Call scheduler.monitorThreads after installing the Tool, to kick off its thread (if it exists).
		<<12/01/01; 6:34:14 PM by JES
			<<Fixed a bug installing Tools windowTypes in the table.
		<<11/30/01; 5:04:11 PM by JES
			<<Install windowTypes and noteTypes addresses inside a try statement, so that installation won't fail if there's already a table at the address.
		<<11/29/01; 5:12:36 PM by JES
			<<Fixed a bug installing windowTypes.
		<<11/26/01; 10:58:48 PM by JES
			<<Call callbacks at with the path to the Tool database before installing the Tool. If the callback returns false, don't install the Tool.
			<<Call callbacks at with the address of the Tool's database, after installing the Tool. The return value is ignored.
		<<10/07/01; 8:32:22 PM by JES
			<<Only create the table for this tool if it's not already defined. Create[toolName].flEnabled if not already defined.
		<<07/02/01; 2:54:03 AM by JES
			<<Install user windowTypes.
		<<05/10/01; 4:52:47 PM by JES
			<<If this is a Macintosh, make sure that .root files have the correct type/creator codes.
		<<04/28/01; 7:44:27 PM by JES
			<<Install the website framework site in a try block, because user.webserver.responders.websiteFramework may not exist.
		<<12/26/00; 5:39:46 PM by PBS
			<<Rebuild the menubar, in case the Tool has a menu referenced in user.menus.
		<<11/28/00; 12:30:13 by JES
			<<Call playlist.init before installing tools. Call the tool's upgradeToTool script if flUpgradeToTool is true.
		<<10/27/00; 2:39:32 PM by JES
			<<Make sure the icons folder exists before attempting to write icons to disk.
		<<10/18/00; 8:17:36 PM by JES
			<<Fixed a bug where a tool's icon files would not be written to disk.
		<<10/03/00; 10:33:37 PM by PBS
			<<Fix for installing callbacks -- the parameters to table.assign were switched.
		<<10/01/00; 1:16:35 AM by PBS
			<<Minor cleanups.
		<<Tuesday, September 26, 2000 at 4:50:49 PM by JES
	bundle { //run beforeInstall callbacks -- if any of the callbacks returns false, don't install the Tool
		local (adrcallbacks =;
		local (adrcallback);
		for adrcallback in adrcallbacks {
			try {
				while typeOf (adrcallback^) == addressType {
					adrcallback = adrcallback^};
				if not adrcallback^ (f) { //callback returned false -- don't install
					return (false)}}}}; //not installed (); //11/28/00 JES
	if not defined ([f]) {
		if system.environment.isMac { //05/10/2001 JES: set type/creator
			if not (file.type (f) == 'TABL') {
				file.setType (f, 'TABL');
				file.setCreator (f, 'LAND')}}; (f, true)};
	local (adrTool = @[f]);
	local (fname = file.fileFromPath (f));
	local (name = (fname));
	on getTable (itemName, adrAdrTable) {
		<<Return true if the table exists in the tool gdb and is non-empty. Return false otherwise. adrAdrTable^ gets the address of the table.
		local (adrTable = @adrTool^.[name + itemName]);
		if defined (adrTable^) { //does the item exist?
			if sizeOf (adrTable^) > 0 { //is the table non-empty?
				adrAdrTable^ = adrTable;
				return (true)}};
		return (false)};
	on installItem (adrTable, itemName, flCopy=false) {
		<<Install only if the item exists in the tool database.
		local (adrItem);
		if getTable (itemName, @adrItem) {
			if flCopy {
				table.assign (@adrTable^.[name], adrItem^)}
			else {
				table.assign (@adrTable^.[name], adrItem)}}};
	installItem (@user.webserver.responders, "Responder", true); //true to make a copy
	installItem (@user.betty.rpcHandlers, "RpcHandlers");
	installItem (@user.soap.rpcHandlers, "SoapHandlers");
	installItem (@user.scheduler.threads, "Thread");
	try { //websiteFramework responder might not be installed
		installItem (, "Website")};
	bundle { //suite
		local (adrSuite);
		if getTable ("Suite", @adrSuite) {
			bundle { //background
				local (backgroundName = name);
				local (adrBackground = @adrSuite^.background);
				if defined (adrBackground^) {
					local (adrscheduler, adrotherscheduler);
					bundle { //set adrscheduler, 9/17/10 by DW
						if {
							adrscheduler = @user.scheduler2;
							adrotherscheduler = @user.scheduler}
						else {
							adrscheduler = @user.scheduler;
							adrotherscheduler = @user.scheduler2}};
					if defined (adrBackground^.everyMinute) {
						adrscheduler^.everyMinute.[name] = @adrBackground^.everyMinute;
						if defined (adrotherscheduler^.everyMinute.[name]) {
							delete (@adrotherscheduler^.everyMinute.[name])}};
					if defined (adrBackground^.everyHour) {
						adrscheduler^.hourly.[name] = @adrBackground^.everyHour;
						if defined (adrotherscheduler^.hourly.[name]) {
							delete (@adrotherscheduler^.hourly.[name])}};
					if defined (adrBackground^.everyNight) {
						adrscheduler^.overnight.[name] = @adrBackground^.everyNight;
						if defined (adrotherscheduler^.overnight.[name]) {
							delete (@adrotherscheduler^.overnight.[name])}}}};
			bundle { //callbacks
				local (adrCallbacks = @adrSuite^.callbacks);
				on installCallbacks (adrCallbacks, adrTable) {
					if defined (adrCallbacks^) {
						local (adr);
						for adr in adrTable {
							local (callbackName = nameOf (adr^));
							if defined (adrCallbacks^.[callbackName]) {
								table.assign (@adr^.[name], @adrCallbacks^.[callbackName])}}}};
				if defined (adrCallbacks^) {
					if system.environment.isPike {
						installCallbacks (@adrCallbacks^.fileMenu,};
					if defined ( {
						installCallbacks (@adrCallbacks^.radio,};
					installCallbacks (@adrCallbacks^.user, @user.callbacks);
					installCallbacks (@adrCallbacks^.ftp, @user.html.callbacks.fileWriters.ftp)}};
			bundle { //menu
				local (adrMenu = @adrSuite^.menu);
				if defined (adrMenu^) { (adrMenu)}};
			bundle { //localization
				local (adrLoc = @adrSuite^.localization);
				if defined (adrLoc^) {
					on installLocalizations (adrLocalizations, installIn) {
						local (adrlang);
						for adrlang in adrLocalizations {
							local (langName = nameOf (adrlang^));
							if not defined (installIn^.[langName]) {
								installIn^.[langName] = adrlang}}};
					if defined ( {
						if defined (adrLoc^.radio) {
							installLocalizations (@adrLoc^.radio,}};
					if defined (mainResponder.localization.languages) {
						if defined (adrLoc^.mainResponder) {
							installLocalizations (@adrLoc^.mainResponder, @mainResponder.localization.languages)}};
					if defined (manilaData.localization.languages) {
						if defined (adrLoc^.manila) {
							installLocalizations (@adrLoc^.manila, @manilaData.localization.languages)}}}}}};
	bundle { //nodeTypes
		local (appFolder = file.folderFromPath (Frontier.getProgramPath ()));
		local (pc = file.getPathChar ());
		local (iconsFolder = appFolder + "Appearance" + pc + "Icons" + pc);
		local (platform = "windows");
		if system.environment.isMac {
			platform = "mac"};
		on writeIcon (adrIconTable) {
			local (adrIcon = @adrIconTable^.[platform]);
			if defined (adrIcon^) {
				local (iconName = nameOf (parentOf (adrIconTable^)^));
				local (fname = iconName);
				if system.environment.isWindows {
					fname = fname + ".bmp"};
				local (f = iconsFolder + fname);
				file.sureFilePath (f); //JES 10/27/00: make sure the icons folder exists
				if not (file.exists (f)) { //write only if file does not exist
					if system.environment.isWindows {
						file.writeWholeFile (f, adrIcon^)};
					if system.environment.isMac { //write to resource fork
						file.writeWholeFile (f, "", 'rsrc', 'RSED'); //type is resource, creator is ResEdit
						local (adrResource);
						for adrResource in adrIcon { //write each resource
							rez.putResource (f, getBinaryType (adrResource^), 128, adrResource)}}}}};
		local (adrNodeTypes);
		if getTable ("NodeTypes", @adrNodeTypes) {
			for adr in adrNodeTypes {
				local (adrNodeType =[nameOf (adr^)]);
				try {
					adrNodeType^ = adr};
				if defined (adr^.icon) {
					writeIcon (@adr^.icon)}}}};
	bundle { //windowTypes
		local (adrWindowTypes);
		if getTable ("WindowTypes", @adrWindowTypes) {
			for adr in adrWindowTypes {
				local (adrWindowType =[nameOf (adr^)]);
				try {
					adrWindowType^ = adr}}}};
	bundle { //set up root updates prefs
		local (adrData);
		if getTable ("Data", @adrData) {
			local (adrVirginPrefs = @adrData^.initialRootUpdatesPrefs);
			if defined (adrVirginPrefs^) {
				local (tableName = fname);
				if string.lower (tableName) endsWith ".root" {
					tableName = string.popSuffix (tableName)};
				local (adrTable = @user.rootUpdates.servers.[tableName]);
				if not defined (adrTable^) {
					new (tableType, adrTable)};
				if not defined (adrTable^.autobackup) {
					adrTable^.autobackup = true};
				if not defined (adrTable^.dbName) {
					adrTable^.dbName = fname};
				if not defined (adrTable^.dialogs) {
					adrTable^.dialogs = true};
				if not defined (adrTable^.lastUpdate) {
					if defined (adrData^.initialRootUpdatesPrefs.lastUpdate) {
						adrTable^.lastUpdate = adrVirginPrefs^.lastUpdate}
					else {
						adrTable^.lastUpdate = date (0)}};
				if not defined (adrTable^.method) {
					if defined (adrVirginPrefs^.method) {
						adrTable^.method = adrVirginPrefs^.method}
					else {
						adrTable^.method = "mainResponder.subscriptions.update"}};
				if not defined (adrTable^.openLog) {
					adrTable^.openLog = false};
				if not defined (adrTable^.port) {
					if defined (adrVirginPrefs^.port) {
						adrTable^.port = adrVirginPrefs^.port}
					else {
						adrTable^.port = 80}};
				if not defined (adrTable^.serialNum) {
					adrTable^.serialNum = 0};
				if not defined (adrTable^.server) {
					adrTable^.server = adrVirginPrefs^.server};
				if not defined (adrTable^.url) {
					if defined (adrVirginPrefs^.url) {
						adrTable^.url = adrVirginPrefs^.url}
					else {
						adrTable^.url = ""}}}}};
	bundle { //save the fact that it's an installed tool
		local (adrTable =[name]);
		if not defined (adrTable^) {
			new (tableType, adrTable)};
		adrTable^.path = f;
		local (now = ());
		adrTable^.lastModified = now;
		adrTable^.flInstalled = true;
		if not defined (adrtable^.flEnabled) {
			adrtable^.flEnabled = true}};
	bundle { //store tool info in the temp table
		local (adrtempdata =[ (name)]);
		if not defined (adrtempdata^) {
			new (tableType, adrtempdata)};
		if not defined (adrtempdata^.lastModified) {
			adrtempdata^.lastModified = file.modified (f)};
		if defined ([name + "Info"]) {
			adrtempdata^.info = [name + "Info"]};
		if defined ([name + "Website"]) {
			adrtempdata^.url = "/" + name + "/"}};
	menus.buildMenuBar (); //PBS 12/26/00: a Tool may have a menu references in user.menus
	bundle { //run afterInstall callbacks -- the return value is ignored
		local (adrcallbacks =;
		local (adrcallback);
		for adrcallback in adrcallbacks {
			try {
				while typeOf (adrcallback^) == addressType {
					adrcallback = adrcallback^};
				adrcallback^ (adrTool)}}}; //return value ignored
	scheduler.monitorThreads (); //start the Tool's thread immediately
	return (true)};
bundle { //debugging
	install ("Macintosh HD:Users:davewiner:Desktop:OPML:Guest Databases:apps:Tools:codeLister.root")}

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.