set_title('GtkDiff'); $win->connect_simple('destroy', array('gtk', 'main_quit')); $vbox = new GtkVBox(); $filehbox = new gtkhbox(); $filevbox1 = new gtkvbox(); $filevbox2 = new gtkvbox(); $filevbox3 = new gtkvbox(); $oldlabel = new GtkLabel('Old file'); $oldfile = new GtkEntry(); $oldlocate = new GtkButton('Locate'); $oldlocate->connect_simple('clicked','open',$oldfile); $newlabel = new GtkLabel('New file'); $newfile = new GtkEntry(); $newlocate = new GtkButton('Locate'); $newlocate->connect_simple('clicked','open',$newfile); $filehbox->pack_start($filevbox1,false,false); $filehbox->pack_start($filevbox2); $filehbox->pack_start($filevbox3,false,false); $filevbox1->pack_start($oldlabel); $filevbox1->pack_start($newlabel); $filevbox2->pack_start($oldfile); $filevbox2->pack_start($newfile); $filevbox3->pack_start($oldlocate); $filevbox3->pack_start($newlocate); $patchscroll = new GtkScrolledWindow(); $patch = new GtkTextView(); $patchscroll->add_with_viewport($patch); $vbox->pack_start($filehbox,false,false); $vbox->pack_start($patchscroll); $create = new GtkButton('Create'); $create->connect_simple('clicked', 'create_patch',$oldfile,$newfile,$patch); $save = new GtkButton('Save'); $bhbox = new GtkHBox(); $bhbox->pack_start($create); $bhbox->pack_start($save); $save->set_sensitive(false); $vbox->pack_start($bhbox,false,false); $win->add($vbox); $win->show_all(); Gtk::main(); function create_patch($oldfile,$newfile,$patch){ $old = $oldfile->get_text(); $new = $newfile->get_text(); if (file_exists($old) && file_exists($new)) { $old = file_get_contents($old); $new = file_get_contents($new); $buffer = $patch->get_buffer(); $buffer->set_text(PHPDiff($old,$new)); } } function open($file) { $dialog = new GtkFileChooserDialog("File Open", null, Gtk::FILE_CHOOSER_ACTION_OPEN, array(Gtk::STOCK_OK, Gtk::RESPONSE_OK), null); $dialog->show_all(); if ($dialog->run() == Gtk::RESPONSE_OK) { $selected_file = $dialog->get_filename(); $file->set_text($selected_file); } $dialog->destroy(); } function PHPDiff($old,$new) { # split the source text into arrays of lines $t1 = explode("\n",$old); $x=array_pop($t1); if ($x>'') $t1[]="$x\n\\ No newline at end of file"; $t2 = explode("\n",$new); $x=array_pop($t2); if ($x>'') $t2[]="$x\n\\ No newline at end of file"; # build a reverse-index array using the line as key and line number as value # don't store blank lines, so they won't be targets of the shortest distance # search foreach($t1 as $i=>$x) if ($x>'') $r1[$x][]=$i; foreach($t2 as $i=>$x) if ($x>'') $r2[$x][]=$i; $a1=0; $a2=0; # start at beginning of each list $actions=array(); # walk this loop until we reach the end of one of the lists while ($a1=$s1) { $d=$n; break; } if ($d>=$s1 && ($d+$s2-$a1-$a2)<($best1+$best2-$a1-$a2)) { $best1=$d; $best2=$s2; } $d=-1; foreach((array)@$r2[$t1[$s1]] as $n) if ($n>=$s2) { $d=$n; break; } if ($d>=$s2 && ($s1+$d-$a1-$a2)<($best1+$best2-$a1-$a2)) { $best1=$s1; $best2=$d; } $s1++; $s2++; } while ($a1<$best1) { $actions[]=1; $a1++; } # deleted elements while ($a2<$best2) { $actions[]=2; $a2++; } # added elements } # we've reached the end of one list, now walk to the end of the other while($a10) { $xstr = ($x1==($x0+1)) ? $x1 : ($x0+1).",$x1"; $ystr = ($y1==($y0+1)) ? $y1 : ($y0+1).",$y1"; if ($op==1) $out[] = "{$xstr}d{$y1}"; elseif ($op==3) $out[] = "{$xstr}c{$ystr}"; while ($x0<$x1) { $out[] = '< '.$t1[$x0]; $x0++; } # deleted elems if ($op==2) $out[] = "{$x1}a{$ystr}"; elseif ($op==3) $out[] = '---'; while ($y0<$y1) { $out[] = '> '.$t2[$y0]; $y0++; } # added elems } $x1++; $x0=$x1; $y1++; $y0=$y1; $op=0; } $out[] = ''; return join("\n",$out); } ?>