Logo Search packages:      
Sourcecode: easydiff.app version File versions  Download package

DiffWindowController.m

/*
 * DiffWindowController.m
 *
 * Copyright (c) 2002 Pierre-Yves Rivaille <pyrivail@ens-lyon.fr>
 *
 * This file is part of EasyDiff.app.
 *
 * EasyDiff.app is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * EasyDiff.app is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EasyDiff.app; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <AppKit/AppKit.h>
//#include "DiffTextView.h"
//#include "DiffMiddleView.h"
#include "DiffView.h"
#include "DiffWindowController.h"
#include "DiffWrapper.h"

//extern void tasktest(NSString *file1, NSString *file2, NSMutableArray **r1, NSMutableArray **r2);


00034 @interface PatchData : NSObject
{
@public
  NSMutableString *patchString;
  int start;
  int end;
  int lineDifference;
} 
@end

@implementation PatchData
@end




@interface DiffWindowController (Private)
- (void) diffViewFrameDidChange: (NSNotification*) aNotification;
- (id) _initWithFilename: (NSString *) filename1
           andFilename: (NSString *) filename2;
- (NSMutableString *) _patchMutableString: (int) direction;
- (void) saveMergedAt: (NSString *) mergedName;
@end

@implementation DiffWindowController


- (id) initWithFilename: (NSString *) filename1
      andTempFilename: (NSString *) filename2
{
  [self _initWithFilename: filename1
      andFilename: filename2];

  tempFilename = filename2;

  [[self window] setTitle:
               [NSString 
                 stringWithFormat: 
                   @"Comparing %@ to the CVS version",
                 [filename1 lastPathComponent]]];
               
  [[self window] makeKeyAndOrderFront: self];

  leftFileName = RETAIN(filename1);
  rightFileName = nil;

  return self;
}

- (id) initWithFilename: (NSString *) filename1
          andFilename: (NSString *) filename2
{
  [self _initWithFilename: filename1
      andFilename: filename2];

  tempFilename = nil;

  [[self window] setTitle:
               [NSString 
                 stringWithFormat: 
                   @"Comparing %@ to %@",
                 [filename1 lastPathComponent],
                 [filename2 lastPathComponent]]];


  [[self window] makeKeyAndOrderFront: self];

  /*
  [NSApp addWindowsItem: [self window]
       title: [[self window] title]
       filename: NO];
  */

  leftFileName = RETAIN(filename1);
  rightFileName = RETAIN(filename2);

  NSDebugLog(@"windowsMenu %@", [NSApp windowsMenu]);

  return self;
}


- (id) _initWithFilename: (NSString *) filename1
           andFilename: (NSString *) filename2
{
  [self initWithWindowNibName: @"window"];

  [self window];


  NSDebugLog(@"%@", scroller);
  [scroller setArrowsPosition: NSScrollerArrowsMaxEnd];
  [scroller setFloatValue:0.5 knobProportion:0.2];
  [scroller setEnabled: YES];

  diffWrapper = [[DiffWrapper alloc] initWithFilename: filename1
                             andFilename: filename2];

  [diffWrapper compare];

  leftChanges = [diffWrapper leftChanges];
  rightChanges = [diffWrapper rightChanges];
  //  tasktest(filename1, filename2, &leftChanges, &rightChanges);

  RETAIN(leftChanges);
  RETAIN(rightChanges);

  {
    NSString *string1;
    NSString *string2;

    string1 = [NSString stringWithContentsOfFile: 
                   filename1];
    string2 = [NSString stringWithContentsOfFile: 
                   filename2];

    
    [diffView setLeftString: string1];
    [diffView setRightString: string2];

    [diffView setLeftChanges: leftChanges
            andRightChanges: rightChanges];

    [diffView setLeftLineRanges: [diffWrapper leftLineRanges]
            andRightLineRanges: [diffWrapper rightLineRanges]];

    [scroller setFloatValue: 0.
            knobProportion: 
            ([diffView frame].size.height /
             [diffView mergeFileHeight])];

    [diffView tile];

    [diffView setPostsFrameChangedNotifications: YES];
    [[NSNotificationCenter defaultCenter]
      addObserver: self
      selector: @selector(diffViewFrameDidChange:)
      name: NSViewFrameDidChangeNotification
      object: diffView];

    choices = (int *) calloc([leftChanges count], sizeof(int));

  }

  //  NSLog(@"gonna orderFront %@",[self window]);
  [self diffViewFrameDidChange: nil];
  //  [[self window] orderFrontRegardless];
  
  return self;
  
}

- (void) diffViewFrameDidChange: (NSNotification*) aNotification
{

  [diffView computeScrollerSize];

  if ([diffView frame].size.height >= [diffView mergeFileHeight])
    {
      [scroller setEnabled: NO];
    }
  else
    {
      [scroller setEnabled: YES];
      [scroller setFloatValue: [scroller floatValue]
            knobProportion: 
              ([diffView frame].size.height /
               [diffView mergeFileHeight])];
      [diffView doScroll: scroller];
    }
}

- (void) windowWillClose: (id) sender
{
  NSDebugLog(@"windowWillClose called");
  //  RELEASE([self window]);
  AUTORELEASE(self);
}

- (void) dealloc
{
  NSDebugLog(@"dealloc called");
  if (tempFilename != nil)
    {
      if ([[NSFileManager defaultManager]
          removeFileAtPath: tempFilename
          handler: nil] == NO)
      NSLog(@"We could not delete %@", tempFilename);
    }
  TEST_RELEASE(leftFileName);
  TEST_RELEASE(rightFileName);
  [super dealloc];
}


- (void) matrixButtonClicked: (id) sender
{
  int oldChoice = choices[[sender tag]];

  NSDebugLog(@"matrixButtonClicked %d, %d", [sender tag],
           [sender selectedColumn]);

 
  choices[[sender tag]] = [sender selectedColumn] - 1;

  if ((oldChoice == -1) && (choices[[sender tag]] != -1))
    {
      [[diffView leftTextView] setColor: 
                         [NSColor colorWithDeviceRed:0.7 
                                 green:0.7 
                                 blue:1. 
                                 alpha:1.]
                         forChangeNumber: [sender tag]];
    }
  else if ((oldChoice != -1) && (choices[[sender tag]] == -1))
    {
      [[diffView leftTextView] setColor: 
                         [NSColor whiteColor]
                         forChangeNumber: [sender tag]];
    }

  if ((oldChoice == 1) && (choices[[sender tag]] != 1))
    {
      [[diffView rightTextView] setColor: 
                          [NSColor colorWithDeviceRed:0.7 
                                  green:0.7 
                                  blue:1. 
                                  alpha:1.]
                        forChangeNumber: [sender tag]];
    }
  else if ((oldChoice != 1) && (choices[[sender tag]] == 1))
    {
      [[diffView rightTextView] setColor: 
                          [NSColor whiteColor]
                        forChangeNumber: [sender tag]];
    }
}

- (void) selectAllLeftChanges: (id) sender
{
  int i;
  NSArray *matrixArray = [[diffView middleView] matrixArray];
  int count = [matrixArray count];

  for ( i = 0; i < count; i ++ )
    {
      if (choices[i] != - 1)
      {
        choices[i] = -1;
        [[diffView leftTextView] setColor: 
                             [NSColor whiteColor]
                           forChangeNumber: i];
        [[diffView rightTextView] setColor: 
                          [NSColor colorWithDeviceRed:0.7 
                                  green:0.7 
                                  blue:1. 
                                  alpha:1.]
                        forChangeNumber: i];
        [[matrixArray objectAtIndex: i] selectCellAtRow: 0 column:0];
      }
    }
}

- (void) selectAllRightChanges: (id) sender
{
  int i;
  NSArray *matrixArray = [[diffView middleView] matrixArray];
  int count = [matrixArray count];

  for ( i = 0; i < count; i ++ )
    {
      if (choices[i] != 1)
      {
        choices[i] = 1;
        [[diffView rightTextView] setColor: 
                             [NSColor whiteColor]
                           forChangeNumber: i];
        [[diffView leftTextView] setColor: 
                          [NSColor colorWithDeviceRed:0.7 
                                  green:0.7 
                                  blue:1. 
                                  alpha:1.]
                        forChangeNumber: i];
        [[matrixArray objectAtIndex: i] selectCellAtRow: 0 column:2];
      }
    }
}


- (void) selectNoChanges: (id) sender
{
  int i;
  NSArray *matrixArray = [[diffView middleView] matrixArray];
  int count = [matrixArray count];

  for ( i = 0; i < count; i ++ )
    {
      if (choices[i] != 0)
      {
        choices[i] = 0;
        [[diffView leftTextView] setColor: 
                             [NSColor colorWithDeviceRed:0.7 
                                    green:0.7 
                                    blue:1. 
                                    alpha:1.]
                           forChangeNumber: i];
        [[diffView rightTextView] setColor: 
                              [NSColor colorWithDeviceRed:0.7 
                                     green:0.7 
                                     blue:1. 
                                     alpha:1.]
                            forChangeNumber: i];
        [[matrixArray objectAtIndex: i] selectCellAtRow: 0 column:1];
      }
    }
  
}

- (void) savePatchFromRight: (id) sender
{
  NSMutableString *patchString;

  int result;
  NSSavePanel *sPanel;
  NSString *path = [[NSUserDefaults standardUserDefaults] 
                objectForKey:@"OpenDirectory"];
  NSString *mergedName;


  sPanel = [NSSavePanel savePanel];
  //  [sPanel setAllowsMultipleSelection:NO];
  result = [sPanel runModalForDirectory: path
               file: @""];
  
  if (result != NSOKButton)
    return;

  path = [sPanel directory];

  mergedName = [sPanel filename];

  [[NSUserDefaults standardUserDefaults] 
    setObject: path
    forKey:@"OpenDirectory"]; 


  patchString = [self _patchMutableString: -1];
  [patchString insertString: [NSString stringWithFormat: @"+++ %@\n", 
                               leftFileName]
             atIndex: 0];
  if (rightFileName)
    {
      [patchString insertString: [NSString stringWithFormat: @"--- %@\n", 
                                 rightFileName]
               atIndex: 0];
    }
  else
    {
      [patchString insertString: [NSString stringWithFormat: @"--- %@\n", 
                                 leftFileName]
               atIndex: 0];
    }
    
  [patchString writeToFile: mergedName atomically: YES];
}

- (void) savePatchFromLeft: (id) sender
{
  NSMutableString *patchString;

  int result;
  NSSavePanel *sPanel;
  NSString *path = [[NSUserDefaults standardUserDefaults] 
                objectForKey:@"OpenDirectory"];
  NSString *mergedName;


  sPanel = [NSSavePanel savePanel];
  //  [sPanel setAllowsMultipleSelection:NO];
  result = [sPanel runModalForDirectory: path
               file: @""];
  
  if (result != NSOKButton)
    return;

  path = [sPanel directory];

  mergedName = [sPanel filename];

  [[NSUserDefaults standardUserDefaults] 
    setObject: path
    forKey:@"OpenDirectory"]; 


  patchString = [self _patchMutableString: 1];
  if (rightFileName)
    {
      [patchString insertString: [NSString stringWithFormat: @"+++ %@\n", 
                                 rightFileName]
               atIndex: 0];
    }
  else
    {
      [patchString insertString: [NSString stringWithFormat: @"+++ %@\n", 
                                 leftFileName]
               atIndex: 0];
    }
  [patchString insertString: [NSString stringWithFormat: @"--- %@\n", 
                               leftFileName]
             atIndex: 0];
  

  [patchString writeToFile: mergedName atomically: YES];
}

- (NSMutableString *) _patchMutableString: (int) direction
{
  NSArray *flr;
  NSArray *tlr;
  NSString *fstr;
  NSString *tstr;
  
  NSMutableArray *patchArray = [[NSMutableArray alloc] 
                         initWithCapacity:
                           ([leftChanges count] / 2) + 1];

  NSMutableArray *finalArray = [[NSMutableArray alloc] 
                         initWithCapacity:
                           ([leftChanges count] / 2) + 1];
  NSArray *fromChanges;
  NSArray *toChanges;
  NSMutableString *stringToInsert;
  PatchData *p, *pp;
  int i, j, k;
  int toStart;
  int toEnd;
  int count;
  int linesCount;

  if (direction > 0)
    {
      flr = [diffWrapper leftLineRanges];
      tlr = [diffWrapper rightLineRanges];
      fstr = [diffWrapper leftString];
      tstr = [diffWrapper rightString];
      fromChanges = leftChanges;
      toChanges = rightChanges;
    }
  else
    {
      flr = [diffWrapper rightLineRanges];
      tlr = [diffWrapper leftLineRanges];
      fstr = [diffWrapper rightString];
      tstr = [diffWrapper leftString];
      fromChanges = rightChanges;
      toChanges = leftChanges;
    }
  linesCount = [flr count] - 1;

  for ( i = 0; i < [fromChanges count] - 1; i += 2 )
    {
      p = [[PatchData alloc] init];
      p->patchString = (NSMutableString*)[NSMutableString string];

      if (choices[i/2] * direction > 0)
      {
        p->start = [[fromChanges objectAtIndex: i] 
                     intValue];
        p->end = [[fromChanges objectAtIndex: i + 1] 
                   intValue];
        toStart = [[toChanges objectAtIndex: i] 
                   intValue];
        toEnd = [[toChanges objectAtIndex: i + 1] 
                   intValue];
        p->lineDifference = (toEnd - toStart) - 
          (p->end - p->start);

        for (j = p->start; j < p->end; j++ )
          {
            [p->patchString appendString: @"-"];
            [p->patchString appendString:[fstr 
                                   substringWithRange: 
                                     NSMakeRange
                                   ([[flr objectAtIndex: j] intValue] + 1,
                                    [[flr objectAtIndex: j+1] intValue] -
                                    [[flr objectAtIndex: j] intValue])]];
          }
        for (j = toStart; j < toEnd; j++ )
          {
            [p->patchString appendString: @"+"];
            [p->patchString appendString:[tstr
                                   substringWithRange: 
                                     NSMakeRange
                                   ([[tlr objectAtIndex: j] intValue] + 1,
                                    [[tlr objectAtIndex: j+1] intValue] -
                                    [[tlr objectAtIndex: j] intValue])]];
          }
        [patchArray addObject: p];

      }
      else if (choices[i/2] * direction < 0)
      {
      }
      else if (choices[i/2] == 0)
      {
        p->start = [[fromChanges objectAtIndex: i] 
                     intValue];
        p->end = [[fromChanges objectAtIndex: i + 1] 
                   intValue];
        p->lineDifference = - (p->end - p->start);

        for (j = p->start; j < p->end; j++ )
          {
            [p->patchString appendString: @"-"];
            [p->patchString appendString:[fstr 
                                   substringWithRange: 
                                     NSMakeRange
                                   ([[flr objectAtIndex: j] intValue] + 1,
                                    [[flr objectAtIndex: j+1] intValue] -
                                    [[flr objectAtIndex: j] intValue])]];
          }
        
        if (p->lineDifference != 0)
          [patchArray addObject: p];
        
      }
    }

  


  i = 0;
  count = [patchArray count];
  
  pp = nil;

  while( i < count )
    {
      p = [patchArray objectAtIndex: i];


      if ((pp == nil) || (p->start - pp->end >= 6))
      {
        // two separate chunks
        if (pp != nil)
          {
            j = pp->end + 3;
            if (j >= linesCount)
            j = linesCount;
            stringToInsert = (NSMutableString*)[NSMutableString string];
            for ( k = pp->end; k < j; k++ )
            {
              [stringToInsert appendString: @" "];
              [stringToInsert appendString: [fstr 
                                      substringWithRange: 
                                        NSMakeRange
                                      ([[flr objectAtIndex: k] intValue] + 1,
                                       [[flr objectAtIndex: k+1] intValue] -
                                       [[flr objectAtIndex: k] intValue])]];
            }
            [pp->patchString appendString: stringToInsert];
            pp->end = j;
            
            [finalArray addObject: pp];
          }

        // new chunk
        pp = [[PatchData alloc] init];;

        j = p->start - 3;
        if ( j < 0)
          j = 0;
        pp = [[PatchData alloc] init];
        pp->patchString = p->patchString;
        stringToInsert = (NSMutableString*)[NSMutableString string];
        for ( k = j; k < p->start; k++ )
          {
            [stringToInsert appendString: @" "];
            [stringToInsert appendString: [fstr 
                                   substringWithRange: 
                                     NSMakeRange
                                   ([[flr objectAtIndex: k] intValue] + 1,
                                    [[flr objectAtIndex: k+1] intValue] -
                                    [[flr objectAtIndex: k] intValue])]];
          }
        [pp->patchString insertString: stringToInsert
          atIndex: 0];
        pp->start = j;
        pp->end = p->end;
        pp->lineDifference = p->lineDifference;
        
      }
      else
      {
        // merge the two chunks
        stringToInsert = (NSMutableString*)[NSMutableString string];
        for ( k = pp->end; k < p->start; k++ )
          {
            [stringToInsert appendString: @" "];
            [stringToInsert appendString: [fstr 
                                   substringWithRange: 
                                     NSMakeRange
                                   ([[flr objectAtIndex: k] intValue] + 1,
                                    [[flr objectAtIndex: k+1] intValue] -
                                    [[flr objectAtIndex: k] intValue])]];
          }

        [pp->patchString appendString: stringToInsert];
        [pp->patchString appendString: p->patchString];
        pp->end = p->end;
        pp->lineDifference += p->lineDifference;
      }
      i++;
    }
  
  if (pp != nil)
    {
      j = pp->end + 3;
      if (j >= linesCount)
      j = linesCount;
      stringToInsert = (NSMutableString*)[NSMutableString string];
      for ( k = pp->end; k < j; k++ )
      {
        [stringToInsert appendString: @" "];
        [stringToInsert appendString: [fstr 
                                substringWithRange: 
                                  NSMakeRange
                                ([[flr objectAtIndex: k] intValue] + 1,
                                 [[flr objectAtIndex: k+1] intValue] -
                                 [[flr objectAtIndex: k] intValue])]];
      }
      [pp->patchString appendString: stringToInsert];
      pp->end = j;
      
      [finalArray addObject: pp];
    }


  {
    NSMutableString *patchFileString =
      (NSMutableString*)[NSMutableString string];

    int d = 0;
    for ( i = 0; i < [finalArray count]; i++ )
      {
      p = [finalArray objectAtIndex: i];
      [patchFileString appendFormat: 
                     @"@@ -%d,%d +%d,%d @@\n%@",
                   p->start+1,
                   p->end - p->start,
                   p->start + d + 1,
                   p->end - p->start + p->lineDifference, 
                   p->patchString];
      d += p->lineDifference;
      }

    //    NSLog(@"\n%@", patchFileString);
    return patchFileString;
  }

}


- (void) saveMergedAt: (NSString *) mergedName
{
  NSMutableString *mergedString = [NSMutableString string];
  int i;

  {
    NSArray *llr = [diffWrapper leftLineRanges];
    NSArray *rlr = [diffWrapper rightLineRanges];

    [mergedString appendString:
                [[diffWrapper leftString] 
                  substringWithRange: 
                  NSMakeRange
                  (0,
                   [[llr objectAtIndex: 
                         [[leftChanges objectAtIndex: 0] 
                         intValue]] intValue]
                   )]];
    

    for ( i = 0; i < [leftChanges count] - 1; i++ )
      {
      if (i % 2 == 1)
        {
          [mergedString appendString:
                      [[diffWrapper leftString] 
                        substringWithRange: 
                        NSMakeRange
                        ([[llr objectAtIndex: 
                               [[leftChanges objectAtIndex: i] 
                               intValue]] intValue],
                         [[llr objectAtIndex: 
                               [[leftChanges objectAtIndex: i+1] 
                               intValue]] intValue] -
                         [[llr objectAtIndex: 
                               [[leftChanges objectAtIndex: i] 
                               intValue]] intValue]
                         )]];
        }
      else
        {
          if (choices[i/2] < 0)
            {
            [mergedString appendString:
                        [[diffWrapper leftString] 
                          substringWithRange: 
                            NSMakeRange
                          ([[llr objectAtIndex: 
                                 [[leftChanges objectAtIndex: i] 
                                   intValue]] intValue],
                           [[llr objectAtIndex: 
                                 [[leftChanges objectAtIndex: i+1] 
                                   intValue]] intValue] -
                           [[llr objectAtIndex: 
                                 [[leftChanges objectAtIndex: i] 
                                   intValue]] intValue]
                           )]];
            
            }
          else if (choices[i/2] > 0)
            {
            [mergedString appendString:
                        [[diffWrapper rightString] 
                          substringWithRange: 
                            NSMakeRange
                          ([[rlr objectAtIndex: 
                                 [[rightChanges objectAtIndex: i] 
                                   intValue]] intValue],
                           [[rlr objectAtIndex: 
                                 [[rightChanges objectAtIndex: i+1] 
                                   intValue]] intValue] -
                           [[rlr objectAtIndex: 
                                 [[rightChanges objectAtIndex: i] 
                                   intValue]] intValue]
                           )]];
            
            }
          else
            {
            
            }
        }
      }

    [mergedString appendString:
                [[diffWrapper leftString] 
                  substringFromIndex: 
                  [[llr objectAtIndex: 
                         [[leftChanges objectAtIndex: 
                                     [leftChanges count] - 1] 
                         intValue]] intValue]]];
    
    //    NSLog(@"%@", mergedString);
  }
  
  
  [mergedString writeToFile: mergedName atomically: YES];
}

- (void) saveMergedFile: (id) sender
{

  int result;
  NSSavePanel *sPanel;
  NSString *path = [[NSUserDefaults standardUserDefaults] 
                objectForKey:@"OpenDirectory"];
  NSString *mergedName;


  sPanel = [NSSavePanel savePanel];
  //  [sPanel setAllowsMultipleSelection:NO];
  result = [sPanel runModalForDirectory: path
               file: @""];
  
  if (result != NSOKButton)
    return;

  path = [sPanel directory];

  mergedName = [sPanel filename];

  [[NSUserDefaults standardUserDefaults] 
    setObject: path
    forKey:@"OpenDirectory"]; 


  //  NSLog(@"%@", mergedName);

  [self saveMergedAt: mergedName];

}
@end

Generated by  Doxygen 1.6.0   Back to index