home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_50 / PVIC.ZIP / MISCMDS.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  11KB  |  432 lines

  1. /* 
  2.  * Various routines to perform specific editing operations or return
  3.  * useful information about the file.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "pvic.h"
  8. #include "locdefs.h"
  9.  
  10. static  void    openfwd(), openbwd();
  11.  
  12. extern  int     did_ai;
  13.  
  14. /*
  15.  * open_command
  16.  *
  17.  * Add a blank line above or below the current line.
  18.  */
  19.  
  20. void
  21. open_command(dir, can_ai)
  22. int     dir;
  23. int     can_ai;                 /* if true, consider auto-indent */
  24. {
  25.     if (dir == SEARCH_FORWARD)
  26.         openfwd(can_ai);
  27.     else
  28.         openbwd(can_ai);
  29. }
  30.  
  31. static void
  32. openfwd(can_ai)
  33. int     can_ai;
  34. {
  35.     register LINE   *l;
  36.     LPTR    *next;
  37.     register char   *s;     /* string to be moved to new line, if any */
  38.     int     newindex = 0;   /* index of the cursor on the new line */
  39.  
  40.     /*
  41.      * If we're in insert mode, we need to move the remainder of the
  42.      * current line onto the new line. Otherwise the new line is left
  43.      * blank.
  44.      */
  45.     if (current_status == STATUS_INSERT || current_status == STATUS_REPLACE)
  46.         s = &cursor_char->linep->s[cursor_char->index];
  47.     else
  48.         s = "";
  49.  
  50.     if ((next = next_line(cursor_char)) == NULL)        /* open on last line */
  51.         next = end_of_file;
  52.  
  53.     /*
  54.      * By asking for as much space as the prior line had we make sure
  55.      * that we'll have enough space for any auto-indenting.
  56.      */
  57.     if ((l = newline(strlen(cursor_char->linep->s) + SLOP)) == NULL)
  58.         return;
  59.  
  60.     if (*s != '\0')
  61.         strcpy(l->s, s);                /* copy string to new line */
  62.  
  63.     else if (can_ai && PARAMETER_VALUE(PARAMETER_AUTOINDENT) && !is_input_pending()) {
  64.         char    *p;
  65.  
  66.         /*
  67.          * Copy prior line, and truncate after white space
  68.          */
  69.         strcpy(l->s, cursor_char->linep->s);
  70.  
  71.         for (p = l->s; *p == ' ' || *p == CTRL_I ;p++)
  72.             ;
  73.         *p = '\0';
  74.         newindex = p - l->s;
  75.  
  76.         /*
  77.          * If we just did an auto-indent, then we didn't type
  78.          * anything on the prior line, and it should be truncated.
  79.          */
  80.         if (did_ai)
  81.             cursor_char->linep->s[0] = '\0';
  82.  
  83.         did_ai = (1);
  84.     }
  85.  
  86.     /* truncate current line at cursor */
  87.     if (current_status == STATUS_INSERT || current_status == STATUS_REPLACE)
  88.         *s = '\0';
  89.             
  90.  
  91.     cursor_char->linep->next = l;      /* link neighbors to new line */
  92.     next->linep->prev = l;
  93.  
  94.     l->prev = cursor_char->linep;      /* link new line to neighbors */
  95.     l->next = next->linep;
  96.  
  97.     if (next == end_of_file)                    /* new line at end */
  98.         l->num = cursor_char->linep->num + LINEINC;
  99.  
  100.     else if ((l->prev->num) + 1 == l->next->num)    /* no gap, renumber */
  101.         renum();
  102.  
  103.     else {                                  /* stick it in the middle */
  104.         unsigned long   lnum;
  105.         lnum = ((long)l->prev->num + (long)l->next->num) / 2;
  106.         l->num = lnum;
  107.     }
  108.  
  109.     /*
  110.      * Get the cursor to the start of the line, so that 'cursor_row'
  111.      * gets set to the right physical line number for the stuff
  112.      * that follows...
  113.      */
  114.     cursor_char->index = 0;
  115.     update_cursor(0);
  116.  
  117.     /*
  118.      * If we're doing an open on the last logical line, then
  119.      * go ahead and scroll the screen up. Otherwise, just insert
  120.      * a blank line at the right place. We use calls to plines()
  121.      * in case the cursor is resting on a long line.
  122.      */
  123.     if (cursor_row + plines(cursor_char) == (current_lines - 1))
  124.         scroll_up(1);
  125.  
  126.     *cursor_char = *next_line(cursor_char);        /* cursor moves down */
  127.     cursor_char->index = newindex;
  128.  
  129.     update_screen(0);         /* because bottom_char is now invalid... */
  130.  
  131.     update_cursor(0);           /* update cursor_row before insert */
  132. }
  133.  
  134. static void
  135. openbwd(can_ai)
  136. int     can_ai;
  137. {
  138.     register LINE   *l;
  139.     LINE    *prev;
  140.     int     newindex = 0;
  141.  
  142.     prev = cursor_char->linep->prev;
  143.  
  144.     if ((l = newline(strlen(cursor_char->linep->s) + SLOP)) == NULL)
  145.         return;
  146.  
  147.     cursor_char->linep->prev = l;      /* link neighbors to new line */
  148.     prev->next = l;
  149.  
  150.     l->next = cursor_char->linep;      /* link new line to neighbors */
  151.     l->prev = prev;
  152.  
  153.     if (can_ai && PARAMETER_VALUE(PARAMETER_AUTOINDENT) && !is_input_pending()) {
  154.         char    *p;
  155.  
  156.         /*
  157.          * Copy current line, and truncate after white space
  158.          */
  159.         strcpy(l->s, cursor_char->linep->s);
  160.  
  161.         for (p = l->s; *p == ' ' || *p == CTRL_I ;p++)
  162.             ;
  163.         *p = '\0';
  164.         newindex = p - l->s;
  165.  
  166.         did_ai = (1);
  167.     }
  168.  
  169.     cursor_char->linep = cursor_char->linep->prev;
  170.     cursor_char->index = newindex;
  171.  
  172.     if (prev == top_of_file->linep)             /* new start of file */
  173.         file_memory->linep = l;
  174.  
  175.     renum();        /* keep it simple - we don't do this often */
  176.  
  177.     update_cursor(0);                   /* update cursor_row before insert */
  178.     update_screen(0);
  179. }
  180.  
  181. int
  182. cntllines(pbegin,pend)
  183. register LPTR   *pbegin, *pend;
  184. {
  185.     register LINE   *lp;
  186.     int     lnum = 1;
  187.  
  188.     for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
  189.         lnum++;
  190.  
  191.     return(lnum);
  192. }
  193.  
  194. /*
  195.  * plines(p) - return the number of physical screen lines taken by line 'p'
  196.  */
  197. int
  198. plines(p)
  199. LPTR    *p;
  200. {
  201.     register int    col = 0;
  202.     register char   *s;
  203.  
  204.     s = p->linep->s;
  205.  
  206.     if (*s == '\0')         /* empty line */
  207.         return 1;
  208.  
  209.     for (; *s != '\0' ;s++) {
  210.         if ( *s == CTRL_I && !PARAMETER_VALUE(PARAMETER_LIST))
  211.             col += PARAMETER_VALUE(PARAMETER_TABSTOP) - (col % PARAMETER_VALUE(PARAMETER_TABSTOP));
  212.         else
  213.             col += chars[(unsigned)(*s & 0xff)].ch_size;
  214.     }
  215.  
  216.     /*
  217.      * If list mode is on, then the '$' at the end of
  218.      * the line takes up one extra column.
  219.      */
  220.     if (PARAMETER_VALUE(PARAMETER_LIST))
  221.         col += 1;
  222.     /*
  223.      * If 'number' mode is on, add another 8.
  224.      */
  225.     if (PARAMETER_VALUE(PARAMETER_NUMBER))
  226.         col += 8;
  227.  
  228.     return ((col + (current_columns-1)) / current_columns);
  229. }
  230.  
  231. void
  232. file_info()
  233. {
  234.     extern  int     number_of_files, current_file;
  235.     register long   l1, l2;
  236.  
  237.     if (buffer_empty()) {
  238.         l1 = 0;
  239.         l2 = 1;                 /* don't div by zero */
  240.     } else {
  241.         l1 = cntllines(file_memory, cursor_char);
  242.         l2 = cntllines(file_memory, end_of_file) - 1;
  243.     }
  244.  
  245.     if (number_of_files > 1)
  246.         show_message("\"%s\"%s line %ld of %ld -- %ld %% -- (file %d of %d)",
  247.             (file_name != NULL) ? file_name : "No File",
  248.             changed ? " [Modified]" : "",
  249.             l1, l2, (l1 * 100)/l2,
  250.             current_file+1, number_of_files);
  251.     else
  252.         show_message("\"%s\"%s line %ld of %ld -- %ld %% --",
  253.             (file_name != NULL) ? file_name : "No File",
  254.             changed ? " [Modified]" : "",
  255.             l1, l2, (l1 * 100)/l2);
  256. }
  257.  
  258. /*
  259.  * goto_line(n) - return a pointer to line 'n'
  260.  *
  261.  * Returns a pointer to the last line of the file if n is zero, or
  262.  * beyond the end of the file.
  263.  */
  264. LPTR *
  265. goto_line(n)
  266. register int    n;
  267. {
  268.     static  LPTR    l;
  269.  
  270.     l.index = 0;
  271.  
  272.     if ( n == 0 )
  273.         l = *previous_line(end_of_file);
  274.     else {
  275.         LPTR    *p;
  276.  
  277.         for (l = *file_memory; --n > 0 ;l = *p)
  278.             if ((p = next_line(&l)) == NULL)
  279.                 break;
  280.     }
  281.     return &l;
  282. }
  283.  
  284. void
  285. inschar(c)
  286. int     c;
  287. {
  288.     register char   *p, *pend;
  289.  
  290.     /* make room for the new char. */
  291.     if ( ! can_increase(1) )
  292.         return;
  293.  
  294.     if (current_status != STATUS_REPLACE) {
  295.         p = &cursor_char->linep->s[strlen(cursor_char->linep->s) + 1];
  296.         pend = &cursor_char->linep->s[cursor_char->index];
  297.  
  298.         for (; p > pend ;p--)
  299.             *p = *(p-1);
  300.  
  301.         *p = c;
  302.  
  303.     } else {        /* replace mode */
  304.         /*
  305.          * Once we reach the end of the line, we are effectively
  306.          * inserting new text, so make sure the string terminator
  307.          * stays out there.
  308.          */
  309.         if (gchar(cursor_char) == '\0')
  310.             cursor_char->linep->s[cursor_char->index+1] = '\0';
  311.         pchar(cursor_char, c);
  312.     }
  313.  
  314.     /*
  315.      * If we're in insert mode and show_match mode is set, then
  316.      * check for right parens and braces. If there isn't a match,
  317.      * then beep. If there is a match AND it's on the screen, then
  318.      * flash to it briefly. If it isn't on the screen, don't do anything.
  319.      */
  320.     if (PARAMETER_VALUE(PARAMETER_SHOWMATCH) && current_status == STATUS_INSERT && (c == ')' || c == '}' || c == ']')) {
  321.         LPTR    *lpos, csave;
  322.  
  323.         if ((lpos = show_match()) == NULL)       /* no match, so beep */
  324.             beep();
  325.         else if (LINEOF(lpos) >= LINEOF(top_char)) {
  326.             update_screen(1);         /* show the new char first */
  327.             csave = *cursor_char;
  328.             *cursor_char = *lpos;      /* move to matching char */
  329.             update_cursor(1);
  330.             goto_screen_pos(cursor_row, cursor_column);
  331.             loop_n_seconds(1);                /* brief pause */
  332.             *cursor_char = csave;      /* restore cursor position */
  333.             update_cursor(0);
  334.         }
  335.     }
  336.  
  337.     inc(cursor_char);
  338.     CHANGED;
  339. }
  340.  
  341. int
  342. delete_char(fixpos)
  343. int     fixpos;         /* if (1), fix the cursor position when done */
  344. {
  345.     register int    i;
  346.  
  347.     /* Check for degenerate case; there's nothing in the file. */
  348.     if (buffer_empty())
  349.         return (0);
  350.  
  351.     if (line_empty())        /* can't do anything */
  352.         return (0);
  353.  
  354.     /* Delete the char. at cursor_char by shifting everything */
  355.     /* in the line down. */
  356.     for ( i=cursor_char->index+1; i < cursor_char->linep->size ;i++)
  357.         cursor_char->linep->s[i-1] = cursor_char->linep->s[i];
  358.  
  359.     /* If we just took off the last character of a non-blank line, */
  360.     /* we don't want to end up positioned at the newline. */
  361.     if (fixpos) {
  362.         if (gchar(cursor_char)=='\0' && cursor_char->index>0 && current_status!=STATUS_INSERT)
  363.             cursor_char->index--;
  364.     }
  365.     CHANGED;
  366.  
  367.     return (1);
  368. }
  369.  
  370.  
  371. void
  372. delete_line(nlines, can_update)
  373. int     nlines;
  374. int     can_update;
  375. {
  376.     register LINE   *p, *q;
  377.     int     doscreen;               /* if true, update the screen */
  378.  
  379.     doscreen = can_update;
  380.     /*
  381.      * There's no point in keeping the screen updated if we're
  382.      * deleting more than a screen's worth of lines.
  383.      */
  384.     if (nlines > (current_lines - 1) && can_update) {
  385.         doscreen = (0);
  386.     }
  387.  
  388.     while ( nlines-- > 0 ) {
  389.  
  390.         if (buffer_empty())                 /* nothing to delete */
  391.             break;
  392.  
  393.         if (buf1line()) {               /* just clear the line */
  394.             cursor_char->linep->s[0] = '\0';
  395.             cursor_char->index = 0;
  396.             break;
  397.         }
  398.  
  399.         p = cursor_char->linep->prev;
  400.         q = cursor_char->linep->next;
  401.  
  402.         if (p == top_of_file->linep) {      /* first line of file so... */
  403.             file_memory->linep = q;     /* adjust start of file */
  404.             top_char->linep = q;     /* and screen */
  405.         }
  406.         p->next = q;
  407.         q->prev = p;
  408.  
  409.         clear_mark(cursor_char->linep);       /* clear marks for the line */
  410.  
  411.         /*
  412.          * If deleting the top line on the screen, adjust top_char
  413.          */
  414.         if (top_char->linep == cursor_char->linep)
  415.             top_char->linep = q;
  416.  
  417.         free(cursor_char->linep->s);
  418.         free((char *) cursor_char->linep);
  419.  
  420.         cursor_char->linep = q;
  421.         cursor_char->index = 0;            /* is this right? */
  422.         CHANGED;
  423.  
  424.         /* If we delete the last line in the file, back up */
  425.         if ( cursor_char->linep == end_of_file->linep) {
  426.             cursor_char->linep = cursor_char->linep->prev;
  427.             /* and don't try to delete any more lines */
  428.             break;
  429.         }
  430.     }
  431. }
  432.