home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 182_01 / edit.c < prev    next >
Text File  |  1990-07-31  |  25KB  |  625 lines

  1. /*              EDIT.C  - Screen Editor
  2.                 by Bill Kinnersley
  3.                 MSU Physics Dept
  4.                 January 1982
  5. EDIT has many of the conveniences of WordStar, but is a much smaller and
  6. faster program.  The program is presently limited to editing files of less
  7. than 44K total length, and lines shorter than 80 characters. */
  8. #include <stdioa.h>
  9. #include <iolib.asm>
  10. #include <call.asm>
  11. #define ESC 27
  12. #define BELL 07
  13. #define DC1 17
  14. #define DC3 19
  15. #define EOFCHAR 26
  16. char *topmem;                   /* pointer to top of memory */
  17. char *topfile;                  /* pointer to top of file */
  18. char *botfile;                  /* pointer to bottom of file */
  19. char *topscr;                   /* pointer to top of screen */
  20. char *botscr;                   /* pointer to bottom of screen */
  21. char *cursor;                   /* pointer to current cursor position in file */
  22. char *null;                     /* null pointer*/
  23. char *mark;                     /* temporary pointer */
  24. int lines;                      /* line # where botscr is (1 <= lines <=25) */
  25. int csr_col;                    /* current cursor column # */
  26. int want_col;                   /* cursor column desired */
  27. int csr_line;                   /* current cursor line # */
  28. int next_char;                  /* next input char, input during screen output*/
  29. int ch;                         /* current character input from keyboard */
  30. int flag;                       /* true if cursor==topscr */
  31. int itop;                       /* topfile as an integer */
  32. int ibot;                       /* botfile as an integer */
  33. char bufin[80];
  34. char fid[20];                   /* name of file to edit */
  35. char backup[20];                /* name of backup file */
  36. int file;                       /* file descriptor # used by C */
  37. int new;                        /* true if file was new */
  38. int i;                          /* number of records written to disk */
  39. main(argc,argv)
  40. int argc;                       /* number of arguments in command line */
  41. int argv[];
  42. {
  43.         topmem = CCAVAIL() - 4096;      /* get size of available memory */
  44.         botfile = topfile = botscr = topscr = cursor = CCALLOC(topmem);
  45.         topmem = botfile + topmem;      /* point to top of available memory */
  46.         null = "";
  47.         next_char = 0;
  48.         term_init();
  49.         if (argc == 1)          /* no command tail */
  50.         {       fputs("\nFILE? : ",stderr);     /* ask for fid */
  51.                 gets(fid);
  52.         }
  53.         else strcpy(fid,argv[1]);       /* fid from command line */
  54.         fid[14] = 0;                    /* trim to 14 chars */
  55.         new = - swapin(fid,topfile);            /* try to read in */
  56.         clear_screen();
  57.         csr_line = csr_col = want_col = 0;
  58.         if (new)
  59.         {       fputs("NEW FILE\n\n",stderr);   /* must be new file*/
  60.                 lines = 3;
  61.                 *botfile = EOFCHAR;
  62.                 csr_line = 2;
  63.         }
  64.         else
  65.         {       while (*botfile != EOFCHAR) botfile++;  /* look for botfile*/
  66.                 lines = 1;
  67.                 setbot();
  68.                 putscr(topfile);
  69.                 home();
  70.         }
  71.  
  72.         while(TRUE)
  73.         {       ch = get_conin();       /* wait for console input */
  74.                 if (ch == ESC ) ch = escape();  /* convert escape sequence */
  75.                 if (((ch >= ' ') && (ch < 127)) || (ch == '\t') || (ch == '\r'))
  76.                         ins_character();
  77.                 else if (special())     /* process special characters */
  78.                         return;         /* quit */
  79.         }
  80. }
  81. ins_character()
  82. /* insert character c at current cursor position */
  83. {       disable_keyboard();
  84.         e_eol();
  85.         ibot = ++botfile; itop = ++cursor;
  86.         ++botscr;
  87.         movmem(cursor-1,cursor,ibot-itop+1);
  88.         *(cursor-1) = ch;
  89.         if (ch == '\n')
  90.                 {where();
  91.                 csr_col = want_col = 0;
  92.                 if (csr_line == 23)
  93.                         {botscr = cursor;
  94.                         lines = 25;
  95.                         printbot();
  96.                         }
  97.                 else
  98.                         {putch('\n');
  99.                         setbot();
  100.                         ins_line();
  101.                         putline(cursor);
  102.                         csr_line++;
  103.                         put_cursor(csr_line,csr_col);
  104.                         }
  105.                 }
  106.         else
  107.                 {putch(ch);
  108.                 if (ch != '\t') csr_col++;
  109.                 else csr_col = ((csr_col>>3)+1)<<3;
  110.                 want_col = csr_col;
  111.                 putline(cursor);
  112.                 position();
  113.                 }
  114.         enable_keyboard();
  115. }
  116. special()
  117. /* procedure to process special characters */
  118. {               switch (ch) {
  119. /* cursor right */      case 'D'-64 :if (cursor == botfile) break;
  120.                                 else if ((ch=*cursor++)=='\n')
  121.                                         {printbot(); csr_col=0;}
  122.                                 else if (ch=='\t')
  123.                                         {putch('\t');
  124.                                         csr_col = ((csr_col>>3)+1)<<3;}
  125.                                 else {cup_right(); csr_col++;}
  126.                                 want_col = csr_col;
  127.                                 break;
  128. /* cursor left */       case 'S'-64 :
  129.                         case 'H'-64 : flag = (cursor==topscr);
  130.                                 if (cursor==topfile) break;
  131.                                 else if ((ch=*--cursor)=='\n')
  132.                                         {reverse_index();
  133.                                         if (flag)
  134.                                                 {topscr=startline(cursor);
  135.                                                 setbot();
  136.                                                 putch('\r');
  137.                                                 putline(topscr);}
  138.                                         position();
  139.                                         }
  140.                                 else if (ch=='\t') position();
  141.                                 else {putch('\b'); csr_col--;}
  142.                                 want_col = csr_col;
  143.                                 break;
  144. /* cursor up */         case 'E'-64 :
  145.                                 if ((mark=startline(cursor))==topfile) break;
  146.                                 cursor = startline(mark-1);
  147.                                 disable_keyboard();
  148.                                 reverse_index();
  149.                                 where();
  150.                                 if (mark==topscr) {topscr = cursor;
  151.                                                 setbot();
  152.                                                 cup_home();
  153.                                                 putline(topscr);}
  154.                                 set_cursor();
  155.                                 enable_keyboard();
  156.                                 break;
  157. /* cursor down */       case 'X'-64 :
  158.                         case 'J'-64 : if ((mark = next(cursor))==null) break;
  159.                                 cursor = mark;
  160.                                 printbot();
  161.                                 where();
  162.                                 set_cursor();
  163.                                 break;
  164. /* up screenful */      case 'R'-64 : if (topscr==topfile) break;
  165.                                 disable_keyboard();
  166.                                 where();
  167.                                 botscr = topscr;
  168.                                 settop();
  169.                                 newscr();
  170.                                 enable_keyboard();
  171.                                 break;
  172. /* down screenful */    case 'C'-64 : if (botscr==botfile) break;
  173.                                 disable_keyboard();
  174.                                 topscr = botscr;
  175.                                 setbot();
  176.                                 newscr();
  177.                                 enable_keyboard();
  178.                                 break;
  179. /* top file */          case 'T'-64 : if (topscr==topfile) break;
  180.                         top:    topscr = topfile;
  181.                                 setbot();
  182.                                 newscr();
  183.                                 break;
  184. /* bottom file */       case 'B'-64 : if (botscr==botfile) break;
  185.                                 botscr = botfile;
  186.                                 settop();
  187.                                 lines = 24;
  188.                                 newscr();
  189.                                 cursor=botscr;
  190.                                 csr_line=23; csr_col=0;
  191.                                 put_cursor(csr_line,csr_col);
  192.                                 break;
  193. /* scroll down */       case 'Z'-64 : if (botscr==botfile) break;
  194.                                 where();
  195.                                 put_cursor(23,0);
  196.                                 bdos(6,'\n');
  197.                                 botscr=next(botscr);
  198.                                 settop();
  199.                                 putline(startline(botscr-1));
  200.                                 if (cursor < topscr) cursor=next(cursor);
  201.                                 if (csr_line > 0) csr_line--;
  202.                                 set_cursor();
  203.                                 break;
  204. /* scroll up */         case 'W'-64 : if (topscr==topfile) break;
  205.                                 cup_down();     /* move cursor down */
  206.                                 where();        /* save current cursor position 
  207.                                 cup_home();
  208.                                 reverse_index();
  209.                                 topscr=startline(topscr-1);
  210.                                 setbot();
  211.                                 putline(topscr);
  212.                                 if (cursor >= botscr) cursor=startline(botscr-1)
  213.                                 set_cursor();
  214.                                 break;
  215. /* find */              case 'F'-64 : clear_screen(); con_flush();
  216.                                 fputs("FIND? :",stderr);
  217.                                 gets(bufin);
  218.                                 cursor = topfile;
  219. /* refind */            case 'L'-64 : for (mark=cursor; mark!=botfile; mark++)
  220.                                         if (*mark == bufin[0])
  221.                                                 if (comp())
  222.                                                         {topscr=startline(mark);
  223.                                                         setbot();
  224.                                                         newscr();
  225.                                                         cursor=mark;
  226.                                                         position();
  227.                                                         break;}
  228.                                 if (mark==botfile) {putch(BELL); goto top;}
  229.                                 break;
  230. /* keep */              case 'K'-64 : clear_screen(); con_flush();
  231.                                 printf("Saving %s\n",fid);
  232.                                 if (!new) {strcpy(backup,fid);
  233.                                         for (ch=0; ch<15; ch++)
  234.                                                 backup[ch]=0;
  235.                                         strcat(backup,".BAK");
  236.                                         unlink(backup); rename(fid,backup);
  237.                                         }
  238.                                 if ((file=creat(fid))==ERR)
  239.                                         {printf("can't open %s",fid); return;}
  240.                                 ibot = botfile; /* change pointers */
  241.                                 itop = topfile; /* to integers  */
  242.                                 i = (ibot-itop)/128+1;
  243.                                 if (write(file,topfile,i)!=i)
  244.                                         fputs("WRITE ERROR\nDisk full?",stderr);
  245.                                 term_reset();
  246.                                 exit();
  247. /* quit */              case 'Q'-64 : clear_screen(); con_flush();
  248.                                 fputs("QUIT? ",stderr);
  249.                                 if((ch=getchar())=='Y'||ch=='y'||ch=='Y'-64)
  250.                                         {fputs("\nEdit Abandoned",stderr);
  251.                                         term_reset(); return TRUE;}
  252.                                 clear_screen();
  253.                                 putscr(cursor=topscr);
  254.                                 home();
  255.                                 break;
  256. /* delete character */  case 'G'-64 : if (cursor == botfile) break;
  257.                                 disable_keyboard();
  258.                                 ibot = --botfile; itop = cursor;
  259.                                 --botscr;
  260.                                 movmem(cursor+1,cursor,ibot-itop);
  261.                                 if (*cursor == '\n')
  262.                                         {position();
  263.                                          where();
  264.                                          setbot();
  265.                                          putline(cursor);
  266.                                          putch('\n');
  267.                                          delete_line();
  268.                                          put_cursor(csr_line,csr_col);
  269.                                         }
  270.                                 else {putline(cursor);
  271.                                         position();}
  272.                                 enable_keyboard();
  273.                                 break;
  274. /* delete */            case BELL : if (cursor == topfile) break;
  275.                                 disable_keyboard();
  276.                                 flag = (cursor == topscr);
  277.                                 ibot = --botfile; itop = --cursor;
  278.                                 --botscr;
  279.                                 ch = *cursor;
  280.                                 movmem(cursor+1,cursor,ibot-itop+1);
  281.                                 if (flag)
  282.                                         {putline(topscr=startline(cursor));
  283.                                         position();
  284.                                         }
  285.                                 else if (ch == '\n')
  286.                                         {cup_up();
  287.                                          position();
  288.                                          where();
  289.                                          setbot();
  290.                                          putline(cursor);
  291.                                          putch('\n');
  292.                                          delete_line();
  293.                                          put_cursor(csr_line,csr_col);
  294.                                         }
  295.                                 else {if (ch == '\t') position();
  296.                                                 else putch('\b');
  297.                                         putline(cursor);
  298.                                         position();}
  299.                                 enable_keyboard();
  300.                                 break;
  301.                         default: putch(BELL);   /* invalid character */
  302.         }
  303.         return FALSE;
  304. }
  305. comp()
  306. {int i;
  307.         for (i=0; bufin[i]!=0; i++) if (bufin[i] != mark[i]) return FALSE;
  308.         mark = mark + i;
  309.         return TRUE;
  310. }
  311. newscr()
  312. /* puts a new screen */
  313. {       clear_screen();
  314.         putscr(cursor=topscr);
  315.         home();
  316. }
  317. startline(start)
  318. char *start;
  319. /* returns pointer to first character in current line */
  320. {char *mark;
  321.         for(mark=start; mark!=topfile; mark--)
  322.                 if (*mark=='\n') return ++mark;
  323.         return topfile;
  324. }
  325. next(start)
  326. char *start;
  327. /* returns pointer to first character in next line */
  328. {char *mark;
  329.         for(mark=start; mark!=botfile; mark++)
  330.                 if (*mark=='\n') return ++mark;
  331.         return null;
  332. }
  333. position()
  334. /* positions screen cursor in the current line */
  335. {char *mark,i;
  336.         csr_col=0;
  337.         for (mark=startline(cursor); mark!=cursor; mark++)
  338.                 if (*mark=='\t')
  339.                         csr_col=((csr_col>>3)+1)<<3;/* count up column position*
  340.                         else csr_col++;
  341.         put_cursor(26,csr_col); /* dummy for H19 */
  342.         want_col = csr_col;
  343. }
  344. set_cursor()
  345. /* positions file cursor to position screen cursor on desired column */
  346. {int tab_col;
  347.         csr_col=0;
  348.         for (cursor=startline(cursor); *cursor!='\n'; cursor++)
  349.                 { if (csr_col == want_col) goto move_cursor;
  350.                 if (*cursor != '\t') csr_col++;
  351.                 else    {tab_col=((csr_col>>3)+1)<<3;
  352.                         if (want_col < tab_col) goto move_cursor;
  353.                         csr_col = tab_col;
  354.                 }
  355.         }
  356. move_cursor:
  357.         put_cursor(csr_line,csr_col);
  358. }
  359. putline(start)
  360. char *start;
  361. /* outputs from "start" to end of current line;
  362.    returns pointer to first char in next line */
  363. {char *mark; int i;
  364.         e_eol();
  365.         for (mark=start; mark!=botfile; mark++)
  366.                 if (*mark=='\n') return mark+1;
  367.                 else putch(*mark);
  368.         return botfile;
  369. }
  370. printbot()
  371. /* prints a line at the bottom of screen and scrolls up */
  372. {       putch('\n');
  373.         if (cursor == botscr)
  374.                 {if (lines==25) while (*topscr++ != '\n');
  375.                 if (botscr == botfile);
  376.                 botscr = putline(cursor);
  377.                 putch('\r');
  378.                 }
  379. }
  380. setbot()
  381. /* measures down 24 lines from topscr to set botscr */
  382. {       lines=0;
  383.         for (botscr=topscr; botscr!=null; botscr=next(botscr))
  384.                  if (++lines==25) return;
  385.         botscr=botfile;
  386. }
  387. putscr(start)
  388. char *start;
  389. /* outputs from "start" to botscr */
  390. {char *mark;
  391.         if (start==botscr) return;
  392.         e_eol();
  393.         for (mark=start; mark!=(botscr-1); mark++)
  394.                 { putch(*mark);
  395.                 if (!next_char)
  396.                         { next_char = bdos(6,-1);       /* look-ahead for dc3 */
  397.                         if (next_char == DC3)
  398.                                 { while (!(next_char=bdos(6,-1)));
  399.                                 if (next_char == DC1) next_char = 0;
  400.                                 }
  401.                         }
  402.                         }
  403.                 if (*mark=='\n') {e_eol();}
  404.                 }
  405.         if (lines<25) {bdos(6,*mark++); bdos(6,*mark);}
  406.         e_eos();
  407. }
  408. home()
  409. {       cup_home();
  410.         csr_line = csr_col = want_col = 0;
  411. }
  412. settop()
  413. /* measures up 23 or 24 lines from "botscr" */
  414. {int i,j;
  415.         i = j = (botscr == botfile);
  416.         for (topscr=botscr; topscr!=topfile; topscr=startline(topscr-1))
  417.                         if (++i==25) break;
  418.         lines = i - j;
  419.         setbot();
  420. }
  421. reverse_index()
  422. /* move cursor up one line, scrolling screen down if at top */
  423. {       putch(ESC); putch('I');
  424. }
  425. ins_line()
  426. /* insert new blank line on screen at current position */
  427. {       putch(ESC); putch('L');
  428. }
  429. delete_line()
  430. /* delete the current line, scroll bottom of screen, output bottom line */
  431. {       putch(ESC); putch('M');
  432.         if (lines<25) return;
  433.         putch(ESC); putch('Y'); putch('7'); putch(' ');
  434.         putline(startline(botscr-1));
  435. }
  436. putch(c)
  437. int c;
  438. /* replacement for library putc (will not swallow characters) */
  439. {       if (c == '\n') bdos(6,'\r');
  440.         bdos(6,c);
  441. }
  442. get_conin()
  443. {int c;
  444.         c = next_char;
  445.         if (c) next_char = 0;
  446.         else while (!(c=bdos(6,-1)));;
  447.         return c;
  448. }
  449. con_flush()
  450. {       while(bdos(6,-1));              /* flush type-ahead */
  451. }
  452. escape()
  453. /* procedure to process escape sequences */
  454. {int c;
  455.         c = get_conin();        /* get next character */
  456.         switch(c) {
  457. /* cursor up */         case 'A' : c = 'E'-64; break;
  458. /* cursor down */       case 'B' : c = 'X'-64; break;
  459. /* cursor forward */    case 'C' : c = 'D'-64; break;
  460. /* cursor backword */   case 'D' : c = 'S'-64; break;
  461. /* home */              case 'H' : c = 'T'-64; break;
  462. /* delete character */  case 'N' : c = 'G'-64; break;
  463. /* blue */              case 'P' : c = 'K'-64; break;
  464. /* red */               case 'Q' : c = 'Q'-64; break;
  465. /* f1 */                case 'S' : c = 'F'-64; break;
  466. /* f2 */                case 'T' : c = 'L'-64; break;
  467. /* keypad */            case '?' : c = get_conin();     /* get 3rd char */
  468.                                 switch (c) {
  469.         /* shift down */        case 'r' : c = 'C'-64; break;
  470.         /* shift home */        case 'u' : c = 'B'-64; break;
  471.         /* shift up */          case 'x' : c = 'R'-64; break;
  472.                                 default : c = 0;
  473.                                 }
  474.                                 break;
  475.                         default : c = 0;
  476.                         }
  477.         return c;       /* return modified character */
  478. }
  479. where()
  480. {       bdos(6,ESC); bdos(6,'n');               /* get cursor position */
  481.         while (get_conin() != ESC);
  482.         while (get_conin() != 'Y');
  483.         while ( 24 < (csr_line = get_conin()-32));
  484.         while ( 80 < (csr_col = get_conin()-32));
  485. }
  486. put_cursor(line,col)
  487. int line;
  488. int col;
  489. {       bdos(6,ESC); bdos(6,'Y');
  490.         bdos(6,line+32); bdos(6,col+32);
  491. }
  492. clear_screen()
  493. {       bdos(6,ESC); bdos(6,'E');
  494. }
  495. e_eol()
  496. {       bdos(6,ESC); bdos(6,'K');
  497. }
  498. e_eos()
  499. {       bdos(6,ESC); bdos(6,'J');
  500. }
  501. cup_home()
  502. {       bdos(6,ESC); bdos(6,'H');
  503. }
  504. cup_up()
  505. {       bdos(6,ESC); bdos(6,'A');
  506. }
  507. cup_down()
  508. {       bdos(6,ESC); bdos(6,'B');
  509. }
  510. cup_right()
  511. {       bdos(6,ESC); bdos(6,'C');
  512. }
  513. disable_keyboard()
  514. {       bdos(6,ESC); bdos(6,'}');
  515. }
  516. enable_keyboard()
  517. {       bdos(6,ESC); bdos(6,'{');
  518. }
  519. term_init()
  520. {       bdos(6,ESC); bdos(6,'t');               /* Enter keypad shifted mode */
  521.         bdos(6,ESC); bdos(6,'=');               /* Enter alternate keypad mode *
  522. }
  523. term_reset()
  524. {       bdos(6,ESC); bdos(6,'u');               /* Exit keypad shifted mode */
  525.         bdos(6,ESC); bdos(6,'>');               /* Exit alternate keypad mode */
  526. }
  527. bdos( bc, de) int bc, de; {
  528. #asm
  529.         POP     H                       ; pop return
  530.         POP     D                       ; pop DE register contents
  531.         POP     B                       ; pop BC register contents
  532.         PUSH    B                       ; restore stack
  533.         PUSH    D
  534.         PUSH    H
  535.         JMP     0005H                   ; return via BDOS
  536. #endasm
  537. }
  538. strcpy( d, s) char *d, *s; {
  539.         while (*s) *d++ = *s++;
  540.         *d = 0;
  541. }
  542. strcat( d, s) char *d, *s; {
  543.         while (*d) ++d;                 /* locate end of destination string */
  544.         while (*s) *d++ = *s++;         /* copy source to destination */
  545.         *d = 0;
  546. }
  547. movmem(s, d, l) char *s, *d; int l; {
  548. #asm
  549.         POP     H               ; pop return address
  550.         POP     B               ; pop length
  551.         POP     D               ; pop destination
  552.         XTHL                    ; swap source with return
  553.         MOV     A,B             ; test if length = 0
  554.         ORA     C
  555.         JZ      .MM1            ; don't move it
  556.         MOV     A,H             ; test if source > destination
  557.         CMP     D
  558.         JC      .MM0            ; source < destination
  559.         MOV     A,L
  560.         CMP     E
  561.         JC      .MM0            ; source < destination
  562.         DB      0EDH,0B0H       ; LDIR
  563.         JMP     .MM1            ; return after restoring stack
  564. .MM0:   DAD     B               ; point to end of source
  565.         DCX     H               ; point to last character in source
  566.         XCHG
  567.         DAD     B               ; point to end of destination
  568.         DCX     H               ; point to last character in destination
  569.         XCHG
  570.         DB      0EDH,0B8H       ; LDDR
  571. .MM1:   XTHL                    ; get return address
  572.         PUSH    H               ; restore stack
  573.         PUSH    H
  574.         PUSH    H
  575. ;       RET                     ; return supplied by CC
  576. #endasm
  577. }
  578. gets(s) char *s; {
  579.         return (fgets(s, 20, stdin));
  580. }
  581. swapin( fname, addr) char *fname, *addr; {
  582.         int i;
  583.         if ((file=fopen(fname,"r"))==NULL) return 1;
  584.         while (1) {
  585.                 if ((fgets(addr,topmem-addr,file))==0) break;
  586.                 while (*addr) ++addr;
  587.                 *addr++ = '\n';
  588.         }
  589.         *addr = EOFCHAR;
  590.         fclose(file);
  591.         return 0;
  592. }
  593. rename(from, to) char *from, *to; {
  594.         puts("'rename' not implemented.");
  595.         exit(1);
  596. }
  597. creat(fname) char *fname; {
  598.         puts("'creat' not implemented.");
  599.         exit(1);
  600. }
  601. write(file,buf,sects) int file, sects; char *buf; {
  602.         puts("'write' not implemented.");
  603.         exit(1);
  604. }
  605.  
  606. /*
  607. ** lib.c -- function library
  608. **
  609. ** Copyright 1982 J. E. Hendrix
  610. */
  611. #define NOCCARGC /* don't pass arg count to functions */
  612.                  /* called by these functions */
  613. #include "abs.c"
  614. #include "dtoi.c"
  615. #include "itod.c"
  616. #include "itou.c"
  617. #include "itox.c"
  618. #include "left.c"
  619. #include "out.c"
  620. #include "printf.c"
  621. #include "sign.c"
  622. #include "strcmp.c"
  623. #include "utoi.c"
  624. #include "xtoi.c"
  625.