📄 compitem.c
字号:
/****************************** Module Header *******************************
* Module Name: COMPITEM.C
*
* Module which does the comparison between two files.
*
* Functions:
*
* ci_copytext()
* ci_makecomposite()
* ci_compare()
* ci_onesection()
* compitem_new()
* compitem_delete()
* compitem_discardsections()
* compitem_getcomposite()
* compitem_getleftsections()
* compitem_getrightsections()
* compitem_getleftfile()
* compitem_getrightfile()
* compitem_getstate()
* compitem_gettext_tag()
* compitem_gettext_result()
* compitem_getfilename()
* compitem_frefilename()
*
* Comments:
*
* This module uses the structure compitem which is a data type that knows
* about two files, and can compare them. The result of the comparison
* is a list of sections for each file, and a composite list of sections
* representing the comparison of the two files.
*
* A compitem has a state (one of the integer values defined in state.h)
* representing the result of the comparison. It can also be
* queried for the text result (text equivalent of the state) as well
* as the tag - or title for this compitem (usually a text string containing
* the name(s) of the files being compared).
*
* A compitem will supply a composite section list even if the files are
* the same, or if there is only one file. The composite section list will
* only be built (and the files read in) when the compitem_getcomposite()
* call is made (and not at compitem_new time).
*
*
****************************************************************************/
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include "gutils.h"
#include "state.h"
#include "windiff.h"
#include "wdiffrc.h"
#include "list.h"
#include "line.h"
#include "scandir.h"
#include "file.h"
#include "section.h"
#include "compitem.h"
struct compitem {
FILEDATA left; /* handle for left-hand file */
FILEDATA right; /* handle for right-hand file */
LIST secs_composite; /* list of sections (composite file)*/
LIST secs_left; /* list of sections (left file) */
LIST secs_right; /* list of sections (right file) */
int state; /* compitem state - result of compare */
BOOL bDiscard; /* true if not alloc-ed on list */
LPSTR tag; /* text for tag (title of compitem) */
LPSTR result; /* text equivalent of state */
};
LPSTR ci_copytext(LPSTR in);
void ci_makecomposite(COMPITEM ci);
void ci_compare(COMPITEM ci);
/***************************************************************************
* Function: compitem_new
*
* Purpose:
*
* Returns a handle to a new compitem - given the filenames for the
* left and right files to be compared. Either left or right or neither
* (but not both) may be null. In this case we set the state accordingly.
*
* The parameters are handles to DIRITEM objects: these allow us to get the
* the name of the file relative to the compare roots (needed for the tag)
* and the absolute name of the file (needed for opening the file).
*
* Comments:
*
* If the list parameter is not null, the List_New* functions are used to
* allocate memory for the compitem. We remember this (in the bDiscard flag)
* so we do not delete the compitem if it was allocated on the list.
*
* If the list parameter is null, the memory
* for the compitem is allocated from the gmem_* heap initialised by the app.
*
****************************************************************************/
COMPITEM
compitem_new(DIRITEM leftname, DIRITEM rightname, LIST list, BOOL fExact)
{
COMPITEM ci;
LPSTR str1, str2;
char buf[2*MAX_PATH+20];
/*
* Allocate the memory for the compitem, either at the end of the
* list or in the gmem_* heap.
*/
if (list == NULL) {
/* no list passed */
ci = (COMPITEM) gmem_get(hHeap, sizeof(struct compitem));
memset(ci, 0, sizeof(struct compitem));
ci->bDiscard = TRUE;
} else {
/* add to end of list */
ci = (COMPITEM) List_NewLast(list, sizeof(struct compitem));
ci->bDiscard = FALSE;
}
ci->secs_composite = NULL;
ci->secs_left = NULL;
ci->secs_right = NULL;
/*
* Make a filedata for each of the files that are non-null.
* Filedata objects are responsible for reading the file and
* accessing the lines in it. Don't read in the files until we need to.
*/
if (leftname != NULL) {
ci->left = file_new(leftname, FALSE);
if (ci->left == NULL) {
return(NULL);
}
} else {
ci->left = NULL;
}
if ( rightname != NULL) {
ci->right = file_new(rightname, FALSE);
if (ci->right == NULL) {
return(NULL);
}
} else {
ci->right = NULL;
}
/*
* See if we have one or two files, and set the state accordingly
*/
if ( ! ci->left && !ci->right) {
/* two NULL files - this is wrong */
return(NULL);
}
/* Set the tag (title field) for this item. If the
* two files have names that match, we use just that name -
* otherwise we use both names separated by a colon 'left : right'.
*
* In both cases, use the names relative to compare root (the
* names will certainly be different if we compare the abs paths)
*/
str1 = dir_getrelname(leftname);
str2 = dir_getrelname(rightname);
/* If only one file - set name to that */
if (ci->left == NULL) {
ci->tag = ci_copytext(str2);
} else if (ci->right == NULL) {
ci->tag = ci_copytext(str1);
} else {
if (lstrcmpi(str1, str2) == 0) {
ci->tag = ci_copytext(str2);
} else {
wsprintf(buf, "%s : %s", str1, str2);
ci->tag = ci_copytext(buf);
}
}
dir_freerelname(leftname, str1);
dir_freerelname(leftname, str2);
if (ci->left == NULL) {
str1 = dir_getroot_item(rightname);
wsprintf(buf, LoadRcString(IDS_ONLY_IN), str1);
dir_freeroot_item(rightname, str1);
ci->result = ci_copytext(buf);
ci->state = STATE_FILERIGHTONLY;
} else if (ci->right == NULL) {
str1 = dir_getroot_item(leftname);
wsprintf(buf, LoadRcString(IDS_ONLY_IN), str1);
dir_freeroot_item(leftname, str1);
ci->result = ci_copytext(buf);
ci->state = STATE_FILELEFTONLY;
} else {
/* two files - are they the same ? compare
* the file sizes
*/
if (dir_getfilesize(leftname) != dir_getfilesize(rightname))
{
ci->state = STATE_DIFFER;
ci->result = ci_copytext(LoadRcString(IDS_DIFFERENT_SIZES));
} else if (!fExact){
ci->result = ci_copytext(LoadRcString(IDS_SAME_SIZE));
ci->state = STATE_SAME;
} else {
ci->result = ci_copytext(LoadRcString(IDS_IDENTICAL));
ci->state = STATE_SAME;
}
}
#if FALSE
if (dir_getfilesize(leftname) == dir_getfilesize(rightname)) {
if ( !fExact )
{
ci->result = ci_copytext("same size etc.");
ci->state = STATE_SAME;
} else {
ci->result = ci_copytext("files differ");
ci->state = STATE_DIFFER;
ci->result = ci_copytext("files differ");
}
} else {
ci->result = ci_copytext("files differ");
ci->state = STATE_DIFFER;
}
}
#endif
/*
* Building the section lists and composite lists can wait
* until needed.
*/
return(ci);
} /* compitem_new */
/***************************************************************************
* Function: compitem_delete
*
* Purpose:
*
* Deletes a compitem and free all associated data.
*
* Comments:
*
* If the ci->bDiscard flag is set, the compitem was alloc-ed on a list,
* and should not be discarded (the list itself will be deleted).
*
* The DIRDATA we were passed are not deleted. the filedata, lines
* and sections are.
***************************************************************************/
void
compitem_delete(COMPITEM ci)
{
if (ci == NULL) {
return;
}
compitem_discardsections(ci);
/* Delete the two filedatas (and associated line lists) */
file_delete(ci->left);
file_delete(ci->right);
/* text we allocated */
gmem_free(hHeap, ci->tag, lstrlen(ci->tag) + 1);
gmem_free(hHeap, ci->result, lstrlen(ci->result) + 1);
/* Free the compitem struct itself if not alloced on a list */
if (ci->bDiscard) {
gmem_free(hHeap, (LPSTR) ci, sizeof(struct compitem));
}
}
/*
/***************************************************************************
* Function: compitem_discardsections
*
* Purpose:
*
* To discard sections - throw away cached information relating to the
* comparison (but not the files if they are read into memory). This
* is used to force a re-compare if changes in the comparison options
* are made
*
***************************************************************************/
void
compitem_discardsections(COMPITEM ci)
{
/* delete the lists of sections we built */
if (ci == NULL) {
return;
}
if (ci->secs_composite) {
section_deletelist(ci->secs_composite);
ci->secs_composite = NULL;
}
if (ci->secs_left) {
section_deletelist(ci->secs_left);
ci->secs_left = NULL;
}
if (ci->secs_right) {
section_deletelist(ci->secs_right);
ci->secs_right = NULL;
}
/* reset the line lists to throw away cached hash codes and links */
if (ci->left != NULL) {
file_reset(ci->left);
}
if (ci->right != NULL) {
file_reset(ci->right);
}
}
/***************************************************************************
* Function: compitem_getcomposite
*
* Purpose:
*
* To get the handle for the composite section list
*
***************************************************************************/
LIST
compitem_getcomposite(COMPITEM ci)
{
if (ci == NULL) {
return NULL;
}
/*
* do the comparison if we haven't already done it
*/
if (ci->secs_composite == NULL) {
ci_makecomposite(ci);
}
return(ci->secs_composite);
}
/***************************************************************************
* Function: compitem_getleftsections
*
* Purpose:
*
* To get the handle for the list of sections in the left file
*
***************************************************************************/
LIST
compitem_getleftsections(COMPITEM ci)
{
if (ci == NULL) {
return NULL;
}
/*
* do the comparison if we haven't already done it
*/
if (ci->secs_composite == NULL) {
ci_makecomposite(ci);
}
return(ci->secs_left);
}
/***************************************************************************
* Function: compitem_getrightsections
*
* Purpose:
*
* To get the handle for the list of sections in the right file
*
***************************************************************************/
LIST
compitem_getrightsections(COMPITEM ci)
{
if (ci == NULL) {
return NULL;
}
/*
* do the comparison if we haven't already done it
*/
if (ci->secs_composite == NULL) {
ci_makecomposite(ci);
}
return(ci->secs_right);
}
/***************************************************************************
* Function: compitem_getleftfile
*
* Purpose:
*
* To get the handle to the left file itself
*
***************************************************************************/
FILEDATA
compitem_getleftfile(COMPITEM ci)
{
if (ci == NULL) {
return(NULL);
}
return(ci->left);
}
/***************************************************************************
* Function: compitem_getrightfile
*
* Purpose:
*
* To get the handle to the right file itself
*
***************************************************************************/
FILEDATA
compitem_getrightfile(COMPITEM ci)
{
if (ci == NULL) {
return(NULL);
}
return(ci->right);
}
/***************************************************************************
* Function: compitem_getstate
*
* Purpose:
*
* To get the state (compare result) of this compitem
*
***************************************************************************/
int
compitem_getstate(COMPITEM ci)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -