static char rcsid[] = "$Id: random.c,v 1.1 1992/09/05 01:13:32 mike Exp $"; /* $Log: random.c,v $ * Revision 1.1 1992/09/05 01:13:32 mike * Initial revision * */ /* * RANDOM.C MODULE * This file contains the command processing functions for a number of random * commands. There is no functional grouping here, for sure. */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include "me2.h" int overstrike = FALSE; /* insert mode is default */ /* * Calculate stats for a buffer. * Calculate the current position of the cursor, in origin 1 X-Y coordinates, * from the start of the current buffer. * Note: dot is orgin 0. */ void buffer_stats(bp,bsize,dotat,nlines,catdot,r,wasted) Buffer *bp; int *catdot; long int *wasted, *dotat, *bsize, *nlines, *r; { register Line *lp; int cac; long int unused = 0, dot_count = -1, num_chars = 0, num_lines = 0, row; /* loop through buffer and collect info */ for (lp = BUFFER_FIRST_LINE(bp); lp != BUFFER_LAST_LINE(bp); lp = lforw(lp)) { num_lines++; if (lp == the_dot->line) /* collect info on dot if at dot */ { dot_count = num_chars + the_dot->offset; if (the_dot->offset == llength(lp)) cac = '\n'; else cac = lgetc(lp,the_dot->offset); row = num_lines; } num_chars += lp->l_used +1; /* remember fake \n */ unused += lp ->l_size -lp->l_used; } num_lines++; /* remember fake line at end of buffer */ if (dot_count == -1) /* then dot is at end of buffer */ { dot_count = num_chars; cac = '\n'; row = num_lines; } *r = row; *nlines = num_lines; *dotat = dot_count; *bsize = num_chars; *catdot = cac; *wasted = unused; } getcol(line,offset) Line *line; { register unsigned char c; register int i, col = 0; for (i = 0; i < offset; ++i) { c = lgetc(line,i); if (c == '\t') col = NEXT_TAB_COLUMN_MINUS_1(col); else if (iscntrl(c)) ++col; ++col; } return col; } /* Return current column */ getccol() { return getcol(the_dot->line,the_dot->offset); } /* * Quote the next character, and insert it into the buffer. All the * characters are taken literally, with the exception of the newline, * which always has its line splitting meaning. The character is * always read, even if it is inserted 0 times, for regularity. * Bound to "C-q" and "C-^" (for terminals that need XON-XOFF). */ quote(f,n) int f,n; { KeyCode kc; int s; get_McKc(&kc,FALSE); if (n <= 0) return FALSE; /* could not insert c */ if (kc == '\n') { while (n-- && (s = lnewline()) == TRUE) ; /* Insert newlines */ return s; } return linsert(n,(unsigned char)kc,overstrike); } /* * Open up some blank space. The basic plan is to insert a bunch of * newlines, and then back up over them. Everything is done by the * subcommand procerssors. They even handle the looping. * Bound to "C-o". */ openline(f,n) int f,n; { register int i = n, s; if (i <= 0) return FALSE; while (i-- && (s = lnewline()) == TRUE) ; /* Insert newlines */ if (s == TRUE) s = next_character(-n); /* Then backup over them */ return s; } /* * Insert a newline. * Bound to "C-m". */ newline(f,n) int f,n; { if (n < 0) return FALSE; /* I can insert 0 or more newlines but not less */ while (n--) if (!lnewline()) return FALSE; return TRUE; } /* * Insert a newline, then enough tabs and spaces to duplicate the * indentation of the previous line. Assumes tabs are every eight * characters. Quite simple. Figure out the indentation of the * current line. Insert a newline by calling the standard routine. * Insert the indentation by inserting the right number of tabs and * spaces. Return TRUE if all ok. Return FALSE if one of the * subcomands failed. * Bound to "C-j". */ indent(f,n) int f,n; { register char c; int nicol, i; register Line *lp = the_dot->line; if (n <= 0) return FALSE; for (i = nicol = 0; i < llength(lp); ++i) { c = lgetc(lp,i); if (c=='\t') nicol = NEXT_TAB_COLUMN_MINUS_1(nicol); else if (c!=' ') break; nicol++; } while (n--) if (lnewline()!=TRUE || to_col(nicol)!=TRUE) return FALSE; return TRUE; } /* * Insert n tabs into buffer. * If tabsize ==0, use true tabs. Otherwise, simulate tab stops every * tabsize characters using blanks. * Bound to "C-i". */ tab(f,n) int f,n; { register int tabsize = curbp->tabsize; if (n <= 0) return FALSE; if (tabsize == 0) return linsert(n,'\t',FALSE); return linsert(n*tabsize -(getccol() % tabsize),' ',FALSE); } to_col(n) /* insert tabs and spaces to column n (0==left margin) */ { register int col, t1,t2; col = getccol(); t1 = NEXT_TAB_STOP(col); t2 = PREVIOUS_TAB_STOP(n); if (curbp->tabsize == 0 && t1 <= t2) { if (!linsert(t2-t1+1, '\t', FALSE)) return FALSE; col = TSTOC(t2); } n -= col; if (n <= 0) return TRUE; /* already past n */ return linsert(n,' ',FALSE); } /* Delete n characters at the dot in the current buffer. If n is * negative, delete n characters before the dot. If you want * Emacs-like kill buffer stuff, set a_cut to TRUE. * Input: * n : number of characters to delete. * a_cut : TRUE if you want the deleted characters put into the cut * buffer. * Returns: * TRUE: If everything went as expected. * FALSE: Tried to -ve delete off the end of the buffer or ldelete() * failed (malloc problem). * Notes: * If called from a Mutt program, don't save in the cut buffer. The * program has to do it. I do this because I haven't added a * (delete-text n) function. */ delete_characters(n,a_cut) int n; { int s; /* bandaid for Mutt because I don't have a delete-text function */ if (MMpgm_running()) a_cut = FALSE; if (a_cut) { if (!(lastflag & CFCUT)) clear_bag(cut_buffer); thisflag |= CFCUT; } if (0 <= n) return ldelete((int32)n, a_cut); if (s = next_character(n)) s = ldelete((int32)-n, a_cut); return s; } /* ??? since we now got undo, why put stuff in the cut buffer???????? */ /* * Delete forward. This is real easy, because the basic delete routine * does all of the work. Watches for negative arguments, and does the * right thing. If any argument is present, it cuts rather than * deletes, to prevent loss of text if typed with a big argument. * Normally bound to "C-d". */ forwdel(f,n) int f,n; { return delete_characters(n,f); } /* * Delete backwards. This is quite easy too, because it's all done with * other functions. Just move the cursor back, and delete forwards. * Like delete forward, this actually does a cut if argument (^U) * used. * Bound to both "RUBOUT" and "C-h". */ backdel(f,n) int f,n; { return delete_characters(-n,f); } /* Insert string at dot in current buffer. * Returns: * TRUE: string inserted. * FALSE: memory problems. */ insert_text(text,n) char *text; int n; { register char c; int s = TRUE; while (n-- && s) { c = *text++; if (c == '\n') s = newline(FALSE,1); else s = linsert(1,c,FALSE); } return s; }