summaryrefslogtreecommitdiff
path: root/src/Fl_Text_Buffer.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2010-04-05 20:22:43 +0000
committerMatthias Melcher <fltk@matthiasm.com>2010-04-05 20:22:43 +0000
commitfca1c022e7affbd01087acea46b321f1648c3c9a (patch)
treeaa9156dad9991bf489bf02cd8b11b5b1f0d68385 /src/Fl_Text_Buffer.cxx
parentd5175c0b88db543be968ecc81d94453d0795bc90 (diff)
Holy Gucamole! NEdit was designed with 'C' style strings in mind. Until that is that someone had the great idea to allow <nul> as a valid character in the text editor. The developers jumped through quite some hoops to allow that without rewriting the core. Well, actually they did: they added a parameter to pretty much every internal call that conatined the null-replacement-character. Anyway, since we only handle 'C' strings, I remove all related code.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7437 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Text_Buffer.cxx')
-rw-r--r--src/Fl_Text_Buffer.cxx980
1 files changed, 420 insertions, 560 deletions
diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx
index b03a3f7be..490729337 100644
--- a/src/Fl_Text_Buffer.cxx
+++ b/src/Fl_Text_Buffer.cxx
@@ -34,36 +34,27 @@
#include <FL/Fl_Text_Buffer.H>
-static void histogramCharacters(const char *string, int length,
- char hist[256], int init);
-static void subsChars(char *string, int length, char fromChar,
- char toChar);
-static char chooseNullSubsChar(char hist[256]);
static void insertColInLine(const char *line, char *insLine, int column,
int insWidth, int tabDist, int useTabs,
- char nullSubsChar, char *outStr, int *outLen,
+ char *outStr, int *outLen,
int *endOffset);
static void deleteRectFromLine(const char *line, int rectStart,
int rectEnd, int tabDist, int useTabs,
- char nullSubsChar, char *outStr,
+ char *outStr,
int *outLen, int *endOffset);
static void overlayRectInLine(const char *line, char *insLine,
int rectStart, int rectEnd, int tabDist,
- int useTabs, char nullSubsChar, char *outStr,
+ int useTabs, char *outStr,
int *outLen, int *endOffset);
static void addPadding(char *string, int startIndent, int toIndent,
- int tabDist, int useTabs, char nullSubsChar,
- int *charsAdded);
+ int tabDist, int useTabs, int *charsAdded);
static char *copyLine(const char *text, int *lineLen);
static int countLines(const char *string);
-static int textWidth(const char *text, int tabDist, char nullSubsChar);
+static int textWidth(const char *text, int tabDist);
static char *realignTabs(const char *text, int origIndent, int newIndent,
- int tabDist, int useTabs, char nullSubsChar,
- int *newLength);
-static char *expandTabs(const char *text, int startIndent, int tabDist,
- char nullSubsChar, int *newLen);
-static char *unexpandTabs(char *text, int startIndent, int tabDist,
- char nullSubsChar, int *newLen);
+ int tabDist, int useTabs, int *newLength);
+static char *expandTabs(const char *text, int startIndent, int tabDist, int *newLen);
+static char *unexpandTabs(char *text, int startIndent, int tabDist, int *newLen);
#ifndef min
static int max(int i1, int i2)
{
@@ -131,7 +122,6 @@ Fl_Text_Buffer::Fl_Text_Buffer(int requestedSize, int preferredGapSize)
mPredeleteProcs = NULL;
mPredeleteCbArgs = NULL;
mCursorPosHint = 0;
- mNullSubsChar = '\0';
mCanUndo = 1;
#ifdef PURIFY
{
@@ -157,7 +147,7 @@ Fl_Text_Buffer::~Fl_Text_Buffer()
char *Fl_Text_Buffer::text() const {
char *t = (char *) malloc(mLength + 1); //UTF8: we alloc from a string len, but as (non-utf8 aware) strlen()
- // is used to affect mLength, it is equal to buffer size - 1 and thus correct.
+ // is used to affect mLength, it is equal to buffer size - 1 and thus correct.
memcpy(t, mBuf, mGapStart);
memcpy(&t[mGapStart], &mBuf[mGapEnd], mLength - mGapStart);
t[mLength] = '\0';
@@ -165,12 +155,12 @@ char *Fl_Text_Buffer::text() const {
} void Fl_Text_Buffer::text(const char *t)
{
call_predelete_callbacks(0, length());
-
+
/* Save information for redisplay, and get rid of the old buffer */
const char *deletedText = text();
int deletedLength = mLength;
free((void *) mBuf);
-
+
/* Start a new buffer with a gap of mPreferredGapSize in the center */
int insertedLength = strlen(t);
mBuf = (char *) malloc(insertedLength + mPreferredGapSize);
@@ -186,10 +176,10 @@ char *Fl_Text_Buffer::text() const {
mBuf[i] = '.';
}
#endif
-
+
/* Zero all of the existing selections */
update_selections(0, deletedLength, 0);
-
+
/* Call the saved display routine(s) to update the screen */
call_modify_callbacks(0, deletedLength, insertedLength, 0, deletedText);
free((void *) deletedText);
@@ -197,15 +187,15 @@ char *Fl_Text_Buffer::text() const {
char *Fl_Text_Buffer::text_range(int start, int end) const {
char *s = NULL;
-
+
/* Make sure start and end are ok, and allocate memory for returned string.
- If start is bad, return "", if end is bad, adjust it. */
+ If start is bad, return "", if end is bad, adjust it. */
if (start < 0 || start > mLength)
-{
-s = (char *) malloc(1);
-s[0] = '\0';
-return s;
-}
+ {
+ s = (char *) malloc(1);
+ s[0] = '\0';
+ return s;
+ }
if (end < start) {
int temp = start;
start = end;
@@ -215,7 +205,7 @@ return s;
end = mLength;
int copiedLength = end - start;
s = (char *) malloc(copiedLength + 1);
-
+
/* Copy the text from the buffer to the returned string */
if (end <= mGapStart) {
memcpy(s, &mBuf[start], copiedLength);
@@ -244,10 +234,10 @@ char Fl_Text_Buffer::character(int pos) const {
pos = mLength;
if (pos < 0)
pos = 0;
-
+
/* Even if nothing is deleted, we must call these callbacks */
call_predelete_callbacks(pos, 0);
-
+
/* insert and redisplay */
int nInserted = insert_(pos, text);
mCursorPosHint = pos + nInserted;
@@ -263,7 +253,7 @@ void Fl_Text_Buffer::replace(int start, int end, const char *text)
start = 0;
if (end > mLength)
end = mLength;
-
+
call_predelete_callbacks(start, end - start);
const char *deletedText = text_range(start, end);
remove_(start, end);
@@ -290,10 +280,10 @@ void Fl_Text_Buffer::remove(int start, int end)
end = mLength;
if (end < 0)
end = 0;
-
+
if (start == end)
return;
-
+
call_predelete_callbacks(start, end - start);
/* Remove and redisplay */
const char *deletedText = text_range(start, end);
@@ -307,17 +297,17 @@ void Fl_Text_Buffer::copy(Fl_Text_Buffer * fromBuf, int fromStart,
int fromEnd, int toPos)
{
int copiedLength = fromEnd - fromStart;
-
+
/* Prepare the buffer to receive the new text. If the new text fits in
- the current buffer, just move the gap (if necessary) to where
- the text should be inserted. If the new text is too large, reallocate
- the buffer with a gap large enough to accomodate the new text and a
- gap of mPreferredGapSize */
+ the current buffer, just move the gap (if necessary) to where
+ the text should be inserted. If the new text is too large, reallocate
+ the buffer with a gap large enough to accomodate the new text and a
+ gap of mPreferredGapSize */
if (copiedLength > mGapEnd - mGapStart)
reallocate_with_gap(toPos, copiedLength + mPreferredGapSize);
else if (toPos != mGapStart)
move_gap(toPos);
-
+
/* Insert the new text (toPos now corresponds to the start of the gap) */
if (fromEnd <= fromBuf->mGapStart) {
memcpy(&mBuf[toPos], &fromBuf->mBuf[fromStart], copiedLength);
@@ -341,15 +331,15 @@ int Fl_Text_Buffer::undo(int *cursorPos)
{
if (undowidget != this || !undocut && !undoinsert && !mCanUndo)
return 0;
-
+
int ilen = undocut;
int xlen = undoinsert;
int b = undoat - xlen;
-
+
if (xlen && undoyankcut && !ilen) {
ilen = undoyankcut;
}
-
+
if (xlen && ilen) {
undobuffersize(ilen + 1);
undobuffer[ilen] = 0;
@@ -370,7 +360,7 @@ int Fl_Text_Buffer::undo(int *cursorPos)
*cursorPos = mCursorPosHint;
undoyankcut = 0;
}
-
+
return 1;
}
@@ -388,13 +378,13 @@ void Fl_Text_Buffer::insert_column(int column, int startPos,
int nDeleted = line_end(skip_lines(startPos, nLines)) - lineStartPos;
call_predelete_callbacks(lineStartPos, nDeleted);
const char *deletedText =
- text_range(lineStartPos, lineStartPos + nDeleted);
+ text_range(lineStartPos, lineStartPos + nDeleted);
int insertDeleted, nInserted;
insert_column_(column, lineStartPos, text, &insertDeleted, &nInserted,
&mCursorPosHint);
if (nDeleted != insertDeleted)
Fl::error
- ("Fl_Text_Buffer::insert_column(): internal consistency check ins1 failed");
+ ("Fl_Text_Buffer::insert_column(): internal consistency check ins1 failed");
call_modify_callbacks(lineStartPos, nDeleted, nInserted, 0, deletedText);
free((void *) deletedText);
if (charsInserted != NULL)
@@ -408,19 +398,19 @@ void Fl_Text_Buffer::overlay_rectangular(int startPos, int rectStart,
int *charsInserted,
int *charsDeleted)
{
-
+
int nLines = countLines(text);
int lineStartPos = line_start(startPos);
int nDeleted = line_end(skip_lines(startPos, nLines)) - lineStartPos;
call_predelete_callbacks(lineStartPos, nDeleted);
const char *deletedText =
- text_range(lineStartPos, lineStartPos + nDeleted);
+ text_range(lineStartPos, lineStartPos + nDeleted);
int insertDeleted, nInserted;
overlay_rectangular_(lineStartPos, rectStart, rectEnd, text,
&insertDeleted, &nInserted, &mCursorPosHint);
if (nDeleted != insertDeleted)
Fl::error
- ("Fl_Text_Buffer::overlay_rectangle(): internal consistency check ovly1 failed");
+ ("Fl_Text_Buffer::overlay_rectangle(): internal consistency check ovly1 failed");
call_modify_callbacks(lineStartPos, nDeleted, nInserted, 0, deletedText);
free((void *) deletedText);
if (charsInserted != NULL)
@@ -434,20 +424,20 @@ void Fl_Text_Buffer::replace_rectangular(int start, int end, int rectStart,
{
char *insText = (char *) "";
int linesPadded = 0;
-
+
/* Make sure start and end refer to complete lines, since the
- columnar delete and insert operations will replace whole lines */
+ columnar delete and insert operations will replace whole lines */
start = line_start(start);
end = line_end(end);
-
+
call_predelete_callbacks(start, end - start);
-
+
/* If more lines will be deleted than inserted, pad the inserted text
- with newlines to make it as long as the number of deleted lines. This
- will indent all of the text to the right of the rectangle to the same
- column. If more lines will be inserted than deleted, insert extra
- lines in the buffer at the end of the rectangle to make room for the
- additional lines in "text" */
+ with newlines to make it as long as the number of deleted lines. This
+ will indent all of the text to the right of the rectangle to the same
+ column. If more lines will be inserted than deleted, insert extra
+ lines in the buffer at the end of the rectangle to make room for the
+ additional lines in "text" */
int nInsertedLines = countLines(text);
int nDeletedLines = count_lines(start, end);
if (nInsertedLines < nDeletedLines) {
@@ -463,22 +453,22 @@ void Fl_Text_Buffer::replace_rectangular(int start, int end, int rectStart,
for (int i = 0; i < linesPadded; i++)
insert_(end, "\n");
}
-
+
/* else nDeletedLines == nInsertedLines; */
/* Save a copy of the text which will be modified for the modify CBs */
const char *deletedText = text_range(start, end);
-
+
/* Delete then insert */
int insertDeleted, insertInserted, deleteInserted, hint;
remove_rectangular_(start, end, rectStart, rectEnd, &deleteInserted,
&hint);
insert_column_(rectStart, start, insText, &insertDeleted,
&insertInserted, &mCursorPosHint);
-
+
/* Figure out how many chars were inserted and call modify callbacks */
if (insertDeleted != deleteInserted + linesPadded)
Fl::error
- ("Fl_Text_Buffer::replace_rectangular(): internal consistency check repl1 failed");
+ ("Fl_Text_Buffer::replace_rectangular(): internal consistency check repl1 failed");
call_modify_callbacks(start, end - start, insertInserted, 0,
deletedText);
free((void *) deletedText);
@@ -489,7 +479,7 @@ void Fl_Text_Buffer::replace_rectangular(int start, int end, int rectStart,
void Fl_Text_Buffer::remove_rectangular(int start, int end, int rectStart,
int rectEnd)
{
-
+
start = line_start(start);
end = line_end(end);
call_predelete_callbacks(start, end - start);
@@ -525,25 +515,25 @@ char *Fl_Text_Buffer::text_in_rectangle(int start, int end,
char *outPtr = textOut;
int selLeft, selRight;
while (lineStart <= end)
-{
-rectangular_selection_boundaries(lineStart, rectStart, rectEnd,
- &selLeft, &selRight);
-const char *textIn = text_range(selLeft, selRight);
-int len = selRight - selLeft;
-memcpy(outPtr, textIn, len);
-free((void *) textIn);
-outPtr += len;
-lineStart = line_end(selRight) + 1;
-*outPtr++ = '\n';
+ {
+ rectangular_selection_boundaries(lineStart, rectStart, rectEnd,
+ &selLeft, &selRight);
+ const char *textIn = text_range(selLeft, selRight);
+ int len = selRight - selLeft;
+ memcpy(outPtr, textIn, len);
+ free((void *) textIn);
+ outPtr += len;
+ lineStart = line_end(selRight) + 1;
+ *outPtr++ = '\n';
} if (outPtr != textOut)
- outPtr--; /* don't leave trailing newline */
+ outPtr--; /* don't leave trailing newline */
*outPtr = '\0';
-
+
/* If necessary, realign the tabs in the selection as if the text were
- positioned at the left margin */
+ positioned at the left margin */
int len;
char *retabbedStr = realignTabs(textOut, rectStart, 0, mTabDist,
- mUseTabs, mNullSubsChar, &len);
+ mUseTabs, &len);
free((void *) textOut);
return retabbedStr;
}
@@ -551,14 +541,14 @@ lineStart = line_end(selRight) + 1;
void Fl_Text_Buffer::tab_distance(int tabDist)
{
/* First call the pre-delete callbacks with the previous tab setting
- still active. */
+ still active. */
call_predelete_callbacks(0, mLength);
-
+
/* Change the tab setting */
mTabDist = tabDist;
-
+
/* Force any display routines to redisplay everything (unfortunately,
- this means copying the whole buffer contents to provide "deletedText" */
+ this means copying the whole buffer contents to provide "deletedText" */
const char *deletedText = text();
call_modify_callbacks(0, mLength, mLength, 0, deletedText);
free((void *) deletedText);
@@ -567,7 +557,7 @@ void Fl_Text_Buffer::tab_distance(int tabDist)
void Fl_Text_Buffer::select(int start, int end)
{
Fl_Text_Selection oldSelection = mPrimary;
-
+
mPrimary.set(start, end);
redisplay_selection(&oldSelection, &mPrimary);
}
@@ -575,7 +565,7 @@ void Fl_Text_Buffer::select(int start, int end)
void Fl_Text_Buffer::unselect()
{
Fl_Text_Selection oldSelection = mPrimary;
-
+
mPrimary.mSelected = 0;
redisplay_selection(&oldSelection, &mPrimary);
}
@@ -584,7 +574,7 @@ void Fl_Text_Buffer::select_rectangular(int start, int end, int rectStart,
int rectEnd)
{
Fl_Text_Selection oldSelection = mPrimary;
-
+
mPrimary.set_rectangular(start, end, rectStart, rectEnd);
redisplay_selection(&oldSelection, &mPrimary);
}
@@ -619,7 +609,7 @@ void Fl_Text_Buffer::replace_selection(const char *text)
void Fl_Text_Buffer::secondary_select(int start, int end)
{
Fl_Text_Selection oldSelection = mSecondary;
-
+
mSecondary.set(start, end);
redisplay_selection(&oldSelection, &mSecondary);
}
@@ -627,7 +617,7 @@ void Fl_Text_Buffer::secondary_select(int start, int end)
void Fl_Text_Buffer::secondary_unselect()
{
Fl_Text_Selection oldSelection = mSecondary;
-
+
mSecondary.mSelected = 0;
redisplay_selection(&oldSelection, &mSecondary);
}
@@ -637,7 +627,7 @@ void Fl_Text_Buffer::secondary_select_rectangular(int start, int end,
int rectEnd)
{
Fl_Text_Selection oldSelection = mSecondary;
-
+
mSecondary.set_rectangular(start, end, rectStart, rectEnd);
redisplay_selection(&oldSelection, &mSecondary);
}
@@ -673,7 +663,7 @@ void Fl_Text_Buffer::replace_secondary_selection(const char *text)
void Fl_Text_Buffer::highlight(int start, int end)
{
Fl_Text_Selection oldSelection = mHighlight;
-
+
mHighlight.set(start, end);
redisplay_selection(&oldSelection, &mHighlight);
}
@@ -681,7 +671,7 @@ void Fl_Text_Buffer::highlight(int start, int end)
void Fl_Text_Buffer::unhighlight()
{
Fl_Text_Selection oldSelection = mHighlight;
-
+
mHighlight.mSelected = 0;
redisplay_selection(&oldSelection, &mHighlight);
}
@@ -690,7 +680,7 @@ void Fl_Text_Buffer::highlight_rectangular(int start, int end,
int rectStart, int rectEnd)
{
Fl_Text_Selection oldSelection = mHighlight;
-
+
mHighlight.set_rectangular(start, end, rectStart, rectEnd);
redisplay_selection(&oldSelection, &mHighlight);
}
@@ -716,7 +706,7 @@ void Fl_Text_Buffer::add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB,
void *cbArg)
{
Fl_Text_Modify_Cb *newModifyProcs =
- new Fl_Text_Modify_Cb[mNModifyProcs + 1];
+ new Fl_Text_Modify_Cb[mNModifyProcs + 1];
void **newCBArgs = new void *[mNModifyProcs + 1];
for (int i = 0; i < mNModifyProcs; i++) {
newModifyProcs[i + 1] = mModifyProcs[i];
@@ -737,7 +727,7 @@ void Fl_Text_Buffer::
remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg)
{
int i, toRemove = -1;
-
+
/* find the matching callback to remove */
for (i = 0; i < mNModifyProcs; i++) {
if (mModifyProcs[i] == bufModifiedCB && mCbArgs[i] == cbArg) {
@@ -747,12 +737,12 @@ remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg)
}
if (toRemove == -1) {
Fl::error
- ("Fl_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove");
+ ("Fl_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove");
return;
}
-
+
/* Allocate new lists for remaining callback procs and args (if
- any are left) */
+ any are left) */
mNModifyProcs--;
if (mNModifyProcs == 0) {
mNModifyProcs = 0;
@@ -764,7 +754,7 @@ remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg)
}
Fl_Text_Modify_Cb *newModifyProcs = new Fl_Text_Modify_Cb[mNModifyProcs];
void **newCBArgs = new void *[mNModifyProcs];
-
+
/* copy out the remaining members and free the old lists */
for (i = 0; i < toRemove; i++) {
newModifyProcs[i] = mModifyProcs[i];
@@ -784,7 +774,7 @@ void Fl_Text_Buffer::
add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg)
{
Fl_Text_Predelete_Cb *newPreDeleteProcs =
- new Fl_Text_Predelete_Cb[mNPredeleteProcs + 1];
+ new Fl_Text_Predelete_Cb[mNPredeleteProcs + 1];
void **newCBArgs = new void *[mNPredeleteProcs + 1];
for (int i = 0; i < mNPredeleteProcs; i++) {
newPreDeleteProcs[i + 1] = mPredeleteProcs[i];
@@ -815,12 +805,12 @@ remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg)
}
if (toRemove == -1) {
Fl::error
- ("Fl_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove");
+ ("Fl_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove");
return;
}
-
+
/* Allocate new lists for remaining callback procs and args (if
- any are left) */
+ any are left) */
mNPredeleteProcs--;
if (mNPredeleteProcs == 0) {
mNPredeleteProcs = 0;
@@ -831,9 +821,9 @@ remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg)
return;
}
Fl_Text_Predelete_Cb *newPreDeleteProcs =
- new Fl_Text_Predelete_Cb[mNPredeleteProcs];
+ new Fl_Text_Predelete_Cb[mNPredeleteProcs];
void **newCBArgs = new void *[mNPredeleteProcs];
-
+
/* copy out the remaining members and free the old lists */
for (i = 0; i < toRemove; i++) {
newPreDeleteProcs[i] = mPredeleteProcs[i];
@@ -861,8 +851,8 @@ char *Fl_Text_Buffer::line_text(int pos) const {
return pos;
} int Fl_Text_Buffer::word_start(int pos) const {
while (pos && (isalnum(character(pos)) || character(pos) == '_'))
-{
-pos--;
+ {
+ pos--;
} if (!(isalnum(character(pos)) || character(pos) == '_'))
pos++;
return pos;
@@ -871,31 +861,29 @@ pos--;
int Fl_Text_Buffer::word_end(int pos) const {
while (pos < length()
&& (isalnum(character(pos)) || character(pos) == '_'))
-{
-pos++;
-} return pos;
+ {
+ pos++;
+ } return pos;
}
int Fl_Text_Buffer::expand_character(int pos, int indent, char *outStr) const {
char c = character(pos);
- int ret = expand_character(c, indent, outStr,
- mTabDist, mNullSubsChar);
+ int ret = expand_character(c, indent, outStr, mTabDist);
if (ret > 1 && (c & 0x80))
-{
-int i;
-i = fl_utf8len(c);
-while (i > 1) {
- i--;
- pos++;
- outStr++;
- *outStr = character(pos);
-}}
-
+ {
+ int i;
+ i = fl_utf8len(c);
+ while (i > 1) {
+ i--;
+ pos++;
+ outStr++;
+ *outStr = character(pos);
+ }}
+
return ret;
}
-int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr,
- int tabDist, char nullSubsChar)
+int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr, int tabDist)
{
/* Convert tabs to spaces */
if (c == '\t') {
@@ -904,7 +892,7 @@ int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr,
outStr[i] = ' ';
return nSpaces;
}
-
+
/* Convert control codes to readable character sequences */
/*... is this safe with international character sets? */
if (((unsigned char) c) <= 31) {
@@ -913,7 +901,7 @@ int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr,
} else if (c == 127) {
sprintf(outStr, "<del>");
return 5;
- } else if (c == nullSubsChar) {
+ } else if (c == 0) {
sprintf(outStr, "<nul>");
return 5;
} else if ((c & 0x80) && !(c & 0x40)) {
@@ -922,14 +910,13 @@ int Fl_Text_Buffer::expand_character(char c, int indent, char *outStr,
*outStr = c;
return fl_utf8len(c);
}
-
+
/* Otherwise, just return the character */
*outStr = c;
return 1;
}
-int Fl_Text_Buffer::character_width(char c, int indent, int tabDist,
- char nullSubsChar)
+int Fl_Text_Buffer::character_width(char c, int indent, int tabDist)
{
/* Note, this code must parallel that in Fl_Text_Buffer::ExpandCharacter */
if (c == '\t')
@@ -938,7 +925,7 @@ int Fl_Text_Buffer::character_width(char c, int indent, int tabDist,
return strlen(ControlCodeTable[(unsigned char) c]) + 2;
else if (c == 127)
return 5;
- else if (c == nullSubsChar)
+ else if (c == 0)
return 5;
else if ((c & 0x80) && !(c & 0x40))
return 0;
@@ -953,7 +940,7 @@ int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
{
int charCount = 0;
char expandedChar[FL_TEXT_MAX_EXP_CHAR_LEN];
-
+
int pos = lineStartPos;
while (pos < targetPos)
charCount += expand_character(pos++, charCount, expandedChar);
@@ -963,12 +950,12 @@ int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
{
int pos = lineStartPos;
char c;
-
+
for (int charCount = 0; charCount < nChars && pos < mLength;) {
c = character(pos);
if (c == '\n')
return pos;
- charCount += character_width(c, charCount, mTabDist, mNullSubsChar);
+ charCount += character_width(c, charCount, mTabDist);
pos++;
}
return pos;
@@ -977,20 +964,20 @@ int Fl_Text_Buffer::count_displayed_characters(int lineStartPos,
int Fl_Text_Buffer::count_lines(int startPos, int endPos) const {
int gapLen = mGapEnd - mGapStart;
int lineCount = 0;
-
+
int pos = startPos;
while (pos < mGapStart)
-{
-if (pos == endPos)
- return lineCount;
-if (mBuf[pos++] == '\n')
- lineCount++;
-} while (pos < mLength) {
+ {
+ if (pos == endPos)
+ return lineCount;
+ if (mBuf[pos++] == '\n')
+ lineCount++;
+ } while (pos < mLength) {
if (pos == endPos)
return lineCount;
if (mBuf[pos++ + gapLen] == '\n')
lineCount++;
-}
+ }
return lineCount;
}
@@ -998,7 +985,7 @@ int Fl_Text_Buffer::skip_lines(int startPos, int nLines)
{
if (nLines == 0)
return startPos;
-
+
int gapLen = mGapEnd - mGapStart;
int pos = startPos;
int lineCount = 0;
@@ -1024,7 +1011,7 @@ int Fl_Text_Buffer::rewind_lines(int startPos, int nLines)
int pos = startPos - 1;
if (pos <= 0)
return 0;
-
+
int gapLen = mGapEnd - mGapStart;
int lineCount = -1;
while (pos >= mGapStart) {
@@ -1052,19 +1039,19 @@ int Fl_Text_Buffer::search_forward(int startPos, const char *searchString,
int bp;
const char *sp;
while (startPos < length())
-{
-bp = startPos;
-sp = searchString;
-do {
- if (!*sp) {
- *foundPos = startPos;
- return 1;
+ {
+ bp = startPos;
+ sp = searchString;
+ do {
+ if (!*sp) {
+ *foundPos = startPos;
+ return 1;
+ }
+ } while ((matchCase ? character(bp++) == *sp++ :
+ toupper(character(bp++)) == toupper(*sp++))
+ && bp < length());
+ startPos++;
}
-} while ((matchCase ? character(bp++) == *sp++ :
- toupper(character(bp++)) == toupper(*sp++))
- && bp < length());
-startPos++;
-}
return 0;
}
@@ -1076,19 +1063,19 @@ int Fl_Text_Buffer::search_backward(int startPos, const char *searchString,
int bp;
const char *sp;
while (startPos > 0)
-{
-bp = startPos - 1;
-sp = searchString + strlen(searchString) - 1;
-do {
- if (sp < searchString) {
- *foundPos = bp + 1;
- return 1;
+ {
+ bp = startPos - 1;
+ sp = searchString + strlen(searchString) - 1;
+ do {
+ if (sp < searchString) {
+ *foundPos = bp + 1;
+ return 1;
+ }
+ } while ((matchCase ? character(bp--) == *sp-- :
+ toupper(character(bp--)) == toupper(*sp--))
+ && bp >= 0);
+ startPos--;
}
-} while ((matchCase ? character(bp--) == *sp-- :
- toupper(character(bp--)) == toupper(*sp--))
- && bp >= 0);
-startPos--;
-}
return 0;
}
@@ -1097,17 +1084,17 @@ int Fl_Text_Buffer::findchars_forward(int startPos,
int *foundPos) const {
int gapLen = mGapEnd - mGapStart;
const char *c;
-
+
int pos = startPos;
while (pos < mGapStart)
-{
-for (c = searchChars; *c != '\0'; c++) {
- if (mBuf[pos] == *c) {
- *foundPos = pos;
- return 1;
+ {
+ for (c = searchChars; *c != '\0'; c++) {
+ if (mBuf[pos] == *c) {
+ *foundPos = pos;
+ return 1;
+ }
+ } pos++;
}
-} pos++;
-}
while (pos < mLength) {
for (c = searchChars; *c != '\0'; c++) {
if (mBuf[pos + gapLen] == *c) {
@@ -1126,12 +1113,12 @@ int Fl_Text_Buffer::findchars_backward(int startPos,
int *foundPos) const {
int gapLen = mGapEnd - mGapStart;
const char *c;
-
+
if (startPos == 0)
-{
-*foundPos = 0;
-return 0;
-}
+ {
+ *foundPos = 0;
+ return 0;
+ }
int pos = startPos == 0 ? 0 : startPos - 1;
while (pos >= mGapStart) {
for (c = searchChars; *c != '\0'; c++) {
@@ -1155,126 +1142,26 @@ return 0;
return 0;
}
-/*
- A horrible design flaw in NEdit (from the very start, before we knew that
- NEdit would become so popular), is that it uses C NULL terminated strings
- to hold text. This means editing text containing NUL characters is not
- possible without special consideration. Here is the special consideration.
- The routines below maintain a special substitution-character which stands
- in for a null, and translates strings and buffers back and forth from/to
- the substituted form, figure out what to substitute, and figure out
- when we're in over our heads and no translation is possible.
-*/
-
-int Fl_Text_Buffer::substitute_null_characters(char *string, int len)
-{
- char histogram[256];
-
- /* Find out what characters the string contains */
- histogramCharacters(string, len, histogram, 1);
-
- /* Does the string contain the null-substitute character? If so, re-
- histogram the buffer text to find a character which is ok in both the
- string and the buffer, and change the buffer's null-substitution
- character. If none can be found, give up and return 0 */
- if (histogram[(unsigned char) mNullSubsChar] != 0) {
- char *bufString;
- char newSubsChar;
- bufString = (char *) text();
- histogramCharacters(bufString, mLength, histogram, 0);
- newSubsChar = chooseNullSubsChar(histogram);
- if (newSubsChar == '\0')
- return 0;
- subsChars(bufString, mLength, mNullSubsChar, newSubsChar);
- remove_(0, mLength);
- insert_(0, bufString);
- free((void *) bufString);
- mNullSubsChar = newSubsChar;
- }
-
- /* If the string contains null characters, substitute them with the
- buffer's null substitution character */
- if (histogram[0] != 0)
- subsChars(string, len, '\0', mNullSubsChar);
- return 1;
-}
-
-void Fl_Text_Buffer::unsubstitute_null_characters(char *string)
-{
- register char *c, subsChar = mNullSubsChar;
-
- if (subsChar == '\0')
- return;
- for (c = string; *c != '\0'; c++)
- if (*c == subsChar)
- *c = '\0';
-}
-
-/*
- Creates a pseudo-histogram of the characters in a string (don't actually
- count, because we don't want overflow, just mark the character's presence
- with a 1). If init is true, initialize the histogram before acumulating.
- if not, add the new data to an existing histogram.
-*/
-static void histogramCharacters(const char *string, int length,
- char hist[256], int init)
-{
- if (init)
- memset(hist, 0, sizeof(char) * 256); // faster than the original per-char for loop
- for (const char *c = string; c < &string[length]; c++)
- hist[*((unsigned char *) c)] |= 1;
-}
-
-/*
- Substitute fromChar with toChar in string.
-*/
-static void subsChars(char *string, int length, char fromChar, char toChar)
-{
- for (char *c = string; c < &string[length]; c++)
- if (*c == fromChar)
- *c = toChar;
-}
-
-/*
- Search through ascii control characters in histogram in order of least
- likelihood of use, find an unused character to use as a stand-in for a
- null. If the character set is full (no available characters outside of
- the printable set, return the null character.
-*/
-static char chooseNullSubsChar(char hist[256])
-{
-#define N_REPLACEMENTS 25
- static char replacements[N_REPLACEMENTS] =
- { 1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 11, 7
- };
-
- for (int i = 0; i < N_REPLACEMENTS; i++)
- if (hist[replacements[i]] == 0)
- return replacements[i];
- return '\0';
-}
-
int Fl_Text_Buffer::insert_(int pos, const char *text)
{
int insertedLength = strlen(text);
-
+
/* Prepare the buffer to receive the new text. If the new text fits in
- the current buffer, just move the gap (if necessary) to where
- the text should be inserted. If the new text is too large, reallocate
- the buffer with a gap large enough to accomodate the new text and a
- gap of mPreferredGapSize */
+ the current buffer, just move the gap (if necessary) to where
+ the text should be inserted. If the new text is too large, reallocate
+ the buffer with a gap large enough to accomodate the new text and a
+ gap of mPreferredGapSize */
if (insertedLength > mGapEnd - mGapStart)
reallocate_with_gap(pos, insertedLength + mPreferredGapSize);
else if (pos != mGapStart)
move_gap(pos);
-
+
/* Insert the new text (pos now corresponds to the start of the gap) */
memcpy(&mBuf[pos], text, insertedLength);
mGapStart += insertedLength;
mLength += insertedLength;
update_selections(pos, 0, insertedLength);
-
+
if (mCanUndo) {
if (undowidget == this && undoat == pos && undoinsert) {
undoinsert += insertedLength;
@@ -1286,14 +1173,14 @@ int Fl_Text_Buffer::insert_(int pos, const char *text)
undocut = 0;
undowidget = this;
}
-
+
return insertedLength;
}
void Fl_Text_Buffer::remove_(int start, int end)
{
/* if the gap is not contiguous to the area to remove, move it there */
-
+
if (mCanUndo) {
if (undowidget == this && undoat == end && undocut) {
undobuffersize(undocut + end - start + 1);
@@ -1308,7 +1195,7 @@ void Fl_Text_Buffer::remove_(int start, int end)
undoyankcut = 0;
undowidget = this;
}
-
+
if (start > mGapStart) {
if (mCanUndo)
memcpy(undobuffer, mBuf + (mGapEnd - mGapStart) + start,
@@ -1325,14 +1212,14 @@ void Fl_Text_Buffer::remove_(int start, int end)
memcpy(undobuffer + prelen, mBuf + mGapEnd, end - start - prelen);
}
}
-
+
/* expand the gap to encompass the deleted characters */
mGapEnd += end - mGapStart;
mGapStart -= mGapStart - start;
-
+
/* update the length */
mLength -= end - start;
-
+
/* fix up any selections which might be affected by the change */
update_selections(start, end - start, 0);
}
@@ -1343,37 +1230,36 @@ void Fl_Text_Buffer::insert_column_(int column, int startPos,
{
if (column < 0)
column = 0;
-
+
/* Allocate a buffer for the replacement string large enough to hold
- possibly expanded tabs in both the inserted text and the replaced
- area, as well as per line: 1) an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN
- characters for padding where tabs and control characters cross the
- column of the selection, 2) up to "column" additional spaces per
- line for padding out to the position of "column", 3) padding up
- to the width of the inserted text if that must be padded to align
- the text beyond the inserted column. (Space for additional
- newlines if the inserted text extends beyond the end of the buffer
- is counted with the length of insText) */
+ possibly expanded tabs in both the inserted text and the replaced
+ area, as well as per line: 1) an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN
+ characters for padding where tabs and control characters cross the
+ column of the selection, 2) up to "column" additional spaces per
+ line for padding out to the position of "column", 3) padding up
+ to the width of the inserted text if that must be padded to align
+ the text beyond the inserted column. (Space for additional
+ newlines if the inserted text extends beyond the end of the buffer
+ is counted with the length of insText) */
int start = line_start(startPos);
int nLines = countLines(insText) + 1;
- int insWidth = textWidth(insText, mTabDist, mNullSubsChar);
+ int insWidth = textWidth(insText, mTabDist);
int end = line_end(skip_lines(start, nLines - 1));
int expReplLen, expInsLen, len, endOffset;
const char *replText = text_range(start, end);
- char *expText = expandTabs(replText, 0, mTabDist, mNullSubsChar,
- &expReplLen);
+ char *expText = expandTabs(replText, 0, mTabDist, &expReplLen);
free((void *) replText);
free((void *) expText);
- expText = expandTabs(insText, 0, mTabDist, mNullSubsChar, &expInsLen);
+ expText = expandTabs(insText, 0, mTabDist, &expInsLen);
free((void *) expText);
char *outStr = (char *) malloc(expReplLen + expInsLen +
nLines * (column + insWidth +
FL_TEXT_MAX_EXP_CHAR_LEN) + 1);
-
+
/* Loop over all lines in the buffer between start and end removing the
- text between rectStart and rectEnd and padding appropriately. Trim
- trailing space from line (whitespace at the ends of lines otherwise
- tends to multiply, since additional padding is added to maintain it */
+ text between rectStart and rectEnd and padding appropriately. Trim
+ trailing space from line (whitespace at the ends of lines otherwise
+ tends to multiply, since additional padding is added to maintain it */
char *outPtr = outStr, *insLine;
const char *insPtr = insText, *line;
for (int lineStart = start, lineEnd;;) {
@@ -1382,7 +1268,7 @@ void Fl_Text_Buffer::insert_column_(int column, int startPos,
insLine = copyLine(insPtr, &len);
insPtr += len;
insertColInLine(line, insLine, column, insWidth, mTabDist,
- mUseTabs, mNullSubsChar, outPtr, &len, &endOffset);
+ mUseTabs, outPtr, &len, &endOffset);
free((void *) line);
free((void *) insLine);
for (const char *c = outPtr + len - 1; c > outPtr && isspace(*c); c--)
@@ -1397,7 +1283,7 @@ void Fl_Text_Buffer::insert_column_(int column, int startPos,
if (outPtr != outStr)
outPtr--; /* trim back off extra newline */
*outPtr = '\0';
-
+
/* replace the text between start and end with the new stuff */
remove_(start, end);
insert_(start, outStr);
@@ -1412,22 +1298,22 @@ void Fl_Text_Buffer::remove_rectangular_(int start, int end, int rectStart,
int *endPos)
{
/* allocate a buffer for the replacement string large enough to hold
- possibly expanded tabs as well as an additional FL_TEXT_MAX_EXP_CHAR_LEN * 2
- characters per line for padding where tabs and control characters cross
- the edges of the selection */
+ possibly expanded tabs as well as an additional FL_TEXT_MAX_EXP_CHAR_LEN * 2
+ characters per line for padding where tabs and control characters cross
+ the edges of the selection */
start = line_start(start);
end = line_end(end);
int nLines = count_lines(start, end) + 1;
const char *s = text_range(start, end);
int len;
- char *expText = expandTabs(s, 0, mTabDist, mNullSubsChar, &len);
+ char *expText = expandTabs(s, 0, mTabDist, &len);
free((void *) s);
free((void *) expText);
char *outStr =
- (char *) malloc(len + nLines * FL_TEXT_MAX_EXP_CHAR_LEN * 2 + 1);
-
+ (char *) malloc(len + nLines * FL_TEXT_MAX_EXP_CHAR_LEN * 2 + 1);
+
/* loop over all lines in the buffer between start and end removing
- the text between rectStart and rectEnd and padding appropriately */
+ the text between rectStart and rectEnd and padding appropriately */
int endOffset = 0;
char *outPtr = outStr;
const char *line;
@@ -1436,7 +1322,7 @@ void Fl_Text_Buffer::remove_rectangular_(int start, int end, int rectStart,
lineEnd = line_end(lineStart);
line = text_range(lineStart, lineEnd);
deleteRectFromLine(line, rectStart, rectEnd, mTabDist,
- mUseTabs, mNullSubsChar, outPtr, &len, &endOffset);
+ mUseTabs, outPtr, &len, &endOffset);
free((void *) line);
outPtr += len;
*outPtr++ = '\n';
@@ -1445,7 +1331,7 @@ void Fl_Text_Buffer::remove_rectangular_(int start, int end, int rectStart,
if (outPtr != outStr)
outPtr--; /* trim back off extra newline */
*outPtr = '\0';
-
+
/* replace the text between start and end with the newly created string */
remove_(start, end);
insert_(start, outStr);
@@ -1459,30 +1345,29 @@ void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
int *nDeleted, int *nInserted,
int *endPos)
{
-
+
/* Allocate a buffer for the replacement string large enough to hold
- possibly expanded tabs in the inserted text, as well as per line: 1)
- an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs
- and control characters cross the column of the selection, 2) up to
- "column" additional spaces per line for padding out to the position
- of "column", 3) padding up to the width of the inserted text if that
- must be padded to align the text beyond the inserted column. (Space
- for additional newlines if the inserted text extends beyond the end
- of the buffer is counted with the length of insText) */
+ possibly expanded tabs in the inserted text, as well as per line: 1)
+ an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs
+ and control characters cross the column of the selection, 2) up to
+ "column" additional spaces per line for padding out to the position
+ of "column", 3) padding up to the width of the inserted text if that
+ must be padded to align the text beyond the inserted column. (Space
+ for additional newlines if the inserted text extends beyond the end
+ of the buffer is counted with the length of insText) */
int start = line_start(startPos);
int nLines = countLines(insText) + 1;
int end = line_end(skip_lines(start, nLines - 1)), expInsLen;
- char *expText = expandTabs(insText, 0, mTabDist, mNullSubsChar,
- &expInsLen);
+ char *expText = expandTabs(insText, 0, mTabDist, &expInsLen);
free((void *) expText);
char *outStr = (char *) malloc(end - start + expInsLen +
nLines * (rectEnd +
FL_TEXT_MAX_EXP_CHAR_LEN) + 1);
-
+
/* Loop over all lines in the buffer between start and end overlaying the
- text between rectStart and rectEnd and padding appropriately. Trim
- trailing space from line (whitespace at the ends of lines otherwise
- tends to multiply, since additional padding is added to maintain it */
+ text between rectStart and rectEnd and padding appropriately. Trim
+ trailing space from line (whitespace at the ends of lines otherwise
+ tends to multiply, since additional padding is added to maintain it */
int len, endOffset;
char *outPtr = outStr, *insLine;
const char *insPtr = insText, *line;
@@ -1492,7 +1377,7 @@ void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
insLine = copyLine(insPtr, &len);
insPtr += len;
overlayRectInLine(line, insLine, rectStart, rectEnd, mTabDist,
- mUseTabs, mNullSubsChar, outPtr, &len, &endOffset);
+ mUseTabs, outPtr, &len, &endOffset);
free((void *) line);
free((void *) insLine);
for (const char *c = outPtr + len - 1; c > outPtr && isspace(*c); c--)
@@ -1507,7 +1392,7 @@ void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
if (outPtr != outStr)
outPtr--; /* trim back off extra newline */
*outPtr = '\0';
-
+
/* replace the text between start and end with the new stuff */
remove_(start, end);
insert_(start, outStr);
@@ -1518,37 +1403,36 @@ void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
}
/*
- Inserts characters from single-line string \p insLine in single-line string
- \p line at \p column, leaving \p insWidth space before continuing line.
- \p outLen returns the number of characters written to \p outStr, \p endOffset
- returns the number of characters from the beginning of the string to
- the right edge of the inserted text (as a hint for routines which need
- to position the cursor).
-*/
+ Inserts characters from single-line string \p insLine in single-line string
+ \p line at \p column, leaving \p insWidth space before continuing line.
+ \p outLen returns the number of characters written to \p outStr, \p endOffset
+ returns the number of characters from the beginning of the string to
+ the right edge of the inserted text (as a hint for routines which need
+ to position the cursor).
+ */
static void insertColInLine(const char *line, char *insLine, int column,
int insWidth, int tabDist, int useTabs,
- char nullSubsChar, char *outStr, int *outLen,
+ char *outStr, int *outLen,
int *endOffset)
{
/* copy the line up to "column" */
char *outPtr = outStr;
int indent = 0, len;
const char *linePtr;
-
+
for (linePtr = line; *linePtr != '\0'; linePtr++) {
len =
- Fl_Text_Buffer::character_width(*linePtr, indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*linePtr, indent, tabDist);
if (indent + len > column)
break;
indent += len;
*outPtr++ = *linePtr;
}
-
+
/* If "column" falls in the middle of a character, and the character is a
- tab, leave it off and leave the indent short and it will get padded
- later. If it's a control character, insert it and adjust indent
- accordingly. */
+ tab, leave it off and leave the indent short and it will get padded
+ later. If it's a control character, insert it and adjust indent
+ accordingly. */
int postColIndent;
if (indent < column && *linePtr != '\0') {
postColIndent = indent + len;
@@ -1560,53 +1444,50 @@ static void insertColInLine(const char *line, char *insLine, int column,
}
} else
postColIndent = indent;
-
+
/* If there's no text after the column and no text to insert, that's all */
if (*insLine == '\0' && *linePtr == '\0') {
*outLen = *endOffset = outPtr - outStr;
return;
}
-
+
/* pad out to column if text is too short */
if (indent < column) {
- addPadding(outPtr, indent, column, tabDist, useTabs, nullSubsChar,
- &len);
+ addPadding(outPtr, indent, column, tabDist, useTabs, &len);
outPtr += len;
indent = column;
}
-
+
/* Copy the text from "insLine" (if any), recalculating the tabs as if
- the inserted string began at column 0 to its new column destination */
+ the inserted string began at column 0 to its new column destination */
if (*insLine != '\0') {
char *retabbedStr = realignTabs(insLine, 0, indent, tabDist, useTabs,
- nullSubsChar, &len);
+ &len);
for (const char *c = retabbedStr; *c != '\0'; c++) {
*outPtr++ = *c;
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
indent += len;
}
free((void *) retabbedStr);
}
-
+
/* If the original line did not extend past "column", that's all */
if (*linePtr == '\0') {
*outLen = *endOffset = outPtr - outStr;
return;
}
-
+
/* Pad out to column + width of inserted text + (additional original
- offset due to non-breaking character at column) */
+ offset due to non-breaking character at column) */
int toIndent = column + insWidth + postColIndent - column;
- addPadding(outPtr, indent, toIndent, tabDist, useTabs, nullSubsChar,
- &len);
+ addPadding(outPtr, indent, toIndent, tabDist, useTabs, &len);
outPtr += len;
indent = toIndent;
-
+
/* realign tabs for text beyond "column" and write it out */
char *retabbedStr = realignTabs(linePtr, postColIndent, indent, tabDist,
- useTabs, nullSubsChar, &len);
+ useTabs, &len);
strcpy(outPtr, retabbedStr);
free((void *) retabbedStr);
*endOffset = outPtr - outStr;
@@ -1614,20 +1495,20 @@ static void insertColInLine(const char *line, char *insLine, int column,
}
/**
- Removes characters in single-line string \p line between displayed positions
- \p rectStart and \p rectEnd, and write the result to \p outStr, which is
- assumed to be large enough to hold the returned string. Note that in
- certain cases, it is possible for the string to get longer due to
- expansion of tabs. \p endOffset returns the number of characters from
- the beginning of the string to the point where the characters were
- deleted (as a hint for routines which need to position the cursor).
-*/
+ Removes characters in single-line string \p line between displayed positions
+ \p rectStart and \p rectEnd, and write the result to \p outStr, which is
+ assumed to be large enough to hold the returned string. Note that in
+ certain cases, it is possible for the string to get longer due to
+ expansion of tabs. \p endOffset returns the number of characters from
+ the beginning of the string to the point where the characters were
+ deleted (as a hint for routines which need to position the cursor).
+ */
static void deleteRectFromLine(const char *line, int rectStart,
int rectEnd, int tabDist, int useTabs,
- char nullSubsChar, char *outStr,
+ char *outStr,
int *outLen, int *endOffset)
{
-
+
/* copy the line up to rectStart */
char *outPtr = outStr;
int indent = 0, len;
@@ -1636,40 +1517,38 @@ static void deleteRectFromLine(const char *line, int rectStart,
if (indent > rectStart)
break;
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist, nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
if (indent + len > rectStart && (indent == rectStart || *c == '\t'))
break;
indent += len;
*outPtr++ = *c;
}
int preRectIndent = indent;
-
+
/* skip the characters between rectStart and rectEnd */
for (; *c != '\0' && indent < rectEnd; c++)
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist, nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
int postRectIndent = indent;
-
+
/* If the line ended before rectEnd, there's nothing more to do */
if (*c == '\0') {
*outPtr = '\0';
*outLen = *endOffset = outPtr - outStr;
return;
}
-
+
/* fill in any space left by removed tabs or control characters
- which straddled the boundaries */
+ which straddled the boundaries */
indent = max(rectStart + postRectIndent - rectEnd, preRectIndent);
- addPadding(outPtr, preRectIndent, indent, tabDist, useTabs,
- nullSubsChar, &len);
+ addPadding(outPtr, preRectIndent, indent, tabDist, useTabs, &len);
outPtr += len;
-
+
/* Copy the rest of the line. If the indentation has changed, preserve
- the position of non-whitespace characters by converting tabs to
- spaces, then back to tabs with the correct offset */
+ the position of non-whitespace characters by converting tabs to
+ spaces, then back to tabs with the correct offset */
char *retabbedStr =
- realignTabs(c, postRectIndent, indent, tabDist, useTabs,
- nullSubsChar, &len);
+ realignTabs(c, postRectIndent, indent, tabDist, useTabs, &len);
strcpy(outPtr, retabbedStr);
free((void *) retabbedStr);
*endOffset = outPtr - outStr;
@@ -1677,38 +1556,37 @@ static void deleteRectFromLine(const char *line, int rectStart,
}
/**
- Overlay characters from single-line string \p insLine on single-line string
- \p line between displayed character offsets \p rectStart and \p rectEnd.
- \p outLen returns the number of characters written to \p outStr, \p endOffset
- returns the number of characters from the beginning of the string to
- the right edge of the inserted text (as a hint for routines which need
- to position the cursor).
-*/
+ Overlay characters from single-line string \p insLine on single-line string
+ \p line between displayed character offsets \p rectStart and \p rectEnd.
+ \p outLen returns the number of characters written to \p outStr, \p endOffset
+ returns the number of characters from the beginning of the string to
+ the right edge of the inserted text (as a hint for routines which need
+ to position the cursor).
+ */
static void overlayRectInLine(const char *line, char *insLine,
int rectStart, int rectEnd, int tabDist,
- int useTabs, char nullSubsChar, char *outStr,
+ int useTabs, char *outStr,
int *outLen, int *endOffset)
{
/* copy the line up to "rectStart" */
char *outPtr = outStr;
int inIndent = 0, outIndent = 0, len;
const char *linePtr = line;
-
+
for (; *linePtr != '\0'; linePtr++) {
len =
- Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist);
if (inIndent + len > rectStart)
break;
inIndent += len;
outIndent += len;
*outPtr++ = *linePtr;
}
-
+
/* If "rectStart" falls in the middle of a character, and the character
- is a tab, leave it off and leave the outIndent short and it will get
- padded later. If it's a control character, insert it and adjust
- outIndent accordingly. */
+ is a tab, leave it off and leave the outIndent short and it will get
+ padded later. If it's a control character, insert it and adjust
+ outIndent accordingly. */
if (inIndent < rectStart && *linePtr != '\0') {
if (*linePtr == '\t') {
linePtr++;
@@ -1719,63 +1597,58 @@ static void overlayRectInLine(const char *line, char *insLine,
inIndent += len;
}
}
-
+
/* skip the characters between rectStart and rectEnd */
int postRectIndent = rectEnd;
for (; *linePtr != '\0'; linePtr++) {
inIndent +=
- Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*linePtr, inIndent, tabDist);
if (inIndent >= rectEnd) {
linePtr++;
postRectIndent = inIndent;
break;
}
}
-
+
/* If there's no text after rectStart and no text to insert, that's all */
if (*insLine == '\0' && *linePtr == '\0') {
*outLen = *endOffset = outPtr - outStr;
return;
}
-
+
/* pad out to rectStart if text is too short */
if (outIndent < rectStart) {
- addPadding(outPtr, outIndent, rectStart, tabDist, useTabs,
- nullSubsChar, &len);
+ addPadding(outPtr, outIndent, rectStart, tabDist, useTabs, &len);
outPtr += len;
}
outIndent = rectStart;
-
+
/* Copy the text from "insLine" (if any), recalculating the tabs as if
- the inserted string began at column 0 to its new column destination */
+ the inserted string began at column 0 to its new column destination */
if (*insLine != '\0') {
char *retabbedStr =
- realignTabs(insLine, 0, rectStart, tabDist, useTabs,
- nullSubsChar, &len);
+ realignTabs(insLine, 0, rectStart, tabDist, useTabs, &len);
for (const char *c = retabbedStr; *c != '\0'; c++) {
*outPtr++ = *c;
len =
- Fl_Text_Buffer::character_width(*c, outIndent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, outIndent, tabDist);
outIndent += len;
}
free((void *) retabbedStr);
}
-
+
/* If the original line did not extend past "rectStart", that's all */
if (*linePtr == '\0') {
*outLen = *endOffset = outPtr - outStr;
return;
}
-
+
/* Pad out to rectEnd + (additional original offset
- due to non-breaking character at right boundary) */
- addPadding(outPtr, outIndent, postRectIndent, tabDist, useTabs,
- nullSubsChar, &len);
+ due to non-breaking character at right boundary) */
+ addPadding(outPtr, outIndent, postRectIndent, tabDist, useTabs, &len);
outPtr += len;
outIndent = postRectIndent;
-
+
/* copy the text beyond "rectEnd" */
strcpy(outPtr, linePtr);
*endOffset = outPtr - outStr;
@@ -1806,7 +1679,7 @@ int Fl_Text_Selection::position(int *startpos, int *endpos) const {
return 0;
*startpos = mStart;
*endpos = mEnd;
-
+
return 1;
} int Fl_Text_Selection::position(int *startpos, int *endpos,
int *isRect, int *rectStart,
@@ -1817,33 +1690,33 @@ int Fl_Text_Selection::position(int *startpos, int *endpos) const {
*startpos = mStart;
*endpos = mEnd;
if (mRectangular)
-{
-*rectStart = mRectStart;
-*rectEnd = mRectEnd;
-}
+ {
+ *rectStart = mRectStart;
+ *rectEnd = mRectEnd;
+ }
return 1;
}
int Fl_Text_Selection::includes(int pos, int lineStartPos, int dispIndex) const {
return selected() &&
- ((!rectangular() && pos >= start() && pos < end()) ||
- (rectangular() && pos >= start() && lineStartPos <= end() &&
- dispIndex >= rect_start() && dispIndex < rect_end())
- );
+ ((!rectangular() && pos >= start() && pos < end()) ||
+ (rectangular() && pos >= start() && lineStartPos <= end() &&
+ dispIndex >= rect_start() && dispIndex < rect_end())
+ );
} char *Fl_Text_Buffer::selection_text_(Fl_Text_Selection * sel) const {
int start, end, isRect, rectStart, rectEnd;
-
+
/* If there's no selection, return an allocated empty string */
if (!sel->position(&start, &end, &isRect, &rectStart, &rectEnd))
-{
-char *s = (char *) malloc(1);
-*s = '\0';
-return s;
-}
-
+ {
+ char *s = (char *) malloc(1);
+ *s = '\0';
+ return s;
+ }
+
/* If the selection is not rectangular, return the selected range */
- if (isRect)
- return text_in_rectangle(start, end, rectStart, rectEnd);
+ if (isRect)
+ return text_in_rectangle(start, end, rectStart, rectEnd);
else
return text_range(start, end);
}
@@ -1851,7 +1724,7 @@ return s;
void Fl_Text_Buffer::remove_selection_(Fl_Text_Selection * sel)
{
int start, end, isRect, rectStart, rectEnd;
-
+
if (!sel->position(&start, &end, &isRect, &rectStart, &rectEnd))
return;
if (isRect)
@@ -1867,36 +1740,34 @@ void Fl_Text_Buffer::replace_selection_(Fl_Text_Selection * sel,
const char *text)
{
Fl_Text_Selection oldSelection = *sel;
-
+
/* If there's no selection, return */
int start, end, isRect, rectStart, rectEnd;
if (!sel->position(&start, &end, &isRect, &rectStart, &rectEnd))
return;
-
+
/* Do the appropriate type of replace */
if (isRect)
replace_rectangular(start, end, rectStart, rectEnd, text);
else
replace(start, end, text);
-
+
/* Unselect (happens automatically in BufReplace, but BufReplaceRect
- can't detect when the contents of a selection goes away) */
+ can't detect when the contents of a selection goes away) */
sel->mSelected = 0;
redisplay_selection(&oldSelection, sel);
}
static void addPadding(char *string, int startIndent, int toIndent,
- int tabDist, int useTabs, char nullSubsChar,
- int *charsAdded)
+ int tabDist, int useTabs, int *charsAdded)
{
int indent = startIndent, len;
char *outPtr = string;
-
+
if (useTabs) {
while (indent < toIndent) {
len =
- Fl_Text_Buffer::character_width('\t', indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width('\t', indent, tabDist);
if (len > 1 && indent + len <= toIndent) {
*outPtr++ = '\t';
indent += len;
@@ -1929,11 +1800,11 @@ void Fl_Text_Buffer::call_modify_callbacks(int pos, int nDeleted,
newSelection) const
{
int oldStart, oldEnd, newStart, newEnd, ch1Start, ch1End, ch2Start,
- ch2End;
-
+ ch2End;
+
/* If either selection is rectangular, add an additional character to
- the end of the selection to request the redraw routines to wipe out
- the parts of the selection beyond the end of the line */
+ the end of the selection to request the redraw routines to wipe out
+ the parts of the selection beyond the end of the line */
oldStart = oldSelection->mStart;
newStart = newSelection->mStart;
oldEnd = oldSelection->mEnd;
@@ -1942,46 +1813,46 @@ void Fl_Text_Buffer::call_modify_callbacks(int pos, int nDeleted,
oldEnd++;
if (newSelection->mRectangular)
newEnd++;
-
+
/* If the old or new selection is unselected, just redisplay the
- single area that is (was) selected and return */
+ single area that is (was) selected and return */
if (!oldSelection->mSelected && !newSelection->mSelected)
return;
if (!oldSelection->mSelected)
-{
-call_modify_callbacks(newStart, 0, 0, newEnd - newStart, NULL);
-return;
-}
+ {
+ call_modify_callbacks(newStart, 0, 0, newEnd - newStart, NULL);
+ return;
+ }
if (!newSelection->mSelected) {
call_modify_callbacks(oldStart, 0, 0, oldEnd - oldStart, NULL);
return;
}
-
+
/* If the selection changed from normal to rectangular or visa versa, or
- if a rectangular selection changed boundaries, redisplay everything */
+ if a rectangular selection changed boundaries, redisplay everything */
if ((oldSelection->mRectangular && !newSelection->mRectangular) ||
(!oldSelection->mRectangular && newSelection->mRectangular) ||
(oldSelection->mRectangular && ((oldSelection->mRectStart !=
newSelection->mRectStart)
|| (oldSelection->mRectEnd !=
newSelection->mRectEnd)))) {
- call_modify_callbacks(min(oldStart, newStart), 0, 0,
- max(oldEnd, newEnd) - min(oldStart,
- newStart), NULL);
- return;
- }
-
+ call_modify_callbacks(min(oldStart, newStart), 0, 0,
+ max(oldEnd, newEnd) - min(oldStart,
+ newStart), NULL);
+ return;
+ }
+
/* If the selections are non-contiguous, do two separate updates
- and return */
+ and return */
if (oldEnd < newStart || newEnd < oldStart) {
call_modify_callbacks(oldStart, 0, 0, oldEnd - oldStart, NULL);
call_modify_callbacks(newStart, 0, 0, newEnd - newStart, NULL);
return;
}
-
+
/* Otherwise, separate into 3 separate regions: ch1, and ch2 (the two
- changed areas), and the unchanged area of their intersection,
- and update only the changed area(s) */
+ changed areas), and the unchanged area of their intersection,
+ and update only the changed area(s) */
ch1Start = min(oldStart, newStart);
ch2End = max(oldEnd, newEnd);
ch1End = max(oldStart, newStart);
@@ -1995,7 +1866,7 @@ return;
void Fl_Text_Buffer::move_gap(int pos)
{
int gapLen = mGapEnd - mGapStart;
-
+
if (pos > mGapStart)
memmove(&mBuf[mGapStart], &mBuf[mGapEnd], pos - mGapStart);
else
@@ -2008,7 +1879,7 @@ void Fl_Text_Buffer::reallocate_with_gap(int newGapStart, int newGapLen)
{
char *newBuf = (char *) malloc(mLength + newGapLen);
int newGapEnd = newGapStart + newGapLen;
-
+
if (newGapStart <= mGapStart) {
memcpy(newBuf, mBuf, newGapStart);
memcpy(&newBuf[newGapEnd], &mBuf[newGapStart],
@@ -2067,11 +1938,11 @@ void Fl_Text_Selection::update(int pos, int nDeleted, int nInserted)
int Fl_Text_Buffer::findchar_forward(int startPos, char searchChar,
int *foundPos) const {
if (startPos < 0 || startPos >= mLength)
-{
-*foundPos = mLength;
-return 0;
-}
-
+ {
+ *foundPos = mLength;
+ return 0;
+ }
+
int pos = startPos;
while (pos < mGapStart) {
if (mBuf[pos] == searchChar) {
@@ -2080,7 +1951,7 @@ return 0;
}
pos++;
}
-
+
for (int gapLen = mGapEnd - mGapStart; pos < mLength; pos++) {
if (mBuf[pos + gapLen] == searchChar) {
*foundPos = pos;
@@ -2093,13 +1964,13 @@ return 0;
int Fl_Text_Buffer::findchar_backward(int startPos, char searchChar,
int *foundPos) const {
-
+
if (startPos <= 0 || startPos > mLength)
-{
-*foundPos = 0;
-return 0;
-}
-
+ {
+ *foundPos = 0;
+ return 0;
+ }
+
int pos = startPos - 1;
for (int gapLen = mGapEnd - mGapStart; pos >= mGapStart; pos--) {
if (mBuf[pos + gapLen] == searchChar) {
@@ -2107,7 +1978,7 @@ return 0;
return 1;
}
}
-
+
for (; pos >= 0; pos--) {
if (mBuf[pos] == searchChar) {
*foundPos = pos;
@@ -2119,14 +1990,14 @@ return 0;
}
/*
- Copies from \p text to end up to but not including newline (or end of \p text)
- and return the copy as the function value, and the length of the line in
- \p lineLen
-*/
+ Copies from \p text to end up to but not including newline (or end of \p text)
+ and return the copy as the function value, and the length of the line in
+ \p lineLen
+ */
static char *copyLine(const char *text, int *lineLen)
{
int len = 0;
-
+
for (const char *c = text; *c != '\0' && *c != '\n'; c++)
len++;
char *outStr = (char *) malloc(len + 1);
@@ -2136,12 +2007,12 @@ static char *copyLine(const char *text, int *lineLen)
}
/*
- Counts the number of newlines in a null-terminated text string;
-*/
+ Counts the number of newlines in a null-terminated text string;
+ */
static int countLines(const char *string)
{
int lineCount = 0;
-
+
for (const char *c = string; *c != '\0'; c++)
if (*c == '\n')
lineCount++;
@@ -2149,12 +2020,12 @@ static int countLines(const char *string)
}
/*
- Measures the width in displayed characters of string \p text
-*/
-static int textWidth(const char *text, int tabDist, char nullSubsChar)
+ Measures the width in displayed characters of string \p text
+ */
+static int textWidth(const char *text, int tabDist)
{
int width = 0, maxWidth = 0;
-
+
for (const char *c = text; *c != '\0'; c++) {
if (*c == '\n') {
if (width > maxWidth)
@@ -2162,8 +2033,7 @@ static int textWidth(const char *text, int tabDist, char nullSubsChar)
width = 0;
} else
width +=
- Fl_Text_Buffer::character_width(*c, width, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, width, tabDist);
}
if (width > maxWidth)
return width;
@@ -2178,34 +2048,33 @@ void Fl_Text_Buffer::rectangular_selection_boundaries(int lineStartPos,
{
int pos, width, indent = 0;
char c;
-
+
/* find the start of the selection */
for (pos = lineStartPos; pos < mLength; pos++)
-{
-c = character(pos);
-if (c == '\n')
- break;
-width =
- Fl_Text_Buffer::character_width(c, indent, mTabDist, mNullSubsChar);
-if (indent + width > rectStart) {
- if (indent != rectStart && c != '\t') {
- pos++;
+ {
+ c = character(pos);
+ if (c == '\n')
+ break;
+ width =
+ Fl_Text_Buffer::character_width(c, indent, mTabDist);
+ if (indent + width > rectStart) {
+ if (indent != rectStart && c != '\t') {
+ pos++;
+ indent += width;
+ }
+ break;
+ }
indent += width;
}
- break;
-}
-indent += width;
-}
*selStart = pos;
-
+
/* find the end */
for (; pos < mLength; pos++) {
c = character(pos);
if (c == '\n')
break;
width =
- Fl_Text_Buffer::character_width(c, indent, mTabDist,
- mNullSubsChar);
+ Fl_Text_Buffer::character_width(c, indent, mTabDist);
indent += width;
if (indent > rectEnd) {
if (indent - width != rectEnd && c != '\t')
@@ -2217,14 +2086,13 @@ indent += width;
}
/*
- Adjust the space and tab characters from string \p text so that non-white
- characters remain stationary when the text is shifted from starting at
- \p origIndent to starting at \p newIndent. Returns an allocated string
- which must be freed by the caller with XtFree.
-*/
+ Adjust the space and tab characters from string \p text so that non-white
+ characters remain stationary when the text is shifted from starting at
+ \p origIndent to starting at \p newIndent. Returns an allocated string
+ which must be freed by the caller with XtFree.
+ */
static char *realignTabs(const char *text, int origIndent, int newIndent,
- int tabDist, int useTabs, char nullSubsChar,
- int *newLength)
+ int tabDist, int useTabs, int *newLength)
{
/* If the tabs settings are the same, retain original tabs */
int len;
@@ -2236,27 +2104,26 @@ static char *realignTabs(const char *text, int origIndent, int newIndent,
*newLength = len;
return outStr;
}
-
+
/* If the tab settings are not the same, brutally convert tabs to
- spaces, then back to tabs in the new position */
- char *expStr = expandTabs(text, origIndent, tabDist, nullSubsChar, &len);
+ spaces, then back to tabs in the new position */
+ char *expStr = expandTabs(text, origIndent, tabDist, &len);
if (!useTabs) {
*newLength = len;
return expStr;
}
outStr =
- unexpandTabs(expStr, newIndent, tabDist, nullSubsChar, newLength);
+ unexpandTabs(expStr, newIndent, tabDist, newLength);
free((void *) expStr);
return outStr;
}
/*
- Expand tabs to spaces for a block of text. The additional parameter
- \p startIndent if nonzero, indicates that the text is a rectangular selection
- beginning at column \p startIndent
-*/
-static char *expandTabs(const char *text, int startIndent, int tabDist,
- char nullSubsChar, int *newLen)
+ Expand tabs to spaces for a block of text. The additional parameter
+ \p startIndent if nonzero, indicates that the text is a rectangular selection
+ beginning at column \p startIndent
+ */
+static char *expandTabs(const char *text, int startIndent, int tabDist, int *newLen)
{
/* rehearse the expansion to figure out length for output string */
int indent = startIndent, len, outLen = 0;
@@ -2264,8 +2131,7 @@ static char *expandTabs(const char *text, int startIndent, int tabDist,
for (c = text; *c != '\0'; c++) {
if (*c == '\t') {
len =
- Fl_Text_Buffer::character_width(*c, indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
outLen += len;
indent += len;
} else if (*c == '\n') {
@@ -2273,12 +2139,11 @@ static char *expandTabs(const char *text, int startIndent, int tabDist,
outLen++;
} else {
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
outLen++;
}
}
-
+
/* do the expansion */
char *outStr = (char *) malloc(outLen + 1);
char *outPtr = outStr;
@@ -2286,8 +2151,7 @@ static char *expandTabs(const char *text, int startIndent, int tabDist,
for (c = text; *c != '\0'; c++) {
if (*c == '\t') {
len =
- Fl_Text_Buffer::expand_character(*c, indent, outPtr,
- tabDist, nullSubsChar);
+ Fl_Text_Buffer::expand_character(*c, indent, outPtr, tabDist);
outPtr += len;
indent += len;
} else if (*c == '\n') {
@@ -2295,8 +2159,7 @@ static char *expandTabs(const char *text, int startIndent, int tabDist,
*outPtr++ = *c;
} else {
indent +=
- Fl_Text_Buffer::character_width(*c, indent, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::character_width(*c, indent, tabDist);
*outPtr++ = *c;
}
}
@@ -2306,24 +2169,21 @@ static char *expandTabs(const char *text, int startIndent, int tabDist,
}
/*
- Convert sequences of spaces into tabs. The threshold for conversion is
- when 3 or more spaces can be converted into a single tab, this avoids
- converting double spaces after a period withing a block of text.
-*/
-static char *unexpandTabs(char *text, int startIndent, int tabDist,
- char nullSubsChar, int *newLen)
+ Convert sequences of spaces into tabs. The threshold for conversion is
+ when 3 or more spaces can be converted into a single tab, this avoids
+ converting double spaces after a period withing a block of text.
+ */
+static char *unexpandTabs(char *text, int startIndent, int tabDist, int *newLen)
{
char expandedChar[FL_TEXT_MAX_EXP_CHAR_LEN];
char *outStr = (char *) malloc(strlen(text) + 1);
char *outPtr = outStr;
int indent = startIndent, len;
-
+
for (const char *c = text; *c != '\0';) {
if (*c == ' ') {
len =
- Fl_Text_Buffer::expand_character('\t', indent,
- expandedChar, tabDist,
- nullSubsChar);
+ Fl_Text_Buffer::expand_character('\t', indent, expandedChar, tabDist);
if (len >= 3 && !strncmp(c, expandedChar, len)) {
c += len;
*outPtr++ = '\t';
@@ -2355,7 +2215,7 @@ int Fl_Text_Buffer::insertfile(const char *file, int pos, int buflen)
buffer[r] = (char) 0;
insert(pos, buffer);
}
-
+
int e = ferror(fp) ? 2 : 0;
fclose(fp);
delete[]buffer;
@@ -2375,7 +2235,7 @@ int Fl_Text_Buffer::outputfile(const char *file, int start, int end,
if (r != n)
break;
}
-
+
int e = ferror(fp) ? 2 : 0;
fclose(fp);
return e;