From: Richard Burgess <> Date: Thu, 9 Feb 1995 15:56:34 +0000 (+0000) Subject: autocommit for file dated 1995-02-09 15:56:34 X-Git-Url: https://pd.if.org/git/?p=mmurtl;a=commitdiff_plain;h=8ed7a4c1f8c8ffbe52b02a52ee95f2d46ec1764b autocommit for file dated 1995-02-09 15:56:34 --- diff --git a/msamples/editor/edit.c b/msamples/editor/edit.c new file mode 100644 index 0000000..cfb1d13 --- /dev/null +++ b/msamples/editor/edit.c @@ -0,0 +1,1380 @@ +/* Edit.c A simple editor using MMURTL file system and keyboard services + Use MakeIT.Bat to build this MMURTL samples application, or + use CM32 and DASM spearately: + CM32 Edit.c + DASM Edit.bat +*/ + +#define U32 unsigned long +#define S32 long +#define U16 unsigned int +#define S16 int +#define U8 unsigned char +#define S8 char + +#define TRUE 1 +#define FALSE 0 + +#include +#include +#include + +/* Includes for OS public calls and structures */ + +#include "\OSSOURCE\MKernel.h" +#include "\OSSOURCE\MMemory.h" +#include "\OSSOURCE\MData.h" +#include "\OSSOURCE\MTimer.h" +#include "\OSSOURCE\MVid.h" +#include "\OSSOURCE\MKbd.h" +#include "\OSSOURCE\MJob.h" +#include "\OSSOURCE\MFiles.h" + +#define EDVID BRITEWHITE|BGBLUE +#define NORMVID WHITE|BGBLACK +#define MARKVID WHITE|BGRED +#define STATVID BLACK|BGCYAN + +#define EMPTY 99999 +#define NLINESMAX 26 + +struct EditRecType { + U8 *pBuf; + U8 *pBufWork; /* For copy and move */ + U32 Line[NLINESMAX]; /* Offset in buf for 1st char in line */ + U32 iBufMax; /* sBuf - 1 */ + U32 iColMin; /* Screen coords */ + U32 iRowMin; + U32 iColMax; + U32 iRowMax; + U32 sLine; + U8 bSpace; + U8 fVisible; + U32 iAttrMark; + U32 iAttrNorm; + U32 iTabNorm; + U32 oBufLine0 /* oBufLine0 */ + U32 iCol; /* cursor, 0..sLine-1 */ + U32 iLine; /* cursor, 0..cLines-1 */ + U32 oBufInsert; /* offset of next char in */ + U32 oBufLast; /* offset+1 of last char */ + U32 oBufMark; + U32 oBufBound; + }; + +struct EditRecType EdRec; +struct EditRecType *pEdit; +char *pBuf1, *pBuf2; +unsigned char b, b1; +long erc, fh; +char fModified; +char fOvertype; +char aStat[80]; +char aStat1[80]; +char aCmd[80]; /* Get our command line */ +long cbCmd = 0; +char *apParam[13]; /* Param 0 is cmd name */ +long acbParam[13]; +#define nParamsMax 13 +char Filename[60]; +long cbFilename; +unsigned char filler[100]; + + +void clearbuf(void); /* prototype for forward usage */ + +/********************************************************* + Displays errors if they occur for certain file operations. +*********************************************************/ + +long CheckErc(long call, long erc) +{ +char st[40]; +long i; + + if (erc) { + FillData(st, 40, 0); + Beep(); + switch (call) { + case 1: + sprintf(st, "Error %05d occurred on OpenFile", erc); + break; + case 2: + sprintf(st, "Error %05d occurred on ReadBytes", erc); + break; + case 3: + sprintf(st, "Error %05d occurred on WriteBytes", erc); + break; + case 4: + sprintf(st, "Error %05d occurred on CreateFile", erc); + break; + case 5: + sprintf(st, "Error %05d occurred on SetFileSize", erc); + break; + case 6: + sprintf(st, "Error %05d occurred on SetFileLFA", erc); + break; + case 7: + sprintf(st, "Error %05d occurred on ReadKbd", erc); + break; + default: + sprintf(st, "Error %05d occurred on last command", erc); + break; + } + for (i=0; i<40; i++) + if (!st[i]) + st[i] = ' '; + + PutVidChars (40, 24, st, 39, STATVID); + } + return (erc); +} + +/********************************************************* + Clears the status line with 80 blank chars. +*********************************************************/ +void ClearStatus(void) +{ +char st[80]; + FillData(st, 80, 0); + PutVidChars (0, 24, st, 80, NORMVID); +} + + +/************************************************************* + Saves a file you are editing. If fPrompt is true, this + will prompt you to save. If fClose is true, the file will be + closed and the buffer will be closed. +**************************************************************/ + +void SaveFile(int fPrompt, int fClose) +{ +U32 i, keycode, fYes; +unsigned char *pBuff; + + pBuff = pEdit->pBuf; + + if ((fh) && (fModified)) + { + if (pEdit->fVisible) + { /* fix visible characters */ + for (i=0; i <=pEdit->iBufMax; i++) + if (pBuff[i] == 0x07) + pBuff[i] = 0x20; + pEdit->fVisible = FALSE; + } + fYes = 1; + if (fPrompt) + { + ClearStatus(); + SetXY(0, 24); + TTYOut("This file has been modified. SAVE IT? (Y/N)", 43, BLACK|BGCYAN); + ReadKbd(&keycode, 1); + if (((keycode & 0xff) == 'N') || ((keycode & 0xff) == 'n')) + { + fYes = 0; + ClearStatus(); + } + } + + if (fYes) + { + erc = CheckErc(6, SetFileLFA(fh, 0)); + if (!erc) + erc = CheckErc(5, SetFileSize(fh, + pEdit->oBufLast)); + if (!erc) + erc = CheckErc(3, WriteBytes (fh, pBuf1, + pEdit->oBufLast, &i)); + fModified = 0; + ClearStatus(); + PutVidChars (0, 24, "DONE... ", 10, STATVID); + Sleep(150); + ClearStatus(); + } + + } + + if (fh && fClose) + { + CloseFile(fh); + fh = 0; + cbFilename = 0; + clearbuf(); + } +} + +/************************************************************* + This prompts for a filename to open and opens it if it + exists. If not, it will prompts to create. +**************************************************************/ + +void OpenAFile(char *name) +{ +U32 filesize, dret, keycode; + + erc = 0; + cbFilename = 0; + if (!name) + { + SetXY(0,24); + PutVidChars (0,24, "Filename: ", 10, BLACK|BGWHITE); + SetXY(10,24); + EditLine(Filename, 0, 60, &cbFilename, &b1, BLACK|BGCYAN); + SetXY(0,0); + } + else + { + b1=0x0d; + strncpy(Filename, name, 13); + cbFilename = strlen(Filename); + } + if ((b1==0x0d) && (cbFilename)) { + erc = OpenFile(Filename, cbFilename, ModeModify, 1, &fh); + if (!erc) { + GetFileSize(fh, &filesize); + if (filesize < 131000) /* Buf is 131071 */ + { + erc = ReadBytes (fh, pBuf1, filesize, &dret); + if (erc > 1) + erc = CheckErc(2, erc); + else erc = 0; + pEdit->oBufLast = dret; /* offset+1 of last char */ + pBuf1[pEdit->oBufLast] = 0x0F; /* the SUN */ + } + else + { + CloseFile(fh); + fh = 0; + Beep(); + SetXY(50, 24); + TTYOut("File is too large to edit.", 26, BLACK|BGCYAN); + ReadKbd(&keycode, 1); + } + } + else if (erc == 203) { /* no such file */ + Beep(); + SetXY(50, 24); + TTYOut("Doesn't exist. Create?? (Y/N)", 29, BLACK|BGCYAN); + ReadKbd(&keycode, 1); + if (((keycode & 0xff) == 'Y') || ((keycode & 0xff) == 'y')) { + erc = CheckErc(4, CreateFile(Filename, cbFilename, 0)); + + if (!erc) + erc = CheckErc(1, OpenFile(Filename, cbFilename, + ModeModify, 1, &fh)); + + if (erc) { + fh = 0; + cbFilename = 0; + } + + } + else { + cbFilename = 0; + ClearStatus(); + } + } + else + CheckErc(1, erc); + } + + if (!erc) + ClearStatus(); +} + +/************************************************************ + This counts ABSOLUTE LINES from the begining of the buffer + up to point of oBufLine0 (which is the first char displayed + in the window. ABSOLUTE means LFs were found, even though + we word wrap always. +*************************************************************/ + +unsigned long CountEols (void) +{ +unsigned long nEols, i; +unsigned char *pBuff; + + pBuff = pEdit->pBuf; + nEols = 0; + i = 0; + + while (i < pEdit->oBufLine0) /* count LFs */ + if (pBuff[i++] == 0x0A) + nEols++; + + return(nEols); +} + + + +/************************************************************ + This returns the index to the the last character in a line + upto a maximum of sLine-1. iBuf points to the beginning + point in the buffer to find the end of line for. +*************************************************************/ + +unsigned long findEol (unsigned long iBuf) +{ + +unsigned long iEol, iEolMax; +unsigned char *pBuff; + + pBuff = pEdit->pBuf; + + /* Calculate the most it could be */ + + iEolMax = iBuf + pEdit->sLine-1; + + /* Fix it if EOL is past end of data */ + + if (iEolMax > pEdit->oBufLast) + iEolMax = pEdit->oBufLast; + + iEol = iBuf; + while ((pBuff[iEol] != 0x0A) && (iEol < iEolMax)) /* Find CR */ + iEol++; + if ((iEol == iEolMax) && (pBuff[iEol] != 0x0A)) { /* if no CR... */ + iEol = iEolMax; + if (iEolMax < pEdit->oBufLast) { + + /* now work back to last space */ + while ((pBuff[iEol] != pEdit->bSpace) && (iEol > iBuf)) + iEol--; + + /* now find first non-space - allows */ + if ((iEol > iBuf) && + (pBuff[iEol] == pEdit->bSpace) && /* wrap-around w/ double space */ + (iEol == iEolMax)) { + + if ((pBuff[iEol-1] == pEdit->bSpace) || + ((iEol == iEolMax) && (pBuff[iEol+1] == pEdit->bSpace))) { + while ((pBuff[iEol] == pEdit->bSpace) && (iEol > iBuf)) + iEol--; + while ((pBuff[iEol] != pEdit->bSpace) && (iEol > iBuf)) + iEol--; + } + } + if ((iEol == iBuf) && + (pBuff[iBuf] > 0) && + (pBuff[iEolMax] > 0)) /* handles "all-char" of full line */ + iEol = iEolMax; + } + } + return(iEol); +} + +/************************************************************ + This walks back through the buffer looking for the + logical end of a line. +*************************************************************/ + + +unsigned long findPrevLine (unsigned long oBufStart) +{ +unsigned long i, j; +char *pBuff; + + pBuff = pEdit->pBuf; + + i = 0; + if (oBufStart) + i = oBufStart - 1; + while ((i) && (pBuff[i] != 0x0A)) + i--; + if (i > 0) + i--; + while ((i > 0) && (pBuff[i] != 0x0A)) + i--; + if (i) + i++; /* Get to known start of line */ + do { + j = i; + i = (findEol (j)) + 1; + } + while (i < oBufStart); + return(j); +} + +/************************************************************ + This executes the BEGIN BLOCK (Mark) command. +*************************************************************/ + + +void doMark (unsigned long iLn) +{ +unsigned long iColStart, iColFinish, iMarkLoc, iBoundLoc; + + if (pEdit->oBufMark < EMPTY) { + if (pEdit->oBufMark <= pEdit->oBufBound) { + iMarkLoc = pEdit->oBufMark; + iBoundLoc = pEdit->oBufBound; + } + else { + iMarkLoc = pEdit->oBufBound; + iBoundLoc = pEdit->oBufMark; + } + if ( ((iMarkLoc >= pEdit->Line[iLn]) && (iMarkLoc < pEdit->Line[iLn+1])) || + ((iBoundLoc >= pEdit->Line[iLn]) && (iBoundLoc < pEdit->Line[iLn+1])) || + ((iMarkLoc < pEdit->Line[iLn]) && (iBoundLoc >= pEdit->Line[iLn+1])) ) + { + if (iMarkLoc >= pEdit->Line[iLn]) + iColStart = pEdit->iColMin + iMarkLoc - pEdit->Line[iLn]; + else + iColStart = pEdit->iColMin; + + if (iBoundLoc < pEdit->Line[iLn+1]) + iColFinish = pEdit->iColMin + iBoundLoc - pEdit->Line[iLn]; + else + iColFinish = pEdit->iColMin + pEdit->Line[iLn+1] - pEdit->Line[iLn] - 1; + + if (iColStart > pEdit->iColMin) + PutVidAttrs (pEdit->iColMin, + iLn, + iColStart-pEdit->iColMin, + pEdit->iAttrNorm); + PutVidAttrs (iColStart, iLn, iColFinish - iColStart +1, pEdit->iAttrMark); + + if (iColFinish < pEdit->iColMax) + PutVidAttrs (iColFinish+1, + iLn, + pEdit->iColMax - iColFinish, + pEdit->iAttrNorm); + } + else /*buf col*/ + PutVidAttrs (pEdit->iColMin, + iLn, + pEdit->sLine, + pEdit->iAttrNorm); + } +} + + +/************************************************************ + This inserts data into the main editing buffer. +*************************************************************/ + + +char putInBuf( unsigned char bPutIn, + char fOvertype, + char fSpecInsert) +{ +unsigned long cb; +char fOK, *pBuff; + + fModified = 1; + pBuff = pEdit->pBuf; + + if ((pEdit->oBufInsert < pEdit->iBufMax) && + ((pEdit->oBufLast < pEdit->iBufMax) || + ((fOvertype) && (!fSpecInsert)))) + { + fOK = 1; + if ((fOvertype) && (!fSpecInsert)) { + pBuff[pEdit->oBufInsert] = bPutIn; + if (pEdit->oBufLast == pEdit->oBufInsert) + pEdit->oBufLast++; + pEdit->oBufInsert++; + } + else { + cb = pEdit->oBufLast - pEdit->oBufInsert + 1; + CopyData (&pBuff[pEdit->oBufInsert], pEdit->pBufWork, cb); + pBuff[pEdit->oBufInsert] = bPutIn; + CopyData (pEdit->pBufWork, &pBuff[pEdit->oBufInsert+1], cb); + pEdit->oBufLast++; + pEdit->oBufInsert++; + if (pEdit->oBufMark < EMPTY) { + if (pEdit->oBufInsert-1 < pEdit->oBufMark) + pEdit->oBufMark++; + if (pEdit->oBufInsert-1 <= pEdit->oBufBound) + pEdit->oBufBound++; + } + } + } + else { + fOK = 0; + Beep(); + erc = 40400; + } + return (fOK); +} + +/************************************************************ + This executes the MOVE command which moves a marked + block to the cursor's current location in the file. +*************************************************************/ + +void moveData (void) +{ +unsigned long i, iMk, iBd; +char *pBuff, *pBuffWork; + + pBuff = pEdit->pBuf; + pBuffWork = pEdit->pBufWork; + +if (pEdit->oBufMark < EMPTY) { + fModified = 1; + if (pEdit->oBufMark <= pEdit->oBufBound) { + iMk = pEdit->oBufMark; + iBd = pEdit->oBufBound; + } + else { + iBd = pEdit->oBufMark; + iMk = pEdit->oBufBound; + } + if ((pEdit->oBufInsert < iMk) || (pEdit->oBufInsert > iBd)) { + for (i=0; i <= pEdit->oBufLast; i++) + pBuffWork[i] = pBuff[i]; + if (pEdit->oBufInsert < iMk) { + for (i=0; i<=iBd-iMk; i++) /* Move mk/bd */ + pBuff[pEdit->oBufInsert+i] = pBuffWork[iMk+i]; + for (i=0; i<=iMk - pEdit->oBufInsert - 1; i++) /* Shift overwritten ahead */ + pBuff[pEdit->oBufInsert+iBd-iMk+1+i] = + pBuffWork[pEdit->oBufInsert+i]; + } + if (pEdit->oBufInsert > iBd) { + for (i=0; pEdit->oBufInsert - iBd - 1; i++) + pBuff[iMk+i] = pBuffWork[iBd+1+i]; + pEdit->oBufInsert = pEdit->oBufInsert - iBd + iMk - 1; + for (i=0; i <=iBd-iMk; i++) + pBuff[pEdit->oBufInsert+i] = pBuffWork[iMk+i]; + } + iBd = pEdit->oBufInsert + iBd - iMk; + iMk = pEdit->oBufInsert; + if (pEdit->oBufBound > pEdit->oBufMark) { + pEdit->oBufBound = iBd; + pEdit->oBufMark = iMk; + } + else { + pEdit->oBufMark = iBd; + pEdit->oBufBound = iMk; + } + } +} + else Beep(); +} + +/************************************************************ + This executes the COPY command which copies a marked + block to the cursor's current location in the file. +*************************************************************/ + +void CopyIt (void) +{ +unsigned long iMk, iBd; +char *pBuff, *pBuffWork; + + pBuff = pEdit->pBuf; + pBuffWork = pEdit->pBufWork; + +if (pEdit->oBufMark < EMPTY) { + fModified = 1; + + if (pEdit->oBufMark <= pEdit->oBufBound) { + iMk = pEdit->oBufMark; + iBd = pEdit->oBufBound; + } else { + iBd = pEdit->oBufMark; + iMk = pEdit->oBufBound; + } + if (pEdit->oBufLast+iBd-iMk+1 < pEdit->iBufMax) { + CopyData(pBuff, pBuffWork, pEdit->oBufLast+1); + CopyData(&pBuffWork[iMk], &pBuff[pEdit->oBufInsert], iBd-iMk+1); + if (pEdit->oBufLast >= pEdit->oBufInsert) + CopyData(&pBuffWork[pEdit->oBufInsert], + &pBuff[pEdit->oBufInsert+iBd-iMk+1], + pEdit->oBufLast - pEdit->oBufInsert+1); + iBd = pEdit->oBufInsert + iBd - iMk; + iMk = pEdit->oBufInsert; + pEdit->oBufInsert = pEdit->oBufInsert + iBd - iMk + 1; + pEdit->oBufLast = pEdit->oBufLast + iBd - iMk + 1; + if (pEdit->oBufBound > pEdit->oBufMark) { + pEdit->oBufBound = iBd; + pEdit->oBufMark = iMk; + } + else { + pEdit->oBufMark = iBd; + pEdit->oBufBound = iMk; + } + } +} +else Beep(); +} + +/************************************************************ + This sets the characters on the screen to normal attributes +*************************************************************/ + +void normAttr (void) +{ +unsigned long i; + + for (i = pEdit->iRowMin; i <= pEdit->iRowMax; i++) + PutVidAttrs (pEdit->iColMin, i, pEdit->sLine, pEdit->iAttrNorm); +} + +/************************************************************ + This unmarks a selected block. (hides it). +*************************************************************/ + +void nullMarkBound (void) +{ + pEdit->oBufMark = EMPTY; + pEdit->oBufBound = EMPTY; + normAttr (); +} + +/************************************************************ + This DELETES a selected block. +*************************************************************/ + +void deleteData (void) +{ +unsigned long i, iMk, iBd; +char fProb; +char *pBuff, *pBuffWork; + + pBuff = pEdit->pBuf; + pBuffWork = pEdit->pBufWork; + +if (pEdit->oBufMark < EMPTY) { + fModified = 1; + if (pEdit->oBufMark <= pEdit->oBufBound) { + iMk = pEdit->oBufMark; + iBd = pEdit->oBufBound; + } else { + iBd = pEdit->oBufMark; + iMk = pEdit->oBufBound; + } + if ((pEdit->oBufLine0 >= iMk) && (pEdit->oBufLine0 <= iBd)) + fProb = TRUE; + else fProb = FALSE; + CopyData(&pBuff[iBd+1], &pBuff[iMk], pEdit->oBufLast-iBd); + pEdit->oBufLast = pEdit->oBufLast - iBd + iMk - 1; + if (pEdit->oBufInsert > iBd) + pEdit->oBufInsert = pEdit->oBufInsert - iBd + iMk; + else if ((pEdit->oBufInsert > iMk) && (pEdit->oBufInsert <= iBd)) + pEdit->oBufInsert = iMk; + if (pEdit->oBufInsert > pEdit->oBufLast) + pEdit->oBufInsert = pEdit->oBufLast; + if (fProb) { + i = findPrevLine (pEdit->oBufInsert); + pEdit->oBufLine0 = i; + } + nullMarkBound (); +} +} + +/************************************************************ + After screen movement (such as scrolling), this + finds the proper location of the cursor in relationship + to the portion of the file currently displayed. +*************************************************************/ + +void findCursor (void) +{ + /* locates cursor based on oBufInsert + - might be off screen - if it is, this + will adjust screen */ + +unsigned long i, j; + + i = pEdit->iRowMin; + while ((i <= pEdit->iRowMax) && (pEdit->oBufInsert >= pEdit->Line[i])) + i++; + pEdit->iLine = i - 1; + if (pEdit->iLine < pEdit->iRowMin) + pEdit->iLine = pEdit->iRowMin; + + j = pEdit->iLine; + if ((pEdit->Line[j+1] < EMPTY) && + (pEdit->oBufInsert >= pEdit->Line[j+1])) + pEdit->iLine = pEdit->iLine + 1; + j = pEdit->iLine; + pEdit->iCol = pEdit->oBufInsert - pEdit->Line[j] + pEdit->iColMin; + if (pEdit->iLine > pEdit->iRowMax + 1) + pEdit->iLine = pEdit->iRowMax; +} + +/************************************************************ + This readjusts iCol & iLine to get them back in sync with + oBufInsert if oBufInsert is on screen. If oBufInsert is + not onscreen, this makes it so it is! +*************************************************************/ + +void coordCursor_oBuf (void) +{ +unsigned long oBuf, i; + + i = pEdit->iRowMax+1; + if ((pEdit->oBufInsert >= pEdit->oBufLine0) && + (pEdit->oBufInsert < pEdit->Line[i])) { + + /* if bogus line, guarantee end of good */ + + i = pEdit->iLine; + if (pEdit->Line[i] == EMPTY) + pEdit->iCol = pEdit->iColMax; + + /* if bogus line, find last good line */ + + while ((pEdit->Line[i] == EMPTY) && + (i > pEdit->iRowMin)) { + pEdit->iLine--; + i = pEdit->iLine; + } + + i = pEdit->iLine; + pEdit->oBufInsert = + pEdit->Line[i] + pEdit->iCol - pEdit->iColMin; + if (pEdit->oBufInsert > pEdit->oBufLast) + pEdit->oBufInsert = pEdit->oBufLast; + oBuf = pEdit->Line[i+1]; + if (pEdit->oBufInsert > oBuf) + pEdit->oBufInsert = oBuf; /* get to potential insert - is, if + prev char <> CR, is not if prev = CR */ + if (pEdit->oBufInsert == oBuf) /* if at EOL */ + if (pEdit->pBuf[oBuf-1] == 0x0A) + pEdit->oBufInsert--; + pEdit->iCol = pEdit->oBufInsert + pEdit->iColMin - + pEdit->Line[i]; + } +} + + +/************************************************************ + Adjusts oBufLine0 to make sure that oBufInsert is on the screen. + This also sets all of the Line array values (Line[n]) +*************************************************************/ + +void makeOnScreen (void) +{ +unsigned long i, j, k; + + /* If oBufInsert is not on screen (above current display) + then find the previous line beginning and make that + the new first line 1 until it is! + */ + + while (pEdit->oBufInsert < pEdit->oBufLine0) + pEdit->oBufLine0 = findPrevLine (pEdit->oBufLine0); + + /* Set Line[iRowMin] to match oBufLine0 */ + + k = pEdit->iRowMin; + pEdit->Line[k] = pEdit->oBufLine0; + + /* Set all subsequent Line[s] by calling findEol for each. */ + + for (i = k; i <= pEdit->iRowMax; i++) { + if (pEdit->Line[i] < EMPTY) { + j = findEol (pEdit->Line[i]); + if (j < pEdit->oBufLast) /* j = offset of last char of line */ + pEdit->Line[i+1] = j + 1; + else + for (j=i+1; jLine[j] = EMPTY; + } + } + + /* If the InsertPoint (your cursor position) is past + the last line then do this junk to fix it */ + + j = pEdit->iRowMin; + k = pEdit->iRowMax; + while (pEdit->oBufInsert >= pEdit->Line[k+1]) { + for (i=j; i<=k; i++) + pEdit->Line[i] = pEdit->Line[i+1]; + pEdit->oBufLine0 = pEdit->Line[j]; + + i = findEol (pEdit->Line[k]); /* EOL of iRowMax */ + if (i < pEdit->oBufLast) /* i = offset of last char of line */ + pEdit->Line[k+1] = i + 1; + else pEdit->Line[k+1] = EMPTY; + } +} + +/************************************************************ + Redisplay all data on the screen. +*************************************************************/ + +void showScreen (char *pFiller) +{ +unsigned long i, iLn, cb, oBuf; +char *pBuff; + + pBuff = pEdit->pBuf; + + makeOnScreen (); /* oBufInsert on screen - Line correct */ + + for (iLn = pEdit->iRowMin; iLn <= pEdit->iRowMax; iLn++) { + + /* i = offset in buf of last char on line */ + /* cb = nchars in line */ + + cb = 0; + oBuf = pEdit->Line[iLn]; + if (oBuf < EMPTY) { + if (pEdit->Line[iLn+1] < EMPTY) + i = pEdit->Line[iLn+1] - 1; + else + i = pEdit->oBufLast; + cb = i - oBuf + 1; /* Make size, not offset */ + + + if ((!pEdit->fVisible) && + (pBuff[i] == 0x0A) && + (cb)) + cb--; + } + + if ((cb) && (oBuf < EMPTY)) + PutVidChars (pEdit->iColMin, iLn, pBuff+oBuf, cb, + pEdit->iAttrNorm); + + if (cb < pEdit->sLine) + PutVidChars (pEdit->iColMin+cb, iLn, pFiller, pEdit->sLine-cb, + pEdit->iAttrNorm); + + doMark (iLn); + } +} + +/************************************************************ + Resets all variables for the editor and clears the + buffers. Called before use and after closure. +*************************************************************/ + +void clearbuf (void) +{ +unsigned long i; +char *pBuff; + + pBuff = pEdit->pBuf; + FillData(filler, 80, 0x20); + for (i=0; iLine[i] = EMPTY; + i = pEdit->iRowMin; + pEdit->Line[i] = 0; + + pEdit->iCol = pEdit->iColMin; + pEdit->iLine = pEdit->iRowMin; + pEdit->bSpace = 0x20; + pEdit->fVisible = FALSE; + fModified = 0; + fOvertype = FALSE; + pEdit->oBufLast = 0; + pEdit->oBufInsert = 0; + pEdit->oBufLine0 = 0; + pBuff[pEdit->oBufLast] = 0x0F; /* the SUN */ + nullMarkBound(); + normAttr (); +} + +/************************************************************ + This is the main editing function. It is a HUGE while + loop which reads keystrokes and processes them. +*************************************************************/ + +void Editor(char *pbExitRet) +{ +unsigned long i, j, k, key; +char fSpecInsert; /* TRUE = insert no matter what fOvertype is */ +char fScreen; /* TRUE = display entire screen */ +char fDone; +unsigned char b; +char *pBuff, *pBuffWork; +long exch; + +char testkey[10]; + + pBuff = pEdit->pBuf; + pBuffWork = pEdit->pBufWork; + fDone = FALSE; + + if (pEdit->fVisible) + { + pEdit->bSpace = 0x07; + for (i=0; i <=pEdit->oBufLast; i++) + if (pBuff[i] == 0x20) + pBuff[i] = pEdit->bSpace; + } else + pEdit->bSpace = 0x20; + + + normAttr (); + fScreen = TRUE; + + pBuff[pEdit->oBufLast] = 0x0F; /* the SUN */ + + erc = AllocExch(&exch); + + while (!fDone) + { + if (fScreen) + { + showScreen (filler); /* we know oBufInsert on screen */ + findCursor (); + fScreen = FALSE; + } + SetXY (pEdit->iCol, pEdit->iLine); + FillData(aStat, 80, 0x20); + i= CountEols() + pEdit->iLine; + sprintf(aStat,"C: %02d L: %05d nChars: %05d", + pEdit->iCol, i, pEdit->oBufLast); + if (cbFilename) + CopyData(Filename, &aStat[40], cbFilename); + if (fOvertype) + CopyData("OVR", &aStat[77], 3); + else + CopyData("INS", &aStat[77], 3); + PutVidChars (0, 0, aStat, 80, STATVID); + + fSpecInsert = FALSE; /* True if char should be inserted even if fOver */ + + CheckErc(7, ReadKbd (&key, 1)); /* Wait for char */ + + b = key & 0xff; + + if (key & 0x3000) /* ALT key is down */ + { + switch (b) + { + + case 0x42: /* ALT-B -- Beginning of Text */ + case 0x62: /* ALT-b */ + pEdit->oBufLine0 = 0; + pEdit->oBufInsert = 0; + pEdit->iCol = pEdit->iColMin; + pEdit->iLine = pEdit->iRowMin; + fScreen = TRUE; + break; + + case 0x43: /* ALT-C -- CloseFile */ + case 0x63: /* ALT-c */ + SaveFile(TRUE, TRUE); + fScreen = TRUE; + break; + case 0x45: /* ALT-E -- End of Text */ + case 0x65: /* ALT-e */ + pEdit->oBufInsert = pEdit->oBufLast; + coordCursor_oBuf (); + fScreen = TRUE; + break; + case 0x01: /* ALT-UP Arrow - Cursor to top of screen */ + pEdit->iLine = pEdit->iRowMin; + pEdit->iCol = pEdit->iColMin; + break; + case 0x02: /* ALT Down Arrow - Cursor to bottom of screen */ + pEdit->iLine = pEdit->iRowMin; + i = pEdit->iLine; + while ((pEdit->Line[i+1] < EMPTY) && + (i < pEdit->iRowMax)) { + pEdit->iLine++; + i = pEdit->iLine; + } + pEdit->iCol = pEdit->iColMax; + coordCursor_oBuf (); + break; + case 0x03: /* ALT-Left Arrow - Cursor to BOL */ + pEdit->iCol = pEdit->iColMin; + break; + case 0x04: /* ALT-Right Arrow - Cursor to EOL */ + i = pEdit->iLine; + if (pEdit->Line[i+1] < EMPTY) { + pEdit->iCol = + pEdit->iColMin + + pEdit->Line[i+1] - + pEdit->Line[i]; + i = pEdit->iLine+1; + if ((pBuff[pEdit->Line[i]-1] == 0x0A) + && (pEdit->iCol > pEdit->iColMin)) + pEdit->iCol--; + } + else pEdit->iCol = pEdit->iColMin + + pEdit->oBufLast - pEdit->Line[i]; + break; + + case 0x56: /* ALT-V Make nontext chars Visible/Invisible */ + case 0x76: /* ALT-v */ + if (pEdit->fVisible) { + for (i=0; i <= pEdit->oBufLast; i++) + if (pBuff[i] == 0x07) + pBuff[i] = 0x20; + pEdit->fVisible = FALSE; + pEdit->bSpace = 0x20; + } else { + for (i=0; i<=pEdit->oBufLast; i++) + if (pBuff[i] == 0x20) + pBuff[i] = 0x07; + pEdit->fVisible = TRUE; + pEdit->bSpace = 0x07; + } + fScreen = TRUE; + break; + case 0x4F: /* ALT-O OpenFile */ + case 0x6F: /* ALT-o */ + if (!fh) { + clearbuf(); + OpenAFile(0); + fScreen = TRUE; + } + break; + case 0x51: /* ALT Q - Quit */ + case 0x71: + SaveFile(TRUE, TRUE); + fDone = TRUE; + break; + case 0x53: /* ALT S - SaveFile */ + case 0x73: /* ALT s */ + SaveFile(FALSE, FALSE); + fScreen = TRUE; + break; + case 0x7F: /* ALT Delete (Delete Marked Block) */ + if (pEdit->oBufMark < EMPTY) { + deleteData (); + fScreen = TRUE; + } + break; + default: + break; + } + } + + else if (key & 0x0300) /* CTRL key is down */ + { + + + } + + /* Standard editing keys including LF */ + + else if (((b >= 0x20) && (b <= 0x7E)) || (b == 0x0D)) + { + coordCursor_oBuf (); + if (b == 0x20) + b = pEdit->bSpace; + if (b == 0x0D) + b = 0x0A; + /* Don't overwrite CR */ + if (pBuff[pEdit->oBufInsert] == 0x0A) + fSpecInsert = TRUE; + if (!(putInBuf (b, fOvertype, fSpecInsert))) + Beep(); + findCursor (); + fScreen = TRUE; + + } + + else if (key & 0x0C00) { /* SHIFT key is down & NOT letter keys */ + switch (b) + { + case 0x03: /* SHIFT Left */ + if (pEdit->iCol > pEdit->iColMin + 5) + pEdit->iCol -= 5; + else + if (pEdit->iCol > pEdit->iColMin) + pEdit->iCol--; + break; + case 0x04: /* SHIFT Right */ + if (pEdit->iCol < pEdit->iColMax - 5) + pEdit->iCol += 5; + else + if (pEdit->iCol < pEdit->iColMax) + pEdit->iCol++; + break; + default: + break; + } + } + + else { /* Unshifted editing keys */ + switch (b) { + case 0x08: /* Backspace */ + if (pEdit->oBufLast) { + coordCursor_oBuf (); + if (pEdit->oBufInsert) { + pEdit->oBufInsert = pEdit->oBufInsert - 1; + if (!fOvertype) { + CopyData(pBuff, + pBuffWork, + pEdit->oBufLast+1); + CopyData(&pBuffWork[pEdit->oBufInsert+1], + &pBuff[pEdit->oBufInsert], + pEdit->oBufLast-pEdit->oBufInsert); + pBuff[pEdit->oBufLast] = 0; + pEdit->oBufLast = pEdit->oBufLast - 1; + if ((pEdit->oBufMark == pEdit->oBufBound) && + (pEdit->oBufMark == pEdit->oBufInsert)) + nullMarkBound (); + if (pEdit->oBufMark < EMPTY) { + if (pEdit->oBufInsert <= pEdit->oBufMark) + pEdit->oBufMark--; + if (pEdit->oBufInsert <= pEdit->oBufBound) + pEdit->oBufBound--; + } + } + } + if (pEdit->oBufInsert < pEdit->oBufLine0) + pEdit->oBufLine0 = findPrevLine (pEdit->oBufLine0); + fScreen = TRUE; + fModified = TRUE; + } + break; + case 0x06: /* Home - Cursor to BOL */ + pEdit->iCol = pEdit->iColMin; + break; + case 0x09: /* Tab */ + if (pEdit->oBufLast + pEdit->iTabNorm < pEdit->iBufMax) + { + coordCursor_oBuf(); + j = pEdit->iTabNorm - (pEdit->iCol % pEdit->iTabNorm); + for (i=1; i <=j; i++) + putInBuf (pEdit->bSpace, FALSE, FALSE); + fScreen = TRUE; + } + break; + case 0x10: /* F2 -- UNMARK BLOCK */ + nullMarkBound (); + break; + case 0x11: /* F3 -- Begin Block */ + if (pEdit->oBufLast > 0) { + coordCursor_oBuf (); + pEdit->oBufMark = pEdit->oBufInsert; + i = pEdit->iLine; + if (pEdit->oBufMark >= pEdit->Line[i+1]) + pEdit->oBufMark = pEdit->oBufMark - 1; + if (pEdit->oBufMark == pEdit->oBufLast) + pEdit->oBufMark = pEdit->oBufLast - 1; + pEdit->oBufBound = pEdit->oBufMark; + fScreen = TRUE; + } + break; + case 0x12: /* F4 -- End Block */ + if (pEdit->oBufMark < EMPTY) { + coordCursor_oBuf (); + pEdit->oBufBound = pEdit->oBufInsert; + i = pEdit->iLine; + if (pEdit->oBufBound >= pEdit->Line[i+1]) + pEdit->oBufBound--; + if (pEdit->oBufBound == pEdit->oBufLast) + pEdit->oBufBound = pEdit->oBufLast - 1; + fScreen = TRUE; + } + break; + case 0x17: /* F9 - MOVE */ + coordCursor_oBuf (); + moveData (); + if (pEdit->oBufInsert < pEdit->oBufLine0) + pEdit->oBufLine0 = pEdit->oBufInsert; + fScreen = TRUE; + break; + case 0x18: /* F10 - COPY */ + coordCursor_oBuf (); + CopyIt (); + coordCursor_oBuf (); + fScreen = TRUE; + break; + case 0x0C: /* Page Down */ + coordCursor_oBuf (); + i = pEdit->iRowMax; + while ((pEdit->Line[i] == EMPTY) && (i > pEdit->iRowMin)) + i--; + pEdit->oBufLine0 = pEdit->Line[i]; + /*always keep onScreen*/ + if (pEdit->oBufInsert < pEdit->oBufLine0) + pEdit->oBufInsert = pEdit->oBufLine0; + pEdit->iLine = pEdit->iRowMin; + pEdit->iCol = pEdit->iColMin; + fScreen = TRUE; + break; + case 0x05: /* Page Up */ + if (pEdit->oBufLine0) { + coordCursor_oBuf (); + j = pEdit->iRowMax - pEdit->iRowMin; + i = pEdit->oBufLine0; + k = pEdit->iLine; /*fix for scrolling when iLine=iRowMax */ + do { + i = findPrevLine (i); + j--; + k--; + } + while ((j > 0) && (i > 0)); + pEdit->oBufLine0 = i; + /*fix for scroll when iLine=iRowMax*/ + if (pEdit->iLine == pEdit->iRowMax) + pEdit->oBufInsert = pEdit->Line[k]; + /*keep on screen*/ + i = pEdit->iRowMax; + if (pEdit->oBufInsert >= pEdit->Line[i+1]) + pEdit->oBufInsert = pEdit->Line[i]; + fScreen = TRUE; + } + break; + case 0x01: /* Up */ + if (pEdit->iLine > pEdit->iRowMin) { + pEdit->iLine--; + } else { /* scroll screen down if we can */ + i = pEdit->oBufLine0; + if (i > 0) { + i = findPrevLine (i); + pEdit->oBufLine0 = i; + pEdit->oBufInsert = i; + fScreen = TRUE; + } + } + break; + case 0x02: /* Down */ + i = pEdit->iLine; + if ((pEdit->Line[i+1] < EMPTY) && /*Down Arrow*/ + (i < pEdit->iRowMax)) { + pEdit->iLine++; + } + else { /* ELSE scroll screen UP if we can */ + i = pEdit->iRowMax; + if (pEdit->Line[i+1] < EMPTY) { + pEdit->oBufInsert = pEdit->Line[i+1]; + i = pEdit->iCol; + j = pEdit->iLine; + coordCursor_oBuf (); + pEdit->iCol = i; + pEdit->iLine = j; + fScreen = TRUE; + } + } + break; + case 0x03: /* Left */ + if (pEdit->iCol > pEdit->iColMin) { /*Left Arrow*/ + pEdit->iCol--; + } + break; + case 0x04: /* Right */ + if (pEdit->iCol < pEdit->iColMax) { + pEdit->iCol++; + } + break; + case 0x0E: /* Insert */ + if (fOvertype) + fOvertype = FALSE; + else fOvertype = TRUE; + break; + case 0x7F: /* Delete */ + coordCursor_oBuf (); + if ((pEdit->oBufLast) && + (pEdit->oBufLast > pEdit->oBufInsert)) { + CopyData(pBuff, + pBuffWork, + pEdit->oBufLast+1); + CopyData(&pBuffWork[pEdit->oBufInsert+1], + &pBuff[pEdit->oBufInsert], + pEdit->oBufLast-pEdit->oBufInsert); + pBuff[pEdit->oBufLast] = 0; + pEdit->oBufLast--; + if ((pEdit->oBufInsert == pEdit->oBufMark) && + (pEdit->oBufMark == pEdit->oBufBound)) + nullMarkBound (); + if (pEdit->oBufMark < EMPTY) { + if (pEdit->oBufInsert < pEdit->oBufMark) + pEdit->oBufMark--; + if (pEdit->oBufInsert < pEdit->oBufBound) + pEdit->oBufBound--; + if (pEdit->oBufMark == pEdit->oBufLast) + pEdit->oBufMark--; + if (pEdit->oBufBound == pEdit->oBufLast) + pEdit->oBufBound--; + } + fScreen = TRUE; + fModified = TRUE; + } + break; + default: + break; + } + } + } /* Not fDone */ + + + for (i=pEdit->iRowMin; i <=pEdit->iRowMax; i++) + PutVidAttrs (pEdit->iColMin, i, pEdit->sLine+1, 0); /* REM buffer column */ + + if (fh) { + if (pEdit->fVisible) /* fix visible characters */ + for (i=0; i <=pEdit->iBufMax; i++) + if (pBuff[i] == 0x07) + pBuff[i] = 0x20; + pBuff[pEdit->oBufLast] = 0; + if (fModified) { + erc = CheckErc(6, SetFileLFA(fh, 0)); + if (!erc) + erc = CheckErc(5, SetFileSize(fh,pEdit->oBufLast)); + if (!erc) + erc = CheckErc(3, WriteBytes (fh, pBuf1, pEdit->oBufLast, &i)); + fModified = 0; + } + CloseFile(fh); + cbFilename = 0; + } + + *pbExitRet = b; + return; +} + +/************************************************************ + This is the main entry point for the editor. It aloocates + two buffers of equal size(a main and a working buffer), + and then checks for a single parameter which should be the + name of the file to edit. +*************************************************************/ + +void main(U32 argc, U8 *argv[]) +{ +long i; + + ClrScr(); + SetJobName("Editor", 6); + fh = 0; + + pEdit = &EdRec; + erc = AllocPage(32, &pBuf1); /* 32 pages = 128K */ + erc = AllocPage(32, &pBuf2); + + pEdit->pBuf = pBuf1; + pEdit->pBufWork = pBuf2; + pEdit->iBufMax = 131071; /*sBuf - 1 */ + pEdit->iColMin = 0; /*Screen coordinates*/ + pEdit->iColMax = 79; + pEdit->iRowMin = 1; + pEdit->iRowMax = 23; + pEdit->sLine = 80; /* iColMax-iColMin+1 */ + pEdit->bSpace = 0x20; + pEdit->fVisible = FALSE; + pEdit->iAttrMark = MARKVID; /* Rev Vid*/ + pEdit->iAttrNorm = EDVID; /* Rev Vid Half Bright */ + pEdit->iTabNorm = 4; /* Tabs every 4th column */ + pEdit->oBufLine0 = 0; /* oBufLine0 */ + pEdit->iCol = 0; /* cursor, 0..sLine-1 */ + pEdit->iLine = 0; /* cursor, 0..cLines-1 */ + pEdit->oBufInsert = 0; /* offset of next char in */ + pEdit->oBufLast = 0; /* offset+1 of last char */ + pEdit->oBufMark = EMPTY; + pEdit->oBufBound = EMPTY; + + SetNormVid(NORMVID); + + FillData(filler, 80, 0x20); + for (i=0; iLine[i] = EMPTY; + i = pEdit->iRowMin; + pEdit->Line[i] = 0; + + fModified = 0; + fOvertype = FALSE; /* Set Overtype OFF */ + + if (argc > 1) + { + OpenAFile(argv[1]); + } + + Editor(&b); + ExitJob(0); +}