More unitialized variable cleanup && 'pure' register_globals cleanup...
[lhc/web/wiklou.git] / includes / Skin.php
index e5638f7..36752f5 100644 (file)
@@ -1,4 +1,4 @@
-<?
+<?php
 # See skin.doc
 
 # These are the INTERNAL names, which get mapped
@@ -9,41 +9,51 @@
        "Standard", "Nostalgia", "CologneBlue" #, "Smarty", "Montparnasse"
 );
 
+include_once( "RecentChange.php" );
+
 # For some odd PHP bug, this function can't be part of a class
 function getCategories ()
 {
-  global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser ;
+  global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser , $wgParser ;
   if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return "" ;
-  if ( count ( $wgOut->mCategoryLinks ) == 0 ) return "" ;
+  if ( count ( $wgParser->mCategoryLinks ) == 0 ) return "" ;
   if ( !$wgOut->isArticle() ) return "" ;
   $sk = $wgUser->getSkin() ;
   $s = "" ;
   $s .=  "\n<br>\n";
   $s .= $sk->makeKnownLink ( "Special:Categories" , "Categories" , "article=".$wgTitle->getDBkey() ) ;
-  $t = implode ( " | " , $wgOut->mCategoryLinks ) ;
+  $t = implode ( " | " , $wgParser->mCategoryLinks ) ;
   if ( $t != "" ) $s .= " : " ;
   $s .= $t ;
   return $s ;
 }
 
+class RCCacheEntry extends RecentChange
+{
+       var $secureName, $link;
+       var $curlink , $lastlink , $usertalklink , $versionlink ;
+       var $userlink, $timestamp, $watched;
 
-class RecentChangesClass {
-       var $secureName , $displayName , $link , $namespace ;
-       var $oldid , $diffid , $timestamp , $curlink , $lastlink , $usertalklink , $versionlink ;
-       var $usercomment , $userlink ;
-       var $isminor , $isnew , $watched , $islog ;
-       } ;
+       function newFromParent( $rc )
+       {
+               $rc2 = new RCCacheEntry;
+               $rc2->mAttribs = $rc->mAttribs;
+               $rc2->mExtra = $rc->mExtra;
+               return $rc2;
+       }
+} ;
 
 class Skin {
 
        /* private */ var $lastdate, $lastline;
-
+       var $linktrail ; # linktrail regexp
        var $rc_cache ; # Cache for Enhanced Recent Changes
-       var $rccc ; # Recent Changes Cache Counter for visibility toggle
-
+       var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
+       var $rcMoveIndex;
 
        function Skin()
        {
+               $this->linktrail = wfMsg("linktrail");
        }
 
        function getSkinNames()
@@ -61,22 +71,20 @@ class Skin {
        {
                global $wgOut, $wgUser;
 
-               if ( $wgOut->isQuickbarSupressed() ) { return 0; }
+               if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
                $q = $wgUser->getOption( "quickbar" );
                if ( "" == $q ) { $q = 0; }
                return $q;
        }
 
-       function initPage()
+       function initPage( &$out )
        {
-               global $wgOut, $wgStyleSheetPath;
+               global $wgStyleSheetPath;
                $fname = "Skin::initPage";
                wfProfileIn( $fname );
-
-               $wgOut->addLink( "shortcut icon", "", "/favicon.ico" );
-               if ( $wgOut->isPrintable() ) { $ss = "wikiprintable.css"; }
-               else { $ss = $this->getStylesheet(); }
-               $wgOut->addLink( "stylesheet", "", "{$wgStyleSheetPath}/{$ss}" );
+               
+               $out->addLink( "shortcut icon", "", "/favicon.ico" );
+               
                wfProfileOut( $fname );
        }
        
@@ -84,7 +92,7 @@ class Skin {
                global $wgDebugComments;
                
                wfProfileIn( "Skin::outputPage" );
-               $this->initPage();
+               $this->initPage( $out );
                $out->out( $out->headElement() );
 
                $out->out( "\n<body" );
@@ -117,8 +125,17 @@ class Skin {
 
        function getUserStyles()
        {
+               global $wgOut, $wgStyleSheetPath;
+               if( $wgOut->isPrintable() ) {
+                       $sheet = "wikiprintable.css";
+               } else {
+                       $sheet = $this->getStylesheet();
+               }
                $s = "<style type='text/css'><!--\n";
+               $s .= "@import url(\"$wgStyleSheetPath/$sheet\");\n";
+               $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
                $s .= $this->doGetUserStyles();
+               $s .= "/* */\n";
                $s .= "//--></style>\n";
                return $s;
        }
@@ -158,14 +175,13 @@ class Skin {
                        (!$wgTitle->isProtected() || $wgUser->isSysop())
                        
                        ) {
-                       $n = $wgTitle->getPrefixedURL();
                        $t = wfMsg( "editthispage" );
                        $oid = $red = "";
                        if ( $redirect ) { $red = "&redirect={$redirect}"; }
                        if ( $oldid && ! isset( $diff ) ) {
                                $oid = "&oldid={$oldid}";
                        }
-                       $s = wfLocalUrlE($n,"action=edit{$oid}{$red}");
+                       $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
                        $s = "document.location = \"" .$s ."\";";
                        $a += array ("ondblclick" => $s);
 
@@ -332,7 +348,7 @@ class Skin {
        function afterContent()
        {
                global $wgUser, $wgOut, $wgServer;
-               global $wgTitle;
+               global $wgTitle, $wgLang;
                
                if ( $wgOut->isPrintable() ) {
                        $s = "\n</div>\n";
@@ -346,7 +362,7 @@ class Skin {
                        } else { $lm = ""; }
 
                        $cr = wfMsg( "gnunote" );
-                       $s .= "<p><em>{$rf}{$lm} {$cr}</em>\n";
+                       $s .= "<p>" . $wgLang->emphasize("{$rf}{$lm} {$cr}\n");
                        return $s;
                }
                return $this->doAfterContent();
@@ -407,7 +423,7 @@ class Skin {
                $s = $this->printableLink();
                if ( wfMsg ( "disclaimers" ) != "-" ) $s .= " | " . $this->makeKnownLink( wfMsg( "disclaimerpage" ), wfMsg( "disclaimers" ) ) ;
 
-               if ( $wgOut->isArticle() ) {
+               if ( $wgOut->isArticleRelated() ) {
                        if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
                                $name = $wgTitle->getDBkey();
                                $link = wfEscapeHTML( wfImageUrl( $name ) );
@@ -423,33 +439,34 @@ class Skin {
                                #wfEscapeHTML( wfImageUrl( $name ) );
                                $style = $this->getExternalLinkAttributes( $link, $name );
                                $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
-                       }               }
-                       if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
-                               $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
-                                               wfMsg( "currentrev" ) );
-                       }
+                       }               
+               }
+               if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
+                       $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
+                                       wfMsg( "currentrev" ) );
+               }
 
-                       if ( $wgUser->getNewtalk() ) {
-                       # do not show "You have new messages" text when we are viewing our 
-                       # own talk page 
-
-                               if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
-                                                       $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
-                                       $n =$wgUser->getName();
-                                       $tl = $this->makeKnownLink( $wgLang->getNsText(
-                                                               Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
-                                                       wfMsg("newmessageslink") );
-                                       $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
-                               }
-                       }
-                       if( $wgUser->isSysop() &&
-                                       (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
-                                       ($n = $wgTitle->isDeleted() ) ) {
-                               $s .= " | " . wfMsg( "thisisdeleted",
-                                               $this->makeKnownLink(
-                                                       $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
-                                                       wfMsg( "restorelink", $n ) ) );
+               if ( $wgUser->getNewtalk() ) {
+               # do not show "You have new messages" text when we are viewing our 
+               # own talk page 
+
+                       if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
+                                               $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
+                               $n =$wgUser->getName();
+                               $tl = $this->makeKnownLink( $wgLang->getNsText(
+                                                       Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
+                                               wfMsg("newmessageslink") );
+                               $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
                        }
+               }
+               if( $wgUser->isSysop() &&
+                               (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
+                               ($n = $wgTitle->isDeleted() ) ) {
+                       $s .= " | " . wfMsg( "thisisdeleted",
+                                       $this->makeKnownLink(
+                                               $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
+                                               wfMsg( "restorelink", $n ) ) );
+               }
                return $s;
        }
 
@@ -518,15 +535,15 @@ class Skin {
 
        function nameAndLogin()
        {
-               global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader;
+               global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
 
                $li = $wgLang->specialPage( "Userlogin" );
                $lo = $wgLang->specialPage( "Userlogout" );
 
                $s = "";
                if ( 0 == $wgUser->getID() ) {
-                       if( $wgShowIPinHeader ) {
-                               $n = getenv( "REMOTE_ADDR" );
+                       if( $wgShowIPinHeader && isset(  $_COOKIE[ini_get("session.name")] ) ) {
+                               $n = $wgIP;
 
                                $tl = $this->makeKnownLink( $wgLang->getNsText(
                                  Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
@@ -569,12 +586,12 @@ class Skin {
        {
                global $search;
 
-               $s = "<form name='search' class='inline' method=get action=\""
+               $s = "<form name='search' class='inline' method=post action=\""
                  . wfLocalUrl( "" ) . "\">"
                  . "<input type=text name=\"search\" size=19 value=\""
                  . htmlspecialchars(substr($search,0,256)) . "\">\n"
                  . "<input type=submit name=\"go\" value=\"" . wfMsg ("go") . "\">&nbsp;"
-                 . "<input type=submit value=\"" . wfMsg ("search") . "\"></form>";
+                 . "<input type=submit name=\"fulltext\" value=\"" . wfMsg ("search") . "\"></form>";
 
                return $s;
        }
@@ -587,7 +604,7 @@ class Skin {
                $s = $this->mainPageLink() . $sep
                  . $this->specialLink( "recentchanges" );
 
-               if ( $wgOut->isArticle() ) {
+               if ( $wgOut->isArticleRelated() ) {
                        $s .=  $sep . $this->editThisPage()
                          . $sep . $this->historyLink();
                }
@@ -603,7 +620,7 @@ class Skin {
                $sep = " |\n";
 
                $s = "";
-               if ( $wgOut->isArticle() ) {
+               if ( $wgOut->isArticleRelated() ) {
                        $s .= "<strong>" . $this->editThisPage() . "</strong>";
                        if ( 0 != $wgUser->getID() ) {
                                $s .= $sep . $this->watchThisPage();
@@ -651,7 +668,7 @@ class Skin {
                if ( $wgDisableCounters ) {
                        $s = "";
                } else {
-                       $count = $wgArticle->getCount();
+                       $count = $wgLang->formatNum( $wgArticle->getCount() );
                        $s = wfMsg( "viewcount", $count );
                }
                $s .= $this->lastModified();
@@ -672,9 +689,10 @@ class Skin {
        {
                if ( "" != $align ) { $a = " align='{$align}'"; }
                else { $a = ""; }
-
+               
                $mp = wfMsg( "mainpage" );
-               $s = "<a href=\"" . wfLocalUrlE( urlencode( $mp ) )
+               $titleObj = Title::newFromText( $mp );
+               $s = "<a href=\"" . $titleObj->escapeLocalURL()
                  . "\"><img{$a} border=0 src=\""
                  . $this->getLogo() . "\" alt=\"" . "[{$mp}]\"></a>";
                return $s;
@@ -683,7 +701,7 @@ class Skin {
        function quickBar()
        {
                global $wgOut, $wgTitle, $wgUser, $action, $wgLang;
-               global $wpPreview, $wgDisableUploads;
+               global $wpPreview, $wgDisableUploads, $wgRemoteUploads;
            
                $fname =  "Skin::quickBar";
                wfProfileIn( $fname );
@@ -767,8 +785,7 @@ class Skin {
                        unwatched. Therefore we do not show the "Watch this page" link in edit mode
                        */                      
                        if ( 0 != $wgUser->getID() && $articleExists) {
-                               if($action!="edit" && $action!="history" && 
-                                       $action != "submit" ) 
+                               if($action!="edit" && $action != "submit" ) 
                                {
                                        $s .= $sep . $this->watchThisPage(); 
                                }
@@ -785,7 +802,7 @@ class Skin {
                        }
                        $s.=$sep . $this->whatLinksHere();
                        
-                       if($wgOut->isArticle()) {
+                       if($wgOut->isArticleRelated()) {
                                $s .= $sep . $this->watchPageLinksLink();
                        }
 
@@ -808,7 +825,7 @@ class Skin {
                        $s .= "\n<br><hr class='sep'>";
                } 
                
-               if ( 0 != $wgUser->getID() && !$wgDisableUploads ) {
+               if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
                        $s .= $this->specialLink( "upload" ) . $sep;
                }
                $s .= $this->specialLink( "specialpages" )
@@ -906,7 +923,7 @@ class Skin {
        {
                global $wgOut, $wgTitle, $oldid, $redirect, $diff;
 
-               if ( ! $wgOut->isArticle() || $diff ) {
+               if ( ! $wgOut->isArticleRelated() ) {
                        $s = wfMsg( "protectedpage" );
                } else {
                        $n = $wgTitle->getPrefixedText();
@@ -967,7 +984,7 @@ class Skin {
        {
                global $wgUser, $wgOut, $wgTitle, $diff;
 
-               if ( $wgOut->isArticle() && ( ! $diff ) ) {
+               if ( $wgOut->isArticleRelated() ) {
                        $n = $wgTitle->getPrefixedText();
 
                        if ( $wgTitle->userIsWatching() ) {
@@ -1018,7 +1035,7 @@ class Skin {
                global $wgTitle, $wgLang;
 
                $s = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
-                 wfMsg( "contributions" ), "target=" . $wgTitle->getURL() );
+                 wfMsg( "contributions" ), "target=" . $wgTitle->getPartialURL() );
                return $s;
        }
 
@@ -1027,7 +1044,7 @@ class Skin {
                global $wgTitle, $wgLang;
 
                $s = $this->makeKnownLink( $wgLang->specialPage( "Emailuser" ),
-                 wfMsg( "emailuser" ), "target=" . $wgTitle->getURL() );
+                 wfMsg( "emailuser" ), "target=" . $wgTitle->getPartialURL() );
                return $s;
        }
 
@@ -1035,7 +1052,7 @@ class Skin {
        {
                global $wgOut, $wgTitle, $wgLang;
 
-               if ( ! $wgOut->isArticle() ) {
+               if ( ! $wgOut->isArticleRelated() ) {
                        $s = "(" . wfMsg( "notanarticle" ) . ")";
                } else {
                        $s = $this->makeKnownLink( $wgLang->specialPage(
@@ -1248,7 +1265,7 @@ class Skin {
        }
 
        # Pass a title object, not a title string
-       function makeLinkObj( &$nt, $text= "", $query = "", $trail = "" )
+       function makeLinkObj( &$nt, $text= "", $query = "", $trail = "", $prefix = "" )
        {
                global $wgOut, $wgUser;
                if ( $nt->isExternal() ) {
@@ -1265,18 +1282,18 @@ class Skin {
                        }
                        $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
                } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
-                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
+                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
                } elseif ( ( -1 == $nt->getNamespace() ) ||
                                ( Namespace::getImage() == $nt->getNamespace() ) ) {
-                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
+                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
                } else {
                        $aid = $nt->getArticleID() ;
                        if ( 0 == $aid ) {
-                               $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail );
+                               $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
                        } else {
                                $threshold = $wgUser->getOption("stubthreshold") ;
                                if ( $threshold > 0 ) {
-                                       $res = wfQuery ( "SELECT HIGH_PRIORITY length(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
+                                       $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
 
                                        if ( wfNumRows( $res ) > 0 ) {
                                                $s = wfFetchObject( $res );
@@ -1292,9 +1309,9 @@ class Skin {
                                        $size = 1 ;
                                }       
                                if ( $size < $threshold ) {
-                                       $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail );
+                                       $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
                                } else {
-                                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
+                                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
                                }
                        }
                }
@@ -1302,7 +1319,7 @@ class Skin {
        }
 
        # Pass a title object, not a title string
-       function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "" )
+       function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
        {
                global $wgOut, $wgTitle;
 
@@ -1315,7 +1332,7 @@ class Skin {
                        $u = "";
                        if ( "" == $text ) { $text = $nt->getFragment(); }
                } else {
-                       $u = wfLocalUrlE( $link, $query );
+                       $u = $nt->escapeLocalURL( $query );
                }
                if ( "" != $nt->getFragment() ) {
                        $u .= "#" . wfEscapeHTML( $nt->getFragment() );
@@ -1325,45 +1342,46 @@ class Skin {
 
                $inside = "";
                if ( "" != $trail ) {
-                       if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
+                       if ( preg_match( $this->linktrail, $trail, $m ) ) {
                                $inside = $m[1];
                                $trail = $m[2];
                        }
                }
-               $r = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
+               $r = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
                wfProfileOut( $fname );
                return $r;
        }
        
        # Pass a title object, not a title string
-       function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "" )
+       function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
        {
                global $wgOut, $wgUser;
                
                $fname = "Skin::makeBrokenLinkObj";
                wfProfileIn( $fname );
 
-               $link = $nt->getPrefixedURL();
-
-               if ( "" == $query ) { $q = "action=edit"; }
-               else { $q = "action=edit&{$query}"; }
-               $u = wfLocalUrlE( $link, $q );
+               if ( "" == $query ) {
+                       $q = "action=edit";
+               } else {
+                       $q = "action=edit&{$query}";
+               }
+               $u = $nt->escapeLocalURL( $q );
 
                if ( "" == $text ) { $text = $nt->getPrefixedText(); }
                $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
 
                $inside = "";
                if ( "" != $trail ) {
-                       if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
+                       if ( preg_match( $this->linktrail, $trail, $m ) ) {
                                $inside = $m[1];
                                $trail = $m[2];
                        }
                }
                if ( $wgOut->isPrintable() ||
                  ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
-                       $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
+                       $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
                } else {
-                       $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
+                       $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
                }
 
                wfProfileOut( $fname );
@@ -1371,29 +1389,29 @@ class Skin {
        }
        
        # Pass a title object, not a title string
-       function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "" )
+       function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
        {
                global $wgOut, $wgUser;
 
                $link = $nt->getPrefixedURL();
 
-               $u = wfLocalUrlE( $link, $query );
+               $u = $nt->escapeLocalURL( $query );
 
                if ( "" == $text ) { $text = $nt->getPrefixedText(); }
                $style = $this->getInternalLinkAttributesObj( $nt, $text, "stub" );
 
                $inside = "";
                if ( "" != $trail ) {
-                       if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
+                       if ( preg_match( $this->linktrail, $trail, $m ) ) {
                                $inside = $m[1];
                                $trail = $m[2];
                        }
                }
                if ( $wgOut->isPrintable() ||
                                ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
-                       $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
+                       $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
                } else {
-                       $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
+                       $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
                }
                return $s;
        }
@@ -1421,17 +1439,247 @@ class Skin {
        }
 
        function makeImageLinkObj( $nt, $alt = "" ) {
-               $link = $nt->getPrefixedURL();
-               $name = $nt->getDBKey();
-               $url = wfImageUrl( $name );
+               global $wgLang, $wgUseImageResize;
+               $name  = $nt->getDBKey();
+               $url   = wfImageUrl( $name );
+               $align = "";
+               $prefix = $postfix = "";
+
+               if ( $wgUseImageResize ) {
+                       # Check if the alt text is of the form "options|alt text"
+                       # Options are:
+                       #  * thumbnail          make a thumbnail with enlarge-icon and caption, alignment depends on lang
+                       #  * left               no resizing, just left align. label is used for alt= only
+                       #  * right              same, but right aligned
+                       #  * none               same, but not aligned
+                       #  * ___px              scale to ___ pixels width, no aligning. e.g. use in taxobox
+       
+                       $part = explode( "|", $alt);
+       
+                       $mwThumb  =& MagicWord::get( MAG_IMG_THUMBNAIL );
+                       $mwLeft   =& MagicWord::get( MAG_IMG_LEFT );
+                       $mwRight  =& MagicWord::get( MAG_IMG_RIGHT );
+                       $mwNone   =& MagicWord::get( MAG_IMG_NONE );
+                       $mwWidth  =& MagicWord::get( MAG_IMG_WIDTH );
+                       $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
+                       $alt = $part[count($part)-1];
+
+                       $thumb=false;
+
+                       foreach( $part as $key => $val ) {
+                               if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
+                                       $thumb=true;
+                               } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
+                                       # remember to set an alignment, don't render immediately
+                                       $align = "right";
+                               } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
+                                       # remember to set an alignment, don't render immediately
+                                       $align = "left";
+                               } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
+                                       # remember to set an alignment, don't render immediately
+                                       $align = "center";
+                               } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
+                                       # remember to set an alignment, don't render immediately
+                                       $align = "none";
+                               } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
+                                       # $match is the image width in pixels
+                                       $width = intval($match);
+                               }
+                       }
+                       if ( "center" == $align )
+                       {
+                               $prefix  = "<center>";
+                               $postfix = "</center>";
+                               $align   = "none";
+                       }
+       
+                       if ( $thumb ) {
+       
+                               # Create a thumbnail. Alignment depends on language
+                               # writing direction, # right aligned for left-to-right-
+                               # languages ("Western languages"), left-aligned
+                               # for right-to-left-languages ("Semitic languages")
+                               #
+                               # If  thumbnail width has not been provided, it is set
+                               # here to 180 pixels
+                               if ( $align == "" ) {
+                                       $align = $wgLang->isRTL() ? "left" : "right";
+                               }
+                               if ( ! isset($width) ) {
+                                       $width = 180;
+                               }
+                               return $prefix.$this->makeThumbLinkObj( $nt, $alt, $align, $width ).$postfix;
+       
+                       } elseif ( isset($width) ) {
+                               
+                               # Create a resized image, without the additional thumbnail
+                               # features
+                               $url = $this->createThumb( $name, $width );
+                       }
+               } # endif $wgUseImageResize
+                       
                if ( empty( $alt ) ) {
                        $alt = preg_replace( '/\.(.+?)^/', '', $name );
                }
                $alt = htmlspecialchars( $alt );
 
-               $u = wfLocalUrlE( $link );
-               $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
-                 "<img border=\"0\" src=\"{$url}\" alt=\"{$alt}\"></a>";
+               $u = $nt->escapeLocalURL();
+               if ( $url == "" )
+               {
+                       $s = str_replace( "$1", $name, wfMsg("missingimage") );
+               } else {
+                       $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
+                               "<img border=\"0\" src=\"{$url}\" alt=\"{$alt}\"></a>";
+               }
+               if ( "" != $align ) {
+                       $s = "<div class=\"float{$align}\">{$s}</div>";
+               }
+               return $prefix.$s.$postfix;
+       }
+
+       function createThumb( $name, $width ) {
+               global $wgUploadDirectory;
+               global $wgImageMagickConvertCommand;
+               global $wgUseImageMagick;
+               global $wgUseSquid, $wgInternalServer;
+               $imgPath   = wfImagePath( $name );
+               $thumbName = $width."px-".$icon.$name;
+               $thumbPath = wfImageThumbDir( $thumbName )."/".$thumbName;
+               $thumbUrl  = wfImageThumbUrl( $thumbName );
+
+               if ( ! file_exists( $imgPath ) )
+               {
+                       # If there is no image, there will be no thumbnail
+                       return "";
+               }
+
+               if (     (! file_exists( $thumbPath ) )
+               ||  ( filemtime($thumbPath) < filemtime($imgPath) ) ) {
+                       # Squid purging
+                       if ( $wgUseSquid ) {
+                               $urlArr = Array(
+                                       $wgInternalServer.$thumbUrl
+                               );
+                               wfPurgeSquidServers($urlArr);
+                       }
+
+                       if ( $wgUseImageMagick ) {
+                               # use ImageMagick
+                               $cmd  =  $wgImageMagickConvertCommand .
+                                       " -quality 85 -geometry {$width} ".
+                                       escapeshellarg($imgPath) . " " .
+                                       escapeshellarg($thumbPath);
+                               $conv = shell_exec( $cmd );
+                       } else {
+                               # Use PHP's builtin GD library functions.
+                               #
+                               # First find out what kind of file this is, and select the correct
+                               # input routine for this.
+                               list($src_width, $src_height, $src_type, $src_attr) = getimagesize( $imgPath );
+                               switch( $src_type ) {
+                                       case 1: # GIF
+                                               $src_image = imagecreatefromgif( $imgPath );
+                                               break;
+                                       case 2: # JPG
+                                               $src_image = imagecreatefromjpeg( $imgPath );
+                                               break;
+                                       case 3: # PNG
+                                               $src_image = imagecreatefrompng( $imgPath );
+                                               break;
+                                       case 15: # WBMP for WML
+                                               $src_image = imagecreatefromwbmp( $imgPath );
+                                               break;
+                                       case 16: # XBM
+                                               $src_image = imagecreatefromxbm( $imgPath );
+                                               break;
+                                       default:
+                                               return "Image type not supported";
+                                               break;
+                               }
+                               $height = floor( $src_height * ( $width/$src_width ) );
+                               $dst_image = imagecreatetruecolor( $width, $height );
+                               imagecopyresampled( $dst_image, $src_image, 
+                                                       0,0,0,0,
+                                                       $width, $height, $src_width, $src_height );
+                               switch( $src_type ) {
+                                       case 1:  # GIF
+                                       case 3:  # PNG
+                                       case 15: # WBMP
+                                       case 16: # XBM
+                                               #$thumbUrl .= ".png";
+                                               #$thumbPath .= ".png";
+                                               imagepng( $dst_image, $thumbPath );
+                                               break;
+                                       case 2:  # JPEG
+                                               #$thumbUrl .= ".jpg";
+                                               #$thumbPath .= ".jpg";
+                                               imageinterlace( $dst_image );
+                                               imagejpeg( $dst_image, $thumbPath, 95 );
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               imagedestroy( $dst_image );
+                               imagedestroy( $src_image );
+
+
+                       }
+                       #
+                       # Check for zero-sized thumbnails. Those can be generated when 
+                       # no disk space is available or some other error occurs
+                       #
+                       $thumbstat = stat( $thumbPath );
+                       $imgstat   = stat( $imgPath );
+                       if( $thumbstat["size"] == 0 )
+                       {
+                               unlink( $thumbPath );
+                       }
+
+               }
+               return $thumbUrl;
+       }
+
+       function makeThumbLinkObj( $nt, $label = "", $align = "right", $boxwidth = 180 ) {
+               global $wgUploadPath;
+               $name = $nt->getDBKey();
+               $image = Title::makeTitle( Namespace::getImage(), $name );
+               $url  = wfImageUrl( $name );
+               $path = wfImagePath( $name );
+               
+               #$label = htmlspecialchars( $label );
+               $alt = preg_replace( "/<[^>]*>/", "", $label);
+               $alt = htmlspecialchars( $alt );
+               
+               if ( file_exists( $path ) )
+               {
+                       list($width, $height, $type, $attr) = getimagesize( $path );
+               } else {
+                       $width = $height = 200;
+               }
+               $boxheight  = intval( $height/($width/$boxwidth) );
+               if ( $boxwidth > $width ) {
+                       $boxwidth  = $width;
+                       $boxheight = $height;
+               }
+               
+               $thumbUrl = $this->createThumb( $name, $boxwidth );
+
+               $u = $nt->escapeLocalURL();
+
+               $more = htmlspecialchars(wfMsg( "thumbnail-more" ));
+
+               $s = "<div class=\"thumbnail-{$align}\" style=\"width:{$boxwidth}px;\">";
+               if ( $thumbUrl == "" ) {
+                       $s .= str_replace( "$1", $name, wfMsg("missingimage") );
+               } else {
+                       $s .= "<a href=\"{$u}\" class=\"internal\" title=\"{$alt}\">" .
+                               "<img border=\"0\" src=\"{$thumbUrl}\" alt=\"{$alt}\" " .
+                               "  width=\"{$boxwidth}\" height=\"{$boxheight}\"></a>" .
+                               "<a href=\"{$u}\" class=\"internal\" title=\"{$more}\">" .
+                               "<img border=\"0\" src=\"{$wgUploadPath}/magnify-clip.png\" " .
+                               "  width=\"26\" height=\"24\" align=\"right\" alt=\"{$more}\"></a>";
+               }
+               $s .= "<p>{$label}</p></div>";
                return $s;
        }
 
@@ -1466,10 +1714,12 @@ class Skin {
        # Called by history lists and recent changes
        #
 
+       # Returns text for the start of the tabular part of RC
        function beginRecentChangesList()
        {
-               $rc_cache = array() ;
-               $rccc = 0 ;
+               $this->rc_cache = array() ;
+               $this->rcMoveIndex = 0;
+               $this->rcCacheIndex = 0 ;
                $this->lastdate = "";
                return "";
        }
@@ -1481,6 +1731,8 @@ class Skin {
                return $s;
        }
 
+       # Returns text for the end of RC
+       # If enhanced RC is in use, returns pretty much all the text
        function endRecentChangesList()
        {
                $s = $this->recentChangesBlock() ;
@@ -1488,77 +1740,102 @@ class Skin {
                return $s;
        }
 
-       function endImageHistoryList()
+       # Enhanced RC ungrouped line
+       function recentChangesBlockLine ( $rcObj ) 
        {
-               $s = "</ul>\n";
-               return $s;
-       }
-
-       function recentChangesBlockLine ( $y ) {
-               global $wgUploadPath ;
-
-               $M = wfMsg( "minoreditletter" );
-               $N = wfMsg( "newpageletter" );
+               global $wgUploadPath, $wgLang ;
+               
+               # Get rc_xxxx variables
+               extract( $rcObj->mAttribs ) ;
+               $curIdEq = "curid=$rc_cur_id";
+               
+               # Spacer image
                $r = "" ;
-               $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>" ;
-               $r .= "<tt>" ;
-               if ( $y->isnew ) $r .= $N ;
-               else $r .= "&nbsp;" ;
-               if ( $y->isminor ) $r .= $M ;
-               else $r .= "&nbsp;" ;
-               $r .= " ".$y->timestamp." " ;
+               $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>" ;              $r .= "<tt>" ;
+               
+               if ( $rc_type == RC_MOVE ) {
+                       $r .= "&nbsp;&nbsp;";
+               } else {
+                       # M & N (minor & new)
+                       $M = wfMsg( "minoreditletter" );
+                       $N = wfMsg( "newpageletter" );
+               
+                       if ( $rc_type == RC_NEW ) {
+                               $r .= $N ;
+                       } else {
+                               $r .= "&nbsp;" ;
+                       }
+                       if ( $rc_minor ) {
+                               $r .= $M ;
+                       } else {
+                               $r .= "&nbsp;" ;
+                       }
+               }
+               
+               # Timestamp
+               $r .= " ".$rcObj->timestamp." " ;
                $r .= "</tt>" ;
-               $link = $y->link ;
-               if ( $y->watched ) $link = "<strong>{$link}</strong>" ;
+
+               # Article link
+               $link = $rcObj->link ;
+               if ( $rcObj->watched ) $link = "<strong>{$link}</strong>" ;
                $r .= $link ;
 
+               # Cur
                $r .= " (" ;
-               $r .= $y->curlink ;
+               $r .= $rcObj->curlink ;
                $r .= "; " ;
-               $r .= $this->makeKnownLink( $y->secureName, wfMsg( "hist" ), "action=history" );
+               
+               # Hist
+               $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" );
 
-               $r .= ") . . ".$y->userlink ;
-               $r .= $y->usertalklink ;
-               if ( $y->usercomment != "" )
-                       $r .= " <em>(".wfEscapeHTML($y->usercomment).")</em>" ;
+               # User/talk
+               $r .= ") . . ".$rcObj->userlink ;
+               $r .= $rcObj->usertalklink ;
+               
+               # Comment
+               if ( $rc_comment != "" && $rc_type != RC_MOVE ) {
+                       $r .= $wgLang->emphasize( " (".wfEscapeHTML($rc_comment).")" );
+               }
                $r .= "<br>\n" ;
                return $r ;
-               }
-
-       function recentChangesBlockGroup ( $y ) {
-               global $wgUploadPath ;
+       }
 
+       # Enhanced RC group
+       function recentChangesBlockGroup ( $block ) 
+       {
+               global $wgUploadPath, $wgLang ;
+               
                $r = "" ;
                $M = wfMsg( "minoreditletter" );
                $N = wfMsg( "newpageletter" );
+               
+               # Collate list of users
                $isnew = false ;
                $userlinks = array () ;
-               foreach ( $y AS $x ) {
-                       $oldid = $x->diffid ;
-                       if ( $x->isnew ) $isnew = true ;
-                       $u = $x->userlink ;
+               foreach ( $block AS $rcObj ) {
+                       $oldid = $rcObj->mAttribs['rc_last_oldid'];
+                       if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
+                       $u = $rcObj->userlink ;
                        if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
                        $userlinks[$u]++ ;
-                       }
-
+               }
+               
+               # Sort the list and convert to text
                krsort ( $userlinks ) ;
                asort ( $userlinks ) ;
                $users = array () ;
-               $u = array_keys ( $userlinks ) ;
-               foreach ( $u as $x ) {
-                       $z = $x ;
-                       if ( $userlinks[$x] > 1 ) $z .= " ({$userlinks[$x]}&times;)" ;
-                       array_push ( $users , $z ) ;
-                       }
+               foreach ( $userlinks as $userlink => $count) {
+                       $text = $userlink ;
+                       if ( $count > 1 ) $text .= " ({$count}&times;)" ;
+                       array_push ( $users , $text ) ;
+               }
                $users = " <font size='-1'>[".implode("; ",$users)."]</font>" ;
 
-               $e = $y ;
-               $e = array_shift ( $e ) ;
-
                # Arrow
-               $rci = "RCI{$this->rccc}" ;
-               $rcl = "RCL{$this->rccc}" ;
-               $rcm = "RCM{$this->rccc}" ;
+               $rci = "RCI{$this->rcCacheIndex}" ;
+               $rcl = "RCL{$this->rcCacheIndex}" ;
+               $rcm = "RCM{$this->rcCacheIndex}" ;
                $tl = "<a href='javascript:toggleVisibility(\"{$rci}\",\"{$rcm}\",\"{$rcl}\")'>" ;
                $tl .= "<span id='{$rcm}'><img src='{$wgUploadPath}/Arr_r.png' width=12 height=12 border=0></span>" ;
                $tl .= "<span id='{$rcl}' style='display:none'><img src='{$wgUploadPath}/Arr_d.png' width=12 height=12 border=0></span>" ;
@@ -1566,246 +1843,321 @@ class Skin {
                $r .= $tl ;
 
                # Main line
+               # M/N
                $r .= "<tt>" ;
                if ( $isnew ) $r .= $N ;
                else $r .= "&nbsp;" ;
                $r .= "&nbsp;" ; # Minor
-               $r .= " ".$e->timestamp." " ;
-               $r .= "</tt>" ;
 
-               $link = $e->link ;
-               if ( $e->watched ) $link = "<strong>{$link}</strong>" ;
+               # Timestamp
+               $r .= " ".$block[0]->timestamp." " ;
+               $r .= "</tt>" ;
+               
+               # Article link
+               $link = $block[0]->link ;
+               if ( $block[0]->watched ) $link = "<strong>{$link}</strong>" ;
                $r .= $link ;
-
-               if ( !$e->islog ) {
-                       $r .= " (".count($y)." " ;
+               
+               $curIdEq = "curid=" . $block[0]->mAttribs['rc_cur_id'];
+               if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
+                       # Changes
+                       $r .= " (".count($block)." " ;
                        if ( $isnew ) $r .= wfMsg("changes");
-                       else $r .= $this->makeKnownLink( $e->secureName , wfMsg("changes") , "diff=0&oldid=".$oldid ) ;
+                       else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg("changes") , 
+                               "{$curIdEq}&diff=0&oldid=".$oldid ) ;
                        $r .= "; " ;
-                       $r .= $this->makeKnownLink( $e->secureName, wfMsg( "history" ), "action=history" );
+
+                       # History
+                       $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( "history" ), "{$curIdEq}&action=history" );
                        $r .= ")" ;
-                       }
+               }
 
                $r .= $users ;
                $r .= "<br>\n" ;
 
                # Sub-entries
                $r .= "<div id='{$rci}' style='display:none'>" ;
-               foreach ( $y AS $x )
-                       {
+               foreach ( $block AS $rcObj ) {
+                       # Get rc_xxxx variables
+                       extract( $rcObj->mAttribs );
+                       
                        $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>";
                        $r .= "<tt>&nbsp; &nbsp; &nbsp; &nbsp;" ;
-                       if ( $x->isnew ) $r .= $N ;
+                       if ( $rc_new ) $r .= $N ;
                        else $r .= "&nbsp;" ;
-                       if ( $x->isminor ) $r .= $M ;
+                       if ( $rc_minor ) $r .= $M ;
                        else $r .= "&nbsp;" ;
                        $r .= "</tt>" ;
 
                        $o = "" ;
-                       if ( $x->oldid != 0 ) $o = "oldid=".$x->oldid ;
-                       if ( $x->islog ) $link = $x->timestamp ;
-                       else $link = $this->makeKnownLink( $x->secureName, $x->timestamp , $o ) ;
+                       if ( $rc_last_oldid != 0 ) {
+                               $o = "oldid=".$rc_last_oldid ;
+                       }
+                       if ( $rc_type == RC_LOG ) {
+                               $link = $rcObj->timestamp ;
+                       } else {
+                               $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
+                       }
                        $link = "<tt>{$link}</tt>" ;
 
-
                        $r .= $link ;
                        $r .= " (" ;
-                       $r .= $x->curlink ;
+                       $r .= $rcObj->curlink ;
                        $r .= "; " ;
-                       $r .= $x->lastlink ;
-                       $r .= ") . . ".$x->userlink ;
-                       $r .= $x->usertalklink ;
-                       if ( $x->usercomment != "" )
-                               $r .= " <em>(".wfEscapeHTML($x->usercomment).")</em>" ;
-                       $r .= "<br>\n" ;
+                       $r .= $rcObj->lastlink ;
+                       $r .= ") . . ".$rcObj->userlink ;
+                       $r .= $rcObj->usertalklink ;
+                       if ( $rc_comment != "" ) {
+                               $r .= $wgLang->emphasize( " (".wfEscapeHTML($rc_comment).")" ) ;
                        }
+                       $r .= "<br>\n" ;
+               }
                $r .= "</div>\n" ;
 
-               $this->rccc++ ;
+               $this->rcCacheIndex++ ;
                return $r ;
-               }
+       }
 
+       # If enhanced RC is in use, this function takes the previously cached
+       # RC lines, arranges them, and outputs the HTML
        function recentChangesBlock ()
        {
                global $wgUploadPath ;
                if ( count ( $this->rc_cache ) == 0 ) return "" ;
-               $k = array_keys ( $this->rc_cache ) ;
-               foreach ( $k AS $x )
-                       {
-                       $y = $this->rc_cache[$x] ;
-                       if ( count ( $y ) < 2 ) {
-                               $r .= $this->recentChangesBlockLine ( array_shift ( $y ) ) ;
+               $blockOut = "";
+               foreach ( $this->rc_cache AS $secureName => $block ) {
+                       if ( count ( $block ) < 2 ) {
+                               $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
                        } else {
-                               $r .= $this->recentChangesBlockGroup ( $y ) ;
-                               }
+                               $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
                        }
+               }
 
-               return "<div align=left>{$r}</div>" ;
+               return "<div align=left>{$blockOut}</div>" ;
        }
 
-       function recentChangesLine( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
+       # Called in a loop over all displayed RC entries
+       # Either returns the line, or caches it for later use
+       function recentChangesLine( &$rc, $watched = false )
        {
                global $wgUser ;
                $usenew = $wgUser->getOption( "usenewrc" );
                if ( $usenew )
-                       $r = $this->recentChangesLineNew ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
+                       $line = $this->recentChangesLineNew ( $rc, $watched ) ;
                else
-                       $r = $this->recentChangesLineOld ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
-               return $r ;
+                       $line = $this->recentChangesLineOld ( $rc, $watched ) ;
+               return $line ;
        }
-
-       function recentChangesLineOld( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0, $diffid = 0 )
+       
+       function recentChangesLineOld( &$rc, $watched = false )
        {
                global $wgTitle, $wgLang, $wgUser;
-
-               $d = $wgLang->date( $ts, true);
+               
+               # Extract DB fields into local scope
+               extract( $rc->mAttribs );
+               $curIdEq = "curid=" . $rc_cur_id;
+               
+               # Make date header if necessary
+               $date = $wgLang->date( $rc_timestamp, true);
                $s = "";
-               if ( $d != $this->lastdate ) {
+               if ( $date != $this->lastdate ) {
                        if ( "" != $this->lastdate ) { $s .= "</ul>\n"; }
-                       $s .= "<h4>{$d}</h4>\n<ul>";
-                       $this->lastdate = $d;
+                       $s .= "<h4>{$date}</h4>\n<ul>";
+                       $this->lastdate = $date;
                }
-               $h = $wgLang->time( $ts, true );
-               $t = Title::makeName( $ns, $ttl );
-               $clink = $this->makeKnownLink( $t , "" );
-               $nt = Title::newFromText( $t );
+               $s .= "<li> ";
+               
+               if ( $rc_type == RC_MOVE ) {
+                       # Diff
+                       $s .= "(" . wfMsg( "diff" ) . ") (";
+                       # Hist
+                       $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( "hist" ), "action=history" ) .
+                               ") . . ";
+                       
+                       # "[[x]] moved to [[y]]"
+
+                       $s .= wfMsg( "1movedto2", $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" ),
+                               $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" ) );
 
-               if ( $watched ) {
-                       $clink = "<strong>{$clink}</strong>";
-               }
-               $hlink = $this->makeKnownLink( $t, wfMsg( "hist" ), "action=history" );
-               if ( $isnew || $nt->isLog() ) {
-                       $dlink = wfMsg( "diff" );
                } else {
-                       $dlink = $this->makeKnownLink( $t, wfMsg( "diff" ),
-                         "diff={$oldid}&oldid={$diffid}" ); # Finagle's law
+                       # Diff link
+                       if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
+                               $diffLink = wfMsg( "diff" );
+                       } else {
+                               $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "diff" ),
+                                 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" );
+                       }
+                       $s .= "($diffLink) (";
+                       
+                       # History link
+                       $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" ); 
+                       $s .= ") . . ";
+
+                       # M and N (minor and new)
+                       $M = wfMsg( "minoreditletter" );
+                       $N = wfMsg( "newpageletter" );
+                       if ( $rc_minor ) { $s .= " <strong>{$M}</strong>"; }
+                       if ( $rc_type == RC_NEW ) { $s .= "<strong>{$N}</strong>"; }
+
+                       # Article link
+                       $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), "" );
+
+                       if ( $watched ) {
+                               $articleLink = "<strong>{$articleLink}</strong>";
+                       }
+                       $s .= " $articleLink";
+
                }
-               if ( 0 == $u ) {
-               $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
-                       $ut, "target=" . $ut );                                 
+               
+               # Timestamp
+               $s .= "; " . $wgLang->time( $rc_timestamp, true ) . " . . ";
+               
+               # User link (or contributions for unregistered users)
+               if ( 0 == $rc_user ) {
+                       $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
+                       $rc_user_text, "target=" . $rc_user_text );                                     
                } else { 
-                       $ul = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut ); 
+                       $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ":{$rc_user_text}", $rc_user_text ); 
                }
-                 
-               $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
+               $s .= $userLink;
+               
+               # User talk link
+               $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
                global $wgDisableAnonTalk;
-               if( 0 == $u && $wgDisableAnonTalk ) {
-                       $utl = "";
+               if( 0 == $rc_user && $wgDisableAnonTalk ) {
+                       $userTalkLink = "";
                } else {
-                       $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
-                       $utl= $this->makeLink($utns . ":{$ut}", $talkname );
-               }
-               $cr = wfMsg( "currentrev" );
-
-               $s .= "<li> ({$dlink}) ({$hlink}) . .";
-               $M = wfMsg( "minoreditletter" );
-               $N = wfMsg( "newpageletter" );
-               if ( $isminor ) { $s .= " <strong>{$M}</strong>"; }
-               if ( $isnew ) { $s .= "<strong>{$N}</strong>"; }
-               $s .= " {$clink}; {$h} . . {$ul}";
-
-               $blink="";
-               if ( ( 0 == $u ) && $wgUser->isSysop() ) {
-                       $blink = $this->makeKnownLink( $wgLang->specialPage(
-                         "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
+                       $utns=$wgLang->getNsText(NS_USER_TALK);
+                       $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname );
+               }
+               # Block link
+               $blockLink="";
+               if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
+                       $blockLink = $this->makeKnownLink( $wgLang->specialPage(
+                         "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" );
                        
                }
-               if($blink) { 
-                       if($utl) $utl .= " | ";
-                       $utl .= $blink;
+               if($blockLink) { 
+                       if($userTalkLink) $userTalkLink .= " | ";
+                       $userTalkLink .= $blockLink;
                }
-               if($utl) $s.=" ({$utl})";
+               if($userTalkLink) $s.=" ({$userTalkLink})";
 
-               if ( "" != $c && "*" != $c ) {
-                       $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
+               # Add comment
+               if ( "" != $rc_comment && "*" != $rc_comment && $rc_type != RC_MOVE ) {
+                       $s .= $wgLang->emphasize(" (" . wfEscapeHTML( $rc_comment ) . ")");
                }
                $s .= "</li>\n";
 
                return $s;
        }
-
-       function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
+       
+#      function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
+       function recentChangesLineNew( &$baseRC, $watched = false )
        {
                global $wgTitle, $wgLang, $wgUser;
 
-               $rc = new RecentChangesClass ;
+               # Create a specialised object
+               $rc = RCCacheEntry::newFromParent( $baseRC ) ;
 
-               $d = $wgLang->date( $ts, true);
-               $s = "";
+               # Extract fields from DB into the function scope (rc_xxxx variables)
+               extract( $rc->mAttribs );
+               $curIdEq = "curid=" . $rc_cur_id;
+
+               # If it's a new day, add the headline and flush the cache
+               $date = $wgLang->date( $rc_timestamp, true);
                $ret = "" ;
-               if ( $d != $this->lastdate ) {
+               if ( $date != $this->lastdate ) {
+                       # Process current cache
                        $ret = $this->recentChangesBlock () ;
                        $this->rc_cache = array() ;
-                       $ret .= "<h4>{$d}</h4>\n";
-                       $this->lastdate = $d;
-               }
-               $h = $wgLang->time( $ts, true );
-               $t = Title::makeName( $ns, $ttl );
-               $clink = $this->makeKnownLink( $t, "" ) ;
-               if ( $oldid == 0 ) $c2link = $clink ;
-               else $c2link = $this->makeKnownLink( $t, "" , "oldid={$oldid}" );
-               $nt = Title::newFromText( $t );
-
-               $rc->timestamp = $h ;
-               $rc->oldid = $oldid ;
-               $rc->diffid = $diffid ;
+                       $ret .= "<h4>{$date}</h4>\n";
+                       $this->lastdate = $date;
+               }
+               
+               # Make article link
+               if ( $rc_type == RC_MOVE ) {
+                       $clink = $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" );
+                       $clink .= " " . wfMsg("movedto") . " ";
+                       $clink .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" );
+               } else {
+                       $clink = $this->makeKnownLinkObj( $rc->getTitle(), "" ) ;
+               }
+               
+               $time = $wgLang->time( $rc_timestamp, true );
                $rc->watched = $watched ;
-               $rc->isnew = $isnew ;
-               $rc->isminor = $isminor ;
-               $rc->secureName = $t ;
-               $rc->displayName = $nt ;
                $rc->link = $clink ;
-               $rc->usercomment = $c ;
-               $rc->islog = $nt->isLog() ;
-
-               if ( ( $isnew && $oldid == 0 ) || $nt->isLog() ) {
-                       $dlink = wfMsg( "cur" );
+               $rc->timestamp = $time;
+               
+               # Make "cur" link
+               if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE) {
+                       $curLink = wfMsg( "cur" );
                } else {
-                       $dlink = $this->makeKnownLink( $t, wfMsg( "cur" ),
-                         "diff=0&oldid={$oldid}" );
+                       $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "cur" ),
+                         "{$curIdEq}&diff=0&oldid={$rc_this_oldid}" );
                }
 
-               if ( $diffid == 0 || $nt->isLog() ) {
-                       $plink = wfMsg( "last" );
+               # Make "last" link
+               $titleObj = $rc->getTitle();
+               if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE ) {
+                       $lastLink = wfMsg( "last" );
                } else {
-                       $plink = $this->makeKnownLink( $t, wfMsg( "last" ),
-                         "diff={$oldid}&oldid={$diffid}" );
+                       $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "last" ),
+                         "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" );
                }
 
-               if ( 0 == $u ) {
-               $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
-                       $ut, "target=" . $ut );
-               } else { $ul = $this->makeLink( $wgLang->getNsText(
-                 Namespace::getUser() ) . ":{$ut}", $ut ); }
-
-               $rc->userlink = $ul ;
-               $rc->lastlink = $plink ;
-               $rc->curlink = $dlink ;
+               # Make user link (or user contributions for unregistered users)
+               if ( 0 == $rc_user ) {
+                       $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
+                       $rc_user_text, "target=" . $rc_user_text );
+               } else { 
+                       $userLink = $this->makeLink( $wgLang->getNsText(
+                         Namespace::getUser() ) . ":{$rc_user_text}", $rc_user_text ); 
+               }
 
-               $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
-               $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
-               $utl= $this->makeLink($utns . ":{$ut}", $talkname );                                            
+               $rc->userlink = $userLink ;
+               $rc->lastlink = $lastLink ;
+               $rc->curlink = $curLink ;
 
+               # Make user talk link           
+               $utns=$wgLang->getNsText(NS_USER_TALK);
+               $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
+               $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname ); 
+               
                global $wgDisableAnonTalk;
-               if ( ( 0 == $u ) && $wgUser->isSysop() ) {
-                       $blink = $this->makeKnownLink( $wgLang->specialPage(
-                         "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
+               if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
+                       $blockLink = $this->makeKnownLink( $wgLang->specialPage(
+                         "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" );
                        if( $wgDisableAnonTalk )
-                               $rc->usertalklink = " ({$blink})";
+                               $rc->usertalklink = " ({$blockLink})";
                        else
-                               $rc->usertalklink = " ({$utl} | {$blink})";
+                               $rc->usertalklink = " ({$userTalkLink} | {$blockLink})";
                } else {
-                       if( $wgDisableAnonTalk && ($u == 0) )
+                       if( $wgDisableAnonTalk && ($rc_user == 0) )
                                $rc->usertalklink = "";
                        else
-                               $rc->usertalklink = " ({$utl})";
+                               $rc->usertalklink = " ({$userTalkLink})";
                }
 
-               if ( !isset ( $this->rc_cache[$t] ) ) $this->rc_cache[$t] = array() ;
-               array_push ( $this->rc_cache[$t] , $rc ) ;
+               # Put accumulated information into the cache, for later display
+               # Page moves go on their own line
+               $title = $rc->getTitle();
+               $secureName = $title->getPrefixedDBkey();
+               if ( $rc_type == RC_MOVE ) {
+                       # Use an @ character to prevent collision with page names
+                       $this->rc_cache["@@" . ($this->rcMoveIndex++)] = array($rc);
+               } else {
+                       if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
+                       array_push ( $this->rc_cache[$secureName] , $rc ) ;
+               }
                return $ret;
        }
 
+       function endImageHistoryList()
+       {
+               $s = "</ul>\n";
+               return $s;
+       }
 
        function imageHistoryLine( $iscur, $ts, $img, $u, $ut, $size, $c )
        {
@@ -1819,7 +2171,7 @@ class Skin {
                        $url = wfImageUrl( $img );
                        $rlink = $cur;
                        if ( $wgUser->isSysop() ) {
-                               $link = wfLocalUrlE( $wgTitle->getPrefixedText(), "image=" . $wgTitle->getURL() .
+                               $link = $wgTitle->escapeLocalURL( "image=" . $wgTitle->getPartialURL() . 
                                  "&action=delete" );
                                $style = $this->getInternalLinkAttributes( $link, $del );
 
@@ -1854,7 +2206,7 @@ class Skin {
                  . " . . {$ul} ({$nb})";
 
                if ( "" != $c && "*" != $c ) {
-                       $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
+                       $s .= $wgLang->emphasize(" (" . wfEscapeHTML( $c ) . ")");
                }
                $s .= "</li>\n";
                return $s;
@@ -1889,18 +2241,18 @@ class Skin {
        }
 
        function tocTable($toc) {
-       // note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
-       global $printable;
-
-       if (!$printable) {
-               $hideline = " <script type='text/javascript'>showTocToggle(\"" . wfMsg("showtoc") . "\",\"" . wfMsg("hidetoc") . "\")</script>";
-       }
-       return
-       "<p><table border=\"0\" id=\"toc\"><tr><td align=\"center\">\n".
-       "<b>".wfMsg("toc")."</b>" .
-       $hideline .
-       "</td></tr><tr id='tocinside'><td align=\"left\">\n".
-       $toc."</td></tr></table><P>\n";
+               // note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
+               global $printable;
+               
+               if (!$printable) {
+                       $hideline = " <script type='text/javascript'>showTocToggle(\"" . wfMsg("showtoc") . "\",\"" . wfMsg("hidetoc") . "\")</script>";
+               }
+               return
+               "<p><table border=\"0\" id=\"toc\"><tr><td align=\"center\">\n".
+               "<b>".wfMsg("toc")."</b>" .
+               $hideline .
+               "</td></tr><tr id='tocinside'><td>\n".
+               $toc."</td></tr></table><P>\n";
        }
 
        # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
@@ -1908,20 +2260,120 @@ class Skin {
 
                global $wgTitle,$wgUser,$oldid;
                if($oldid) return $head;
-               $url = wfLocalUrlE(urlencode($wgTitle->getPrefixedText()),"action=edit&section=$section");
+               $url = $wgTitle->escapeLocalURL( "action=edit&section=$section" );
                return "<span onContextMenu='document.location=\"".$url."\";return false;'>{$head}</span>";
        }
 
        function editSectionLink($section) {
-
-               global $printable;
-               global $wgTitle,$wgUser,$oldid;
-               if($oldid) return "";
-               if ($printable) return "";
-               $editurl="&section={$section}";
-               $url=$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
-               return "<div style=\"float:right;margin-left:5px;\"><small>[".$url."]</small></div>";
-
+               global $printable,$oldid;
+               global $wgTitle, $wgUser, $wgLang;
+               
+               if( isset( $oldid ) ) return "";
+               if( isset( $printable ) ) return "";
+               
+               $editurl = "&section={$section}";
+               $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
+               
+               if( $wgLang->isRTL() ) {
+                       $farside = "left";
+                       $nearside = "right";
+               } else {
+                       $farside = "right";
+                       $nearside = "left";
+               }
+               return "<div style=\"float:$farside;margin-$nearside:5px;\"><small>[".$url."]</small></div>";
+
+       }
+
+       // This function is called by EditPage.php and shows a bulletin board style
+       // toolbar for common editing functions. It can be disabled in the user preferences.
+       // The necsesary JavaScript code can be found in style/wikibits.js.
+       function getEditToolbar() {
+
+               global $wgUploadPath,$wgLang;
+
+               // toolarray an array of arrays which each include the filename of
+               // the button image (without path), the opening tag, the closing tag,
+               // and optionally a sample text that is inserted between the two when no
+               // selection is highlighted.
+               // The tip text is shown when the user moves the mouse over the button.
+               $toolarray=array(
+                       array(  "image"=>"button_bold.png",
+                               "open"=>"\'\'\'",
+                               "close"=>"\'\'\'",
+                               "sample"=>wfMsg("bold_sample"),
+                               "tip"=>wfMsg("bold_tip")),
+                       array(  "image"=>"button_italic.png",
+                               "open"=>"\'\'",
+                               "close"=>"\'\'",
+                               "sample"=>wfMsg("italic_sample"),
+                               "tip"=>wfMsg("italic_tip")),
+                       array(  "image"=>"button_link.png",
+                               "open"=>"[[",
+                               "close"=>"]]",
+                               "sample"=>wfMsg("link_sample"),
+                               "tip"=>wfMsg("link_tip")),
+                       array(  "image"=>"button_extlink.png",
+                               "open"=>"[",
+                               "close"=>"]",
+                               "sample"=>wfMsg("extlink_sample"),
+                               "tip"=>wfMsg("extlink_tip")),
+                       array(  "image"=>"button_headline.png",
+                               "open"=>"\\n== ",
+                               "close"=>" ==\\n",
+                               "sample"=>wfMsg("headline_sample"),
+                               "tip"=>wfMsg("headline_tip")),
+                       array(  "image"=>"button_image.png",
+                               "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
+                               "close"=>"]]",
+                               "sample"=>wfMsg("image_sample"),
+                               "tip"=>wfMsg("image_tip")),
+                       array(  "image"=>"button_media.png",
+                               "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
+                               "close"=>"]]",
+                               "sample"=>wfMsg("media_sample"),
+                               "tip"=>wfMsg("media_tip")),
+                       array(  "image"=>"button_math.png",
+                               "open"=>"\\<math\\>",
+                               "close"=>"\\</math\\>",
+                               "sample"=>wfMsg("math_sample"),
+                               "tip"=>wfMsg("math_tip")),
+                       array(  "image"=>"button_nowiki.png",
+                               "open"=>"\\<nowiki\\>",
+                               "close"=>"\\</nowiki\\>",
+                               "sample"=>wfMsg("nowiki_sample"),
+                               "tip"=>wfMsg("nowiki_tip")),
+                       array(  "image"=>"button_sig.png",
+                               "open"=>"--~~~~",
+                               "close"=>"",
+                               "sample"=>"",
+                               "tip"=>wfMsg("sig_tip")),
+                       array(  "image"=>"button_hr.png",
+                               "open"=>"\\n----\\n",
+                               "close"=>"",
+                               "sample"=>"",
+                               "tip"=>wfMsg("hr_tip"))
+               );
+               $toolbar ="<script type='text/javascript'>\n";
+               $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
+               foreach($toolarray as $tool) {
+
+                       $image=$wgUploadPath."/".$tool["image"];
+                       $open=$tool["open"];
+                       $close=$tool["close"];
+                       $sample = addslashes( $tool["sample"] );
+
+                       // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
+                       // Older browsers show a "speedtip" type message only for ALT.
+                       // Ideally these should be different, realistically they
+                       // probably don't need to be.
+                       $tip = addslashes( $tool["tip"] );
+                       $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
+               }
+
+               $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "');\n";
+               $toolbar.="document.writeln(\"</div>\");\n</script>";
+               return $toolbar;
        }
 }