home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / pictor15 / ed / ed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-15  |  9.3 KB  |  429 lines

  1. /*
  2. ** ed.c
  3. **
  4. ** Ed, Version 1.51, Copyright (c) 1992-94 SoftCircuits
  5. ** Redistributed by permission.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <pictor.h>
  13. #include "ed.h"
  14.  
  15. char hlp_file[] = "ED.HLP";
  16. static int mainloop = TRUE;
  17.  
  18. /*
  19. ** displays an out-of-memory error message
  20. ** since messagebox creates a window using static memory,
  21. ** there is no danger that messagebox will fail due to lack of memery
  22. */
  23. void outofmemory(void)
  24. {
  25.     messagebox("Out of memory","Error",MB_OK,&msgcolors);
  26.  
  27. } /* outofmemory */
  28.  
  29. /*
  30. ** expands the given line to accommodate the specified
  31. ** number of characters at the specified column
  32. */
  33. int expand_line(LINE **line,int col,int count)
  34. {
  35.     LINE *new;
  36.  
  37.     /* resize buffer */
  38.     new = realloc(*line,sizeof(LINE) + (*line)->len + count);
  39.  
  40.     if(new == NULL) { /* out of memory */
  41.         outofmemory();
  42.         return(FALSE);
  43.     }
  44.  
  45.     /* shift characters to make room */
  46.     memmove(new->text + col + count,new->text + col,new->len - col);
  47.     new->len += count;
  48.  
  49.     /* if realloc() moved the buffer, update any */
  50.     /* pointers that pointed to the old buffer */
  51.     if(new != *line) {
  52.         if(head == *line) head = new;
  53.         if(tail == *line) tail = new;
  54.         if(top_line == *line) top_line = new;
  55.  
  56.         if(new->prev) new->prev->next = new;
  57.         if(new->next) new->next->prev = new;
  58.  
  59.         *line = new;
  60.     }
  61.  
  62.     return(TRUE);
  63.  
  64. } /* expand_line */
  65.  
  66. /*
  67. ** shrinks the given line at the given column count bytes
  68. ** there is no return value since this function assumes realloc
  69. ** will succeed (since we are making the block smaller)
  70. */
  71. void shrink_line(LINE **line,int col,int count)
  72. {
  73.     LINE *new;
  74.  
  75.     /* don't delete more characters than are in the line */
  76.     if(count > (*line)->len)
  77.         count = (*line)->len;
  78.  
  79.     /* shift characters */
  80.     memmove((*line)->text + col,(*line)->text + col + count,
  81.         (*line)->len - (col + count));
  82.  
  83.     /* resize buffer */
  84.     new = realloc(*line,sizeof(LINE) + (*line)->len - count);
  85.     new->len -= count;
  86.  
  87.     /* if realloc() moved the buffer, update any */
  88.     /* pointers that pointed to the old buffer */
  89.     if(new != *line) {
  90.         if(head == *line) head = new;
  91.         if(tail == *line) tail = new;
  92.         if(top_line == *line) top_line = new;
  93.  
  94.         if(new->prev) new->prev->next = new;
  95.         if(new->next) new->next->prev = new;
  96.  
  97.         *line = new;
  98.     }
  99.  
  100. } /* shrink_line */
  101.  
  102. /*
  103. ** splits the current line at the current position
  104. ** into two separate lines
  105. */
  106. void split_line()
  107. {
  108.     LINE *new;
  109.  
  110.     /* allocate new line */
  111.     new = malloc(sizeof(LINE) + (curr_line->len - line_ndx));
  112.     if(new == NULL) { /* out of memory */
  113.         outofmemory();
  114.         return;
  115.     }
  116.  
  117.     add_to_list(new,curr_line);
  118.  
  119.     /* copy split portion of line to new line */
  120.     new->len = (curr_line->len - line_ndx);
  121.     memmove(new->text,curr_line->text + line_ndx,new->len);
  122.  
  123.     /* resize original line */
  124.     shrink_line(&curr_line,line_ndx,new->len);
  125.  
  126.     /* move to start of new line */
  127.     _down();
  128.     line_ndx = 0;
  129.  
  130.     modified = TRUE;
  131.     update_state = UPDATE_REPAINT;
  132.     update_cursor(TRUE);
  133.  
  134. } /* split_line */
  135.  
  136. /*
  137. ** appends the next line to the current line
  138. */
  139. void join_line()
  140. {
  141.     int i;
  142.  
  143.     /* if there is a next line */
  144.     if(curr_line->next != NULL) {
  145.  
  146.         i = curr_line->len;
  147.  
  148.         /* make room for combined line */
  149.         if(!expand_line(&curr_line,curr_line->len,curr_line->next->len))
  150.             return;  /* out of memory */
  151.  
  152.         /* append next line to current line */
  153.         memmove(curr_line->text + i,curr_line->next->text,
  154.             curr_line->next->len);
  155.  
  156.         /* delete next line */
  157.         remove_from_list(curr_line->next);
  158.  
  159.         modified = TRUE;
  160.         update_state = UPDATE_REPAINT;
  161.         update_cursor(TRUE);
  162.     }
  163.  
  164. } /* join_line */
  165.  
  166. /*
  167. ** deletes the current line
  168. */
  169. void delete_line()
  170. {
  171.     /* don't remove last line from list */
  172.     if(curr_line->next == NULL) {
  173.         if(curr_line->len > 0) {
  174.             shrink_line(&curr_line,0,curr_line->len);
  175.         }
  176.     }
  177.     else {
  178.         curr_line = curr_line->next;
  179.         remove_from_list(curr_line->prev);
  180.     }
  181.     line_ndx = 0;
  182.     modified = TRUE;
  183.     update_state = UPDATE_REPAINT;
  184.     update_cursor(TRUE);
  185.  
  186. } /* delete_line */
  187.  
  188. /*
  189. ** deletes the character at the current position
  190. */
  191. void delete_char()
  192. {
  193.     /* if anything at cursor to delete */
  194.     if(line_ndx < curr_line->len) {
  195.         shrink_line(&curr_line,line_ndx,1);
  196.  
  197.         /* show modified line */
  198.         show_line(curr_line,(file_row - top_row) + edit_top);
  199.         modified = TRUE;
  200.         update_cursor(TRUE);
  201.     }
  202.     else join_line();    /* delete line break */
  203.  
  204. } /* delete_char */
  205.  
  206. /*
  207. ** deletes the character left of the current position
  208. */
  209. void backspace_char()
  210. {
  211.     if(line_ndx > 0 || curr_line->prev != NULL) {
  212.         _left();
  213.         delete_char();
  214.     }
  215. } /* backspace_char */
  216.  
  217. /*
  218. ** inserts a character at the current file position
  219. */
  220. void insert_char(char c)
  221. {
  222.     /* expand line if insert mode or at line end */
  223.     if(line_ndx >= curr_line->len || insert_mode) {
  224.         if(!expand_line(&curr_line,line_ndx,1))
  225.             return;  /* error */
  226.     }
  227.  
  228.     /* put character into buffer */
  229.     curr_line->text[line_ndx] = c;
  230.  
  231.     /* show modified line */
  232.     show_line(curr_line,(file_row - top_row) + edit_top);
  233.  
  234.     line_ndx++;
  235.     modified = TRUE;
  236.     update_cursor(TRUE);
  237.  
  238. } /* insert_char */
  239.  
  240. /*
  241. ** displays command line syntax and terminates
  242. ** with errorlevel 1
  243. */
  244. void show_usage()
  245. {
  246.     printf("%s\n\n",copyright);
  247.  
  248.     printf("Usage:\tED <filename> [/b] [/s]\n");
  249.     printf("\t/b Black and white (disables color on color systems)\n");
  250.     printf("\t/s Snow check (write only during video retrace)\n");
  251.  
  252.     exit(1);
  253.  
  254. } /* show_usage */
  255.  
  256. /*
  257. ** causes the main loop to terminate by setting mainloop = FALSE
  258. */
  259. void terminate(void)
  260. {
  261.     helpsetcontext(hlp_exit);
  262.     mainloop = !save_modified();
  263.  
  264. } /* terminate */
  265.  
  266. /*
  267. ** here's main()
  268. */
  269. int main(int argc,char *argv[])
  270. {
  271.     int i,key,blkwht = FALSE,snwchk = FALSE;
  272.     char *fname = NULL;
  273.  
  274.     /* read command line arguments */
  275.     for(i = 1;i < argc;i++) {
  276.         switch(argv[i][0]) {
  277.             case '/':
  278.             case '-':
  279.                 switch(tolower(argv[i][1])) {
  280.                     case 'b':
  281.                         blkwht = TRUE;
  282.                         break;
  283.                     case 's':
  284.                         snwchk = TRUE;
  285.                         break;
  286.                     default:
  287.                         show_usage();
  288.                 }
  289.                 break;
  290.             default:
  291.                 if(fname == NULL)
  292.                     fname = strupr(argv[i]);
  293.                 else
  294.                     show_usage();
  295.         }
  296.     }
  297.     initvideo(); /* initialize library */
  298.     getvconfig(&vcfg);
  299.  
  300.     if(snwchk)
  301.         snowcheckoff();
  302.  
  303.     if(vcfg.colorsupport && !blkwht) {
  304.         edit_color = foreback(BOLD|CYAN,BLUE);
  305.         status_color = foreback(BLACK,CYAN);
  306.         msgcolors.normal = foreback(BLACK,WHITE);
  307.         msgcolors.boldnormal = foreback(BOLD|WHITE,WHITE);
  308.         msgcolors.select = foreback(WHITE,BLACK);
  309.         msgcolors.boldselect = foreback(BOLD|WHITE,BLACK);
  310.         mnucolors.normal = foreback(BLACK,CYAN);
  311.         mnucolors.boldnormal = foreback(BOLD|WHITE,CYAN);
  312.         mnucolors.select = foreback(BOLD|CYAN,BLUE);
  313.         mnucolors.boldselect = foreback(BOLD|WHITE,BLUE);
  314.         _PL_shadowcolor = foreback(BOLD|BLACK,BLACK);
  315.     }
  316.     edit_top = 2;    edit_bottom = vcfg.rows - 1;
  317.     edit_left = 1;    edit_right = vcfg.columns;
  318.  
  319.    vcolor(edit_color); cls();
  320.     showmenu(mainmenu,&mnucolors,FALSE);
  321.     initstatus(vcfg.rows,status_color);
  322.     hookints(&msgcolors);
  323.     helpopen(hlp_file,&msgcolors,&msgcolors);
  324.     installclock(1,vcfg.columns - 7,mnucolors.normal);
  325.  
  326.     if(fname == NULL)
  327.         new_file(fname);
  328.     else
  329.         load_file(fname);
  330.  
  331.     while(mainloop) {
  332.  
  333.         key = runmenu(mainmenu,&mnucolors,&mnucolors);
  334.  
  335.         switch(key) {
  336.             case 0x00:                    /* key processed by runmenu() */
  337.                 break;
  338.             case LEFT_KEY:          /* cursor left */
  339.                 cursor_left();
  340.                 break;
  341.             case RIGHT_KEY:         /* cursor right */
  342.                 cursor_right();
  343.                 break;
  344.             case HOME_KEY:          /* start of line */
  345.                 line_ndx = 0;
  346.                 update_cursor(TRUE);
  347.                 break;
  348.             case END_KEY:           /* end of line */
  349.                 line_ndx = curr_line->len;
  350.                 update_cursor(TRUE);
  351.                 break;
  352.             case UP_KEY:            /* cursor up */
  353.                 cursor_up();
  354.                 break;
  355.             case DOWN_KEY:          /* cursor down */
  356.                 cursor_down();
  357.                 break;
  358.             case PGUP_KEY:          /* page up */
  359.                 page_up();
  360.                 break;
  361.             case PGDN_KEY:          /* page down */
  362.                 page_down();
  363.                 break;
  364.             case CTRL_PGUP:         /* start of file */
  365.             case CTRL_HOME:
  366.                 file_home();
  367.                 break;
  368.             case CTRL_PGDN:         /* end of file */
  369.             case CTRL_END:
  370.                 file_end();
  371.                 break;
  372.             case DELETE_KEY:        /* delete */
  373.                 delete_char();
  374.                 break;
  375.             case BACKSPACE_KEY:     /* backspace */
  376.                 backspace_char();
  377.                 break;
  378.             case CTRL_Y:            /* delete line */
  379.                 delete_line();
  380.                 break;
  381.             case ENTER_KEY:         /* create new line */
  382.                 split_line();
  383.                 break;
  384.             case INSERT_KEY:        /* toggle insert */
  385.                 insert_mode = !(insert_mode);
  386.                 show_status();
  387.                 break;
  388.             case F1_KEY:
  389.                 helprun(hlp_general);
  390.                 break;
  391.             case CTRL_F1:                /* help index */
  392.                 help_index();
  393.                 break;
  394.             case F2_KEY:            /* save file */
  395.                 filesave();
  396.                 break;
  397.             case CTRL_F2:                /* save file as */
  398.                 filesaveas();
  399.                 break;
  400.             case F3_KEY:
  401.                 repeatsearch();        /* repeat last find */
  402.                 break;
  403.             case F4_KEY:                /* find */
  404.                 search();
  405.                 break;
  406.             case F9_KEY:                /* print */
  407.                 fileprint();
  408.                 break;
  409.             case F10_KEY:                /* exit */
  410.                 terminate();
  411.                 break;
  412.             default:
  413.                 key &= 0xFF;
  414.                 if(isprint(key) || key == '\t')
  415.                     insert_char((char)key);
  416.                 else
  417.                     beep();
  418.         }
  419.     }
  420.     removeclock();
  421.  
  422.     /* restore screen */
  423.     vcolor(foreback(WHITE,BLACK));
  424.     cls();
  425.  
  426.     return(0);
  427.  
  428. } /* main */
  429.