///////////////////////////////////////////////////////////////////////////// /* Copyright 2001 Ronald S. Burkey This file is part of GutenMark. GutenMark 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. GutenMark 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 GutenMark; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Filename: AddMarkup.c Purpose: Adds a markup record to the temporary markup file. Mods: 01/01/02 RSB Split off from MarkBody.c. */ #include #include #include #include #include "AutoMark.h" //----------------------------------------------------------------------- // Add a markup record to the markup file. Returns 0 on success. // This function plays a slightly more complex role than it would seem // at first glance. The markup file must be sorted in order of increasing // offsets into the original etext, and in almost all cases the program // actually tries to add the markup in this order. However, there is a // small number of cases (right now, involving only italicizing foreign // text) in which the program finds it necessary to insert a markup record // a few records back. Rather than applying some complex logic to track // this, or sorting the (large) markup file at the end of the process, // we take care of this completely within AddMarkup. // // If called with Offset == -1, AddMarkup's internal buffer (if any) is // instead flushed to disk, so that the file can be safely closed. // // Returns 0 on success. static long LastOffset = -1; // Max offset used so far. int AddMarkup (AnalysisDataset * Dataset, long Offset, enum MarkupType Type, char Insert) { if (Offset >= 0) { MarkupRecord Record; Record.Offset = Offset; Record.Type = Type; Record.Insert = Insert; // If the Offset of the new markup is less than the Offset of // previous markup, we need to backtrack in the output file, // so as to insert the record at the proper point. The seeking // is inefficient, but we expect to do it very seldom, and for // only a few record-positions. if (Offset < LastOffset) { long CurrentPos; int NumRecs; MarkupRecord CheckRecord, *TempRecords; NumRecs = 0; do { if (fseek (Dataset->MarkupFile, -sizeof (CheckRecord), SEEK_CUR)) return (1); if (1 != fread (&CheckRecord, sizeof (CheckRecord), 1, Dataset->MarkupFile)) return (1); if (fseek (Dataset->MarkupFile, -sizeof (CheckRecord), SEEK_CUR)) return (1); NumRecs++; } while (CheckRecord.Offset > Offset); if (fseek (Dataset->MarkupFile, sizeof (CheckRecord), SEEK_CUR)) return (1); NumRecs--; CurrentPos = ftell (Dataset->MarkupFile); TempRecords = (MarkupRecord *) calloc (NumRecs, sizeof (MarkupRecord)); if (TempRecords == NULL) return (2); if (NumRecs != fread (TempRecords, sizeof (MarkupRecord), NumRecs, Dataset->MarkupFile)) return (1); if (fseek (Dataset->MarkupFile, CurrentPos, SEEK_SET)) return (1); if (1 != fwrite (&Record, sizeof (MarkupRecord), 1, Dataset->MarkupFile)) return (1); if (NumRecs != fwrite (TempRecords, sizeof (MarkupRecord), NumRecs, Dataset->MarkupFile)) return (1); } else { if (1 != fwrite (&Record, sizeof (Record), 1, Dataset->MarkupFile)) return (1); LastOffset = Offset; } } return (0); }