
Now we'll describe the final segment, which compares contents.

It is necessary to notice that it is meaningful if the databases are
quite similar to one another. For example, it could be two telephone
directories.

The logic of process:
- If the program achieves a completion of any file, then the process
  will be stopped.
- Program compares fields:
  Memo with Memo,
  any numerical with any numerical,
  otherwise program will compare  fields as strings without trailing
  spaces.

- If memo-fields are different - the program will print the first 20 
  characters of the contents from both databases.
- If the numerical fields are different - the program will print
  their values.
- For other  fields, the program will print the  first 20 characters
  of each field.

The program will not compare memo-fields with any other fields. 
If the program detects such a situation, it will print the concerned
information once ( see variable memo_message ).

I wrote the necessary comments for this function in the body.


void
CmpContent()
{
 int	i, j, k;
 int	ret;
 int	memo_message=0;
 double	x,y;
 char	*f1,*f2;

 f1=strrchr(d1->filename, '\\');
 f2=strrchr(d2->filename, '\\');
 if (f1) ++f1; else f1=d1->filename;
 if (f2) ++f2; else f2=d2->filename;

 for(i=0;i<reccount(d1);i++)
 {
  if (i>=reccount(d2))
  {
	//The end of the second database was found
	printf("EOF found: %s\n", d2->filename);
	break;
  } 

//read record from each database
 
  ReadRecord(d1, i);
  ReadRecord(d2, i);

//cycle by fields
 
  for(j=0;j<fieldcount(d1);j++)
   if (ret=field_exist(d1, j, d2, &k))
   {
	if (if_memo_type(d1, j) && if_memo_type(d2, k))
	{
		//if both fields are memo

		//read fields
		d1->memo_block=GetMemo(d1, j);
		d2->memo_block=GetMemo(d2, j);

		if (!d1->memo_block && !d2->memo_block) continue;
		if (!d1->memo_block || !d2->memo_block)
		{
		// if one of two fields is empty

		   if (d1->memo_block) d1->memo_block[__min(20, strlen(d1->memo_block))]='\0';
		   if (d2->memo_block) d2->memo_block[__min(20, strlen(d2->memo_block))]='\0';
		   printf("%s: %s - %s <> %s: %s - %s\n\n",
		   	f1, d1->fld[j].name, (d1->memo_block)?d1->memo_block:"<empty>",
		   	f2, d2->fld[k].name, (d2->memo_block)?d2->memo_block:"<empty>"
		   	);
		}
		else
		{
		//comparison of contents

		   if (strcmp(d1->memo_block, d2->memo_block))
		      {
			d1->memo_block[__min(20, strlen(d1->memo_block))]='\0';
			d2->memo_block[__min(20, strlen(d2->memo_block))]='\0';
		   printf("%s: %s - %s <> %s: %s - %s\n\n",
		   	f1, d1->fld[j].name, d1->memo_block,
		   	f2, d2->fld[k].name, d2->memo_block
		   	);
		      }
		}
		//release memory
		FreeMemo(d1);
		FreeMemo(d2);
	}
	else
	  if (if_memo_type(d1, j) || if_memo_type(d2, k))
	  {
		//if one field is memo and another is not memo

		if (!memo_message)
		   printf("Can't compare %s: %s (%s) with %s: %s (%s)\n\n",
		   	f1, d1->fld[j].name, GetTypeName(d1, j),
		   	f2, d2->fld[k].name, GetTypeName(d2, k)
		   	);
		memo_message=1;
	  }
	  else
	  {
		if (if_digit_type(d1, j) && if_digit_type(d2, k))
		{
			//if both fields are numeric - N,F,I,B,Y

			if ((x=GetValue(d1, j)) != (y=GetValue(d2, k)))
			   printf("%12s %5d: %-10s (%c) %f <> %12s %5d: %-10s (%c) %f\n\n",
			   	f1, GetOrder(d1, i), d1->fld[j].name, d1->fld[j].type, x,
			   	f2, GetOrder(d2, i), d2->fld[k].name, d2->fld[k].type, y);
		}
		else
		{
			//comparison as strings

			//get contents of fields as strings
			GetStr(d1,j); GetStr(d2, k);

			//remove trailing spaces
			DStrTrim(d1,1); DStrTrim(d2,1);

			if (strcmp(d1->str, d2->str))
			{
			   d1->str[__min(20, strlen(d1->str))]='\0';
			   d2->str[__min(20, strlen(d2->str))]='\0';
			   printf(">%12s  %5d: %-10s (%c) %s\n<>%12s %5d: %-10s (%c) %s\n\n",
			   	f1, GetOrder(d1, i), d1->fld[j].name, d1->fld[j].type, d1->str,
			   	f2, GetOrder(d2, i), d2->fld[k].name, d2->fld[k].type, d2->str);
			}
		}
	  }
   }
 }
 if (i<reccount(d2)) printf("EOF found: %s\n", d1->filename);
}
