Enjoy,
peterb

Code: Select all
;- Author : Petr Vavrin (peterb)
;- Location : Czech Republic
;- Email : pb.pb@centrum.cz
Enumeration
#window
#compare_list
#file1
#file2
#Compare
#InputFile1
#InputFile2
#BrowseInputFile1
#BrowseInputFile2
EndEnumeration
Structure compare
original.s
trimmed.s
md5.s
line.l
line_len.l
line_p.l
shift.l
EndStructure
Macro IIf (expr, truepart, falsepart)
If expr : truepart : Else : falsepart : EndIf
EndMacro
Procedure max ( value1.l, value2.l )
IIf ( value2 > value1, max.l = value2, max.l = value1 )
ProcedureReturn max
EndProcedure
Structure index
line_length.l
line_number.l
EndStructure
Procedure CompareData ( file1.s, file2.s )
ClearGadgetItemList ( #compare_list )
NewList array1.compare()
NewList array2.compare()
NewList array1_index.index()
NewList array2_index.index()
Dim array2_line_len_min.l( 4096 )
Dim array2_line_len_max.l( 4096 )
Dim tmp.l( 65535 )
For c = 0 To 4096
array2_line_len_min( c ) = -1
array2_line_len_max( c ) = -1
Next
c = 0
If FileSize ( file1 )
If OpenFile ( #file1, file1 )
Repeat
line.s = ReadString ( #file1 )
line_trim.s = Trim ( line )
line_len.l = Len ( line_trim )
AddElement ( array1() )
array1()\original = line
array1()\trimmed = line_trim
array1()\md5 = MD5Fingerprint ( @line_trim, line_len )
array1()\line = c
array1()\line_len = line_len
array1()\line_p = -1
array1()\shift = 0
c + 1
Until Eof ( #file1 )
CloseFile ( #file1 )
EndIf
EndIf
c = 0
If FileSize ( file2 )
If OpenFile ( #file2, file2 )
Repeat
line.s = ReadString ( #file2 )
line_trim.s = Trim ( line )
line_len.l = Len ( line_trim )
AddElement ( array2() )
array2()\original = line
array2()\trimmed = line_trim
array2()\md5 = MD5Fingerprint ( @line_trim, line_len )
array2()\line = c
array2()\line_len = line_len
array2()\line_p = -1
array2()\shift = 0
AddElement ( array2_index() )
array2_index()\line_length = line_len
array2_index()\line_number = c
c + 1
Until Eof ( #file2 )
CloseFile ( #file2 )
EndIf
EndIf
SortStructuredList ( array2_index(), 0, OffsetOf ( index\line_length ), #PB_Sort_Long )
c = 0
ResetList ( array2_index() )
While NextElement ( array2_index() )
line_length.l = array2_index()\line_length
If array2_line_len_min( line_length ) = -1
array2_line_len_min( line_length ) = c
EndIf
array2_line_len_max( line_length ) = c
c + 1
Wend
For c = 0 To 4096
If array2_line_len_min( c ) > -1
first = array2_line_len_min( c )
last = array2_line_len_max( c )
ReDim tmp( last - first )
x = 0
For i = first To last
SelectElement ( array2_index(), i)
tmp( x ) = array2_index()\line_number
x + 1
Next
SortArray ( tmp(), 0 )
x = 0
For i = first To last
SelectElement ( array2_index(), i )
array2_index()\line_number = tmp( x )
x + 1
Next
EndIf
Next
array1_count = CountList ( array1() )
array2_count = CountList ( array2() )
If array1_count > 0 And array2_count > 0
p1 = 0
p2_last = 0
While p1 <= array1_count
SelectElement( array1(), p1 )
array1_line_length = array1()\line_len
If array2_line_len_min( array1_line_length ) > -1
For p2 = array2_line_len_min( array1_line_length ) To array2_line_len_max( array1_line_length )
SelectElement ( array2_index(), p2 )
If array2_index()\line_number >= p2_last
SelectElement ( array2(), array2_index()\line_number )
If array1()\md5 = array2()\md5 And Not array1()\trimmed = ""
If array1()\line_p = -1 : array1()\line_p = array2_index()\line_number : EndIf
If array2()\line_p = -1 : array2()\line_p = p1 : EndIf
p2_last = array2_index()\line_number
array2_line_len_min( array1_line_length ) = p2 + 1
Break
EndIf
EndIf
Next
EndIf
p1 + 1
Wend
c.l = 0
shift1.l = 0
shift2.l = 0
While c < max ( CountList ( array1() ), CountList ( array2() ) )
next_ = #True
If c < CountList ( array2() )
SelectElement ( array2(), c )
If array2()\line_p > -1
If ( array2()\line_p > c And array2()\line > -1 ) Or ( array2()\line_p + shift1 > c And array2()\line_p > -1 )
shift2 + 1
InsertElement ( array2() )
array2()\line = -1
array2()\line_p = -1
array2()\shift = shift2
next_ = #False
EndIf
EndIf
EndIf
If c < CountList ( array1() )
SelectElement ( array1(), c )
If array1()\line_p > -1
If ( array1()\line_p > c And array1()\line > -1 ) Or ( array1()\line_p + shift2 > c And array1()\line_p > -1 )
shift1 + 1
InsertElement ( array1() )
array1()\line = -1
array1()\line_p = -1
array1()\shift = shift1
next_ = #False
EndIf
EndIf
EndIf
If next_
c + 1
EndIf
Wend
While CountList ( array1() ) < CountList ( array2() )
AddElement ( array1() )
array1()\line = -1
array1()\line_p = -1
Wend
While CountList ( array2() ) < CountList ( array1() )
AddElement ( array2() )
array2()\line = -1
array2()\line_p = -1
Wend
ResetList ( array1() )
ResetList ( array2() )
ln = 0
While NextElement ( array1() )
NextElement ( array2() )
ln + 1
IIf ( array1()\line > -1, line1.s = Str ( array1()\line + 1 ), line1.s = "" )
IIf ( array2()\line > -1, line2.s = Str ( array2()\line + 1 ), line2.s = "" )
If array1()\line_p > -1 And array1()\line_p = array2()\line
color = RGB ( 255, 255, 255 ) : state.s = "="
ElseIf array2()\line > -1 And array1()\line = -1
color = RGB ( 151, 207, 255 ) : state.s = ">"
ElseIf array1()\line > -1 And array2()\line = -1
color = RGB ( 249, 178, 178 ) : state.s = "<"
ElseIf array1()\trimmed = array2()\trimmed
color = RGB ( 255, 255, 255 ) : state.s = "="
Else
color = RGB ( 172, 251, 133 ) : state.s = "!"
EndIf
AddGadgetItem( #compare_list, ln - 1, Str(ln) + Chr(10) + line1 + Chr(10) + array1()\original + Chr(10) + state + Chr(10) + line2 + Chr(10) + array2()\original )
SetGadgetItemColor(#compare_list, ln - 1, #PB_Gadget_BackColor, color)
SetGadgetItemColor(#compare_list, ln - 1, #PB_Gadget_BackColor, RGB ( 200, 200, 200 ), 0)
SetGadgetItemColor(#compare_list, ln - 1, #PB_Gadget_BackColor, RGB ( 220, 220, 220 ), 1)
SetGadgetItemColor(#compare_list, ln - 1, #PB_Gadget_BackColor, RGB ( 255, 220, 0 ), 3)
SetGadgetItemColor(#compare_list, ln - 1, #PB_Gadget_BackColor, RGB ( 220, 220, 220 ), 4)
Wend
EndIf
EndProcedure
Procedure AlignColumn ( gadget, column, align)
gadget_id = GadgetID ( gadget )
liColumn.LV_COLUMN
liColumn\mask = #LVCF_FMT
liColumn\fmt = align
SendMessage_ ( gadget_id, #LVM_SETCOLUMN, column, liColumn )
EndProcedure
If OpenWindow ( #window, 0, 0, 800, 600, "PB File Compare", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered ) And CreateGadgetList ( WindowID ( #window ) )
TextGadget ( #PB_Any, 15, 15, 60, 20, "Input File 1:")
TextGadget ( #PB_Any, 15, 40, 60, 20, "Input File 2:")
StringGadget ( #InputFile1, 80, 10, 435, 20, "", #WS_EX_STATICEDGE | #WS_BORDER)
StringGadget ( #InputFile2, 80, 35, 435, 20, "", #WS_EX_STATICEDGE | #WS_BORDER)
ButtonGadget ( #BrowseInputFile1, 520, 10, 80, 20, "Browse", #BS_FLAT )
ButtonGadget ( #BrowseInputFile2, 520, 35, 80, 20, "Browse", #BS_FLAT )
ButtonGadget ( #Compare, 620, 10, 160, 45, "Compare", #BS_FLAT )
ListIconGadget ( #compare_list, 15, 70, WindowWidth( #window ) - 30, WindowHeight( #window ) - 90, "line", 50, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #ES_MULTILINE )
AddGadgetColumn ( #compare_list, 1, "line 1", 50)
AddGadgetColumn ( #compare_list, 2, "content 1", 270)
AddGadgetColumn ( #compare_list, 3, "", 30)
AddGadgetColumn ( #compare_list, 4, "line 2", 50)
AddGadgetColumn ( #compare_list, 5, "content 2", 270)
AlignColumn ( #compare_list, 0, #LVCFMT_RIGHT) ; #LVCFMT_LEFT | #LVCFMT_CENTER | #LVCFMT_RIGHT
AlignColumn ( #compare_list, 1, #LVCFMT_RIGHT) ; #LVCFMT_LEFT | #LVCFMT_CENTER | #LVCFMT_RIGHT
AlignColumn ( #compare_list, 3, #LVCFMT_CENTER) ; #LVCFMT_LEFT | #LVCFMT_CENTER | #LVCFMT_RIGHT
AlignColumn ( #compare_list, 4, #LVCFMT_RIGHT) ; #LVCFMT_LEFT | #LVCFMT_CENTER | #LVCFMT_RIGHT
SetGadgetColor ( #compare_list, #PB_Gadget_LineColor, RGB ( 225, 225, 225 ) )
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget
Select EventGadget()
Case #Compare
file1.s = GetGadgetText ( #InputFile1 )
file2.s = GetGadgetText ( #InputFile2 )
If FileSize ( file1 ) > 0
SetGadgetColor ( #InputFile1, #PB_Gadget_BackColor, RGB ( 255, 255, 255 ) )
file1_state = #True
Else
SetGadgetColor ( #InputFile1, #PB_Gadget_BackColor, RGB ( 255, 200, 200 ) )
file1_state = #False
EndIf
If FileSize ( file2 ) > 0
SetGadgetColor ( #InputFile2, #PB_Gadget_BackColor, RGB ( 255, 255, 255 ) )
file2_state = #True
Else
SetGadgetColor ( #InputFile2, #PB_Gadget_BackColor, RGB ( 255, 200, 200 ) )
file2_state = #False
EndIf
If file1_state And file2_state
CompareData ( file1, file2 )
EndIf
Case #BrowseInputFile1
last_path.s = GetPathPart ( GetGadgetText ( #InputFile1 ) )
IIf ( last_path <> "", StandardFile$ = last_path, StandardFile$ = "C:\" )
File$ = OpenFileRequester ( "Please choose file #1 to load", StandardFile$, "(*.*)", 0 )
If File$
SetGadgetText ( #InputFile1, File$ )
EndIf
Case #BrowseInputFile2
last_path.s = GetPathPart ( GetGadgetText ( #InputFile2 ) )
IIf ( last_path <> "", StandardFile$ = last_path, StandardFile$ = "C:\" )
File$ = OpenFileRequester ( "Please choose file #2 to load", StandardFile$, "(*.*)", 0 )
If File$
SetGadgetText ( #InputFile2, File$ )
EndIf
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
End