1 /* Edit.c A simple editor using MMURTL file system and keyboard services
\r
2 Use MakeIT.Bat to build this MMURTL samples application, or
\r
3 use CM32 and DASM spearately:
\r
8 #define U32 unsigned long
\r
10 #define U16 unsigned int
\r
12 #define U8 unsigned char
\r
22 /* Includes for OS public calls and structures */
\r
24 #include "\OSSOURCE\MKernel.h"
\r
25 #include "\OSSOURCE\MMemory.h"
\r
26 #include "\OSSOURCE\MData.h"
\r
27 #include "\OSSOURCE\MTimer.h"
\r
28 #include "\OSSOURCE\MVid.h"
\r
29 #include "\OSSOURCE\MKbd.h"
\r
30 #include "\OSSOURCE\MJob.h"
\r
31 #include "\OSSOURCE\MFiles.h"
\r
33 #define EDVID BRITEWHITE|BGBLUE
\r
34 #define NORMVID WHITE|BGBLACK
\r
35 #define MARKVID WHITE|BGRED
\r
36 #define STATVID BLACK|BGCYAN
\r
39 #define NLINESMAX 26
\r
41 struct EditRecType {
\r
43 U8 *pBufWork; /* For copy and move */
\r
44 U32 Line[NLINESMAX]; /* Offset in buf for 1st char in line */
\r
45 U32 iBufMax; /* sBuf - 1 */
\r
46 U32 iColMin; /* Screen coords */
\r
56 U32 oBufLine0 /* oBufLine0 */
\r
57 U32 iCol; /* cursor, 0..sLine-1 */
\r
58 U32 iLine; /* cursor, 0..cLines-1 */
\r
59 U32 oBufInsert; /* offset of next char in */
\r
60 U32 oBufLast; /* offset+1 of last char */
\r
65 struct EditRecType EdRec;
\r
66 struct EditRecType *pEdit;
\r
67 char *pBuf1, *pBuf2;
\r
68 unsigned char b, b1;
\r
74 char aCmd[80]; /* Get our command line */
\r
76 char *apParam[13]; /* Param 0 is cmd name */
\r
78 #define nParamsMax 13
\r
81 unsigned char filler[100];
\r
84 void clearbuf(void); /* prototype for forward usage */
\r
86 /*********************************************************
\r
87 Displays errors if they occur for certain file operations.
\r
88 *********************************************************/
\r
90 long CheckErc(long call, long erc)
\r
96 FillData(st, 40, 0);
\r
100 sprintf(st, "Error %05d occurred on OpenFile", erc);
\r
103 sprintf(st, "Error %05d occurred on ReadBytes", erc);
\r
106 sprintf(st, "Error %05d occurred on WriteBytes", erc);
\r
109 sprintf(st, "Error %05d occurred on CreateFile", erc);
\r
112 sprintf(st, "Error %05d occurred on SetFileSize", erc);
\r
115 sprintf(st, "Error %05d occurred on SetFileLFA", erc);
\r
118 sprintf(st, "Error %05d occurred on ReadKbd", erc);
\r
121 sprintf(st, "Error %05d occurred on last command", erc);
\r
124 for (i=0; i<40; i++)
\r
128 PutVidChars (40, 24, st, 39, STATVID);
\r
133 /*********************************************************
\r
134 Clears the status line with 80 blank chars.
\r
135 *********************************************************/
\r
136 void ClearStatus(void)
\r
139 FillData(st, 80, 0);
\r
140 PutVidChars (0, 24, st, 80, NORMVID);
\r
144 /*************************************************************
\r
145 Saves a file you are editing. If fPrompt is true, this
\r
146 will prompt you to save. If fClose is true, the file will be
\r
147 closed and the buffer will be closed.
\r
148 **************************************************************/
\r
150 void SaveFile(int fPrompt, int fClose)
\r
152 U32 i, keycode, fYes;
\r
153 unsigned char *pBuff;
\r
155 pBuff = pEdit->pBuf;
\r
157 if ((fh) && (fModified))
\r
159 if (pEdit->fVisible)
\r
160 { /* fix visible characters */
\r
161 for (i=0; i <=pEdit->iBufMax; i++)
\r
162 if (pBuff[i] == 0x07)
\r
164 pEdit->fVisible = FALSE;
\r
171 TTYOut("This file has been modified. SAVE IT? (Y/N)", 43, BLACK|BGCYAN);
\r
172 ReadKbd(&keycode, 1);
\r
173 if (((keycode & 0xff) == 'N') || ((keycode & 0xff) == 'n'))
\r
182 erc = CheckErc(6, SetFileLFA(fh, 0));
\r
184 erc = CheckErc(5, SetFileSize(fh,
\r
187 erc = CheckErc(3, WriteBytes (fh, pBuf1,
\r
188 pEdit->oBufLast, &i));
\r
191 PutVidChars (0, 24, "DONE... ", 10, STATVID);
\r
207 /*************************************************************
\r
208 This prompts for a filename to open and opens it if it
\r
209 exists. If not, it will prompts to create.
\r
210 **************************************************************/
\r
212 void OpenAFile(char *name)
\r
214 U32 filesize, dret, keycode;
\r
221 PutVidChars (0,24, "Filename: ", 10, BLACK|BGWHITE);
\r
223 EditLine(Filename, 0, 60, &cbFilename, &b1, BLACK|BGCYAN);
\r
229 strncpy(Filename, name, 13);
\r
230 cbFilename = strlen(Filename);
\r
232 if ((b1==0x0d) && (cbFilename)) {
\r
233 erc = OpenFile(Filename, cbFilename, ModeModify, 1, &fh);
\r
235 GetFileSize(fh, &filesize);
\r
236 if (filesize < 131000) /* Buf is 131071 */
\r
238 erc = ReadBytes (fh, pBuf1, filesize, &dret);
\r
240 erc = CheckErc(2, erc);
\r
242 pEdit->oBufLast = dret; /* offset+1 of last char */
\r
243 pBuf1[pEdit->oBufLast] = 0x0F; /* the SUN */
\r
251 TTYOut("File is too large to edit.", 26, BLACK|BGCYAN);
\r
252 ReadKbd(&keycode, 1);
\r
255 else if (erc == 203) { /* no such file */
\r
258 TTYOut("Doesn't exist. Create?? (Y/N)", 29, BLACK|BGCYAN);
\r
259 ReadKbd(&keycode, 1);
\r
260 if (((keycode & 0xff) == 'Y') || ((keycode & 0xff) == 'y')) {
\r
261 erc = CheckErc(4, CreateFile(Filename, cbFilename, 0));
\r
264 erc = CheckErc(1, OpenFile(Filename, cbFilename,
\r
265 ModeModify, 1, &fh));
\r
286 /************************************************************
\r
287 This counts ABSOLUTE LINES from the begining of the buffer
\r
288 up to point of oBufLine0 (which is the first char displayed
\r
289 in the window. ABSOLUTE means LFs were found, even though
\r
290 we word wrap always.
\r
291 *************************************************************/
\r
293 unsigned long CountEols (void)
\r
295 unsigned long nEols, i;
\r
296 unsigned char *pBuff;
\r
298 pBuff = pEdit->pBuf;
\r
302 while (i < pEdit->oBufLine0) /* count LFs */
\r
303 if (pBuff[i++] == 0x0A)
\r
311 /************************************************************
\r
312 This returns the index to the the last character in a line
\r
313 upto a maximum of sLine-1. iBuf points to the beginning
\r
314 point in the buffer to find the end of line for.
\r
315 *************************************************************/
\r
317 unsigned long findEol (unsigned long iBuf)
\r
320 unsigned long iEol, iEolMax;
\r
321 unsigned char *pBuff;
\r
323 pBuff = pEdit->pBuf;
\r
325 /* Calculate the most it could be */
\r
327 iEolMax = iBuf + pEdit->sLine-1;
\r
329 /* Fix it if EOL is past end of data */
\r
331 if (iEolMax > pEdit->oBufLast)
\r
332 iEolMax = pEdit->oBufLast;
\r
335 while ((pBuff[iEol] != 0x0A) && (iEol < iEolMax)) /* Find CR */
\r
337 if ((iEol == iEolMax) && (pBuff[iEol] != 0x0A)) { /* if no CR... */
\r
339 if (iEolMax < pEdit->oBufLast) {
\r
341 /* now work back to last space */
\r
342 while ((pBuff[iEol] != pEdit->bSpace) && (iEol > iBuf))
\r
345 /* now find first non-space - allows */
\r
346 if ((iEol > iBuf) &&
\r
347 (pBuff[iEol] == pEdit->bSpace) && /* wrap-around w/ double space */
\r
348 (iEol == iEolMax)) {
\r
350 if ((pBuff[iEol-1] == pEdit->bSpace) ||
\r
351 ((iEol == iEolMax) && (pBuff[iEol+1] == pEdit->bSpace))) {
\r
352 while ((pBuff[iEol] == pEdit->bSpace) && (iEol > iBuf))
\r
354 while ((pBuff[iEol] != pEdit->bSpace) && (iEol > iBuf))
\r
358 if ((iEol == iBuf) &&
\r
359 (pBuff[iBuf] > 0) &&
\r
360 (pBuff[iEolMax] > 0)) /* handles "all-char" of full line */
\r
367 /************************************************************
\r
368 This walks back through the buffer looking for the
\r
369 logical end of a line.
\r
370 *************************************************************/
\r
373 unsigned long findPrevLine (unsigned long oBufStart)
\r
375 unsigned long i, j;
\r
378 pBuff = pEdit->pBuf;
\r
383 while ((i) && (pBuff[i] != 0x0A))
\r
387 while ((i > 0) && (pBuff[i] != 0x0A))
\r
390 i++; /* Get to known start of line */
\r
393 i = (findEol (j)) + 1;
\r
395 while (i < oBufStart);
\r
399 /************************************************************
\r
400 This executes the BEGIN BLOCK (Mark) command.
\r
401 *************************************************************/
\r
404 void doMark (unsigned long iLn)
\r
406 unsigned long iColStart, iColFinish, iMarkLoc, iBoundLoc;
\r
408 if (pEdit->oBufMark < EMPTY) {
\r
409 if (pEdit->oBufMark <= pEdit->oBufBound) {
\r
410 iMarkLoc = pEdit->oBufMark;
\r
411 iBoundLoc = pEdit->oBufBound;
\r
414 iMarkLoc = pEdit->oBufBound;
\r
415 iBoundLoc = pEdit->oBufMark;
\r
417 if ( ((iMarkLoc >= pEdit->Line[iLn]) && (iMarkLoc < pEdit->Line[iLn+1])) ||
\r
418 ((iBoundLoc >= pEdit->Line[iLn]) && (iBoundLoc < pEdit->Line[iLn+1])) ||
\r
419 ((iMarkLoc < pEdit->Line[iLn]) && (iBoundLoc >= pEdit->Line[iLn+1])) )
\r
421 if (iMarkLoc >= pEdit->Line[iLn])
\r
422 iColStart = pEdit->iColMin + iMarkLoc - pEdit->Line[iLn];
\r
424 iColStart = pEdit->iColMin;
\r
426 if (iBoundLoc < pEdit->Line[iLn+1])
\r
427 iColFinish = pEdit->iColMin + iBoundLoc - pEdit->Line[iLn];
\r
429 iColFinish = pEdit->iColMin + pEdit->Line[iLn+1] - pEdit->Line[iLn] - 1;
\r
431 if (iColStart > pEdit->iColMin)
\r
432 PutVidAttrs (pEdit->iColMin,
\r
434 iColStart-pEdit->iColMin,
\r
436 PutVidAttrs (iColStart, iLn, iColFinish - iColStart +1, pEdit->iAttrMark);
\r
438 if (iColFinish < pEdit->iColMax)
\r
439 PutVidAttrs (iColFinish+1,
\r
441 pEdit->iColMax - iColFinish,
\r
445 PutVidAttrs (pEdit->iColMin,
\r
453 /************************************************************
\r
454 This inserts data into the main editing buffer.
\r
455 *************************************************************/
\r
458 char putInBuf( unsigned char bPutIn,
\r
466 pBuff = pEdit->pBuf;
\r
468 if ((pEdit->oBufInsert < pEdit->iBufMax) &&
\r
469 ((pEdit->oBufLast < pEdit->iBufMax) ||
\r
470 ((fOvertype) && (!fSpecInsert))))
\r
473 if ((fOvertype) && (!fSpecInsert)) {
\r
474 pBuff[pEdit->oBufInsert] = bPutIn;
\r
475 if (pEdit->oBufLast == pEdit->oBufInsert)
\r
477 pEdit->oBufInsert++;
\r
480 cb = pEdit->oBufLast - pEdit->oBufInsert + 1;
\r
481 CopyData (&pBuff[pEdit->oBufInsert], pEdit->pBufWork, cb);
\r
482 pBuff[pEdit->oBufInsert] = bPutIn;
\r
483 CopyData (pEdit->pBufWork, &pBuff[pEdit->oBufInsert+1], cb);
\r
485 pEdit->oBufInsert++;
\r
486 if (pEdit->oBufMark < EMPTY) {
\r
487 if (pEdit->oBufInsert-1 < pEdit->oBufMark)
\r
489 if (pEdit->oBufInsert-1 <= pEdit->oBufBound)
\r
490 pEdit->oBufBound++;
\r
502 /************************************************************
\r
503 This executes the MOVE command which moves a marked
\r
504 block to the cursor's current location in the file.
\r
505 *************************************************************/
\r
507 void moveData (void)
\r
509 unsigned long i, iMk, iBd;
\r
510 char *pBuff, *pBuffWork;
\r
512 pBuff = pEdit->pBuf;
\r
513 pBuffWork = pEdit->pBufWork;
\r
515 if (pEdit->oBufMark < EMPTY) {
\r
517 if (pEdit->oBufMark <= pEdit->oBufBound) {
\r
518 iMk = pEdit->oBufMark;
\r
519 iBd = pEdit->oBufBound;
\r
522 iBd = pEdit->oBufMark;
\r
523 iMk = pEdit->oBufBound;
\r
525 if ((pEdit->oBufInsert < iMk) || (pEdit->oBufInsert > iBd)) {
\r
526 for (i=0; i <= pEdit->oBufLast; i++)
\r
527 pBuffWork[i] = pBuff[i];
\r
528 if (pEdit->oBufInsert < iMk) {
\r
529 for (i=0; i<=iBd-iMk; i++) /* Move mk/bd */
\r
530 pBuff[pEdit->oBufInsert+i] = pBuffWork[iMk+i];
\r
531 for (i=0; i<=iMk - pEdit->oBufInsert - 1; i++) /* Shift overwritten ahead */
\r
532 pBuff[pEdit->oBufInsert+iBd-iMk+1+i] =
\r
533 pBuffWork[pEdit->oBufInsert+i];
\r
535 if (pEdit->oBufInsert > iBd) {
\r
536 for (i=0; pEdit->oBufInsert - iBd - 1; i++)
\r
537 pBuff[iMk+i] = pBuffWork[iBd+1+i];
\r
538 pEdit->oBufInsert = pEdit->oBufInsert - iBd + iMk - 1;
\r
539 for (i=0; i <=iBd-iMk; i++)
\r
540 pBuff[pEdit->oBufInsert+i] = pBuffWork[iMk+i];
\r
542 iBd = pEdit->oBufInsert + iBd - iMk;
\r
543 iMk = pEdit->oBufInsert;
\r
544 if (pEdit->oBufBound > pEdit->oBufMark) {
\r
545 pEdit->oBufBound = iBd;
\r
546 pEdit->oBufMark = iMk;
\r
549 pEdit->oBufMark = iBd;
\r
550 pEdit->oBufBound = iMk;
\r
557 /************************************************************
\r
558 This executes the COPY command which copies a marked
\r
559 block to the cursor's current location in the file.
\r
560 *************************************************************/
\r
564 unsigned long iMk, iBd;
\r
565 char *pBuff, *pBuffWork;
\r
567 pBuff = pEdit->pBuf;
\r
568 pBuffWork = pEdit->pBufWork;
\r
570 if (pEdit->oBufMark < EMPTY) {
\r
573 if (pEdit->oBufMark <= pEdit->oBufBound) {
\r
574 iMk = pEdit->oBufMark;
\r
575 iBd = pEdit->oBufBound;
\r
577 iBd = pEdit->oBufMark;
\r
578 iMk = pEdit->oBufBound;
\r
580 if (pEdit->oBufLast+iBd-iMk+1 < pEdit->iBufMax) {
\r
581 CopyData(pBuff, pBuffWork, pEdit->oBufLast+1);
\r
582 CopyData(&pBuffWork[iMk], &pBuff[pEdit->oBufInsert], iBd-iMk+1);
\r
583 if (pEdit->oBufLast >= pEdit->oBufInsert)
\r
584 CopyData(&pBuffWork[pEdit->oBufInsert],
\r
585 &pBuff[pEdit->oBufInsert+iBd-iMk+1],
\r
586 pEdit->oBufLast - pEdit->oBufInsert+1);
\r
587 iBd = pEdit->oBufInsert + iBd - iMk;
\r
588 iMk = pEdit->oBufInsert;
\r
589 pEdit->oBufInsert = pEdit->oBufInsert + iBd - iMk + 1;
\r
590 pEdit->oBufLast = pEdit->oBufLast + iBd - iMk + 1;
\r
591 if (pEdit->oBufBound > pEdit->oBufMark) {
\r
592 pEdit->oBufBound = iBd;
\r
593 pEdit->oBufMark = iMk;
\r
596 pEdit->oBufMark = iBd;
\r
597 pEdit->oBufBound = iMk;
\r
604 /************************************************************
\r
605 This sets the characters on the screen to normal attributes
\r
606 *************************************************************/
\r
608 void normAttr (void)
\r
612 for (i = pEdit->iRowMin; i <= pEdit->iRowMax; i++)
\r
613 PutVidAttrs (pEdit->iColMin, i, pEdit->sLine, pEdit->iAttrNorm);
\r
616 /************************************************************
\r
617 This unmarks a selected block. (hides it).
\r
618 *************************************************************/
\r
620 void nullMarkBound (void)
\r
622 pEdit->oBufMark = EMPTY;
\r
623 pEdit->oBufBound = EMPTY;
\r
627 /************************************************************
\r
628 This DELETES a selected block.
\r
629 *************************************************************/
\r
631 void deleteData (void)
\r
633 unsigned long i, iMk, iBd;
\r
635 char *pBuff, *pBuffWork;
\r
637 pBuff = pEdit->pBuf;
\r
638 pBuffWork = pEdit->pBufWork;
\r
640 if (pEdit->oBufMark < EMPTY) {
\r
642 if (pEdit->oBufMark <= pEdit->oBufBound) {
\r
643 iMk = pEdit->oBufMark;
\r
644 iBd = pEdit->oBufBound;
\r
646 iBd = pEdit->oBufMark;
\r
647 iMk = pEdit->oBufBound;
\r
649 if ((pEdit->oBufLine0 >= iMk) && (pEdit->oBufLine0 <= iBd))
\r
651 else fProb = FALSE;
\r
652 CopyData(&pBuff[iBd+1], &pBuff[iMk], pEdit->oBufLast-iBd);
\r
653 pEdit->oBufLast = pEdit->oBufLast - iBd + iMk - 1;
\r
654 if (pEdit->oBufInsert > iBd)
\r
655 pEdit->oBufInsert = pEdit->oBufInsert - iBd + iMk;
\r
656 else if ((pEdit->oBufInsert > iMk) && (pEdit->oBufInsert <= iBd))
\r
657 pEdit->oBufInsert = iMk;
\r
658 if (pEdit->oBufInsert > pEdit->oBufLast)
\r
659 pEdit->oBufInsert = pEdit->oBufLast;
\r
661 i = findPrevLine (pEdit->oBufInsert);
\r
662 pEdit->oBufLine0 = i;
\r
668 /************************************************************
\r
669 After screen movement (such as scrolling), this
\r
670 finds the proper location of the cursor in relationship
\r
671 to the portion of the file currently displayed.
\r
672 *************************************************************/
\r
674 void findCursor (void)
\r
676 /* locates cursor based on oBufInsert
\r
677 - might be off screen - if it is, this
\r
678 will adjust screen */
\r
680 unsigned long i, j;
\r
682 i = pEdit->iRowMin;
\r
683 while ((i <= pEdit->iRowMax) && (pEdit->oBufInsert >= pEdit->Line[i]))
\r
685 pEdit->iLine = i - 1;
\r
686 if (pEdit->iLine < pEdit->iRowMin)
\r
687 pEdit->iLine = pEdit->iRowMin;
\r
690 if ((pEdit->Line[j+1] < EMPTY) &&
\r
691 (pEdit->oBufInsert >= pEdit->Line[j+1]))
\r
692 pEdit->iLine = pEdit->iLine + 1;
\r
694 pEdit->iCol = pEdit->oBufInsert - pEdit->Line[j] + pEdit->iColMin;
\r
695 if (pEdit->iLine > pEdit->iRowMax + 1)
\r
696 pEdit->iLine = pEdit->iRowMax;
\r
699 /************************************************************
\r
700 This readjusts iCol & iLine to get them back in sync with
\r
701 oBufInsert if oBufInsert is on screen. If oBufInsert is
\r
702 not onscreen, this makes it so it is!
\r
703 *************************************************************/
\r
705 void coordCursor_oBuf (void)
\r
707 unsigned long oBuf, i;
\r
709 i = pEdit->iRowMax+1;
\r
710 if ((pEdit->oBufInsert >= pEdit->oBufLine0) &&
\r
711 (pEdit->oBufInsert < pEdit->Line[i])) {
\r
713 /* if bogus line, guarantee end of good */
\r
716 if (pEdit->Line[i] == EMPTY)
\r
717 pEdit->iCol = pEdit->iColMax;
\r
719 /* if bogus line, find last good line */
\r
721 while ((pEdit->Line[i] == EMPTY) &&
\r
722 (i > pEdit->iRowMin)) {
\r
728 pEdit->oBufInsert =
\r
729 pEdit->Line[i] + pEdit->iCol - pEdit->iColMin;
\r
730 if (pEdit->oBufInsert > pEdit->oBufLast)
\r
731 pEdit->oBufInsert = pEdit->oBufLast;
\r
732 oBuf = pEdit->Line[i+1];
\r
733 if (pEdit->oBufInsert > oBuf)
\r
734 pEdit->oBufInsert = oBuf; /* get to potential insert - is, if
\r
735 prev char <> CR, is not if prev = CR */
\r
736 if (pEdit->oBufInsert == oBuf) /* if at EOL */
\r
737 if (pEdit->pBuf[oBuf-1] == 0x0A)
\r
738 pEdit->oBufInsert--;
\r
739 pEdit->iCol = pEdit->oBufInsert + pEdit->iColMin -
\r
745 /************************************************************
\r
746 Adjusts oBufLine0 to make sure that oBufInsert is on the screen.
\r
747 This also sets all of the Line array values (Line[n])
\r
748 *************************************************************/
\r
750 void makeOnScreen (void)
\r
752 unsigned long i, j, k;
\r
754 /* If oBufInsert is not on screen (above current display)
\r
755 then find the previous line beginning and make that
\r
756 the new first line 1 until it is!
\r
759 while (pEdit->oBufInsert < pEdit->oBufLine0)
\r
760 pEdit->oBufLine0 = findPrevLine (pEdit->oBufLine0);
\r
762 /* Set Line[iRowMin] to match oBufLine0 */
\r
764 k = pEdit->iRowMin;
\r
765 pEdit->Line[k] = pEdit->oBufLine0;
\r
767 /* Set all subsequent Line[s] by calling findEol for each. */
\r
769 for (i = k; i <= pEdit->iRowMax; i++) {
\r
770 if (pEdit->Line[i] < EMPTY) {
\r
771 j = findEol (pEdit->Line[i]);
\r
772 if (j < pEdit->oBufLast) /* j = offset of last char of line */
\r
773 pEdit->Line[i+1] = j + 1;
\r
775 for (j=i+1; j<NLINESMAX; j++)
\r
776 pEdit->Line[j] = EMPTY;
\r
780 /* If the InsertPoint (your cursor position) is past
\r
781 the last line then do this junk to fix it */
\r
783 j = pEdit->iRowMin;
\r
784 k = pEdit->iRowMax;
\r
785 while (pEdit->oBufInsert >= pEdit->Line[k+1]) {
\r
786 for (i=j; i<=k; i++)
\r
787 pEdit->Line[i] = pEdit->Line[i+1];
\r
788 pEdit->oBufLine0 = pEdit->Line[j];
\r
790 i = findEol (pEdit->Line[k]); /* EOL of iRowMax */
\r
791 if (i < pEdit->oBufLast) /* i = offset of last char of line */
\r
792 pEdit->Line[k+1] = i + 1;
\r
793 else pEdit->Line[k+1] = EMPTY;
\r
797 /************************************************************
\r
798 Redisplay all data on the screen.
\r
799 *************************************************************/
\r
801 void showScreen (char *pFiller)
\r
803 unsigned long i, iLn, cb, oBuf;
\r
806 pBuff = pEdit->pBuf;
\r
808 makeOnScreen (); /* oBufInsert on screen - Line correct */
\r
810 for (iLn = pEdit->iRowMin; iLn <= pEdit->iRowMax; iLn++) {
\r
812 /* i = offset in buf of last char on line */
\r
813 /* cb = nchars in line */
\r
816 oBuf = pEdit->Line[iLn];
\r
817 if (oBuf < EMPTY) {
\r
818 if (pEdit->Line[iLn+1] < EMPTY)
\r
819 i = pEdit->Line[iLn+1] - 1;
\r
821 i = pEdit->oBufLast;
\r
822 cb = i - oBuf + 1; /* Make size, not offset */
\r
825 if ((!pEdit->fVisible) &&
\r
826 (pBuff[i] == 0x0A) &&
\r
831 if ((cb) && (oBuf < EMPTY))
\r
832 PutVidChars (pEdit->iColMin, iLn, pBuff+oBuf, cb,
\r
835 if (cb < pEdit->sLine)
\r
836 PutVidChars (pEdit->iColMin+cb, iLn, pFiller, pEdit->sLine-cb,
\r
843 /************************************************************
\r
844 Resets all variables for the editor and clears the
\r
845 buffers. Called before use and after closure.
\r
846 *************************************************************/
\r
848 void clearbuf (void)
\r
853 pBuff = pEdit->pBuf;
\r
854 FillData(filler, 80, 0x20);
\r
855 for (i=0; i<NLINESMAX; i++)
\r
856 pEdit->Line[i] = EMPTY;
\r
857 i = pEdit->iRowMin;
\r
858 pEdit->Line[i] = 0;
\r
860 pEdit->iCol = pEdit->iColMin;
\r
861 pEdit->iLine = pEdit->iRowMin;
\r
862 pEdit->bSpace = 0x20;
\r
863 pEdit->fVisible = FALSE;
\r
866 pEdit->oBufLast = 0;
\r
867 pEdit->oBufInsert = 0;
\r
868 pEdit->oBufLine0 = 0;
\r
869 pBuff[pEdit->oBufLast] = 0x0F; /* the SUN */
\r
874 /************************************************************
\r
875 This is the main editing function. It is a HUGE while
\r
876 loop which reads keystrokes and processes them.
\r
877 *************************************************************/
\r
879 void Editor(char *pbExitRet)
\r
881 unsigned long i, j, k, key;
\r
882 char fSpecInsert; /* TRUE = insert no matter what fOvertype is */
\r
883 char fScreen; /* TRUE = display entire screen */
\r
886 char *pBuff, *pBuffWork;
\r
891 pBuff = pEdit->pBuf;
\r
892 pBuffWork = pEdit->pBufWork;
\r
895 if (pEdit->fVisible)
\r
897 pEdit->bSpace = 0x07;
\r
898 for (i=0; i <=pEdit->oBufLast; i++)
\r
899 if (pBuff[i] == 0x20)
\r
900 pBuff[i] = pEdit->bSpace;
\r
902 pEdit->bSpace = 0x20;
\r
908 pBuff[pEdit->oBufLast] = 0x0F; /* the SUN */
\r
910 erc = AllocExch(&exch);
\r
916 showScreen (filler); /* we know oBufInsert on screen */
\r
920 SetXY (pEdit->iCol, pEdit->iLine);
\r
921 FillData(aStat, 80, 0x20);
\r
922 i= CountEols() + pEdit->iLine;
\r
923 sprintf(aStat,"C: %02d L: %05d nChars: %05d",
\r
924 pEdit->iCol, i, pEdit->oBufLast);
\r
926 CopyData(Filename, &aStat[40], cbFilename);
\r
928 CopyData("OVR", &aStat[77], 3);
\r
930 CopyData("INS", &aStat[77], 3);
\r
931 PutVidChars (0, 0, aStat, 80, STATVID);
\r
933 fSpecInsert = FALSE; /* True if char should be inserted even if fOver */
\r
935 CheckErc(7, ReadKbd (&key, 1)); /* Wait for char */
\r
939 if (key & 0x3000) /* ALT key is down */
\r
944 case 0x42: /* ALT-B -- Beginning of Text */
\r
945 case 0x62: /* ALT-b */
\r
946 pEdit->oBufLine0 = 0;
\r
947 pEdit->oBufInsert = 0;
\r
948 pEdit->iCol = pEdit->iColMin;
\r
949 pEdit->iLine = pEdit->iRowMin;
\r
953 case 0x43: /* ALT-C -- CloseFile */
\r
954 case 0x63: /* ALT-c */
\r
955 SaveFile(TRUE, TRUE);
\r
958 case 0x45: /* ALT-E -- End of Text */
\r
959 case 0x65: /* ALT-e */
\r
960 pEdit->oBufInsert = pEdit->oBufLast;
\r
961 coordCursor_oBuf ();
\r
964 case 0x01: /* ALT-UP Arrow - Cursor to top of screen */
\r
965 pEdit->iLine = pEdit->iRowMin;
\r
966 pEdit->iCol = pEdit->iColMin;
\r
968 case 0x02: /* ALT Down Arrow - Cursor to bottom of screen */
\r
969 pEdit->iLine = pEdit->iRowMin;
\r
971 while ((pEdit->Line[i+1] < EMPTY) &&
\r
972 (i < pEdit->iRowMax)) {
\r
976 pEdit->iCol = pEdit->iColMax;
\r
977 coordCursor_oBuf ();
\r
979 case 0x03: /* ALT-Left Arrow - Cursor to BOL */
\r
980 pEdit->iCol = pEdit->iColMin;
\r
982 case 0x04: /* ALT-Right Arrow - Cursor to EOL */
\r
984 if (pEdit->Line[i+1] < EMPTY) {
\r
989 i = pEdit->iLine+1;
\r
990 if ((pBuff[pEdit->Line[i]-1] == 0x0A)
\r
991 && (pEdit->iCol > pEdit->iColMin))
\r
994 else pEdit->iCol = pEdit->iColMin +
\r
995 pEdit->oBufLast - pEdit->Line[i];
\r
998 case 0x56: /* ALT-V Make nontext chars Visible/Invisible */
\r
999 case 0x76: /* ALT-v */
\r
1000 if (pEdit->fVisible) {
\r
1001 for (i=0; i <= pEdit->oBufLast; i++)
\r
1002 if (pBuff[i] == 0x07)
\r
1004 pEdit->fVisible = FALSE;
\r
1005 pEdit->bSpace = 0x20;
\r
1007 for (i=0; i<=pEdit->oBufLast; i++)
\r
1008 if (pBuff[i] == 0x20)
\r
1010 pEdit->fVisible = TRUE;
\r
1011 pEdit->bSpace = 0x07;
\r
1015 case 0x4F: /* ALT-O OpenFile */
\r
1016 case 0x6F: /* ALT-o */
\r
1023 case 0x51: /* ALT Q - Quit */
\r
1025 SaveFile(TRUE, TRUE);
\r
1028 case 0x53: /* ALT S - SaveFile */
\r
1029 case 0x73: /* ALT s */
\r
1030 SaveFile(FALSE, FALSE);
\r
1033 case 0x7F: /* ALT Delete (Delete Marked Block) */
\r
1034 if (pEdit->oBufMark < EMPTY) {
\r
1044 else if (key & 0x0300) /* CTRL key is down */
\r
1050 /* Standard editing keys including LF */
\r
1052 else if (((b >= 0x20) && (b <= 0x7E)) || (b == 0x0D))
\r
1054 coordCursor_oBuf ();
\r
1056 b = pEdit->bSpace;
\r
1059 /* Don't overwrite CR */
\r
1060 if (pBuff[pEdit->oBufInsert] == 0x0A)
\r
1061 fSpecInsert = TRUE;
\r
1062 if (!(putInBuf (b, fOvertype, fSpecInsert)))
\r
1069 else if (key & 0x0C00) { /* SHIFT key is down & NOT letter keys */
\r
1072 case 0x03: /* SHIFT Left */
\r
1073 if (pEdit->iCol > pEdit->iColMin + 5)
\r
1076 if (pEdit->iCol > pEdit->iColMin)
\r
1079 case 0x04: /* SHIFT Right */
\r
1080 if (pEdit->iCol < pEdit->iColMax - 5)
\r
1083 if (pEdit->iCol < pEdit->iColMax)
\r
1091 else { /* Unshifted editing keys */
\r
1093 case 0x08: /* Backspace */
\r
1094 if (pEdit->oBufLast) {
\r
1095 coordCursor_oBuf ();
\r
1096 if (pEdit->oBufInsert) {
\r
1097 pEdit->oBufInsert = pEdit->oBufInsert - 1;
\r
1101 pEdit->oBufLast+1);
\r
1102 CopyData(&pBuffWork[pEdit->oBufInsert+1],
\r
1103 &pBuff[pEdit->oBufInsert],
\r
1104 pEdit->oBufLast-pEdit->oBufInsert);
\r
1105 pBuff[pEdit->oBufLast] = 0;
\r
1106 pEdit->oBufLast = pEdit->oBufLast - 1;
\r
1107 if ((pEdit->oBufMark == pEdit->oBufBound) &&
\r
1108 (pEdit->oBufMark == pEdit->oBufInsert))
\r
1110 if (pEdit->oBufMark < EMPTY) {
\r
1111 if (pEdit->oBufInsert <= pEdit->oBufMark)
\r
1112 pEdit->oBufMark--;
\r
1113 if (pEdit->oBufInsert <= pEdit->oBufBound)
\r
1114 pEdit->oBufBound--;
\r
1118 if (pEdit->oBufInsert < pEdit->oBufLine0)
\r
1119 pEdit->oBufLine0 = findPrevLine (pEdit->oBufLine0);
\r
1124 case 0x06: /* Home - Cursor to BOL */
\r
1125 pEdit->iCol = pEdit->iColMin;
\r
1127 case 0x09: /* Tab */
\r
1128 if (pEdit->oBufLast + pEdit->iTabNorm < pEdit->iBufMax)
\r
1130 coordCursor_oBuf();
\r
1131 j = pEdit->iTabNorm - (pEdit->iCol % pEdit->iTabNorm);
\r
1132 for (i=1; i <=j; i++)
\r
1133 putInBuf (pEdit->bSpace, FALSE, FALSE);
\r
1137 case 0x10: /* F2 -- UNMARK BLOCK */
\r
1140 case 0x11: /* F3 -- Begin Block */
\r
1141 if (pEdit->oBufLast > 0) {
\r
1142 coordCursor_oBuf ();
\r
1143 pEdit->oBufMark = pEdit->oBufInsert;
\r
1145 if (pEdit->oBufMark >= pEdit->Line[i+1])
\r
1146 pEdit->oBufMark = pEdit->oBufMark - 1;
\r
1147 if (pEdit->oBufMark == pEdit->oBufLast)
\r
1148 pEdit->oBufMark = pEdit->oBufLast - 1;
\r
1149 pEdit->oBufBound = pEdit->oBufMark;
\r
1153 case 0x12: /* F4 -- End Block */
\r
1154 if (pEdit->oBufMark < EMPTY) {
\r
1155 coordCursor_oBuf ();
\r
1156 pEdit->oBufBound = pEdit->oBufInsert;
\r
1158 if (pEdit->oBufBound >= pEdit->Line[i+1])
\r
1159 pEdit->oBufBound--;
\r
1160 if (pEdit->oBufBound == pEdit->oBufLast)
\r
1161 pEdit->oBufBound = pEdit->oBufLast - 1;
\r
1165 case 0x17: /* F9 - MOVE */
\r
1166 coordCursor_oBuf ();
\r
1168 if (pEdit->oBufInsert < pEdit->oBufLine0)
\r
1169 pEdit->oBufLine0 = pEdit->oBufInsert;
\r
1172 case 0x18: /* F10 - COPY */
\r
1173 coordCursor_oBuf ();
\r
1175 coordCursor_oBuf ();
\r
1178 case 0x0C: /* Page Down */
\r
1179 coordCursor_oBuf ();
\r
1180 i = pEdit->iRowMax;
\r
1181 while ((pEdit->Line[i] == EMPTY) && (i > pEdit->iRowMin))
\r
1183 pEdit->oBufLine0 = pEdit->Line[i];
\r
1184 /*always keep onScreen*/
\r
1185 if (pEdit->oBufInsert < pEdit->oBufLine0)
\r
1186 pEdit->oBufInsert = pEdit->oBufLine0;
\r
1187 pEdit->iLine = pEdit->iRowMin;
\r
1188 pEdit->iCol = pEdit->iColMin;
\r
1191 case 0x05: /* Page Up */
\r
1192 if (pEdit->oBufLine0) {
\r
1193 coordCursor_oBuf ();
\r
1194 j = pEdit->iRowMax - pEdit->iRowMin;
\r
1195 i = pEdit->oBufLine0;
\r
1196 k = pEdit->iLine; /*fix for scrolling when iLine=iRowMax */
\r
1198 i = findPrevLine (i);
\r
1202 while ((j > 0) && (i > 0));
\r
1203 pEdit->oBufLine0 = i;
\r
1204 /*fix for scroll when iLine=iRowMax*/
\r
1205 if (pEdit->iLine == pEdit->iRowMax)
\r
1206 pEdit->oBufInsert = pEdit->Line[k];
\r
1207 /*keep on screen*/
\r
1208 i = pEdit->iRowMax;
\r
1209 if (pEdit->oBufInsert >= pEdit->Line[i+1])
\r
1210 pEdit->oBufInsert = pEdit->Line[i];
\r
1214 case 0x01: /* Up */
\r
1215 if (pEdit->iLine > pEdit->iRowMin) {
\r
1217 } else { /* scroll screen down if we can */
\r
1218 i = pEdit->oBufLine0;
\r
1220 i = findPrevLine (i);
\r
1221 pEdit->oBufLine0 = i;
\r
1222 pEdit->oBufInsert = i;
\r
1227 case 0x02: /* Down */
\r
1229 if ((pEdit->Line[i+1] < EMPTY) && /*Down Arrow*/
\r
1230 (i < pEdit->iRowMax)) {
\r
1233 else { /* ELSE scroll screen UP if we can */
\r
1234 i = pEdit->iRowMax;
\r
1235 if (pEdit->Line[i+1] < EMPTY) {
\r
1236 pEdit->oBufInsert = pEdit->Line[i+1];
\r
1239 coordCursor_oBuf ();
\r
1246 case 0x03: /* Left */
\r
1247 if (pEdit->iCol > pEdit->iColMin) { /*Left Arrow*/
\r
1251 case 0x04: /* Right */
\r
1252 if (pEdit->iCol < pEdit->iColMax) {
\r
1256 case 0x0E: /* Insert */
\r
1258 fOvertype = FALSE;
\r
1259 else fOvertype = TRUE;
\r
1261 case 0x7F: /* Delete */
\r
1262 coordCursor_oBuf ();
\r
1263 if ((pEdit->oBufLast) &&
\r
1264 (pEdit->oBufLast > pEdit->oBufInsert)) {
\r
1267 pEdit->oBufLast+1);
\r
1268 CopyData(&pBuffWork[pEdit->oBufInsert+1],
\r
1269 &pBuff[pEdit->oBufInsert],
\r
1270 pEdit->oBufLast-pEdit->oBufInsert);
\r
1271 pBuff[pEdit->oBufLast] = 0;
\r
1272 pEdit->oBufLast--;
\r
1273 if ((pEdit->oBufInsert == pEdit->oBufMark) &&
\r
1274 (pEdit->oBufMark == pEdit->oBufBound))
\r
1276 if (pEdit->oBufMark < EMPTY) {
\r
1277 if (pEdit->oBufInsert < pEdit->oBufMark)
\r
1278 pEdit->oBufMark--;
\r
1279 if (pEdit->oBufInsert < pEdit->oBufBound)
\r
1280 pEdit->oBufBound--;
\r
1281 if (pEdit->oBufMark == pEdit->oBufLast)
\r
1282 pEdit->oBufMark--;
\r
1283 if (pEdit->oBufBound == pEdit->oBufLast)
\r
1284 pEdit->oBufBound--;
\r
1297 for (i=pEdit->iRowMin; i <=pEdit->iRowMax; i++)
\r
1298 PutVidAttrs (pEdit->iColMin, i, pEdit->sLine+1, 0); /* REM buffer column */
\r
1301 if (pEdit->fVisible) /* fix visible characters */
\r
1302 for (i=0; i <=pEdit->iBufMax; i++)
\r
1303 if (pBuff[i] == 0x07)
\r
1305 pBuff[pEdit->oBufLast] = 0;
\r
1307 erc = CheckErc(6, SetFileLFA(fh, 0));
\r
1309 erc = CheckErc(5, SetFileSize(fh,pEdit->oBufLast));
\r
1311 erc = CheckErc(3, WriteBytes (fh, pBuf1, pEdit->oBufLast, &i));
\r
1322 /************************************************************
\r
1323 This is the main entry point for the editor. It aloocates
\r
1324 two buffers of equal size(a main and a working buffer),
\r
1325 and then checks for a single parameter which should be the
\r
1326 name of the file to edit.
\r
1327 *************************************************************/
\r
1329 void main(U32 argc, U8 *argv[])
\r
1334 SetJobName("Editor", 6);
\r
1338 erc = AllocPage(32, &pBuf1); /* 32 pages = 128K */
\r
1339 erc = AllocPage(32, &pBuf2);
\r
1341 pEdit->pBuf = pBuf1;
\r
1342 pEdit->pBufWork = pBuf2;
\r
1343 pEdit->iBufMax = 131071; /*sBuf - 1 */
\r
1344 pEdit->iColMin = 0; /*Screen coordinates*/
\r
1345 pEdit->iColMax = 79;
\r
1346 pEdit->iRowMin = 1;
\r
1347 pEdit->iRowMax = 23;
\r
1348 pEdit->sLine = 80; /* iColMax-iColMin+1 */
\r
1349 pEdit->bSpace = 0x20;
\r
1350 pEdit->fVisible = FALSE;
\r
1351 pEdit->iAttrMark = MARKVID; /* Rev Vid*/
\r
1352 pEdit->iAttrNorm = EDVID; /* Rev Vid Half Bright */
\r
1353 pEdit->iTabNorm = 4; /* Tabs every 4th column */
\r
1354 pEdit->oBufLine0 = 0; /* oBufLine0 */
\r
1355 pEdit->iCol = 0; /* cursor, 0..sLine-1 */
\r
1356 pEdit->iLine = 0; /* cursor, 0..cLines-1 */
\r
1357 pEdit->oBufInsert = 0; /* offset of next char in */
\r
1358 pEdit->oBufLast = 0; /* offset+1 of last char */
\r
1359 pEdit->oBufMark = EMPTY;
\r
1360 pEdit->oBufBound = EMPTY;
\r
1362 SetNormVid(NORMVID);
\r
1364 FillData(filler, 80, 0x20);
\r
1365 for (i=0; i<NLINESMAX; i++)
\r
1366 pEdit->Line[i] = EMPTY;
\r
1367 i = pEdit->iRowMin;
\r
1368 pEdit->Line[i] = 0;
\r
1371 fOvertype = FALSE; /* Set Overtype OFF */
\r
1375 OpenAFile(argv[1]);
\r