Category Archives: Work

WordPress Plugin – Syntax highlighting + github code + Collapsible

WordPress plugin

“if your Plugin will be called “Fabulous Functionality”, you might call your PHP file fabfunc.php. Again, try to choose a unique name. People who install your Plugin will be putting this PHP file into the WordPress Plugin directory in their installation, wp-content/plugins/” – https://codex.wordpress.org/Writing_a_Plugin

  1. installed a new wordpress
  2. checked out wp-content/plugins/
  3. found hello.php, opened it, cloned it to ‘collapse.php’
  4. checked out installed plugins on wordpress and found collapse!
  5. activated it and it worked!

which means

hello.php
<?php
/**
 * @package Hello_Dolly
 * @version 1.6
 */
/*
Plugin Name: Hello Dolly
Plugin URI: http://wordpress.org/extend/plugins/hello-dolly/
Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.
Author: Matt Mullenweg
Version: 1.6
Author URI: http://ma.tt/
*/

function hello_dolly_get_lyric() {
	/** These are the lyrics to Hello Dolly */
	$lyrics = "Hello, Dolly
Well, hello, Dolly
It's so nice to have you back where you belong
You're lookin' swell, Dolly
I can tell, Dolly
You're still glowin', you're still crowin'
You're still goin' strong
We feel the room swayin'
While the band's playin'
One of your old favourite songs from way back when
So, take her wrap, fellas
Find her an empty lap, fellas
Dolly'll never go away again
Hello, Dolly
Well, hello, Dolly
It's so nice to have you back where you belong
You're lookin' swell, Dolly
I can tell, Dolly
You're still glowin', you're still crowin'
You're still goin' strong
We feel the room swayin'
While the band's playin'
One of your old favourite songs from way back when
Golly, gee, fellas
Find her a vacant knee, fellas
Dolly'll never go away
Dolly'll never go away
Dolly'll never go away again";

	// Here we split it into lines
	$lyrics = explode( "\n", $lyrics );

	// And then randomly choose a line
	return wptexturize( $lyrics[ mt_rand( 0, count( $lyrics ) - 1 ) ] );
}

// This just echoes the chosen line, we'll position it later
function hello_dolly() {
	$chosen = hello_dolly_get_lyric();
	echo "<p id='dolly'>$chosen</p>";
}

// Now we set that function up to execute when the admin_notices action is called
add_action( 'admin_notices', 'hello_dolly' );

// We need some CSS to position the paragraph
function dolly_css() {
	// This makes sure that the positioning is also good for right-to-left languages
	$x = is_rtl() ? 'left' : 'right';

	echo "
	<style type='text/css'>
	#dolly {
		float: $x;
		padding-$x: 15px;
		padding-top: 5px;		
		margin: 0;
		font-size: 11px;
	}
	</style>
	";
}

add_action( 'admin_head', 'dolly_css' );

?>

“add_action( ‘admin_notices’, ‘hello_dolly’ );”

admin_notices is a div on top of the dashboard and functions output goes up there!

Hooks

“For instance, before WordPress adds the title of a post to browser output, it first checks to see if any Plugin has registered a function for the “filter” hook called “the_title”. If so, the title text is passed in turn through each registered function, and the final result is what is printed. So, if your Plugin needs to add some information to the printed title, it can register a “the_title” filter function.” – https://codex.wordpress.org/Writing_a_Plugin

“You can sometimes accomplish the same goal with either an action or a filter. For example, if you want your plugin to change the text of a post, you might add an action function to publish_post (so the post is modified as it is saved to the database), or a filter function to the_content (so the post is modified as it is displayed in the browser screen).” – https://codex.wordpress.org/Plugin_API

collapse.php
<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// This just replaces the bad word with censored, we'll style it later
function collapse($content) {
    $profanities = array('badword','alsobad','...');
    $content=str_ireplace($profanities,'{censored}',$content);
    return $content;
}

// Now we set that function up to execute when the the_content filter is called
add_filter( 'the_content', 'collapse' );

// We need some CSS to position the paragraph
function collapse_css() {

	echo "
	<style type='text/css'>
	#dolly {
	}
	</style>
	";
}

add_action( 'admin_head', 'collapse_css' );

?>

Scripts

  1. wordpress plugin add script to head - http://stackoverflow.com/questions/5849057/adding-script-to-wordpress-in-head-elemen
  2. relative paths for referencing files - https://codex.wordpress.org/Function_Reference/plugins_url
collapse.php and collapse.js
<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// This just replaces the bad word with censored, we'll style it later
function collapse($content) {
    $profanities = array('badword','alsobad','...');
    $content=str_ireplace($profanities,'{censored}',$content);
    return $content;
}

// Now we set that function up to execute when the the_content filter is called
add_filter( 'the_content', 'collapse' );

// We need some CSS to position the paragraph
function collapse_css() {

	echo "
	<style type='text/css'>
	#dolly {
	}
	</style>
	";
}

add_action( 'admin_head', 'collapse_css' );

function collapse_js() {
    echo '<script type="text/javascript" src="'.plugins_url('collapse.js',__FILE__).'"></script>';
}

// Add hook for front-end <head></head>
add_action('wp_head', 'collapse_js');

?>

alert("works");

Tags

either process them on server using preg_replace and file_get_contents or on jquery using dom

Jquery

loading jquery as dependency – http://codex.wordpress.org/Function_Reference/wp_enqueue_script
ensuing script runs after page loads – http://api.jquery.com/ready/
wordpress jquery norm – http://stackoverflow.com/questions/10807200/jquery-uncaught-typeerror-property-of-object-object-window-is-not-a-funct

ajax get doest work cross domain – http://stackoverflow.com/questions/2558977/ajax-cross-domain-call

collapse.php and collapse.js
<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// This just replaces the bad word with censored, we'll style it later
function collapse($content) {
    $profanities = array('badword','alsobad','...');
    $content=str_ireplace($profanities,'{censored}',$content);
    return $content;
}

// Now we set that function up to execute when the the_content filter is called
add_filter( 'the_content', 'collapse' );

// We need some CSS to position the paragraph
function collapse_css() {

	echo "
	<style type='text/css'>
	#dolly {
	}
	</style>
	";
}

add_action( 'admin_head', 'collapse_css' );

function my_scripts_method() {
	wp_enqueue_script(
		'collapse',
		plugins_url('collapse.js',__FILE__),
		array('jquery')
	);
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
?>
jQuery(document).ready(function ($) {
  $("pre").html("working");
});

Not RegEx but Shortcode
http://codex.wordpress.org/Shortcode_API

string replace – http://php.net/manual/en/function.str-replace.php
make dictionary keys local variables – http://php.net/manual/en/function.extract.php

code with tags will be displayed wrong

collapse.php
<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// [bartag foo="foo-value"]
function github_func( $atts ) {
	extract($atts);
	$url = trim($file);
	$raw = str_replace(array("https://","/blob/"),array("https://raw.","/"),$url);
	if (strlen($raw) > 0){
		return file_get_contents($raw)."<br><a href='$url'>$name</a>";
	}
}
add_shortcode( 'github', 'github_func' );

?>

Syntax Highlighter
http://wordpress.org/extend/plugins/syntaxhighlighter/installation/

precedence of filters is mixed up, highlighter is running first and doesn’t have code by then

Html Encode
https://forums.digitalpoint.com/threads/how-to-show-html-code-on-a-web-page.36385/

convert soure code to html friendly – http://ca3.php.net/manual/en/function.htmlentities.php

collapse.php
<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// [bartag foo="foo-value"]
function github_func( $atts ) {
	extract($atts);
	$url = trim($file);
	$raw = str_replace(array("https://","/blob/"),array("https://raw.","/"),$url);
	if (strlen($raw) > 0){
		$contents = file_get_contents($raw);
		return "<pre>".htmlentities($contents,ENT_IGNORE, "UTF-8")
		."<br><a href='$url'>$name</a></pre>";
	}
}
add_shortcode( 'github', 'github_func' );

?>

Do_Shortcode()

to correct the precedence there must be a way – http://stackoverflow.com/questions/4773186/shortcodes-inside-a-shortcode-wordpress
example of do_shortcode – http://codex.wordpress.org/Shortcode_API

Collapse

jquery.collapasible – http://www.snyderplace.com/demos/collapsible.html
add styles to it (register and enque) – http://codex.wordpress.org/Function_Reference/wp_register_style

code
syntaxhighlighter.php with do_shortcode()
<?php /*

**************************************************************************

Plugin Name:  SyntaxHighlighter Evolved
Plugin URI:   http://www.viper007bond.com/wordpress-plugins/syntaxhighlighter/
Version:      3.1.3
Description:  Easily post syntax-highlighted code to your site without having to modify the code at all. Uses Alex Gorbatchev's <a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">SyntaxHighlighter</a>. <strong>TIP:</strong> Don't use the Visual editor if you don't want your code mangled. TinyMCE will "clean up" your HTML.
Author:       Viper007Bond
Author URI:   http://www.viper007bond.com/

**************************************************************************

Thanks to:

* Alex Gorbatchev for writing the Javascript-powered synatax highlighter script

* Andrew Ozz for writing the TinyMCE plugin

**************************************************************************/

class SyntaxHighlighter {
	// All of these variables are private. Filters are provided for things that can be modified.
	var $pluginver            = '3.1.3';  // Plugin version
	var $agshver              = false;    // Alex Gorbatchev's SyntaxHighlighter version (dynamically set below due to v2 vs v3)
	var $shfolder             = false;    // Controls what subfolder to load SyntaxHighlighter from (v2 or v3)
	var $settings             = array();  // Contains the user's settings
	var $defaultsettings      = array();  // Contains the default settings
	var $brushes              = array();  // Array of aliases => brushes
	var $shortcodes           = array();  // Array of shortcodes to use
	var $themes               = array();  // Array of themes
	var $usedbrushes          = array();  // Stores used brushes so we know what to output
	var $encoded              = false;    // Used to mark that a character encode took place
	var $codeformat           = false;    // If set, SyntaxHighlighter::get_code_format() will return this value
	var $content_save_pre_ran = false;    // It's possible for the "content_save_pre" filter to run multiple times, so keep track

	// Initalize the plugin by registering the hooks
	function __construct() {
		if ( ! function_exists( 'esc_html' ) )
			return;

		// Load localization domain
		load_plugin_textdomain( 'syntaxhighlighter', false, '/syntaxhighlighter/localization' );

		// Display hooks
		add_filter( 'the_content',                        array( &$this, 'parse_shortcodes' ),                              7 ); // Posts
		add_filter( 'comment_text',                       array( &$this, 'parse_shortcodes_comment' ),                      7 ); // Comments
		add_filter( 'bp_get_the_topic_post_content',      array( &$this, 'parse_shortcodes' ),                              7 ); // BuddyPress

		// Into the database
		add_filter( 'content_save_pre',                   array( &$this, 'encode_shortcode_contents_slashed_noquickedit' ), 1 ); // Posts
		add_filter( 'pre_comment_content',                array( &$this, 'encode_shortcode_contents_slashed' ),             1 ); // Comments
		add_filter( 'group_forum_post_text_before_save',  array( &$this, 'encode_shortcode_contents_slashed' ),             1 ); // BuddyPress
		add_filter( 'group_forum_topic_text_before_save', array( &$this, 'encode_shortcode_contents_slashed' ),             1 ); // BuddyPress

		// Out of the database for editing
		add_filter( 'the_editor_content',                 array( &$this, 'the_editor_content' ),                            1 ); // Posts
		add_filter( 'comment_edit_pre',                   array( &$this, 'decode_shortcode_contents' ),                     1 ); // Comments
		add_filter( 'bp_get_the_topic_text',              array( &$this, 'decode_shortcode_contents' ),                     1 ); // BuddyPress
		add_filter( 'bp_get_the_topic_post_edit_text',    array( &$this, 'decode_shortcode_contents' ),                     1 ); // BuddyPress

		// Outputting SyntaxHighlighter's JS and CSS
		add_action( 'wp_head',                            array( &$this, 'output_header_placeholder' ),                     15 );
		add_action( 'admin_head',                         array( &$this, 'output_header_placeholder' ),                     15 ); // For comments
		add_action( 'wp_footer',                          array( &$this, 'maybe_output_scripts' ),                          15 );
		add_action( 'admin_footer',                       array( &$this, 'maybe_output_scripts' ),                          15 ); // For comments

		// Admin hooks
		add_action( 'admin_init',                         array( &$this, 'register_setting' ) );
		add_action( 'admin_menu',                         array( &$this, 'register_settings_page' ) );
		add_action( 'admin_head',                         array( &$this, 'output_shortcodes_for_tinymce' ) );
		add_filter( 'mce_external_plugins',               array( &$this, 'add_tinymce_plugin' ) );
		add_filter( 'tiny_mce_version',                   array( &$this, 'break_tinymce_cache' ) );
		add_filter( 'save_post',                          array( &$this, 'mark_as_encoded' ),                               10, 2 );
		add_filter( 'plugin_action_links',                array( &$this, 'settings_link' ),                                 10, 2 );

		// Register widget hooks
		// Requires change added in WordPress 2.9
		if ( class_exists('WP_Embed') ) {
			add_filter( 'widget_text',                    array( &$this, 'widget_text_output' ),                            7, 2 );
			add_filter( 'widget_update_callback',         array( &$this, 'widget_text_save' ),                              1, 4 );
			add_filter( 'widget_form_callback',           array( &$this, 'widget_text_form' ),                              1, 2 );
		}


		// Create array of default settings (you can use the filter to modify these)
		$this->defaultsettings = (array) apply_filters( 'syntaxhighlighter_defaultsettings', array(
			'theme'          => 'default',
			'loadallbrushes' => 0,
			'shversion'      => 3,
			'title'          => '',
			'autolinks'      => 1,
			'classname'      => '',
			'collapse'       => 0,
			'firstline'      => 1,
			'gutter'         => 1,
			'htmlscript'     => 0,
			'light'          => 0,
			'padlinenumbers' => 'false',
			'smarttabs'      => 1,
			'tabsize'        => 4,
			'toolbar'        => 0,
			'wraplines'      => 1, // 2.x only
		) );

		// Create the settings array by merging the user's settings and the defaults
		$usersettings = (array) get_option('syntaxhighlighter_settings');
		$this->settings = wp_parse_args( $usersettings, $this->defaultsettings );

		// Dynamically set folder and version names for SynaxHighlighter
		if ( 2 == $this->settings['shversion'] ) {
			$this->shfolder = 'syntaxhighlighter2';
			$this->agshver  = '2.1.364';
		} else {
			$this->shfolder = 'syntaxhighlighter3';
			$this->agshver  = '3.0.83c';
		}

		// Register brush scripts
		wp_register_script( 'syntaxhighlighter-core',             plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shCore.js'),            array(),                         $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-as3',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushAS3.js'),        array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-bash',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushBash.js'),       array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-coldfusion', plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushColdFusion.js'), array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-cpp',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCpp.js'),        array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-csharp',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCSharp.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-css',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCss.js'),        array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-delphi',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushDelphi.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-diff',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushDiff.js'),       array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-erlang',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushErlang.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-groovy',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushGroovy.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-java',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJava.js'),       array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-javafx',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJavaFX.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-jscript',    plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJScript.js'),    array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-perl',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPerl.js'),       array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-php',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPhp.js'),        array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-plain',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPlain.js'),      array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-powershell', plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPowerShell.js'), array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-python',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPython.js'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-ruby',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushRuby.js'),       array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-scala',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushScala.js'),      array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-sql',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushSql.js'),        array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-vb',         plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushVb.js'),         array('syntaxhighlighter-core'), $this->agshver );
		wp_register_script( 'syntaxhighlighter-brush-xml',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushXml.js'),        array('syntaxhighlighter-core'), $this->agshver );

		// Register some popular third-party brushes
		wp_register_script( 'syntaxhighlighter-brush-clojure',    plugins_url('syntaxhighlighter/third-party-brushes/shBrushClojure.js'),          array('syntaxhighlighter-core'), '20090602'     );
		wp_register_script( 'syntaxhighlighter-brush-fsharp',     plugins_url('syntaxhighlighter/third-party-brushes/shBrushFSharp.js'),           array('syntaxhighlighter-core'), '20091003'     );
		wp_register_script( 'syntaxhighlighter-brush-latex',      plugins_url('syntaxhighlighter/third-party-brushes/shBrushLatex.js'),            array('syntaxhighlighter-core'), '20090613'     );
		wp_register_script( 'syntaxhighlighter-brush-matlabkey',  plugins_url('syntaxhighlighter/third-party-brushes/shBrushMatlabKey.js'),        array('syntaxhighlighter-core'), '20091209'     );
		wp_register_script( 'syntaxhighlighter-brush-objc',       plugins_url('syntaxhighlighter/third-party-brushes/shBrushObjC.js'),             array('syntaxhighlighter-core'), '20091207'     );
		wp_register_script( 'syntaxhighlighter-brush-r',          plugins_url('syntaxhighlighter/third-party-brushes/shBrushR.js'),                array('syntaxhighlighter-core'), '20100919'     );

		// Register theme stylesheets
		wp_register_style(  'syntaxhighlighter-core',             plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shCore.css'),            array(),                         $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-default',    plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeDefault.css'),    array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-django',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeDjango.css'),     array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-eclipse',    plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeEclipse.css'),    array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-emacs',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeEmacs.css'),      array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-fadetogrey', plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeFadeToGrey.css'), array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-midnight',   plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeMidnight.css'),   array('syntaxhighlighter-core'), $this->agshver );
		wp_register_style(  'syntaxhighlighter-theme-rdark',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/styles/shThemeRDark.css'),      array('syntaxhighlighter-core'), $this->agshver );


		// Create list of brush aliases and map them to their real brushes
		// The key is the language alias
		// The value is the script handle suffix: syntaxhighlighter-brush-ThisBitHere  (your plugin needs to register the script itself)
		$this->brushes = (array) apply_filters( 'syntaxhighlighter_brushes', array(
			'as3'           => 'as3',
			'actionscript3' => 'as3',
			'bash'          => 'bash',
			'shell'         => 'bash',
			'coldfusion'    => 'coldfusion',
			'cf'            => 'coldfusion',
			'clojure'       => 'clojure',
			'clj'           => 'clojure',
			'cpp'           => 'cpp',
			'c'             => 'cpp',
			'c-sharp'       => 'csharp',
			'csharp'        => 'csharp',
			'css'           => 'css',
			'delphi'        => 'delphi',
			'pas'           => 'delphi',
			'pascal'        => 'delphi',
			'diff'          => 'diff',
			'patch'         => 'diff',
			'erl'           => 'erlang',
			'erlang'        => 'erlang',
			'fsharp'        => 'fsharp',
			'groovy'        => 'groovy',
			'java'          => 'java',
			'jfx'           => 'javafx',
			'javafx'        => 'javafx',
			'js'            => 'jscript',
			'jscript'       => 'jscript',
			'javascript'    => 'jscript',
			'latex'         => 'latex', // Not used as a shortcode
			'tex'           => 'latex',
			'matlab'        => 'matlabkey',
			'objc'          => 'objc',
			'obj-c'         => 'objc',
			'perl'          => 'perl',
			'pl'            => 'perl',
			'php'           => 'php',
			'plain'         => 'plain',
			'text'          => 'plain',
			'ps'            => 'powershell',
			'powershell'    => 'powershell',
			'py'            => 'python',
			'python'        => 'python',
			'r'             => 'r', // Not used as a shortcode
			'splus'         => 'r',
			'rails'         => 'ruby',
			'rb'            => 'ruby',
			'ror'           => 'ruby',
			'ruby'          => 'ruby',
			'scala'         => 'scala',
			'sql'           => 'sql',
			'vb'            => 'vb',
			'vbnet'         => 'vb',
			'xml'           => 'xml',
			'xhtml'         => 'xml',
			'xslt'          => 'xml',
			'html'          => 'xml',
			'xhtml'         => 'xml',
		) );


		// Create a list of shortcodes to use. You can use the filter to add/remove ones.
		// If the language/lang parameter is left out, it's assumed the shortcode name is the language.
		// If that's invalid, then "plain" is used.
		$this->shortcodes = array( 'sourcecode', 'source', 'code' );
		$this->shortcodes = array_merge( $this->shortcodes, array_keys( $this->brushes ) );

		// Remove some shortcodes we don't want while still supporting them as language values
		unset( $this->shortcodes[array_search( 'latex', $this->shortcodes )] ); // Remove "latex" shortcode (it'll collide)
		unset( $this->shortcodes[array_search( 'r', $this->shortcodes )] ); // Remove "r" shortcode (too short)

		$this->shortcodes = (array) apply_filters( 'syntaxhighlighter_shortcodes', $this->shortcodes );


		// Register each shortcode with a placeholder callback so that strip_shortcodes() will work
		// The proper callback and such is done in SyntaxHighlighter::shortcode_hack()
		foreach ( $this->shortcodes as $shortcode )
			add_shortcode( $shortcode, '__return_true' );


		// Create list of themes and their human readable names
		// Plugins can add to this list: http://www.viper007bond.com/wordpress-plugins/syntaxhighlighter/adding-a-new-theme/
		$this->themes = (array) apply_filters( 'syntaxhighlighter_themes', array(
			'default'    => __( 'Default',      'syntaxhighlighter' ),
			'django'     => __( 'Django',       'syntaxhighlighter' ),
			'eclipse'    => __( 'Eclipse',      'syntaxhighlighter' ),
			'emacs'      => __( 'Emacs',        'syntaxhighlighter' ),
			'fadetogrey' => __( 'Fade to Grey', 'syntaxhighlighter' ),
			'midnight'   => __( 'Midnight',     'syntaxhighlighter' ),
			'rdark'      => __( 'RDark',        'syntaxhighlighter' ),
			'none'       => __( '[None]',       'syntaxhighlighter' ),
		) );

		// Other special characters that need to be encoded before going into the database (namely to work around kses)
		$this->specialchars = (array) apply_filters( 'syntaxhighlighter_specialchars', array(
			'\0' => '&#92;&#48;',
		) );
	}


	// Register the settings page
	function register_settings_page() {
		add_options_page( __( 'SyntaxHighlighter Settings', 'syntaxhighlighter' ), __( 'SyntaxHighlighter', 'syntaxhighlighter' ), 'manage_options', 'syntaxhighlighter', array( &$this, 'settings_page' ) );
	}


	// Register the plugin's setting
	function register_setting() {
		register_setting( 'syntaxhighlighter_settings', 'syntaxhighlighter_settings', array( &$this, 'validate_settings' ) );
	}


	// Add the custom TinyMCE plugin which wraps plugin shortcodes in <pre> in TinyMCE
	function add_tinymce_plugin( $plugins ) {
		$plugins['syntaxhighlighter'] = plugins_url('syntaxhighlighter/syntaxhighlighter_mce.js');
		return $plugins;
	}


	// Break the TinyMCE cache
	function break_tinymce_cache( $version ) {
		return $version . '-sh' . $this->pluginver;
	}


	// Add a "Settings" link to the plugins page
	function settings_link( $links, $file ) {
		static $this_plugin;
		
		if( empty($this_plugin) )
			$this_plugin = plugin_basename(__FILE__);

		if ( $file == $this_plugin )
			$links[] = '<a href="' . admin_url( 'options-general.php?page=syntaxhighlighter' ) . '">' . __( 'Settings', 'syntaxhighlighter' ) . '</a>';

		return $links;
	}


	// Output list of shortcode tags for the TinyMCE plugin
	function output_shortcodes_for_tinymce() {
		$shortcodes = array();

		foreach ( $this->shortcodes as $shortcode )
			$shortcodes[] = preg_quote( $shortcode );

		echo "<script type='text/javascript'>\n";
		echo "	var syntaxHLcodes = '" . implode( '|', $shortcodes ) . "';\n";
		echo "</script>\n";
	}


	// Additional CSS for the front end (to ensure themes don't screw too much with the code)
	function enforce_font_size() {
		echo '	<style type="text/css">.syntaxhighlighter { font-size: 12px !important; }</style>' . "\n";
	}


	// A filter function that runs do_shortcode() but only with this plugin's shortcodes
	function shortcode_hack( $content, $callback ) {
		global $shortcode_tags;

		// Backup current registered shortcodes and clear them all out
		$orig_shortcode_tags = $shortcode_tags;
		remove_all_shortcodes();

		// Register all of this plugin's shortcodes
		foreach ( $this->shortcodes as $shortcode )
			add_shortcode( $shortcode, $callback );

		// Do the shortcodes (only this plugins's are registered)
		$content = $this->do_shortcode_keep_escaped_tags( do_shortcode($content) );

		// Put the original shortcodes back
		$shortcode_tags = $orig_shortcode_tags;

		return $content;
	}


	// This is a clone of do_shortcode() that uses a different callback function
	// The new callback function will keep escaped tags escaped, i.e. [[foo]]
	// Up to date as of r18324 (3.2)
	function do_shortcode_keep_escaped_tags( $content ) {
		global $shortcode_tags;

		if (empty($shortcode_tags) || !is_array($shortcode_tags))
			return $content;

		$pattern = get_shortcode_regex();
		return preg_replace_callback('/'.$pattern.'/s', array( &$this, 'do_shortcode_tag_keep_escaped_tags' ), $content);
	}


	// Callback for above do_shortcode_keep_escaped_tags() function
	// It's a clone of core's do_shortcode_tag() function with a modification to the escaped shortcode return
	// Up to date as of r18324 (3.2)
	function do_shortcode_tag_keep_escaped_tags( $m ) {
		global $shortcode_tags;

		// allow [[foo]] syntax for escaping a tag
		if ( $m[1] == '[' && $m[6] == ']' ) {
			return $m[0]; // This line was modified for this plugin (no substr call)
		}

		$tag = $m[2];
		$attr = shortcode_parse_atts( $m[3] );

		if ( isset( $m[5] ) ) {
			// enclosing tag - extra parameter
			return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[5], $tag ) . $m[6];
		} else {
			// self-closing tag
			return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, NULL,  $tag ) . $m[6];
		}
	}

	// The main filter for the post contents. The regular shortcode filter can't be used as it's post-wpautop().
	function parse_shortcodes( $content ) {
		return $this->shortcode_hack( $content, array( &$this, 'shortcode_callback' ) );
	}


	// HTML entity encode the contents of shortcodes
	function encode_shortcode_contents( $content ) {
		return $this->shortcode_hack( $content, array( &$this, 'encode_shortcode_contents_callback' ) );
	}


	// HTML entity encode the contents of shortcodes. Expects slashed content.
	function encode_shortcode_contents_slashed( $content ) {
		return addslashes( $this->encode_shortcode_contents( stripslashes( $content ) ) );
	}


	// HTML entity encode the contents of shortcodes. Expects slashed content. Aborts if AJAX.
	function encode_shortcode_contents_slashed_noquickedit( $content ) {

		// In certain weird circumstances, the content gets run through "content_save_pre" twice
		// Keep track and don't allow this filter to be run twice
		// I couldn't easily figure out why this happens and didn't bother looking into it further as this works fine
		if ( true == $this->content_save_pre_ran )
			return $content;
		$this->content_save_pre_ran = true;

		// Post quick edits aren't decoded for display, so we don't need to encode them (again)
		if ( !empty($_POST) && !empty($_POST['action']) && 'inline-save' == $_POST['action'] )
			return $content;

		return $this->encode_shortcode_contents_slashed( $content );
	}


	// HTML entity decode the contents of shortcodes
	function decode_shortcode_contents( $content ) {
		return $this->shortcode_hack( $content, array( &$this, 'decode_shortcode_contents_callback' ) );
	}


	// The callback function for SyntaxHighlighter::encode_shortcode_contents()
	function encode_shortcode_contents_callback( $atts, $code = '', $tag = false ) {
		$this->encoded = true;
		$code = str_replace( array_keys($this->specialchars), array_values($this->specialchars), htmlspecialchars( $code ) );
		return '[' . $tag . $this->atts2string( $atts ) . "]{$code}[/$tag]";
	}


	// The callback function for SyntaxHighlighter::decode_shortcode_contents()
	// Shortcode attribute values need to not be quoted with TinyMCE disabled for some reason (weird bug)
	function decode_shortcode_contents_callback( $atts, $code = '', $tag = false ) {
		$quotes = ( user_can_richedit() ) ? true : false;
		$code = str_replace(  array_values($this->specialchars), array_keys($this->specialchars), htmlspecialchars_decode( $code ) );
		return '[' . $tag . $this->atts2string( $atts, $quotes ) . "]{$code}[/$tag]";
	}


	// Dynamically format the post content for the edit form
	function the_editor_content( $content ) {
		global $post;

		// New code format (stored encoded in database)
		if ( 2 == $this->get_code_format( $post ) ) {
			// If TinyMCE is disabled or the HTML tab is set to be displayed first, we need to decode the HTML
			if ( !user_can_richedit() || 'html' == wp_default_editor() )
				$content = $this->decode_shortcode_contents( $content );
		}

		// Old code format (stored raw in database)
		else {
			// If TinyMCE is enabled and is set to be displayed first, we need to encode the HTML
			if ( user_can_richedit() && 'html' != wp_default_editor() )
				$content = $this->encode_shortcode_contents( $content );
		}

		return $content;
	}


	// Run SyntaxHighlighter::encode_shortcode_contents() on the contents of the text widget
	function widget_text_save( $instance, $new_instance, $old_instance, $widgetclass ) {
		if ( 'text' == $widgetclass->id_base ) {
			// Re-save the widget settings but this time with the shortcode contents encoded
			$new_instance['text'] = $this->encode_shortcode_contents( $new_instance['text'] );
			$instance = $widgetclass->update( $new_instance, $old_instance );

			// And flag it as encoded
			$instance['syntaxhighlighter_encoded'] = true;
		}

		return $instance;
	}


	// Run SyntaxHighlighter::decode_shortcode_contents_callback() on the contents of the text widget form
	function widget_text_form( $instance, $widgetclass ) {
		if ( 'text' == $widgetclass->id_base && !empty($instance['syntaxhighlighter_encoded']) ) {
			$instance['text'] = $this->shortcode_hack( $instance['text'], array( &$this, 'decode_shortcode_contents_callback' ) );
		}

		return $instance;
	}


	// Run SyntaxHighlighter::parse_shortcodes() on the contents of a text widget
	function widget_text_output( $content, $instance = false ) {
		$this->codeformat = ( false === $instance || empty($instance['syntaxhighlighter_encoded']) ) ? 1 : 2;
		$content = $this->parse_shortcodes( $content );
		$this->codeformat = false;

		return $content;
	}


	// Run SyntaxHighlighter::parse_shortcodes() on the contents of a comment
	function parse_shortcodes_comment( $content ) {
		$this->codeformat = 2;
		$content = $this->parse_shortcodes( $content );
		$this->codeformat = false;

		return $content;
	}


	// This function determines what version of SyntaxHighlighter was used when the post was written
	// This is because the code was stored differently for different versions of SyntaxHighlighter
	function get_code_format( $post ) {
		if ( false !== $this->codeformat )
			return $this->codeformat;

		if ( empty($post) )
			$post = new stdClass();

		if ( null !== $version = apply_filters( 'syntaxhighlighter_pre_getcodeformat', null, $post ) )
			return $version;

		$version = ( empty($post->ID) || get_post_meta( $post->ID, '_syntaxhighlighter_encoded', true ) || get_post_meta( $post->ID, 'syntaxhighlighter_encoded', true ) ) ? 2 : 1;

		return apply_filters( 'syntaxhighlighter_getcodeformat', $version, $post );
	}


	// Adds a post meta saying that HTML entities are encoded (for backwards compatibility)
	function mark_as_encoded( $post_ID, $post ) {
		if ( false == $this->encoded || 'revision' == $post->post_type )
			return;

		delete_post_meta( $post_ID, 'syntaxhighlighter_encoded' ); // Previously used
		add_post_meta( $post_ID, '_syntaxhighlighter_encoded', true, true );
	}


	// Transforms an attributes array into a 'key="value"' format (i.e. reverses the process)
	function atts2string( $atts, $quotes = true ) {
		if ( empty($atts) )
			return '';

		$atts = $this->attributefix( $atts );

		// Re-map [code="php"] style tags
		if ( isset($atts[0]) ) {
			if ( empty($atts['language']) )
				$atts['language'] = $atts[0];

			unset($atts[0]);
		}

		$strings = array();
		foreach ( $atts as $key => $value )
			$strings[] = ( $quotes ) ? $key . '="' . esc_attr( $value ) . '"' : $key . '=' . esc_attr( $value );

		return ' ' . implode( ' ', $strings );
	}


	// Simple function for escaping just single quotes (the original js_escape() escapes more than we need)
	function js_escape_singlequotes( $string ) {
		return str_replace( "'", "\'", $string );
	}


	// Output an anchor in the header for the Javascript to use
	// Might as well use it to output the version to help me debug people's sites
	function output_header_placeholder() {
		echo '<meta id="syntaxhighlighteranchor" name="syntaxhighlighter-version" content="' . esc_attr( $this->pluginver ) . '" />' . "\n";
	}


	// Output any needed scripts. This is meant for the footer.
	function maybe_output_scripts() {
		global $wp_styles;

		if ( 1 == $this->settings['loadallbrushes'] )
			$this->usedbrushes = array_flip( array_values( $this->brushes ) );

		if ( empty($this->usedbrushes) )
			return;

		$scripts = array();
		foreach ( $this->usedbrushes as $brush => $unused )
			$scripts[] = 'syntaxhighlighter-brush-' . strtolower( $brush );

		wp_print_scripts( $scripts );

		// Stylesheets can't be in the footer, so inject them via Javascript
		echo "<script type='text/javascript'>\n";
		echo "	(function(){\n";
		echo "		var corecss = document.createElement('link');\n";
		echo "		var themecss = document.createElement('link');\n";

		if ( !is_a($wp_styles, 'WP_Styles') )
			$wp_styles = new WP_Styles();

		$needcore = false;
		if ( 'none' == $this->settings['theme'] ) {
			$needcore = true;
		} else {
			$theme = ( !empty($this->themes[$this->settings['theme']]) ) ? strtolower($this->settings['theme']) : $this->defaultsettings['theme'];
			$theme = 'syntaxhighlighter-theme-' . $theme;

			// See if the requested theme has been registered
			if ( !empty($wp_styles) && !empty($wp_styles->registered) && !empty($wp_styles->registered[$theme]) && !empty($wp_styles->registered[$theme]->src) ) {

				// Users can register their own stylesheet and may opt to not load the core stylesheet if they wish for some reason
				if ( is_array($wp_styles->registered[$theme]->deps) && in_array( 'syntaxhighlighter-core', $wp_styles->registered[$theme]->deps ) )
					$needcore = true;
			}

			// Otherwise use the default theme
			else {
				$theme = 'syntaxhighlighter-theme-' . $this->defaultsettings['theme'];
				$needcore = true;
			}
		}

		if ( $needcore && !empty($wp_styles) && !empty($wp_styles->registered) && !empty($wp_styles->registered['syntaxhighlighter-core']) && !empty($wp_styles->registered['syntaxhighlighter-core']->src) ) :
			$corecssurl = add_query_arg( 'ver', $this->agshver, $wp_styles->registered['syntaxhighlighter-core']->src );
			$corecssurl = apply_filters( 'syntaxhighlighter_csscoreurl', $corecssurl );
?>
		var corecssurl = "<?php echo esc_js( $corecssurl ); ?>";
		if ( corecss.setAttribute ) {
				corecss.setAttribute( "rel", "stylesheet" );
				corecss.setAttribute( "type", "text/css" );
				corecss.setAttribute( "href", corecssurl );
		} else {
				corecss.rel = "stylesheet";
				corecss.href = corecssurl;
		}
		document.getElementsByTagName("head")[0].insertBefore( corecss, document.getElementById("syntaxhighlighteranchor") );
<?php
		endif; // Endif $needcore

		if ( 'none' != $this->settings['theme'] ) : ?>
		var themecssurl = "<?php echo esc_js( apply_filters( 'syntaxhighlighter_cssthemeurl', add_query_arg( 'ver', $this->agshver, $wp_styles->registered[$theme]->src ) ) ); ?>";
		if ( themecss.setAttribute ) {
				themecss.setAttribute( "rel", "stylesheet" );
				themecss.setAttribute( "type", "text/css" );
				themecss.setAttribute( "href", themecssurl );
		} else {
				themecss.rel = "stylesheet";
				themecss.href = themecssurl;
		}
		//document.getElementById("syntaxhighlighteranchor").appendChild(themecss);
		document.getElementsByTagName("head")[0].insertBefore( themecss, document.getElementById("syntaxhighlighteranchor") );
<?php
		endif; // Endif none != theme

		echo "	})();\n";

		switch ( $this->settings['shversion'] ) {
			case 2:
				echo "	SyntaxHighlighter.config.clipboardSwf = '" . esc_js( apply_filters( 'syntaxhighlighter_clipboardurl', plugins_url('syntaxhighlighter/syntaxhighlighter2/scripts/clipboard.swf') ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.expandSource = '" . $this->js_escape_singlequotes( __( 'show source', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.viewSource = '" . $this->js_escape_singlequotes( __( 'view source', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.copyToClipboard = '" . $this->js_escape_singlequotes( __( 'copy to clipboard', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.copyToClipboardConfirmation = '" . $this->js_escape_singlequotes( __( 'The code is in your clipboard now', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.print = '" . $this->js_escape_singlequotes( __( 'print', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.help = '" . $this->js_escape_singlequotes( __( '?', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.alert = '" . $this->js_escape_singlequotes( __( 'SyntaxHighlighter\n\n', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.noBrush = '" . $this->js_escape_singlequotes( __( "Can't find brush for: ", 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.brushNotHtmlScript = '" . $this->js_escape_singlequotes( __( "Brush wasn't configured for html-script option: ", 'syntaxhighlighter' ) ) . "';\n";
				break;
			case 3:
				echo "	SyntaxHighlighter.config.strings.expandSource = '" . $this->js_escape_singlequotes( __( '+ expand source', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.help = '" . $this->js_escape_singlequotes( __( '?', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.alert = '" . $this->js_escape_singlequotes( __( 'SyntaxHighlighter\n\n', 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.noBrush = '" . $this->js_escape_singlequotes( __( "Can't find brush for: ", 'syntaxhighlighter' ) ) . "';\n";
				echo "	SyntaxHighlighter.config.strings.brushNotHtmlScript = '" . $this->js_escape_singlequotes( __( "Brush wasn't configured for html-script option: ", 'syntaxhighlighter' ) ) . "';\n";
				break;
		}

		if ( 1 != $this->settings['autolinks'] )
			echo "	SyntaxHighlighter.defaults['auto-links'] = false;\n";

		if ( !empty($this->settings['classname']) )
			echo "	SyntaxHighlighter.defaults['class-name'] = '" . $this->js_escape_singlequotes( $this->settings['classname'] ) . "';\n";

		if ( 1 == $this->settings['collapse'] )
			echo "	SyntaxHighlighter.defaults['collapse'] = true;\n";

		if ( 1 != $this->settings['firstline'] )
			echo "	SyntaxHighlighter.defaults['first-line'] = " . $this->settings['firstline'] . ";\n";

		if ( 1 != $this->settings['gutter'] )
			echo "	SyntaxHighlighter.defaults['gutter'] = false;\n";

		/*
		if ( 1 == $this->settings['htmlscript'] )
			echo "	SyntaxHighlighter.defaults['html-script'] = true;\n";
		*/

		if ( 1 == $this->settings['light'] )
			echo "	SyntaxHighlighter.defaults['light'] = true;\n";

		echo "	SyntaxHighlighter.defaults['pad-line-numbers'] = ";
		switch ( $this->settings['padlinenumbers'] ) {
			case 'true':
				echo 'true';
				break;
			case 'false';
				echo 'false';
				break;
			default;
				echo (int) $this->settings['padlinenumbers'];
		}
		echo ";\n";

		if ( 1 != $this->settings['smarttabs'] )
			echo "	SyntaxHighlighter.defaults['smart-tabs'] = false;\n";

		if ( 4 != $this->settings['tabsize'] )
			echo "	SyntaxHighlighter.defaults['tab-size'] = " . $this->settings['tabsize'] . ";\n";

		if ( 1 != $this->settings['toolbar'] )
			echo "	SyntaxHighlighter.defaults['toolbar'] = false;\n";

		// 2.x only for now
		if ( 1 != $this->settings['wraplines'] )
			echo "	SyntaxHighlighter.defaults['wrap-lines'] = false;\n";

?>	SyntaxHighlighter.all();
</script>
<?php
	}


	// No-name attribute fixing
	function attributefix( $atts = array() ) {
		if ( empty($atts[0]) )
			return $atts;

		// Quoted value
		if ( 0 !== preg_match( '#=("|\')(.*?)\1#', $atts[0], $match ) )
			$atts[0] = $match[2];

		// Unquoted value
		elseif ( '=' == substr( $atts[0], 0, 1 ) )
			$atts[0] = substr( $atts[0], 1 );

		return $atts;
	}


	// Shortcode handler for transforming the shortcodes to their final <pre>'s
	function shortcode_callback( $atts, $code = '', $tag = false ) {
		global $post;

		if ( false === $tag || empty($code) )
			return $code;

		// Avoid PHP notices
		if ( !isset($post) )
			$post = null;

		$code = apply_filters( 'syntaxhighlighter_precode', $code, $atts, $tag );

		// Error fixing for [tag="language"]
		if ( isset($atts[0]) ) {
			$atts = $this->attributefix( $atts );
			$atts['language'] = $atts[0];
			unset($atts[0]);
		}

		// Default out all of the available parameters to "false" (easy way to check if they're set or not)
		// Note this isn't the same as if the user passes the string "false" to the shortcode
		$atts = (array) apply_filters( 'syntaxhighlighter_shortcodeatts', shortcode_atts( array(
			'language'       => false,
			'lang'           => false,
			'type'           => false, // language alias
			'autolinks'      => false,
			'classname'      => false,
			'collapse'       => false,
			'firstline'      => false,
			'fontsize'       => false,
			'gutter'         => false,
			'highlight'      => false,
			'htmlscript'     => false,
			'light'          => false,
			'padlinenumbers' => false,
			'smarttabs'      => false,
			'tabsize'        => false,
			'title'          => $this->settings['title'],
			'toolbar'        => false,
			'wraplines'      => false,
		), $atts ) );

		// Check for language shortcode tag such as [php]code[/php]
		if ( isset($this->brushes[$tag]) ) {
			$lang = $tag;
		}

		// If a valid tag is not used, it must be sourcecode/source/code
		else {
			$atts = $this->attributefix( $atts );

			// Check for the "language" attribute
			if ( false !== $atts['language'] )
				$lang = $atts['language'];

			// Check for the "lang" attribute
			elseif ( false !== $atts['lang'] )
				$lang = $atts['lang'];

			// Default to plain text
			else
				$lang = 'text';

			// All language aliases are lowercase
			$lang = strtolower( $lang );

			// Validate passed attribute
			if ( !isset($this->brushes[$lang]) )
				return $code;
		}

		// Switch from the alias to the real brush name (so custom aliases can be used)
		$lang = $this->brushes[$lang];

		// Register this brush as used so it's script will be outputted
		$this->usedbrushes[$lang] = true;

		$params = array();
		$params[] = "brush: $lang;";

		// Fix bug that prevents collapse from working if the toolbar is off or light mode is on
		if ( 'true' == $atts['collapse'] || '1' === $atts['collapse'] || 1 == $this->settings['collapse'] ) {
			$atts['toolbar'] = 'true';
			$atts['light'] = 'false';
		}

		// Parameter renaming (the shortcode API doesn't like parameter names with dashes)
		$rename_map = array(
			'autolinks'      => 'auto-links',
			'classname'      => 'class-name',
			'firstline'      => 'first-line',
			'fontsize'       => 'font-size',
			'htmlscript'     => 'html-script',
			'padlinenumbers' => 'pad-line-numbers',
			'smarttabs'      => 'smart-tabs',
			'tabsize'        => 'tab-size',
			'wraplines'      => 'wrap-lines',
		);

		// Allowed configuration parameters and their type
		// Use the proper names (see above)
		$allowed_atts = (array) apply_filters( 'syntaxhighlighter_allowedatts', array(
			'auto-links'       => 'boolean',
			'class-name'       => 'other',
			'collapse'         => 'boolean',
			'first-line'       => 'integer',
			'font-size'        => 'integer',
			'gutter'           => 'boolean',
			'highlight'        => 'other',
			'html-script'      => 'boolean',
			'light'            => 'boolean',
			'pad-line-numbers' => 'other',
			'smart-tabs'       => 'boolean',
			'tab-size'         => 'integer',
			'title'            => 'other',
			'toolbar'          => 'boolean',
			'wrap-lines'       => 'boolean',
		) );

		$title = '';

		// Sanitize configuration parameters and such
		foreach ( $atts as $key => $value ) {
			$key = strtolower( $key );

			// Put back parameter names that have been renamed for shortcode use
			if ( !empty($rename_map[$key]) )
				$key = $rename_map[$key];

			// This this parameter if it's unknown, not set, or the language which was already handled
			if ( empty($allowed_atts[$key]) || false === $value || in_array( $key, array( 'language', 'lang' ) ) )
				continue;

			// Sanitize values
			switch ( $allowed_atts[$key] ) {
				case 'boolean':
					$value = strtolower( $value );
					if ( 'true' === $value || '1' === $value || 'on' == $value )
						$value = 'true';
					elseif ( 'false' === $value || '0' === $value || 'off' == $value )
						$value = 'false';
					else
						continue 2; // Invalid value, ditch parameter
					break;

				// integer
				case 'integer':
					$value = (int) $value;
					break;
			}

			// Sanitize the "classname" parameter
			if ( 'classname' == $key )
				$value = trim( preg_replace( '/[^a-zA-Z0-9 _-]/i', '', $value ) );

			// Special sanitization for "pad-line-numbers"
			if ( 'pad-line-numbers' == $key ) {
				$value = strtolower( $value );
				if ( 'true' === $value || '1' === $value )
					$value = 'true';
				elseif ( 'false' === $value || '0' === $value )
					$value = 'false';
				else
					$value = (int) $value;
			}

			// Add % sign to "font-size"
			if ( 'font-size' == $key )
				$value = $value . '%';

			// If "html-script", then include the XML brush as it's needed
			if ( 'html-script' == $key && 'true' == $value )
				$this->usedbrushes['xml'] = true;

			// Sanitize row highlights
			if ( 'highlight' == $key ) {
				if ( false === strpos( $value, ',' ) ) {
					$value = (int) $value;
				} else {
					$lines = explode( ',', $value );
					$highlights = array();

					foreach ( $lines as $line ) {
						// Line range
						if ( false !== strpos( $line, '-' ) ) {
							list( $range_start, $range_end ) = array_map( 'intval', explode( '-', $line ) );
							if ( ! $range_start || ! $range_end || $range_end <= $range_start )
								continue;

							for ( $i = $range_start; $i <= $range_end; $i++ )
								$highlights[] = $i;
						} else {
							$highlights[] = (int) $line;
						}
					}

					natsort( $highlights );

					$value = implode( ',', $highlights );
				}

				if ( empty( $value ) )
					continue;

				// Wrap highlight in [ ]
				$params[] = "$key: [$value];";
				continue;
			}

			$params[] = "$key: $value;";

			// Set the title variable if the title parameter is set (but not for feeds)
			if ( 'title' == $key && ! is_feed() )
				$title = ' title="' . esc_attr( $value ) . '"';
		}

		$code = ( false === strpos( $code, '<' ) && false === strpos( $code, '>' ) && 2 == $this->get_code_format($post) ) ? strip_tags( $code ) : htmlspecialchars( $code );

		$params[] = 'notranslate'; // For Google, see http://otto42.com/9k

		$params = apply_filters( 'syntaxhighlighter_cssclasses', $params ); // Use this to add additional CSS classes / SH parameters

		return apply_filters( 'syntaxhighlighter_htmlresult', '<pre class="' . esc_attr( implode( ' ', $params ) ) . '"' . $title . '>' . $code . '</pre>' );;
	}


	// Settings page
	function settings_page() { ?>

<script type="text/javascript">
// <![CDATA[
	jQuery(document).ready(function($) {
		// Confirm pressing of the "Reset to Defaults" button
		$("#syntaxhighlighter-defaults").click(function(){
			var areyousure = confirm("<?php echo esc_js( __( 'Are you sure you want to reset your settings to the defaults?', 'syntaxhighlighter' ) ); ?>");
			if ( true != areyousure ) return false;
		});
<?php if ( !empty( $_GET['defaults'] ) ) : ?>
		$("#message p strong").text("<?php echo esc_js( __( 'Settings reset to defaults.', 'syntaxhighlighter' ) ); ?>");
<?php endif; ?>
	});
// ]]>
</script>

<div class="wrap">
<?php if ( function_exists('screen_icon') ) screen_icon(); ?>
	<h2><?php _e( 'SyntaxHighlighter Settings', 'syntaxhighlighter' ); ?></h2>

	<form method="post" action="options.php">

	<?php settings_fields('syntaxhighlighter_settings'); ?>


	<table class="form-table">
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-shversion"><?php _e( 'Highlighter Version', 'syntaxhighlighter' ); ?></label></th>
			<td>
				<select name="syntaxhighlighter_settings[shversion]" id="syntaxhighlighter-shversion" class="postform">
<?php
					$versions = array(
						3 => __( 'Version 3.x', 'syntaxhighlighter' ),
						2 => __( 'Version 2.x', 'syntaxhighlighter' ),
					);

					foreach ( $versions as $version => $name ) {
						echo '					<option value="' . esc_attr( $version ) . '"' . selected( $this->settings['shversion'], $version, false ) . '>' . esc_html( $name ) . "&nbsp;</option>\n";
					}
?>
				</select><br />
				<?php _e( 'Version 3 allows visitors to easily highlight portions of your code with their mouse (either by dragging or double-clicking) and copy it to their clipboard. No toolbar containing a Flash-based button is required.', 'syntaxhighlighter' ); ?><br />
				<?php _e( 'Version 2 allows for line wrapping, something that version 3 does not do at this time.', 'syntaxhighlighter' ); ?>
			</td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-theme"><?php _e( 'Color Theme', 'syntaxhighlighter' ); ?></label></th>
			<td>
				<select name="syntaxhighlighter_settings[theme]" id="syntaxhighlighter-theme" class="postform">
<?php
					foreach ( $this->themes as $theme => $name ) {
						echo '					<option value="' . esc_attr( $theme ) . '"' . selected( $this->settings['theme'], $theme, false ) . '>' . esc_html( $name ) . "&nbsp;</option>\n";
					}
?>
				</select>
			</td>
		</tr>
		<tr valign="top">
			<th scope="row"><?php _e( 'Load All Brushes', 'syntaxhighlighter' ); ?></th>
			<td>
				<fieldset>
					<legend class="hidden"><?php _e( 'Load All Brushes', 'syntaxhighlighter' ); ?></legend>
					<label for="syntaxhighlighter-loadallbrushes"><input name="syntaxhighlighter_settings[loadallbrushes]" type="checkbox" id="syntaxhighlighter-loadallbrushes" value="1" <?php checked( $this->settings['loadallbrushes'], 1 ); ?> /> <?php _e( 'Always load all language files (for directly using <code>&lt;pre&gt;</code> tags rather than shortcodes)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If left unchecked (default), then language files will only be loaded when needed<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If unsure, leave this box unchecked', 'syntaxhighlighter' ); ?></label>
				</fieldset>
			</td>
		</tr>
	</table>

	<h3><?php _e( 'Defaults', 'syntaxhighlighter' ); ?></h3>

	<p><?php _e( 'All of the settings below can be configured on a per-code block basis, but you can control the defaults of all code blocks here.', 'syntaxhighlighter' ); ?></p>

	<table class="form-table">
		<tr valign="top">
			<th scope="row"><?php _e( 'Miscellaneous', 'syntaxhighlighter' ); ?></th>
			<td>
				<fieldset>
					<legend class="hidden"><?php _e( 'Miscellaneous', 'syntaxhighlighter' ); ?></legend>

					<label for="syntaxhighlighter-gutter"><input name="syntaxhighlighter_settings[gutter]" type="checkbox" id="syntaxhighlighter-gutter" value="1" <?php checked( $this->settings['gutter'], 1 ); ?> /> <?php _e( 'Display line numbers', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-toolbar"><input name="syntaxhighlighter_settings[toolbar]" type="checkbox" id="syntaxhighlighter-toolbar" value="1" <?php checked( $this->settings['toolbar'], 1 ); ?> /> <?php _e( 'Display the toolbar', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-autolinks"><input name="syntaxhighlighter_settings[autolinks]" type="checkbox" id="syntaxhighlighter-autolinks" value="1" <?php checked( $this->settings['autolinks'], 1 ); ?> /> <?php _e( 'Automatically make URLs clickable', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-collapse"><input name="syntaxhighlighter_settings[collapse]" type="checkbox" id="syntaxhighlighter-collapse" value="1" <?php checked( $this->settings['collapse'], 1 ); ?> /> <?php _e( 'Collapse code boxes', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-light"><input name="syntaxhighlighter_settings[light]" type="checkbox" id="syntaxhighlighter-light" value="1" <?php checked( $this->settings['light'], 1 ); ?> /> <?php _e( 'Use the light display mode, best for single lines of code', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-smarttabs"><input name="syntaxhighlighter_settings[smarttabs]" type="checkbox" id="syntaxhighlighter-smarttabs" value="1" <?php checked( $this->settings['smarttabs'], 1 ); ?> /> <?php _e( 'Use smart tabs allowing tabs being used for alignment', 'syntaxhighlighter' ); ?></label><br />
					<label for="syntaxhighlighter-wraplines"><input name="syntaxhighlighter_settings[wraplines]" type="checkbox" id="syntaxhighlighter-wraplines" value="1" <?php checked( $this->settings['wraplines'], 1 ); ?> /> <?php _e( 'Wrap long lines (v2.x only, disabling this will make a scrollbar show instead)', 'syntaxhighlighter' ); ?></label><br />
					<!--<label for="syntaxhighlighter-htmlscript"><input name="syntaxhighlighter_settings[htmlscript]" type="checkbox" id="syntaxhighlighter-htmlscript" value="1" <?php checked( $this->settings['htmlscript'], 1 ); ?> /> <?php _e( 'Enable &quot;HTML script&quot; mode by default (see the bottom of this page for details). Checking this box is not recommended as this mode only works with certain languages.', 'syntaxhighlighter' ); ?></label>-->
				</fieldset>
			</td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-classname"><?php _e( 'Additional CSS Class(es)', 'syntaxhighlighter' ); ?></label></th>
			<td><input name="syntaxhighlighter_settings[classname]" type="text" id="syntaxhighlighter-classname" value="<?php echo esc_attr( $this->settings['classname'] ); ?>" class="regular-text" /></td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-firstline"><?php _e( 'Starting Line Number', 'syntaxhighlighter' ); ?></label></th>
			<td><input name="syntaxhighlighter_settings[firstline]" type="text" id="syntaxhighlighter-firstline" value="<?php echo esc_attr( $this->settings['firstline'] ); ?>" class="small-text" /></td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-padlinenumbers"><?php _e( 'Line Number Padding', 'syntaxhighlighter' ); ?></label></th>
			<td>
				<select name="syntaxhighlighter_settings[padlinenumbers]" id="syntaxhighlighter-padlinenumbers" class="postform">
<?php
					$linepaddings = array(
						'false' => __( 'Off', 'syntaxhighlighter' ),
						'true'  => __( 'Automatic', 'syntaxhighlighter' ),
						1       => 1,
						2       => 2,
						3       => 3,
						4       => 4,
						5       => 5,
					);

					foreach ( $linepaddings as $value => $name ) {
						echo '					<option value="' . esc_attr( $value ) . '"' . selected( $this->settings['padlinenumbers'], $value, false ) . '>' . esc_html( $name ) . "&nbsp;</option>\n";
					}
?>
				</select>
			</td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-tabsize"><?php _e( 'Tab Size', 'syntaxhighlighter' ); ?></label></th>
			<td><input name="syntaxhighlighter_settings[tabsize]" type="text" id="syntaxhighlighter-tabsize" value="<?php echo esc_attr( $this->settings['tabsize'] ); ?>" class="small-text" /></td>
		</tr>
		<tr valign="top">
			<th scope="row"><label for="syntaxhighlighter-title"><?php _e( 'Title', 'syntaxhighlighter' ); ?></label></th>
			<td>
				<input name="syntaxhighlighter_settings[title]" type="text" id="syntaxhighlighter-title" value="<?php echo esc_attr( $this->settings['title'] ); ?>" class="regular-text" /><br />
				<?php _e( 'Some optional default text to display above each code block or as the clickable text for collapsed code blocks.', 'syntaxhighlighter' ); ?>
			</td>
		</tr>
	</table>

	<p class="submit">
<?php
		if ( function_exists( 'submit_button' ) ) {
			submit_button( null, 'primary', 'syntaxhighlighter-submit', false );
			echo ' ';
			submit_button( __( 'Reset to Defaults', 'syntaxhighlighter' ), 'primary', 'syntaxhighlighter-defaults', false );
		} else {
			echo '<input type="submit" name="syntaxhighlighter-submit" class="button-primary" value="' . __( 'Save Changes') . '" />' . "\n";
			echo '<input type="submit" name="syntaxhighlighter-defaults" id="syntaxhighlighter-defaults" class="button-primary" value="' . __( 'Reset to Defaults', 'syntaxhighlighter' ) . '" />' . "\n";
		}
?>
	</p>

	</form>

	<h3><?php _e( 'Preview', 'syntaxhighlighter' ); ?></h3>

	<p><?php _e( 'Click &quot;Save Changes&quot; to update this preview.', 'syntaxhighlighter' ); ?>

	<?php

		echo '<div';
		if ( ! empty( $GLOBALS['content_width'] ) )
			echo ' style="max-width:' . intval( $GLOBALS['content_width'] ) . 'px"';
		echo '>';

		$title = ( empty( $this->settings['title'] ) && 1 != $this->settings['collapse'] ) ? ' title="Code example: (this example was added using the title parameter)"' : '';

		// Site owners may opt to disable the short tags, i.e. [php]
		$democode = apply_filters( 'syntaxhighlighter_democode', '[sourcecode language="php" htmlscript="true" highlight="12"' . $title . ']<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>PHP Code Example</title>
</head>
<body>
	<h1>' . __( 'PHP Code Example', 'syntaxhighlighter' ) . '</h1>

	<p><?php echo \'' . __( 'Hello World!', 'syntaxhighlighter' ) . '\'; ?></p>

	<p>' . __( 'This line is highlighted.', 'syntaxhighlighter' ) . '</p>

	<div class="foobar">
' . __( '		This	is	an
		example	of	smart
		tabs.', 'syntaxhighlighter' ) . '
	</div>

	<p><a href="http://wordpress.org/">' . __( 'WordPress' ) . '</a></p>
</body>
</html>[/sourcecode]' );

		$this->codeformat = 1;
		echo $this->parse_shortcodes( $democode );
		$this->codeformat = false;

		echo '</div>';
?>

	<h3 style="margin-top:30px"><?php _e( 'Shortcode Parameters', 'syntaxhighlighter' ); ?></h3>

	<p><?php printf( __( 'These are the parameters you can pass to the shortcode and what they do. For the booleans (i.e. on/off), pass %1$s/%2$s or %3$s/%4$s.', 'syntaxhighlighter' ), '<code>true</code>', '<code>1</code>', '<code>false</code>', '<code>0</code>' ); ?></p>

	<ul class="ul-disc">
		<li><?php printf( _x( '%1$s or %2$s &#8212; The language syntax to highlight with. You can alternately just use that as the tag, such as <code>[php]code[/php]</code>. <a href="%3$s">Click here</a> for a list of valid tags (under &quot;aliases&quot;).', 'language parameter', 'syntaxhighlighter' ), '<code>lang</code>', '<code>language</code>', 'http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Toggle automatic URL linking.', 'autolinks parameter', 'syntaxhighlighter' ), '<code>autolinks</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Add an additional CSS class to the code box.', 'classname parameter', 'syntaxhighlighter' ), '<code>classname</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Toggle collapsing the code box by default, requiring a click to expand it. Good for large code posts.', 'collapse parameter', 'syntaxhighlighter' ), '<code>collapse</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; An interger specifying what number the first line should be (for the line numbering).', 'firstline parameter', 'syntaxhighlighter' ), '<code>firstline</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Toggle the left-side line numbering.', 'gutter parameter', 'syntaxhighlighter' ), '<code>gutter</code>' ); ?></li>
		<li><?php printf( _x( '%1$s &#8212; A comma-sperated list of line numbers to highlight. You can also specify a range. Example: %2$s', 'highlight parameter', 'syntaxhighlighter' ), '<code>highlight</code>', '<code>2,5-10,12</code>' ); ?></li>
		<li><?php printf( _x( "%s &#8212; Toggle highlighting any extra HTML/XML. Good for when you're mixing HTML/XML with another language, such as having PHP inside an HTML web page. The above preview has it enabled for example. This only works with certain languages.", 'htmlscript parameter', 'syntaxhighlighter' ), '<code>htmlscript</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Toggle light mode which disables the gutter and toolbar all at once.', 'light parameter', 'syntaxhighlighter' ), '<code>light</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Controls line number padding. Valid values are <code>false</code> (no padding), <code>true</code> (automatic padding), or an integer (forced padding).', 'padlinenumbers parameter', 'syntaxhighlighter' ), '<code>padlinenumbers</code>' ); ?></li>
		<li><?php printf( _x( '%1$s (v3 only) &#8212; Sets some text to show up before the code. Very useful when combined with the %2$s parameter.', 'title parameter', 'syntaxhighlighter' ), '<code>title</code>', '<code>collapse</code>' ); ?></li>
		<li><?php printf( _x( '%s &#8212; Toggle the toolbar (buttons in v2, the about question mark in v3)', 'toolbar parameter', 'syntaxhighlighter' ), '<code>toolbar</code>' ); ?></li>
		<li><?php printf( _x( '%s (v2 only) &#8212; Toggle line wrapping.', 'wraplines parameter', 'syntaxhighlighter'), '<code>wraplines</code>' ); ?></li>
	</ul>

	<p><?php _e( 'Some example shortcodes:', 'syntaxhighlighter' ); ?></p>

	<ul class="ul-disc">
		<li><code>[php]<?php _e( 'your code here', 'syntaxhighlighter' ); ?>[/php]</code></li>
		<li><code>[css autolinks=&quot;false&quot; classname=&quot;myclass&quot; collapse=&quot;false&quot; firstline=&quot;1&quot; gutter=&quot;true&quot; highlight=&quot;1-3,6,9&quot; htmlscript=&quot;false&quot; light=&quot;false&quot; padlinenumbers=&quot;false&quot; smarttabs=&quot;true&quot; tabsize=&quot;4&quot; toolbar=&quot;true&quot; title=&quot;<?php _e( 'example-filename.php', 'syntaxhighlighter' ); ?>&quot;]<?php _e( 'your code here', 'syntaxhighlighter' ); ?>[/css]</code></li>
		<li><code>[code lang=&quot;js&quot;]<?php _e( 'your code here', 'syntaxhighlighter' ); ?>[/code]</code></li>
		<li><code>[sourcecode language=&quot;plain&quot;]<?php _e( 'your code here', 'syntaxhighlighter' ); ?>[/sourcecode]</code></li>
	</ul>

<?php $this->maybe_output_scripts(); ?>

</div>

<?php
	}


	// Validate the settings sent from the settings page
	function validate_settings( $settings ) {
		if ( !empty($_POST['syntaxhighlighter-defaults']) ) {
			$settings = $this->defaultsettings;
			$_REQUEST['_wp_http_referer'] = add_query_arg( 'defaults', 'true', $_REQUEST['_wp_http_referer'] );
		} else {
			$settings['shversion']      = ( ! empty($settings['shversion']) && 2 == $settings['shversion'] ) ? 2 : 3;

			$settings['theme']          = ( ! empty($settings['theme']) && isset($this->themes[$settings['theme']]) ) ? strtolower($settings['theme']) : $this->defaultsettings['theme'];

			$settings['loadallbrushes'] = ( ! empty($settings['loadallbrushes']) ) ? 1 : 0;
			$settings['autolinks']      = ( ! empty($settings['autolinks']) )      ? 1 : 0;
			$settings['collapse']       = ( ! empty($settings['collapse']) )       ? 1 : 0;
			$settings['gutter']         = ( ! empty($settings['gutter']) )         ? 1 : 0;
			$settings['light']          = ( ! empty($settings['light']) )          ? 1 : 0;
			$settings['smarttabs']      = ( ! empty($settings['smarttabs']) )      ? 1 : 0;
			$settings['toolbar']        = ( ! empty($settings['toolbar']) )        ? 1 : 0; // May be overridden below
			$settings['wraplines']      = ( ! empty($settings['wraplines']) )      ? 1 : 0; // 2.x only for now

			// If the version changed, then force change the toolbar version setting
			if ( $settings['shversion'] != $this->settings['shversion'] ) {
				$settings['toolbar'] = ( 2 == $settings['shversion'] ) ? 1 : 0;
			}

			if ( 'true' != $settings['padlinenumbers'] && 'false' != $settings['padlinenumbers'] )
				$settings['padlinenumbers'] = (int) $settings['padlinenumbers'];

			$settings['classname']      = ( !empty($settings['classname']) )       ? preg_replace( '/[^ A-Za-z0-9_-]*/', '', $settings['classname'] ) : '';
			$settings['firstline']      = (int) ( !empty($settings['firstline']) ) ? $settings['firstline'] : $this->defaultsettings['firstline'];
			$settings['tabsize']        = (int) ( !empty($settings['tabsize']) )   ? $settings['tabsize']   : $this->defaultsettings['tabsize'];
		}

		return $settings;
	}


	// PHP4 compatibility
	function SyntaxHighlighter() {
		$this->__construct();
	}
}


// Start this plugin once all other plugins are fully loaded
add_action( 'init', 'SyntaxHighlighter', 5 );
function SyntaxHighlighter() {
	global $SyntaxHighlighter;
	$SyntaxHighlighter = new SyntaxHighlighter();
}

?>

collapse.php

<?php
/**
 * @package Collapse
 * @version 0
 */
/*
Plugin Name: Collapse
Description: Collapse
Author: Manojkumar Purushothaman
Version: 0
Author URI: http://pmontu.com/
*/

// [bartag foo="foo-value"]
function github_func( $atts ) {
	extract($atts);
	$url = trim($file);
	$raw = str_replace(array("https://","/blob/"),array("https://raw.","/"),$url);
	if (strlen($raw) > 0){
		$contents = file_get_contents($raw);
		return htmlentities($contents,ENT_IGNORE, "UTF-8");
		//."<br><a href='$url'>$name</a>";
	}
}
add_shortcode( 'github', 'github_func' );

function collapse_func( $atts, $contents ) {
	extract($atts);
	return "<a href='' class='collapsible'>$name<span></span></a>"
	."<div>"
	.do_shortcode($contents)
	."</div>";
}
add_shortcode( 'collapse', 'collapse_func' );

function my_scripts_method() {
	wp_enqueue_script(
		'collapse',
		plugins_url('collapse.js',__FILE__),
		array('jquery')
	);
	wp_enqueue_script(
		'jquery.collapsible',
		plugins_url('jquery.collapsible.js',__FILE__),
		array('jquery')
	);
	wp_register_style( 
		'collapse_css', 
		plugins_url( 'collapse.css', __FILE__ ),
		array(),
		'0',
		'all'
	);
	wp_enqueue_style( 'collapse_css');
 }
add_action('wp_enqueue_scripts', 'my_scripts_method');
?>

collapse.js

jQuery(document).ready(function ($) {
  $('.collapsible').collapsible();
});

collapse.css

.collapse-open span {
    background:url(minus.png);
    display:block;
    float:right;
    padding:10px; 
}
.collapse-close span {
    background:url(plus.png);
    display:block;
    float:right;
    padding:10px;
 }

code on github

Database Archecture for a Windows Form Application

Today problem as simple as clicking on an item from a data bound list and opening its details on a new form.

Its simple, can be achieved in multiple ways yet i choose to do it in a robust challenging fashion where i learn something.

I have previously used django’s ORM in views layer. A big difference on web is that communication involves a cycle with the client, though you can make use of the session its more like the program runs for every request. In the windows form application the program is constantly running meaning when one form communicates to another it could as well pass the db record pointer to the new form rather than doing it like the web ie passing the id field alone and retrieving all the contents.

One solution might be to directly use an ORM. Or combined w/o layers. It has been quite a while so i find myself figuring out good practice every time from scratch. Using a DA(data access layer), BL (Business logic layer), BO/E(Business objects or entities) would definitely make the code look better especially by isolating database calls to one class/layer. But the thing is, with use of a ORM/pattern will layers also be not necessary :)

layered architecture for Windows Form project

phase 1) simple

code up till now on gist

phase 2) with nhibernate

code snapshot

finally, fluent nhibernate is much better, no config files as well as supports refactoring to a better extent. the way you bind is also different with wpf. code at - parent project

git basics and branching

init new repo
git init
git add -A
git commit -m “first commit”
git remote add origin https://github.com/pmontu/asdf.git
git push -u origin master #once -u is used, upstream option is set to remote. so just pull and push can be used later without specifying remote

clone
git clone https://github.com/pmontu/asdf.git

synchronise code
git pull

making changes and pushing code
git diff #checking
git add -A
git commit -m “msg”
git push

fast forward
when origin is further than you in checkout, you cant commit. you need to pull. choose your code or pulled code and commit again. In case you are up to date, your commit will be taken. thats something like fast forward.

branching
you can use branching to revert to an old commit or do fixes, test independently and later merge with master.

reverting commit to new branch, making change, fast forword merge -
$ git checkout sha -b new3
make changes
$ git commit -am “hi again”
$ git checkout master
$ git merge new3

reverting commit, deleting commits
$ git checkout old_commit-sha -b newbranch
git branch -f master temp # force old branch to new
git checkout master
git branch -d temp
git push -f origin master # this does it

fixing
git checkout -b fix1
make changes
git commit -am “fixed”
git push origin fix1

test fix1

git checkout master
git merge fix1 # automatically commits
git branch -d fix1
git push
git push origin –delete fix1

Git-Branching-Basic-Branching-and-Merging
git-undo-reset-or-revert.html
git-rebase-vs-git-merge

C revisiting linked list

I am bored. Interview street problems have goten too complex. so let me do something easy. Revisiting C by doing a linked list program like in school 7 years back when i first learnt C.

#include&lt;stdio.h&gt;
#include&lt;string.h&gt;
#include&lt;stdlib.h&gt;

struct node{
	int data;
	struct node *next;
};

int main(int argk, char** argv){
	struct node header;
	header.next = NULL;
	printf(&quot;1.Add number to Queuen2.Print ListnQ.Quit&quot;);
	char ch[2];
	do{
		printf(&quot;nnEnter Choice:&quot;);
		scanf(&quot;%s&quot;,ch);
		if(strcmp(&quot;1&quot;,ch)==0){
			printf(&quot;enter number:&quot;);
			int num;
			scanf(&quot;%d&quot;,&amp;num);
			struct node* new = malloc(sizeof(struct node));
			new-&gt;data = num;
			new-&gt;next = header.next;
			header.next = new;
		}
		else if(strcmp(&quot;2&quot;,ch)==0){
			struct node* node = header.next;
			while(node!=NULL){
				printf(&quot;%d &quot;,node-&gt;data);
				node = node-&gt;next;
			}
		}
		else{
			printf(&quot;other&quot;);
		}
	}while(strcmp(&quot;Q&quot;,ch)!=0);
	return 0;
}

what i noticed while revisiting c was:
1.variables need declaration
2.program needs main
3.program needs header file declarations
4.printf and scanf have this format
5.scanf uses ampersand ‘&’
6.program blocks have flower brackets
7.switch and case statements exist
8.break needs to be given after every case
9.there is something called default case
10.switches cant be used on strings!
11.you can scanf a character, you need to getchar it, still doesnt work properly on a menu
12.you cant compare two strings directly, you need to use strcmp
13.its else if not elif
14.string declaration is not char[2] str but char str[2].
15.no class in c, its struct
16 no need to use ‘&’ when scaning strings
17.pointers can be used by malloc, then ->. pointers store the address only.
18.struct needs a semicolon
19.malloc needs std lib.h

it takes a hell lot of time just to write a menu functionality. linked list is simple and direct though.

Command Line Arguments and Interprocess Communication Simplified

aim to illustrate what command line arguments are to my young brother.

below is a c program which adds numbers obtained from command line arguments

#include<stdio.h>
#include<ctype.h>

int main(int argk, char** argv)
{
	int a,b;
	a = atoi(argv[1]);
	b = atoi(argv[2]);
	printf("The result is %dn",a+b);
	return 0;
}

this is how you use command line arguments

gcc file.c
./a.out 10 20
The result is 30

illustrating interprocess communication, below python program communicates with above c program

from subprocess import call
call(["./a.out", "10","20"])

executing the python program, obtaining result from the c program using command line arguments

python file2.py
The result is 30

scanned image cropping

i usually scan old photos in batches of 3 as it fits well on my scanner. this script crops them.

reinstalling pil
installing fink
cropping image using python

from PIL import Image
for i in range(1,57):
	filename = 'Scan '+str(i)
	img = Image.open(filename+".jpeg")
	width, height = img.size
	box = (0, 0, width, 295)
	area = img.crop(box)
	area.save('new/'+filename+"a.jpeg", 'jpeg')
	box = (0, 296, width, 591)
	area = img.crop(box)
	area.save('new/'+filename+"b.jpeg", 'jpeg')
	box = (0, 592, width, height)
	area = img.crop(box)
	area.save('new/'+filename+"c.jpeg", 'jpeg')
	print i

twitter user timeline api v1 without authentication

my first post from my mac, just getting a hang around shortcuts and settings. I know diving into javascript will confuse my syntax with my current favourite python. so i decided to leave behind python and django and start javascript. This twitter api venture is to do some natural language processing on user tweets to obtain some knowledge cloud/graph. details not known at the moment!

twitter api v1 statuses/user_timeline
options and brief tutorial

user tweets:

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
function searchTwitter(query) {
    $.ajax({
        url: 'https://api.twitter.com/1/statuses/user_timeline.json?'+jQuery.param(query),
        dataType: 'jsonp',
        success: function(data) {
            var tweets = $('#tweets');
            tweets.html('');
            for (res in data) {
                tweets.append('<div>' + data[res]['created_at'] + ' wrote: <p>' + data[res]['text'] + '</p></div><br />');
        }
        }
    });
}

$(document).ready(function() {
    $('#submit').click(function() {
        var params = {
            screen_name: $('#query').val(),
            count: $('#count').val()
        };
        searchTwitter(params);
    });
});
</script>
</head>
<body>
   <div style="padding: 20px;">
        <input id="query" type="text" value="pmontu2" />
        <input id="count" type="text" value="5" />
        <input id="submit" type="button" value="Search" />
    </div>
    <div id="tweets" style="padding: 20px;">
        Tweets will go here.
    </div>
</body>
</html>

search:

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
function searchTwitter(query) {
    $.ajax({
        url: 'http://search.twitter.com/search.json?' + jQuery.param(query),
        dataType: 'jsonp',
        success: function(data) {
            var tweets = $('#tweets');
            tweets.html('');
            for (res in data['results']) {
                tweets.append('<div>' + data['results'][res]['from_user'] + ' wrote: <p>' + data['results'][res]['text'] + '</p></div><br />');
        }
        }
    });
}

$(document).ready(function() {
    $('#submit').click(function() {
        var params = {
            q: $('#query').val(),
            rpp: 5
        };
        // alert(jQuery.param(params));
        searchTwitter(params);
    });
});
</script>
</head>
<body>
   <div style="padding: 20px;">
        <input id="query" type="text" value="blue angels" />
        <input id="submit" type="button" value="Search" />
    </div>
    <div id="tweets" style="padding: 20px;">
        Tweets will go here.
    </div>
</body>
</html>

New Visit and Adding Details

urls.py

    (r'^newvisit/$', newvisit),
    (r'^addcdt/$', addcdt),

forms.py

class SaveCDTForm(ModelForm):
    class Meta:
        model = CDT
        exclude = ('visit',)

views.py

@login_required
def newvisit(request):
    if "patientid" not in request.session:
        return HttpResponse("Request Expired. Please click on new visit on Patient Details page to create new Visit")
    patientid = request.session["patientid"]
    del request.session["patientid"]
    patients = Patient.objects.filter(id=patientid)
    patient=patients[0]
    visit = Visit(date=datetime.now(),patient=patient)
    visit.save()
    return render_to_response('visit/visitcreated.html',{'visit':visit})

@login_required
def addcdt(request):
    if 'q' not in request.GET:
        return HttpResponse("Invalid query. Visitid missing. Please click on edit visit from patinet details page")
    q = request.GET['q']
    if not q:
        return HttpResponse("Invalid query. Visitid missing. Please click on edit visit from patinet details page")
    if len(q) > 11 or not q.isdigit():
        return HttpResponse("Invalid query. Visitid format error. Please click on edit visit from patinet details page")    
    visits = Visit.objects.filter(id=int(q))        
    if len(visits) == 0:
        return HttpResponse("Invalid query. Please click on edit visit from patinet details page")
    visit = visits[0] 
    if visit.patient.doctor != request.user:
        return HttpResponse("You are unauthorised to view this patient. Please click on edit visit from patinet details page")
    
    if request.method == 'POST':
        form = SaveCDTForm(request.POST)
        if form.is_valid():
            new_cdt = form.save(commit=False)
            new_cdt.visit = visit
            new_cdt.save()
            return HttpResponseRedirect("/details/?q="+str(visit.patient.id))
    else:
        form = SaveCDTForm()
    return render_to_response("visit/addcdt.html", 
    {'form': form,},
    RequestContext(request))

templates/visit/visitcreated.html

{% extends "base.html" %}

{% block title %}<h1>New Visit</h1>{% endblock %}

{% block content %}
<p>New Visit Created</p>
<p><a href="/addcdt/?q={{visit.id}}">Proceed adding more details</a></p>
{% endblock %}

templates/visit/addcdt.html

{% extends "base.html" %}

{% block title %}<h1>Add Details</h1>{% endblock %}

{% block content %}
  <form action="" method="post">
      {% csrf_token %}
      {{ form.as_p }}
      <input type="submit" value="Save">
  </form>
{% endblock %}

screenshot

git

Patient Details and Model.get_FOO_display()

model get display of choice

models.py

class Patient(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
    doctor = models.ForeignKey(User)
    
    def __unicode__(self):
        return self.name

class Visit(models.Model):
    date = models.DateField()
    patient = models.ForeignKey(Patient)

class CDT(models.Model):
    CONDITION_CHOICES = (
        ('1', 'Condition 1'),
        ('2', 'Condition 2'),
        ('3', 'Condition 3'),
        ('4', 'Condition 4'),
        ('5', 'Condition 5'),
        ('6', 'Condition 6'),
        ('7', 'Condition 7'),
        ('8', 'Condition 8'),
        ('9', 'Condition 9'),
        ('10', 'Condition 10'),
    )
    condition = models.CharField(max_length=11, choices=CONDITION_CHOICES)
    DIAGNOSIS_CHOICES = (
        ('1', 'Diagnosis 1'),
        ('2', 'Diagnosis 2'),
        ('3', 'Diagnosis 3'),
        ('4', 'Diagnosis 4'),
        ('5', 'Diagnosis 5'),
        ('6', 'Diagnosis 6'),
        ('7', 'Diagnosis 7'),
        ('8', 'Diagnosis 8'),
        ('9', 'Diagnosis 9'),
        ('10', 'Diagnosis 10'),
    )
    diagnosis = models.CharField(max_length=11, choices=DIAGNOSIS_CHOICES)
    TREATMENT_CHOICES = (
        ('1', 'Treatment 1'),
        ('2', 'Treatment 2'),
        ('3', 'Treatment 3'),
        ('4', 'Treatment 4'),
        ('5', 'Treatment 5'),
        ('6', 'Treatment 6'),
        ('7', 'Treatment 7'),
        ('8', 'Treatment 8'),
        ('9', 'Treatment 9'),
        ('10', 'Treatment 10'),
    )
    treatment = models.CharField(max_length=11, choices=TREATMENT_CHOICES)
    visit = models.ForeignKey(Visit)

views.py

@login_required
def details(request):
    if 'q' in request.GET:
        q = request.GET['q']
        if not q:
            return HttpResponse("Invalid query. Search query missing. Please click on patient from patient list to open their details")
        if len(q) > 11 or not q.isdigit():
            return HttpResponse("Invalid query. Search query format error. Please click on patient from patient list to open their details")
        
        patients = Patient.objects.filter(id=int(q))
        
        if len(patients) == 0:
            return HttpResponse("Invalid query. Please click on patient from patient list to open their details")
        elif len(patients) >1:
            return HttpResponse("Error: more than one patients returned for query")
        
        patient = patients[0]        
        if patient.doctor != request.user:
            return HttpResponse("You are unauthorised to view this patient. Please click on patient from patient list to open their details")
        
        visits = Visit.objects.filter(patient=patient)
        history = []
        for visit in visits:
            cdts = CDT.objects.filter(visit=visit)
            history.append({'cdts':cdts,'date':visit.date})
        return render_to_response('patient/details.html',locals())
    else:
        return HttpResponse("Invalid query. Search query missing. Please click on patient from patient list to open their details")

urls.py

(r'^details/$', details),

templates/patient/details.html

{% extends "base.html" %}

{% block title %}<h1>{{patient.name}}</h1>{% endblock %}

{% block content %}
<p>age:{{patient.age}}</p>
<p>gender:{{patient.get_gender_display}}</p>

<table>
    {% for set in history %}
        <th><td colspan=3>{{set.date}}</td></th>
        {% for cdt in set.cdts %}
            <tr><td>{{cdt.get_condition_display}}</td><td>{{cdt.get_diagnosis_display}}</td><td>{{cdt.get_treatment_display}}</td></tr>
        {% endfor %}
    {% endfor %}
</table>
{% endblock %}

screenshot

test data

>>> from patientrecords.models import Patient
>>> from patientrecords.models import Visit
>>> from patientrecords.models import CDT
>>> from django.contrib.auth.models import User
>>> u = User.objects.filter(id=1)
>>> p = Patient.objects.filter(doctor=u)[0]
>>> v = Visit(date=datetime.datetime.now(),patient=p)
>>> v.save()
>>> cdt = CDT(condition="1",diagnosis="5",treatment="10",visit=v)
>>> cdt.save()
>>> cdt = CDT(condition="10",diagnosis="2",treatment="3",visit=v)
>>> cdt.save()
>>> cdt = CDT(condition="3",diagnosis="4",treatment="5",visit=v)
>>> cdt.save()
>>> v = Visit(date=datetime.datetime.now(),patient=p)
>>> v.save()
>>> cdt = CDT(condition="1",diagnosis="2",treatment="10",visit=v)
>>> cdt.save()
>>> cdt = CDT(condition="7",diagnosis="8",treatment="5",visit=v)
>>> cdt.save()