Index: www/controllers/textblock.php
===================================================================
--- www/controllers/textblock.php	(revision 967)
+++ www/controllers/textblock.php	(working copy)
@@ -51,11 +51,11 @@
     execute_view_die('views/textblock_view.php', $view);
 }
 
-// Show a textblock diff.
-// FIXME: two revisions.
+// Show differences between two textblock revisions.
 function controller_textblock_diff($page_name) {
     global $identity_user;
     $page = textblock_get_revision($page_name);
+    $rev_count = textblock_get_revision_count($page_name);
     if ($page) {
         identity_require('textblock-history', $page);
     } else {
@@ -63,32 +63,35 @@
         redirect(url_home());
     }
 
-    // Get revisions.
-    // FIXME: probably doesn't work.
-    $revfrom_id = (int)request("rev_from");
-    $revto_id = (int)request("rev_to");
+    // Validate revision ids.
+    $revfrom_id = request("rev_from");
+    $revto_id = request("rev_to");
     if (is_null($revfrom_id) || is_null($revto_id)) {
-        flash_error("Nu ati specificat reviziile");
+        flash_error("Nu ati specificat reviziile.");
         redirect(url_textblock($page_name));
     }
-    if ($revfrom_id == $revto_id) {
-        flash_error("Reviziile sunt identice");
+    if (!is_whole_number($revfrom_id) || !is_whole_number($revto_id) ||
+        $revfrom_id < 1 || $revfrom_id > $rev_count ||
+        $revto_id < 1 || $revto_id > $rev_count) {
+        flash_error("Reviziile sunt invalide.");
         redirect(url_textblock($page_name));
     }
-    if ($revfrom_id < 1 || $revto_id < 1) {
-        flash_error("Reviziile sunt invalide");
+    if ($revfrom_id == $revto_id) {
+        flash_error("Reviziile sunt identice.");
         redirect(url_textblock($page_name));
     }
 
+    // Get revisions.
     $revfrom = textblock_get_revision($page_name, $revfrom_id);
     $revto = textblock_get_revision($page_name, $revto_id);
     if (is_null($revfrom) || is_null($revto)) {
-        flash_error("Nu am gasit reviziile");
-        redirect(url_textblock($page_name));
+        log_error("Unable to get revisions $revfrom and $revto for " .
+                  "textblock $page_name.");
     }
     log_assert_valid(textblock_validate($revfrom));
     log_assert_valid(textblock_validate($revto));
 
+    // Get diffs.
     $diff_title = diff_inline(array($revfrom['title'], $revto['title']));
     $diff_content = diff_inline(array($revfrom['text'], $revto['text']));
     $diff_security = diff_inline(array($revfrom['security'], $revto['security']));
@@ -97,6 +100,7 @@
     $view = array();
     $view['page_name'] = $page['name'];
     $view['title'] = "Diferente pentru $page_name intre reviziile $revfrom_id si $revto_id";
+    $view['rev_count'] = $rev_count;
     $view['revfrom_id'] = $revfrom_id;
     $view['revto_id'] = $revto_id;
     $view['diff_title'] = $diff_title;
Index: www/static/css/screen.css
===================================================================
--- www/static/css/screen.css	(revision 967)
+++ www/static/css/screen.css	(working copy)
@@ -693,7 +693,7 @@
 /* Diff */
 .diff {
     font-family: monospace;
-    border: #999988 solid 1px;  
+    border: #999988 solid 1px;
     margin-bottom: 1em;
 }
 
@@ -702,7 +702,7 @@
     border: #CC0000 solid 1px;
     display: block;
 }
-    
+
 .diff .added {
     background-color: #DDFFDD;
     border: #00AA00 solid 1px;
@@ -729,10 +729,21 @@
 .diff ins {
     background-color: #99EE99;
     text-decoration: none;
-    
 }
 
+.prev_diff {
+    /*float: left;*/
+}
 
+.next_diff {
+    float: right;
+}
+
+.swap_diff {
+    float: right;
+    margin: 0.5em;
+}
+
 /* Wiki text block */
 .wiki_text_block {
 /*    max-width: 600px;*/
@@ -790,7 +801,7 @@
     font-family: Georgia, "Times New Roman", Times, serif;
     font-size: 13pt;
     font-weight: normal;
-    background-color: white;    
+    background-color: white;
 }
 
 /* layout table with 3 columns */
@@ -806,7 +817,7 @@
     font-family: Arial, Tahoma, sans-serif;
     font-size: 1.3em;
     font-weight: normal;
-    background-color: white;    
+    background-color: white;
 }
 
 .wiki_text_block .compact {
@@ -1421,7 +1432,6 @@
     text-align: center;
     line-height: 2em;
     -moz-border-radius: 7px;
-         
 }
 
 .report {
Index: www/views/textblock_diff.php
===================================================================
--- www/views/textblock_diff.php	(revision 967)
+++ www/views/textblock_diff.php	(working copy)
@@ -2,13 +2,34 @@
 
 include('header.php');
 
+$min_rev_id = min($revfrom_id, $revto_id);
+$max_rev_id = max($revfrom_id, $revto_id);
+
 ?>
 
+<div class="swap_diff">
+<?= format_link(url_textblock_diff($page_name, $revto_id, $revfrom_id), "Inverseaza reviziile") ?>
+</div>
+
 <h1>Diferente pentru
 <?= format_link(url_textblock($page_name), $page_name) ?> intre reviziile
     <?= format_link(url_textblock_revision($page_name, $revfrom_id), "#$revfrom_id") ?> si
     <?= format_link(url_textblock_revision($page_name, $revto_id), "#$revto_id") ?>
 </h1>
+
+<div class="diff_navbar">
+<?php if ($max_rev_id < $rev_count) { ?>
+    <div class="next_diff">
+    <?= format_link(url_textblock_diff($page_name, $max_rev_id, $max_rev_id + 1), "Diferente intre #" . $max_rev_id . " si #" . ($max_rev_id + 1)); ?>
+    </div>
+<?php } ?>
+<?php if ($min_rev_id > 1) { ?>
+    <div class="prev_diff">
+    <?= format_link(url_textblock_diff($page_name, $min_rev_id - 1, $min_rev_id), "Diferente intre #" . ($min_rev_id - 1) . " si #" . $min_rev_id); ?>
+    </div>
+<?php } ?>
+</div>
+
 <?php
 
 function print_diff($diff) {
@@ -26,7 +47,7 @@
                         if ($chunk['type'] != 'normal') {
                             $output .= '<'.$chunk['type'].'>';
                         }
-                        $output .= html_escape($chunk['string']); 
+                        $output .= html_escape($chunk['string']);
                         if ($chunk['type'] != 'normal') {
                             $output .= '</'.$chunk['type'].'>';
                         }
