home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * IO.C
- * (c) 1992-3 J.Harper
- *
- * functions for loading files, reading clips, etc
- */
-
- #include "jed.h"
- #include "jed_protos.h"
-
- Prototype BOOL readtx (TX *, STRPTR, LONG);
- Prototype BOOL writetx (TX *, VW *, STRPTR);
- Prototype VALUE * cmd_openfile (LONG, VALUE *);
- Prototype VALUE * cmd_savefileas (LONG, VALUE *);
- Prototype VALUE * cmd_savefile (LONG, VALUE *);
- Prototype VALUE * cmd_savesection (LONG, VALUE *);
- Prototype VOID doserror (VOID);
- Prototype VALUE * cmd_cd (LONG, VALUE *);
- Prototype VOID killclipstuff (VOID);
- Prototype BOOL writeclip (LONG, POS *, POS *);
- Prototype STRPTR readclip (LONG);
- Prototype BOOL writeline (STRPTR, WORD, BPTR, VW *);
- Local BOOL dobackup (STRPTR, VW *);
-
- /* bytes to copy instead of tabs */
- Prototype const UBYTE Spaces[];
- Prototype const UBYTE Tabs[];
- const UBYTE Spaces[] = " "
- " "
- " ";
- const UBYTE Tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
-
- /*
- * read a file into a tx structure, the line list should have been
- * killed.
- * I'm going to have to speed this up somehow.
- * hopefully now loads lines of any length (upto max of 32768)
- */
- #define SIZESTEP 50 /* size at which line list grows by */
- #define BUFFSTART 1024
- BOOL
- readtx(TX *tx, STRPTR fileName, LONG diskTab)
- {
- BOOL rc = FALSE;
- BPTR fh;
- if(fileName && (*fileName) && (fh = Open(fileName, MODE_OLDFILE)))
- {
- STRPTR buff;
- ULONG bufflen = BUFFSTART;
- tx->tx_FileName = savestring(fileName);
- tx->tx_TitleName = savestring(FilePart(fileName));
-
- if(buff = AllocVec(bufflen, 0L))
- {
- LONG c, i = 0;
- LONG linenum = 0, allocedlines = 0;
-
- settitle("loading...");
- while((c = FGetC(fh)) != -1)
- {
- if(i >= bufflen)
- {
- if(i >= 32768)
- {
- settitle("error: line too long (>32768)");
- goto abort;
- }
- STRPTR newbuff = AllocVec(bufflen << 1, 0L);
- if(!newbuff)
- goto abortmem;
- memcpy(newbuff, buff, i);
- FreeVec(buff);
- buff = newbuff;
- bufflen <<= 1;
- }
- if(c == '\n')
- {
- STRPTR newstr;
- LINE *line;
- if(linenum >= allocedlines)
- {
- if(!resizelinelist(tx, SIZESTEP, linenum))
- goto abortmem;
- allocedlines += SIZESTEP;
- }
- if(!(newstr = AllocVec(i + 1, 0L)))
- goto abortmem;
- memcpy(newstr, buff, i);
- newstr[i] = 0;
- line = tx->tx_Lines + linenum;
- line->ln_Strlen = i + 1;
- line->ln_Line = newstr;
- i = 0;
- linenum++;
- }
- else if(c == '\t')
- {
- WORD numspaces = diskTab - (i % diskTab);
- if(i + numspaces >= bufflen)
- {
- STRPTR newbuff = AllocVec(bufflen << 1, 0L);
- if(!newbuff)
- goto abortmem;
- memcpy(newbuff, buff, i);
- FreeVec(buff);
- buff = newbuff;
- bufflen <<= 1;
- }
- strncpy(buff + i, Spaces, numspaces);
- i += numspaces;
- }
- else
- buff[i++] = c;
- }
- if(i)
- {
- STRPTR newstr;
- LINE *line;
- if(!resizelinelist(tx, linenum - allocedlines + 1, linenum))
- goto abortmem;
- if(!(newstr = AllocVec(i + 1, 0L)))
- goto abortmem;
- memcpy(newstr, buff, i);
- newstr[i] = 0;
- line = tx->tx_Lines + linenum;
- line->ln_Strlen = i + 1;
- line->ln_Line = newstr;
- linenum++;
- }
- else
- if(!resizelinelist(tx, linenum - allocedlines, linenum))
- goto abortmem;
- tx->tx_Changes = 0;
- rc = TRUE;
- settitle("OK");
- /* This block only gets executed if we aborted while
- * reading the file.
- */
- if(0)
- {
- abortmem:
- settitle(NoMemMsg);
- abort:
- clearlinelist(tx);
- }
- FreeVec(buff);
- }
- else
- settitle(NoMemMsg);
- Close(fh);
- }
- else
- {
- if(fileName && (*fileName))
- {
- tx->tx_FileName = savestring(fileName);
- tx->tx_TitleName = savestring(FilePart(fileName));
- }
- else
- {
- tx->tx_FileName = savestring("");
- tx->tx_TitleName = savestring("Untitled");
- }
- tx->tx_Changes = 0;
- if(clearlinelist(tx))
- rc = TRUE;
- else
- settitle(NoMemMsg);
- }
- return(rc);
- }
-
- BOOL
- writetx(TX *tx, VW *vw, STRPTR fileName)
- {
- BOOL rc = TRUE;
- if(fileName)
- {
- BPTR fh = Open(fileName, MODE_NEWFILE);
- if(fh)
- {
- LONG i;
- LINE *line = tx->tx_Lines;
- settitle("saving...");
- for(i = 0; i < tx->tx_NumLines; i++, line++)
- {
- if(!writeline(line->ln_Line, line->ln_Strlen - 1, fh, vw))
- {
- doserror();
- rc = FALSE;
- break;
- }
- FPutC(fh, '\n');
- }
- Close(fh);
- }
- else
- {
- doserror();
- rc = FALSE;
- }
- if(rc)
- settitle("OK");
- }
- else
- {
- settitle(NoMemMsg);
- rc = FALSE;
- }
- return(rc);
- }
-
- /*
- * (openfile `fileName')
- */
- VALUE *
- cmd_openfile(LONG argc, VALUE *argv)
- {
- if(TPLATE1(VTF_STRING))
- {
- VW *vw = CurrVW;
- TX *tx = vw->vw_Tx;
- BOOL rc = FALSE;
- if((!tx->tx_Changes) || (ezreq("OK to lose %ld changes\nto file %s", "Yeah|Cancel", tx->tx_Changes, tx->tx_TitleName)))
- {
- killlinelist(tx);
- freestring(tx->tx_FileName);
- freestring(tx->tx_TitleName);
- if(readtx(tx, ARG1.val_Value.String, vw->vw_Prefs.prf_DiskTab))
- rc = TRUE;
- else
- clearlinelist(tx); /* hope for some mem left */
- setupfileprefs(tx);
- updatedimensions(vw);
- resetallviews(tx);
- }
- resetslptxtitles(tx);
- setnumres(rc);
- }
- return(&RES);
- }
-
- /*
- * (savefileas `fileName')
- */
- VALUE *
- cmd_savefileas(LONG argc, VALUE *argv)
- {
- if(TPLATE1(VTF_STRING))
- {
- TX *tx = CurrVW->vw_Tx;
- BOOL rc = FALSE;
- dobackup(ARG1.val_Value.String, CurrVW);
- if(writetx(tx, CurrVW, ARG1.val_Value.String))
- {
- freestring(tx->tx_FileName);
- freestring(tx->tx_TitleName);
- tx->tx_FileName = savestring(ARG1.val_Value.String);
- tx->tx_TitleName = savestring(FilePart(ARG1.val_Value.String));
- tx->tx_Changes = 0;
- savefileprefs(tx);
- rc = TRUE;
- }
- resetslptxtitles(tx);
- setnumres(rc);
- }
- return(&RES);
- }
-
- /*
- * (savefile)
- */
- VALUE *
- cmd_savefile(LONG argc, VALUE *argv)
- {
- TX *tx = CurrVW->vw_Tx;
- BOOL rc = FALSE;
- if(tx->tx_FileName && tx->tx_FileName[0])
- {
- dobackup(tx->tx_FileName, CurrVW);
- if(writetx(tx, CurrVW, tx->tx_FileName))
- {
- tx->tx_Changes = 0;
- savefileprefs(tx);
- rc = TRUE;
- }
- }
- else
- settitle("error: file is untitled");
- setnumres(rc);
- return(&RES);
- }
-
- /*
- * (savesection `sectionType' `fileName')
- */
- VALUE *
- cmd_savesection(LONG argc, VALUE *argv)
- {
- if(TPLATE2(VTF_STRING, VTF_STRING))
- {
- VW *vw = CurrVW;
- POS endpos;
- POS oldcurs = vw->vw_CursorPos;
- BOOL rc = TRUE;
- padcursor();
- if(getsection(ARG1.val_Value.String, &endpos))
- {
- BPTR fh = Open(ARG2.val_Value.String, MODE_NEWFILE);
- if(fh)
- {
- LINE *line = vw->vw_Tx->tx_Lines + vw->vw_CursorPos.pos_Line;
- if(endpos.pos_Line == vw->vw_CursorPos.pos_Line)
- {
- if(!writeline(line->ln_Line + vw->vw_CursorPos.pos_Col, endpos.pos_Col - vw->vw_CursorPos.pos_Col, fh, vw))
- {
- doserror();
- rc = FALSE;
- }
- }
- else
- {
- if(vw->vw_CursorPos.pos_Col)
- {
- if(!writeline(line->ln_Line + vw->vw_CursorPos.pos_Col, line->ln_Strlen - vw->vw_CursorPos.pos_Col - 1, fh, vw))
- goto writeerr;
- FPutC(fh, '\n');
- vw->vw_CursorPos.pos_Line++;
- line++;
- }
- while(vw->vw_CursorPos.pos_Line < endpos.pos_Line)
- {
- if(!writeline(line->ln_Line, line->ln_Strlen - 1, fh, vw))
- goto writeerr;
- FPutC(fh, '\n');
- vw->vw_CursorPos.pos_Line++;
- line++;
- }
- if(endpos.pos_Col)
- {
- if(!writeline(line->ln_Line, endpos.pos_Col, fh, vw))
- {
- writeerr: doserror();
- rc = FALSE;
- }
- }
- }
- Close(fh);
- }
- else
- {
- doserror();
- rc = FALSE;
- }
- }
- vw->vw_CursorPos = oldcurs;
- setnumres(rc);
- }
- return(&RES);
- }
-
- /*
- * Sets title bar to message describing previous DOS error.
- */
- VOID
- doserror(VOID)
- {
- UBYTE errmsg[81];
- if(Fault(IoErr(), "DOS error", errmsg, 81))
- settitle(errmsg);
- else
- settitlefmt("DOS error: %ld", IoErr());
- }
-
- /*
- * (cd `dir')
- */
- VALUE *
- cmd_cd(LONG argc, VALUE *argv)
- {
- if(TPLATE1(VTF_STRING))
- {
- BOOL rc = FALSE;
- BPTR lock = Lock(ARG1.val_Value.String, SHARED_LOCK);
- if(lock)
- {
- lock = CurrentDir(lock);
- UnLock(lock);
- rc = TRUE;
- }
- else
- settitlefmt("can't lock %s", (LONG)ARG1.val_Value.String);
- setnumres(rc);
- }
- return(&RES);
- }
-
- /*
- * IFF code, adapted from the newiff/other/clipftxt.c example on the 2.0
- * native developer set.
- */
-
- #define ID_FTXT MAKE_ID('F','T','X','T')
- #define ID_CHRS MAKE_ID('C','H','R','S')
-
- Local const STRPTR IFFErrorMsgs[] =
- {
- "End of file.",
- "End of context.",
- "No lexical scope.",
- "No memory.",
- "Stream read error.",
- "Stream write error.",
- "Stream seek error.",
- "File is corrupt.",
- "IFF syntax error.",
- "Not an IFF file.",
- "Required call-back hook missing.",
- "Return to client."
- };
-
- APTR IFFParseBase;
- Local STRPTR InternalClip;
- Local LONG IClipLen; /* not including zero terminator */
-
- VOID
- killclipstuff(VOID)
- {
- freestring(InternalClip);
- InternalClip = NULL;
- IClipLen = 0;
- if(IFFParseBase)
- {
- CloseLibrary(IFFParseBase);
- IFFParseBase = NULL;
- }
- }
-
- /*
- * Writes a section of text to the clipboard, *startPos IS trashed (it will
- * point to the end of the copied section (maybe)).
- * if unit is less than 0 the text is copied to my internal clipboard.
- */
- BOOL
- writeclip(LONG unit, POS *startPos, POS *endPos)
- {
- if(unit < 0)
- {
- IClipLen = sectionlength(startPos, endPos);
- freestring(InternalClip);
- if(InternalClip = AllocVec(IClipLen + 1, 0L))
- {
- copysection(startPos, endPos, InternalClip);
- InternalClip[IClipLen] = 0;
- return(TRUE);
- }
- settitle(NoMemMsg);
- return(FALSE);
- }
- else if(IFFParseBase || (IFFParseBase = OpenLibrary("iffparse.library", 36)))
- {
- struct IFFHandle *iff;
- LONG error = 0;
- if(iff = AllocIFF())
- {
- if(iff->iff_Stream = (ULONG)OpenClipboard(unit))
- {
- InitIFFasClip(iff);
- if(!(error = OpenIFF(iff, IFFF_WRITE)))
- {
- if(!(error = PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)))
- {
- if(!(error = PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)))
- {
- LINE *line = CurrVW->vw_Tx->tx_Lines + startPos->pos_Line;
- LONG writelen;
- if(endPos->pos_Line == startPos->pos_Line)
- {
- writelen = endPos->pos_Col - startPos->pos_Col;
- if(WriteChunkBytes(iff, line->ln_Line + startPos->pos_Col, writelen) != writelen)
- error = IFFERR_WRITE;
- }
- else
- {
- if(startPos->pos_Col)
- {
- writelen = line->ln_Strlen - startPos->pos_Col - 1;
- if(WriteChunkBytes(iff, line->ln_Line + startPos->pos_Col, writelen) != writelen)
- goto writeerr;
- if(WriteChunkBytes(iff, "\n", 1) != 1)
- goto writeerr;
- startPos->pos_Line++;
- line++;
- }
- while(startPos->pos_Line < endPos->pos_Line)
- {
- writelen = line->ln_Strlen - 1;
- if(WriteChunkBytes(iff, line->ln_Line, writelen) != writelen)
- goto writeerr;
- if(WriteChunkBytes(iff, "\n", 1) != 1)
- goto writeerr;
- startPos->pos_Line++;
- line++;
- }
- if(endPos->pos_Col)
- {
- writelen = endPos->pos_Col;
- if(WriteChunkBytes(iff, line->ln_Line, writelen) != writelen)
- {
- writeerr:
- error = IFFERR_WRITE;
- }
- }
- }
- if(!error)
- error = PopChunk(iff);
- else
- PopChunk(iff);
- }
- if(!error)
- error = PopChunk(iff);
- else
- PopChunk(iff);
- }
- CloseIFF(iff);
- }
- CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
- }
- else
- error = IFFERR_NOMEM; /* ?? */
- FreeIFF(iff);
- }
- else
- error = IFFERR_NOMEM;
-
- CloseLibrary(IFFParseBase);
- IFFParseBase = NULL;
-
- if(error)
- {
- settitlefmt("clip error: %s", (LONG)IFFErrorMsgs[-error - 1]);
- return(FALSE);
- }
- return(TRUE);
- }
- settitle("need iffparse.library");
- return(FALSE);
- }
-
- /*
- * result should be FreeVec()'ed after use if non-NULL. A unit of -1
- * reads the internal clip.
- *
- * note:
- * Currently this only reads the first CHRS chunk that it finds.
- */
- STRPTR
- readclip(LONG unit)
- {
- STRPTR text = NULL;
- if(unit < 0)
- {
- if(IClipLen)
- {
- if(text = AllocVec(IClipLen + 1, 0L))
- {
- memcpy(text, InternalClip, IClipLen);
- text[IClipLen] = 0;
- }
- else
- settitle(NoMemMsg);
- }
- else
- settitle("error: nothing on internal clipboard");
- }
- else if(IFFParseBase || (IFFParseBase = OpenLibrary("iffparse.library", 36)))
- {
- struct IFFHandle *iff;
- LONG error;
- if(iff = AllocIFF())
- {
- if(iff->iff_Stream = (ULONG)OpenClipboard(unit))
- {
- InitIFFasClip(iff);
- if(!(error = OpenIFF(iff, IFFF_READ)))
- {
- if(!(error = StopChunk(iff, ID_FTXT, ID_CHRS)))
- {
- struct ContextNode *cn;
- if(!(error = ParseIFF(iff, IFFPARSE_SCAN)))
- {
- cn = CurrentChunk(iff);
- if(cn && (cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS))
- {
- if(text = AllocVec(cn->cn_Size + 1, 0L))
- {
- error = ReadChunkBytes(iff, text, cn->cn_Size);
- if(error > 0)
- {
- text[error] = 0;
- error = 0;
- }
- }
- else
- error = IFFERR_NOMEM;
- }
- else
- error = IFFERR_NOTIFF; /* ?? */
- }
- }
- CloseIFF(iff);
- }
- CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
- }
- else
- error = IFFERR_NOMEM;
- FreeIFF(iff);
- }
- else
- error = IFFERR_NOMEM;
- if(error)
- {
- if(text)
- {
- FreeVec(text);
- text = NULL;
- }
- settitlefmt("clip error: %s", (LONG)IFFErrorMsgs[-error - 1]);
- }
- CloseLibrary(IFFParseBase);
- IFFParseBase = NULL;
- }
- else
- settitle("need iffparse.library");
- return(text);
- }
-
- /*
- * Writes out a line of text,
- * if SaveTabs == 1 leading spaces will be changed to tabs,
- * if SaveTabs == 2 all spaces (except after quotes) are made into tabs and
- * trailing spaces are discarded.
- */
- BOOL
- writeline(STRPTR line, WORD len, BPTR fh, VW *vw)
- {
- if(vw->vw_Prefs.prf_SaveTabs)
- {
- WORD lastchg = 0;
- BOOL inspc = FALSE;
- BOOL nodo = FALSE;
- LONG disktab = vw->vw_Prefs.prf_DiskTab;
- WORD i;
- UBYTE c;
- for(i = 0; (i <= len) && (c = line[i]); i++)
- {
- if(!nodo)
- {
- if(c == ' ')
- {
- if(!inspc)
- {
- if(FWrite(fh, line + lastchg, 1, i - lastchg) != i - lastchg)
- goto error;
- lastchg = i;
- inspc = TRUE;
- }
- }
- else
- {
- if(inspc)
- {
- WORD numtabs, numspcs;
- if(lastchg == i - 1)
- {
- numtabs = 0;
- numspcs = 1;
- }
- else
- {
- numtabs = (i - (lastchg - (lastchg % disktab))) / disktab;
- numspcs = i % disktab;
- if(numspcs > i - lastchg)
- numspcs = i - lastchg;
- }
- if(FWrite(fh, Tabs, 1, numtabs) != numtabs)
- goto error;
- if(FWrite(fh, Spaces, 1, numspcs) != numspcs)
- goto error;
- lastchg = i;
- inspc = FALSE;
- }
- if((c == '"') || (c == '\'') || (c == '`') || (vw->vw_Prefs.prf_SaveTabs == 1))
- nodo = TRUE;
- }
- }
- }
- if((!inspc) || nodo)
- {
- if(FWrite(fh, line + lastchg, 1, i - lastchg) != i - lastchg)
- goto error;
- }
- return(TRUE);
- }
- else
- {
- if(FWrite(fh, line, 1, len) == len)
- return(TRUE);
- }
- error:
- return(FALSE);
- }
-
- /*
- * Sorts out backup files.
- * Backups are saved to the directory set by (setpref `bakdir'). The
- * number of backups kept is determined by (setpref `baknum').
- * for a file called `foo' it's backups would be something like this,
- * t:foo.bak1
- * t:foo.bak2
- * t:foo.bakN
- */
- #define COPYSTEP 65536
- Local BOOL
- dobackup(STRPTR fileName, VW *vw)
- {
- BOOL rc = TRUE;
- if(vw->vw_Prefs.prf_MaxBak > 0)
- {
- UBYTE namebuff[110];
- WORD i;
- BPTR srcfh = 0, dstfh = 0;
- strcpy(namebuff, vw->vw_Prefs.prf_BakDir);
- if(AddPart(namebuff, FilePart(fileName), 100))
- {
- for(i = vw->vw_Prefs.prf_MaxBak - 1; i; i--)
- {
- UBYTE srcbuff[110];
- UBYTE dstbuff[110];
- sprintf(srcbuff, "%s.bak%ld", namebuff, i);
- sprintf(dstbuff, "%s.bak%ld", namebuff, i + 1);
- DeleteFile(dstbuff);
- Rename(srcbuff, dstbuff);
- }
- }
- else
- {
- settitle("error: backup directory name too long");
- return(FALSE);
- }
- strcat(namebuff, ".bak1");
- if((srcfh = Open(fileName, MODE_OLDFILE)) && (dstfh = Open(namebuff, MODE_NEWFILE)))
- {
- STRPTR copybuff;
- if(copybuff = AllocVec(COPYSTEP, 0L))
- {
- LONG actual;
- do
- {
- if((actual = Read(srcfh, copybuff, COPYSTEP)) < 0)
- {
- doserror();
- rc = FALSE;
- break;
- }
- if(Write(dstfh, copybuff, actual) != actual)
- {
- doserror();
- rc = FALSE;
- break;
- }
- }
- while(actual == COPYSTEP);
- FreeVec(copybuff);
- }
- else
- {
- settitle(NoMemMsg);
- rc = FALSE;
- }
- }
- if(dstfh)
- Close(dstfh);
- if(srcfh)
- Close(srcfh);
- }
- return(rc);
- }
-