home *** CD-ROM | disk | FTP | other *** search
- { MSFILE.PAS
- MS 4.0
- Copyright (c) 1985, 87 by Borland International, Inc. }
-
- {$I msdirect.inc}
-
- unit MsFile;
- {-Perform MicroStar file operations}
-
- interface
-
- uses
- Crt, {Basic video operations - standard unit}
- Dos, {DOS interface - standard unit}
- Errors, {Runtime error handler}
- MsVars, {Global types and declarations}
- MsScrn1, {Fast screen writing routines}
- MsString, {String primitives}
- MsPtrOp, {Pointer primitives}
- EscSeq, {Returns text string for extended scan codes}
- MsCmds, {Maps keystrokes to commands}
- Int24, {DOS critical error handler}
- Message, {Message system}
- MsUser, {User keyboard input, line edit, error report, help}
- MsMemOp, {Text buffer allocation and deallocation}
- MsBack, {Background processes}
- MsScrn2, {Editor screen updating}
- MsMenu, {Pulldown and custom menu system}
- MsDir, {Popup directory picker}
- MsEdit; {Basic editing commands}
-
- function EdExistFile(Fname : Filepath) : Boolean;
- {-return true if file exists, false if non-existent or a device}
-
- procedure EdShutWindow(ExitEditor : Boolean);
- {-Shut the current window, set Rundown true if last one and ExitEditor true}
-
- procedure EdMakeBakFile(Fname : Filepath);
- {-Create a backup file based on fname}
-
- procedure EdFileWrite(Fname : Filepath; Quitting : Boolean);
- {-Save current text stream to specified file}
-
- procedure EdLogDrive(NewPath : Filepath);
- {-Select a new drive or directory}
-
- function EdWriteNamedFile : Boolean;
- {-Get file name, save current text stream to it, change stream names}
-
- function CheckCurwinModified : boolean;
- {-See if current window is modified, and if so, prompt to save it}
-
- procedure EdAbandonFile(ExitEditor : Boolean);
- {-Close file without saving}
-
- function EdGetFileName(Prompt, DefExt : VarString;
- Row, Attr : Byte;
- var LastFname : Filepath; UseWild : Boolean) : Filepath;
- {-Return a file name to use}
-
- procedure EdDirectory;
- {-Display and allow browsing of file directory}
-
- procedure EdReadtextfile(Fname : Filepath; ReadingBlock : Boolean);
- {-Read text file into current window}
-
- procedure EdReadFile(Fname : Filepath);
- {-Check and open a text file for editing}
-
- procedure EdWriteBlock(Fname : Filepath; Exists, Appending : Boolean);
- {-Write or append marked block to file}
-
- {==========================================================================}
-
- implementation
-
- const
- EofMark : string[1] = ^Z; {Indicates end of file}
- BakFileExt : ExtString = 'BAK'; {Extension given to backup files}
-
- {$L MSFILE}
-
- procedure EdFastExpand(var B, T; var Tlen : Integer;
- Blen, TabSize, Maxlinelength : Integer); external;
- {-Expand tabs in b to blanks in t, returning length in tlen}
-
- procedure EdStripHighBit(var B; Len : Integer); external;
- {-Set bit 8 of each character in buffer b to zero}
-
-
- function EdIsDevice(Fname : Filepath) : Boolean;
- {-return true if fname is a DOS device}
- var
- regs : registers;
- F : file;
- Handle : Word absolute F;
-
- begin {EdIsDevice}
- Assign(F, Fname);
- Reset(F);
- if EdINT24Result <> 0 then
- {Probably a file}
- EdIsDevice := False
- else
- with regs do begin
- ax := $4400;
- Bx := Handle;
- intr($21, regs);
- EdIsDevice := (Dx and $80 <> 0);
- end;
- Close(F);
- end; {EdIsDevice}
-
- function EdExistFile(Fname : Filepath) : Boolean;
- {-return true if file exists, false if non-existent or a device}
- var
- F : file;
- I : Integer;
-
- begin {EdExistFile}
- if EdIsDevice(Fname) then
- {Return false so we don't try to back up devices or get their file size}
- EdExistFile := False
- else begin
- Assign(F, Fname);
- Reset(F);
- EdExistFile := (EdINT24Result = 0);
- Close(F);
- {Clear IOresult}
- I := EdINT24Result;
- end;
- end; {EdExistfile}
-
- function EdInsertbuffer(Ncols : Integer) : Boolean;
- {-Insert buffer into text stream - after current line}
- var
- P : PlineDesc;
- Len : Integer;
-
- begin {EdInsertbuffer}
- with Curwin^ do begin
-
- {Get appropriate length of text buffer}
- Len := EdBufferSize(Ncols);
-
- if not(EdMemAvail(Len+SizeOf(Linedesc), FreeListSpace)) then begin
- {Margin for free list not available}
- EdErrormsg(35);
- EdInsertbuffer := False;
- Exit;
- end;
-
- {Make new text descriptor}
- GetMem(P, SizeOf(Linedesc));
-
- with P^ do begin
- GetMem(Txt, Len);
- {Don't include first unused byte in size of text buffer}
- Bufflen := Pred(Len);
-
- {We don't yet know anything about its font}
- Flags := NewAttr;
- Font := 0;
- end;
-
- {Link new buffer into stream}
- EdLinkbuffer(Curline, P);
-
- {Advance cursor to next line}
- Curline := P;
-
- EdInsertbuffer := True;
- end;
- end; {EdInsertbuffer}
-
- function EdExpandTabs(var B; Blen : Integer; TabSize : Integer) : Boolean;
- {-Convert tabs to spaces on "tabsize" character boundaries}
- {-B is a buffer holding the new text, blen is the number of characters}
- {-Return true if line successfully inserted}
- var
- Tlen, ActLen : Integer;
- T : TextLine;
-
- begin {EdExpandTabs}
-
- {Expand tabs into the buffer T}
- EdFastExpand(B, T, Tlen, Blen, TabSize, Maxlinelength);
-
- {Get length of line to be inserted}
- if Tlen = 0 then
- ActLen := Blen
- else
- ActLen := Tlen;
-
- {Insert it into text stream}
- if EdInsertbuffer(Succ(ActLen)) then begin
- with Curwin^.Curline^ do
- if Tlen = 0 then begin
- {No tabs found}
- {Put original disk buffer into line buffer}
- Move(B, Txt^[1], Blen);
- FillChar(Txt^[Succ(Blen)], Bufflen-Blen, Blank);
- end else begin
- {Put expanded line into the line buffer}
- Move(T[1], Txt^[1], Tlen);
- FillChar(Txt^[Succ(Tlen)], Bufflen-Tlen, Blank);
- end;
- EdExpandTabs := True;
- end else
- EdExpandTabs := False;
-
- end; {EdExpandTabs}
-
- procedure EdConvertFormatChars(var P : PlineDesc);
- {-Convert WordStar dot commands to MicroStar format commands}
-
- begin {EdConvertFormatChars}
- with P^ do
- if Txt^[1] = Period then begin
- Txt^[1] := FormatChar;
- if Txt^[2] = Period then
- Txt^[2] := FormatChar;
- end;
- end; {EdConvertFormatChars}
-
- procedure EdReadtextfile(Fname : Filepath; ReadingBlock : Boolean);
- {-Read text file into current window}
- var
- Infile : file;
- TopSave, Cursave : PlineDesc;
- EdError, Endoffile, GotEol : Boolean;
- Colsave, BufOfs, BufPos, BufCnt, EolPos, EofPos, LineLen : Integer;
-
- begin {EdReadtextfile}
-
- if Abortcmd or EdStringEmpty(Fname) then
- Exit;
-
- {Show "Reading" status}
- EdForceMessage(EdGetMessage(325));
-
- Assign(Infile, Fname);
- Reset(Infile, 1);
- if EdFileerror then
- Exit;
-
- with Curwin^ do begin
-
- {Reduce available memory so we have something left to link with}
- FreeListSpace := FreeListPerm+(Maxlinelength shl 1);
-
- {Start inserting text at current cursor}
- EdInsertLine;
- if Goterror then begin
- Close(Infile);
- Exit;
- end;
-
- {Save line position, which will be starting line of newly read text}
- TopSave := TopLine;
- Cursave := Curline;
- Colsave := Colno;
-
- EdError := False;
- BufOfs := 0;
-
- {Allocate buffers to the nearest byte while reading files}
- ExactAllocation := True;
-
- if ReadingBlock then begin
- Modified := True;
- EdResetPageLine(Curwin);
- end else begin
- {A new file}
- Modified := False;
- Clineno := 1;
- end;
-
- repeat
-
- {Check keyboard for abort and typeahead}
- EdBreathe;
- EdError := EdError or Abortcmd;
-
- if not(EdError) then begin
-
- {Get a new buffer full of characters}
- EdBlockRead(Infile, WorkBuf[Succ(BufOfs)], Bufsize-BufOfs, BufCnt);
- Inc(BufCnt, BufOfs);
- {Bufcnt now holds count of characters in buffer}
-
- EdError := EdError or EdFileerror;
-
- {Adjust BufCnt for first ^Z found in buffer}
- if BufCnt <> 0 then begin
- EofPos := EdLongPosFwd(WorkBuf, 1, BufCnt, EofMark);
- if EofPos <> 0 then
- BufCnt := Pred(EofPos);
- end;
- end;
-
- {End of file if no active characters in buffer}
- Endoffile := EdError or (BufCnt <= 0);
-
- if not(Endoffile) then begin
-
- if SaveStripMode then
- {Set high bit off for WordStar DOC files}
- EdStripHighBit(WorkBuf, BufCnt);
-
- {Scan the buffer, breaking it into <CR><LF> delimited lines}
- BufOfs := 0;
- BufPos := 1;
-
- repeat
-
- {Find next EOL in the buffer}
- EolPos := EdLongPosFwd(WorkBuf, BufPos, BufCnt, EolMark);
-
- if (EolPos = 0) and (BufPos+Maxlinelength >= Bufsize) then begin
-
- {Eolmark not found in buffer}
-
- {Partial line, continue line into next buffer}
- BufOfs := Succ(BufCnt-BufPos);
- Move(WorkBuf[BufPos], WorkBuf[1], BufOfs);
- {Force loop exit}
- BufPos := Succ(BufCnt);
-
- end else begin
-
- {Eolmark found or linebreak forced}
-
- if (EolPos = 0) or ((EolPos-BufPos) >= Maxlinelength) then begin
- {Linebreak forced without finding a <CR><LF>}
- {Always leave at least one blank at end of line}
- EolPos := Pred(BufPos+Maxlinelength);
- if EolPos > BufCnt then
- EolPos := Succ(BufCnt);
- GotEol := False;
- end else
- GotEol := True;
-
- if EolPos > BufPos then begin
-
- {Nonempty line, store it}
- LineLen := EolPos-BufPos;
- if ReadExpandTabs then begin
- {Check for and expand any tab characters}
-
- if not(EdExpandTabs(WorkBuf[BufPos], LineLen, SaveTabSize)) then begin
- {Insufficient memory}
- EdError := True;
- Goterror := False;
- Modified := True;
- end;
- end else begin
- {Not expanding tabs, create new line and fill it}
-
- if EdInsertbuffer(Succ(LineLen)) then
- with Curline^ do begin
- Move(WorkBuf[BufPos], Txt^[1], LineLen);
- FillChar(Txt^[Succ(LineLen)], Bufflen-LineLen, Blank);
- end
- else begin
- EdError := True;
- Goterror := False;
- Modified := True;
- end;
- end;
-
- if SaveStripMode then
- if not(EdError) then
- {Convert WordStar dot commands to MicroStar format commands}
- EdConvertFormatChars(Curline);
-
- end else begin
- {Empty line}
- if EdInsertbuffer(1) then
- with Curline^ do
- {Initialize buffer with blanks}
- FillChar(Txt^[1], Bufflen, Blank)
- else begin
- EdError := True;
- Goterror := False;
- Modified := True;
- end;
- end;
-
- if GotEol then
- {Skip over <CR><LF>}
- BufPos := EolPos+Length(EolMark)
- else
- {Start immediately after break}
- BufPos := EolPos;
-
- end; {Eolmark found}
- until EdError or (BufPos > BufCnt);
- end; {Not endoffile}
-
- until EdError or Endoffile;
-
- Close(Infile);
-
- {Restore free list margin}
- FreeListSpace := FreeListPerm;
-
- {Don't allocate on one byte boundaries any more}
- ExactAllocation := False;
-
- if ReadingBlock then begin
- {Set block markers around what we read in}
- EdRightLine;
- if GotEol then begin
- EdDownLine;
- Colno := 1;
- end else
- EdJoinline;
- with Blockto do begin
- Line := Curline;
- Col := Colno;
- end;
- with Blockfrom do begin
- Line := Cursave;
- Col := Colsave;
- end;
- {Turn off old block marks}
- EdOffblock;
- {Prepare to display new ones}
- Blockhide := False;
- end;
-
- if Curline <> Cursave then begin
- {Restore original line position}
- TopLine := TopSave;
- Curline := Cursave;
- Colno := Colsave;
- {Rejoin the left half of the line we split}
- EdJoinline;
- end;
-
- EdRealign;
- Intrflag := Interr;
- UpdateScreen := True;
-
- EdBufferCurrentLine;
-
- end; {With Curwin^}
-
- EdZapPromptLine;
-
- end; {EdReadtextfile}
-
- procedure EdMakeBakFile(Fname : Filepath);
- {-Create a backup file based on fname}
- var
- I : Integer;
- Bname : Filepath;
- F : file;
-
- begin {EdMakeBakFile}
-
- if not(MakeBackups) then
- Exit;
-
- {Build backup name}
- if EdFileHasExtension(Fname, I) then
- Bname := Copy(Fname, 1, I)+BakFileExt
- else
- Bname := Fname+Period+BakFileExt;
-
- {Erase existing backup}
- if EdExistFile(Bname) then begin
- Assign(F, Bname);
- Erase(F);
- if EdINT24Result <> 0 then
- ;
- end;
-
- {Rename existing file to backup}
- Assign(F, Fname);
- Rename(F, Bname);
- if EdINT24Result <> 0 then
- EdErrormsg(104);
- end; {EdMakebakfile}
-
- procedure EdFlagExit;
- {-If printing not in progress, set flag to exit editor}
-
- begin {EdFlagExit}
- if Printing then begin
- {Ask to abort print job}
- if not(EdYesNo(EdGetMessage(388))) then
- Exit;
- if Abortcmd then
- Exit;
- {Close up the print job}
- EdPrintExit;
- end;
- Rundown := True;
- if CleanupAtExit then begin
- {Clear off the heap and reset the window stack in case editor called in loop}
- EdDeleteAllText(Curwin);
- EdPushWindowStack(Curwin);
- end;
- end; {EdFlagExit}
-
- procedure EdShutWindow(ExitEditor : Boolean);
- {-Shut the current window, set Rundown true if last one and ExitEditor true}
- var
- Rezoom : Boolean;
-
- begin {EdShutWindow}
- {See if there is another window open}
- if WindowCount <= 1 then begin
- if ExitEditor then
- {Exit the editor if printing not in progress}
- EdFlagExit
- else begin
- if WindowCount = 1 then begin
- {Clear the text from the window}
- EdDeleteAllText(Curwin);
- EdResetWindow(Curwin);
- end;
- {Stay in menu system}
- Intrflag := NoInterr;
- if EdPtrNotNil(CurrMenu) then
- {Temporarily remove menu from screen}
- EdEraseMenus;
- {Return to original DOS background color}
- ClrScr;
- EdUserPush(MenuPrime+'F'); {+'FO' to prompt for new file}
- end;
- end else begin
- {Undo zoom if needed}
- Rezoom := Zoomed;
- if Rezoom then
- {Pull current lines up to fit into unzoomed windows}
- EdZoomWindow(True);
- {Delete current window and return in other one}
- EdWindowUp;
- EdWindowDelete(Succ(EdWindowNumber));
- if Rezoom and ((WindowCount > 2) or SaveInitZoomState) then
- EdZoomWindow(True);
- end;
- if WindowCount > 0 then
- Dec(WindowCount);
- end; {EdShutWindow}
-
- procedure EdConvertToTabs(var Sbuf, NsBuf; Slen : Integer; var NsLen : Integer);
- {-Convert spaces to tabs in textbuffer s, returning textbuffer ns}
- const
- Tab = #9;
- DoubleQuote = #34;
- Apostrophe = #39;
- BackSlash = #92;
- var
- S : TextLine absolute Sbuf;
- Ns : TextLine absolute NsBuf;
- Ipos, SpaceCount : Integer;
- Ch : Char;
- EndOfQuote : Boolean;
-
- begin {EdConvertToTabs}
-
- NsLen := 0;
- Ipos := 1;
- SpaceCount := 0;
-
- {Loop through all characters in input buffer}
- while Ipos <= Slen do begin
-
- Ch := S[Ipos];
-
- {Insert tab characters if appropriate}
- if SpaceCount > 1 then
- if (Ipos mod SaveTabSize) = 1 then begin
- NsLen := NsLen-SpaceCount;
- for SpaceCount := 1 to (SpaceCount+Pred(SaveTabSize)) div SaveTabSize do begin
- Inc(NsLen);
- Ns[NsLen] := Tab;
- end;
- SpaceCount := 0;
- end;
-
- {Keep count of contiguous spaces}
- if (Ch = Blank) then
- Inc(SpaceCount)
- else
- SpaceCount := 0;
-
- {See if the start of a quoted region}
- if (Ch = Apostrophe) or (Ch = DoubleQuote) then begin
-
- {Pass quoted region through unchanged}
- repeat
-
- {Store character in output}
- Inc(NsLen);
- Ns[NsLen] := S[Ipos];
-
- {Move to next input character}
- Inc(Ipos);
-
- {Check for end of quote}
- if Ipos >= Slen then
- {End of line}
- EndOfQuote := True
- else if S[Ipos] = Ch then
- {Perhaps end of quote}
- case Ch of
- Apostrophe : EndOfQuote := True;
- DoubleQuote : EndOfQuote := (S[Pred(Ipos)] <> BackSlash);
- end
- else
- EndOfQuote := False;
-
- until EndOfQuote;
-
- end;
-
- Inc(NsLen);
- Ns[NsLen] := S[Ipos];
- Inc(Ipos);
-
- end;
- end; {EdConvertToTabs}
-
- procedure EdFileWrite(Fname : Filepath; Quitting : Boolean);
- {-Save current text stream to specified file}
- var
- OutFile : file;
- P : PlineDesc;
- W : Pwindesc;
- Len, BufPos, BufSiz, Olen : Integer;
-
- begin {EdFileWrite}
- AbortEnable := True;
- EdWait;
-
- if EdExistFile(Fname) then begin
- {Create a .BAK file}
- EdMakeBakFile(Fname);
- if Goterror then
- Exit;
- end;
-
- Assign(OutFile, Fname);
- Rewrite(OutFile, 1);
- if EdFileerror then
- Exit;
-
- {Find top of stream}
- P := EdTopofStream(Curwin);
-
- BufPos := 0;
- BufSiz := Bufsize-Length(EolMark);
-
- with Curwin^ do
- repeat
-
- {Check for abort}
- if not(Quitting) then
- {If leaving the editor, let DOS buffer keystrokes}
- EdBreathe;
-
- Len := EdTextLength(P);
-
- if BufPos+Len > BufSiz then begin
- {Flush write buffer}
- EdBlockWrite(OutFile, WorkBuf[1], BufPos);
- BufPos := 0;
- end;
-
- if Len <> 0 then
- if WriteCompressTabs then begin
- EdConvertToTabs(P^.Txt^, WorkBuf[BufPos], Len, Olen);
- BufPos := BufPos+Olen;
- end else begin
- Move(P^.Txt^[1], WorkBuf[Succ(BufPos)], Len);
- BufPos := BufPos+Len;
- end;
-
- EdFwdPtr(P);
- if EdPtrNotNil(P) then begin
- {Add end of line marker}
- Move(EolMark[1], WorkBuf[Succ(BufPos)], Length(EolMark));
- BufPos := BufPos+Length(EolMark);
- end;
-
- until Abortcmd or Goterror or EdPtrIsNil(P);
-
- if EdPtrIsNil(P) and (BufPos <> 0) then
- {Flush the final chunk}
- EdBlockWrite(OutFile, WorkBuf[1], BufPos);
-
- if EdPtrIsNil(P) and not(EdIsDevice(Fname)) then begin
- {Write EOF marker}
- if not(EdStringEmpty(EofMark)) then
- EdBlockWrite(OutFile, EofMark[1], Length(EofMark));
-
- if not(Goterror) then begin
- {Indicate that window and any linked to it are now saved completely}
- W := Curwin;
- repeat
- if W^.Stream = Curwin^.Stream then
- W^.Modified := False;
- EdFwdPtr(W);
- until W = Curwin;
- end;
-
- end;
-
- Close(OutFile);
- if EdFileerror then
- ;
- end; {EdFileWrite}
-
- procedure EdLogDrive(NewPath : Filepath);
- {-Select a new drive or directory}
- var
- OldPath : Filepath;
-
- begin {EdLogdrive}
- if Abortcmd or EdStringEmpty(NewPath) then
- Exit;
-
- if (Length(NewPath) > 1) and
- (NewPath[Length(NewPath)] = '\') and
- (NewPath[Pred(Length(NewPath))] <> ':') then
- {Remove trailing backslash}
- Delete(NewPath, Length(NewPath), 1);
-
- {Get current path in case of error}
- GetDir(0, OldPath);
-
- {Change to the requested directory}
- ChDir(NewPath);
- if EdINT24Result <> 0 then begin
- {Invalid directory}
- EdErrormsg(122);
- {Change to the previous directory again (DOS quirk requires)}
- ChDir(OldPath);
- end;
- end; {EdLogdrive}
-
- function EdWriteNamedFile : Boolean;
- {-Get file name, save current text stream to it, change stream names}
- var
- Fname, Junk : Filepath;
-
- begin {EdWriteNamedFile}
-
- EdWriteNamedFile := False;
-
- {Get a file name}
- EdClearString(Junk);
- Fname := EdGetFileName(EdGetMessage(386), DefExtension, EdYcenterWindow(3), 0, Junk, False);
- if Abortcmd or EdStringEmpty(Fname) then
- Exit;
-
- if EdExistFile(Fname) then begin
- {Prompt to overwrite}
- if not(EdYesNo(EdGetMessage(319))) then
- Exit;
- if Abortcmd then
- Exit;
- end;
-
- EdFileWrite(Fname, False);
- if Goterror then
- Exit;
-
- {Change the names of all linked streams}
- EdChangeStreamName(Fname);
-
- EdWriteNamedFile := True;
-
- end; {EdWriteNamedFile}
-
- function CheckCurwinModified : boolean;
- {-See if current window is modified, and if so, prompt to save it}
- var
- SaveFirst : Boolean;
-
- begin {CheckCurwinModified}
- CheckCurwinModified := false;
- with Curwin^ do
- if Modified then
- {Prompt user to avoid loss of edits}
- if EdLinkedWindow(Curwin) then
- {Assure other modified flags are set, but abandon this window}
- EdCloneModifiedFlags
- else begin
- {See if user wants to save it before quitting window}
- SaveFirst := EdYesNo(Blank+EdEndOfPath(Filename)+EdGetMessage(306));
- if Abortcmd then
- Exit;
- if SaveFirst then
- if Filename = NoFile then begin
- if not(EdWriteNamedFile) then
- exit;
- end else
- EdFileWrite(Filename, False);
- end;
- CheckCurwinModified := true;
- end; {CheckCurwinModified}
-
- procedure EdAbandonFile(ExitEditor : Boolean);
- {-Close file without saving}
-
- begin {EdAbandonFile}
- if WindowCount >= 1 then
- {If current window is modified, prompt to save it}
- if not CheckCurwinModified then
- {Exit if AbortCmd or <Esc> was entered}
- exit;
-
- {Clearing the text stream from memory takes a little while}
- EdWait;
- EdShutWindow(ExitEditor);
- end; {EdAbandonFile}
-
- procedure EdDirectory;
- {-Display and allow browsing of file directory}
- var
- Fname : Filepath;
-
- begin {EdDirectory}
- EdWritePromptLine('');
- Fname := LastDirectory;
- EdAskfor(EdGetMessage(303), 5, 20, 66, Fname);
- if Abortcmd then
- Exit;
- LastDirectory := Fname;
- EdCleanFileName(Fname);
- {Use popup window when appropriate to allow browsing directory}
- Fname := EdPickdir(Fname, 389, 0, False);
- end; {EdDirectory}
-
- function EdGetFileName(Prompt, DefExt : VarString;
- Row, Attr : Byte;
- var LastFname : Filepath; UseWild : Boolean) : Filepath;
- {-Return a file name to use}
- var
- Fname : Filepath;
-
- begin {EdGetFileName}
-
- EdGetFileName := '';
- if EditUsercommandInput = 0 then
- EdWritePromptLine(EdGetMessage(302));
-
- repeat
- Abortcmd := False;
- Goterror := False;
- {Initialize default value}
- if UseWild and EdStringEmpty(LastFname) then begin
- if EdStringEmpty(DefExtension) then
- Fname := '*.*'
- else
- Fname := '*.'+DefExtension;
- end else
- Fname := LastFname;
- {Prompt for a new string}
- EdAskfor(Prompt, 3, Row, 66, Fname);
- if Abortcmd or EdStringEmpty(Fname) then
- Exit;
- {Clean up the file name}
- EdCleanFileName(Fname);
- {Store response for later use}
- LastFname := Fname;
- {Use popup window when appropriate to allow picking from directory}
- Fname := EdPickdir(Fname, 304, Attr, True);
- if Goterror then
- Exit;
- {Loop if no file selected from pick window}
- until not(EdStringEmpty(Fname));
-
- if Attr = 0 then begin
- {Strip blanks, uppercase, etc.}
- EdCleanFileName(Fname);
- EdDefaultExtension(DefExt, Fname);
- end;
-
- EdGetFileName := Fname;
- end; {EdGetfilename}
-
- procedure EdReadFile(Fname : Filepath);
- {-Check and open a text file for editing}
- var
- Code : Integer;
- F : file;
-
- function EdWindowLinked(Fname : Filepath) : Boolean;
- {-Return true if and when window has been linked to another window}
- var
- IsLinked : Boolean;
- Wthis, Wnext : Integer;
- W : Pwindesc;
-
- procedure EdWindowLink(Wto : Byte; Wfrom : Byte);
- {-Link one window to another}
- var
- Pto, Pfrom : Pwindesc;
-
- begin {EdWindowLink}
-
- Pto := EdFindWindesc(Wto);
- Pfrom := EdFindWindesc(Wfrom);
-
- with Pfrom^ do begin
-
- {Clean out source window's text if no other windows point to it}
- if not(EdLinkedWindow(Pfrom)) then
- EdDeleteAllText(Pfrom);
-
- {Match streams}
- Stream := Pto^.Stream;
-
- {Now equate the two}
- Filename := Pto^.Filename;
- TopLine := Pto^.TopLine;
- Curline := Pto^.TopLine;
- Lmargin := Pto^.Lmargin;
- Wmargin := Pto^.Wmargin;
- Rmargin := Pto^.Rmargin;
- Modified := Pto^.Modified;
- Leftedge := Pto^.Leftedge;
- Lineno := 1;
- Colno := 1;
- end;
-
- end; {EdWindowLink}
-
- begin {EdWindowLinked}
- IsLinked := False;
- {If more than one window, then see if we should link to other window}
- if (Fname <> NoFile) and (WindowCount > 0) then begin
- {Get number of this window}
- Wthis := EdWindowNumber;
- Wnext := Wthis;
- W := Curwin;
- repeat
- EdFwdPtr(W);
- Inc(Wnext);
- if Fname = W^.Filename then begin
- IsLinked := True;
- EdWindowLink(Wnext, Wthis);
- end;
- until IsLinked or (W = Curwin);
- end;
- EdWindowLinked := IsLinked;
- end; {EdWindowLinked}
-
- begin {EdReadfile}
-
- if Abortcmd or Goterror then begin
- Goterror := True;
- Exit;
- end;
-
- if EdStringEmpty(Fname) then
- {Support editing of as yet unnamed files}
- Fname := NoFile
- else if EdIsDevice(Fname) then begin
- {Can't read from a device}
- EdErrormsg(34);
- Exit;
- end;
-
- {Erase the menu system if currently displayed}
- if EdPtrNotNil(CurrMenu) then
- EdEraseMenus;
-
- {Link text stream to existing window if appropriate}
- if not(EdWindowLinked(Fname)) then begin
-
- if Fname <> NoFile then begin
- {Try to open existing file}
- Assign(F, Fname);
- Reset(F);
- Code := EdINT24Result;
- if hi(Code) <> 0 then begin
- {Drive not ready}
- EdErrormsg(128);
- Exit;
- end;
- end else
- Code := 1;
-
- Curwin^.Filename := Fname;
-
- if Code <> 0 then begin
-
- if Fname <> NoFile then begin
- {File was not found. See if illegal name, or just new file}
- Rewrite(F);
- if EdINT24Result <> 0 then begin
- {Illegal file name}
- EdErrormsg(5);
- Exit;
- end;
- Close(F);
- Erase(F);
- end;
-
- {New file}
- EdZapPromptLine;
- EdAppPromptLine(EdGetMessage(301));
- Curwin^.Modified := False;
- Intrflag := NoInterr;
- EdUpdateScreen;
- EdInterruptibleDelay(1500);
-
- end else begin
-
- {Update the screen while the file is read}
- Intrflag := NoInterr;
- EdUpdateScreen;
- {Read in existing file}
- Close(F);
- EdReadtextfile(Fname, False);
-
- end;
-
- end;
- EdZapPromptLine;
- UpdateScreen := True;
- UpdateCursor := True;
-
- end; {EdReadfile}
-
- procedure EdWriteBlock(Fname : Filepath; Exists, Appending : Boolean);
- {-Write or append marked block to file}
- var
- Stop, Start, Len, Olen, BufPos, BufSiz : Integer;
- P : PlineDesc;
- OutFile : file;
-
- procedure EdAddToFile(var OutFile : file);
- {-Append to an existing file terminated with up to 127 ^Z marks}
- var
- Fsize, LastSect : LongInt;
- LastBuf : array[0..128] of Char;
- Bufsize, EofPos, BytesRead : Integer;
-
- begin {EdAddToFile}
- Reset(OutFile, 1);
- Fsize := FileSize(OutFile);
- if Fsize = 0 then
- Rewrite(OutFile, 1)
- else begin
- {Seek last (possibly partial) 128 byte block and search for ^Z}
- LastSect := 128*(Fsize div 128);
- if Abs(LastSect-Fsize) < 1 then
- {File was on an exact 128 byte boundary}
- LastSect := Fsize-128;
- Seek(OutFile, LastSect);
- Bufsize := Fsize-LastSect;
- EdBlockRead(OutFile, LastBuf[1], Bufsize, BytesRead);
- if Goterror then
- Exit;
- EofPos := EdLongPosFwd(LastBuf, 1, BytesRead, EofMark);
- if EofPos <> 0 then
- Fsize := LastSect+LongInt(EofPos)-1;
- {Move file pointer to first ^Z}
- Seek(OutFile, Fsize);
- end;
- end; {EdAddToFile}
-
- begin {EdWriteBlock}
-
- {Append wait signal to command line}
- EdWait;
-
- Assign(OutFile, Fname);
- if Exists and Appending then begin
- EdAddToFile(OutFile);
- if Goterror then
- Exit
- end else begin
- Rewrite(OutFile, 1);
- if EdFileerror then
- Exit;
- end;
-
- P := Blockfrom.Line;
-
- BufPos := 0;
- BufSiz := Bufsize-Length(EolMark);
-
- repeat
-
- {Enable typeahead and abort during writing}
- EdBreathe;
-
- if P = Blockfrom.Line then
- Start := Blockfrom.Col
- else
- Start := 1;
-
- if P = Blockto.Line then
- Stop := Pred(Blockto.Col)
- else
- Stop := EdTextLength(P);
-
- Len := Succ(Stop-Start);
-
- if BufPos+Len > BufSiz then begin
- {Flush write buffer}
- EdBlockWrite(OutFile, WorkBuf[1], BufPos);
- BufPos := 0;
- end;
-
- if Len > 0 then
- if WriteCompressTabs then begin
- EdConvertToTabs(P^.Txt^[Pred(Start)], WorkBuf[BufPos], Len, Olen);
- BufPos := BufPos+Olen;
- end else begin
- Move(P^.Txt^[Start], WorkBuf[Succ(BufPos)], Len);
- BufPos := BufPos+Len;
- end;
-
- if P = Blockto.Line then
- EdSetPtrNil(P)
- else begin
- EdFwdPtr(P);
- Move(EolMark[1], WorkBuf[Succ(BufPos)], Length(EolMark));
- BufPos := BufPos+Length(EolMark);
- end;
-
- until Abortcmd or Goterror or EdPtrIsNil(P);
-
- if EdPtrIsNil(P) and (BufPos <> 0) then
- {Flush the final chunk}
- EdBlockWrite(OutFile, WorkBuf[1], BufPos);
-
- if EdPtrIsNil(P) and not(EdIsDevice(Fname)) then
- {Write EOF marker}
- if not(EdStringEmpty(EofMark)) then
- EdBlockWrite(OutFile, EofMark[1], Length(EofMark));
-
- Close(OutFile);
- if EdFileerror then
- ;
-
- end; {EdWriteBlock}
-
- end.