]> pd.if.org Git - pd_readline/blobdiff - mg/cmode.c
Getting close to a basic working readline now.
[pd_readline] / mg / cmode.c
diff --git a/mg/cmode.c b/mg/cmode.c
deleted file mode 100644 (file)
index 674d89d..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-/* $OpenBSD: cmode.c,v 1.8 2012/05/18 02:13:44 lum Exp $ */
-/*
- * This file is in the public domain.
- *
- * Author: Kjell Wooding <kjell@openbsd.org>
- */
-
-/*
- * Implement an non-irritating KNF-compliant mode for editing
- * C code.
- */
-#include <ctype.h>
-
-#include "def.h"
-#include "kbd.h"
-#include "funmap.h"
-
-/* Pull in from modes.c */
-extern int changemode(int, int, char *);
-
-static int cc_strip_trailp = TRUE;     /* Delete Trailing space? */
-static int cc_basic_indent = 8;                /* Basic Indent multiple */
-static int cc_cont_indent = 4;         /* Continued line indent */
-static int cc_colon_indent = -8;       /* Label / case indent */
-
-static int getmatch(int, int);
-static int getindent(const struct line *, int *);
-static int in_whitespace(struct line *, int);
-static int findcolpos(const struct buffer *, const struct line *, int);
-static struct line *findnonblank(struct line *);
-static int isnonblank(const struct line *, int);
-
-void cmode_init(void);
-int cc_comment(int, int);
-
-/* Keymaps */
-
-static PF cmode_brace[] = {
-       cc_brace,       /* } */
-};
-
-static PF cmode_cCP[] = {
-       compile,                /* C-c P */
-};
-
-
-static PF cmode_cc[] = {
-       NULL,           /* ^C */
-       rescan,         /* ^D */
-       rescan,         /* ^E */
-       rescan,         /* ^F */
-       rescan,         /* ^G */
-       rescan,         /* ^H */
-       cc_tab,         /* ^I */
-       rescan,         /* ^J */
-       rescan,         /* ^K */
-       rescan,         /* ^L */
-       cc_lfindent,    /* ^M */
-};
-
-static PF cmode_spec[] = {
-       cc_char,        /* : */
-};
-
-static struct KEYMAPE (1 + IMAPEXT) cmode_cmap = {
-       1,
-       1 + IMAPEXT,
-       rescan,
-       {
-               { 'P', 'P', cmode_cCP, NULL }
-       }
-};
-
-static struct KEYMAPE (3 + IMAPEXT) cmodemap = {
-       3,
-       3 + IMAPEXT,
-       rescan,
-       {
-               { CCHR('C'), CCHR('M'), cmode_cc, (KEYMAP *) &cmode_cmap },
-               { ':', ':', cmode_spec, NULL },
-               { '}', '}', cmode_brace, NULL }
-       }
-};
-
-/* Funtion, Mode hooks */
-
-void
-cmode_init(void)
-{
-       funmap_add(cmode, "c-mode");
-       funmap_add(cc_char, "c-handle-special-char");
-       funmap_add(cc_brace, "c-handle-special-brace");
-       funmap_add(cc_tab, "c-tab-or-indent");
-       funmap_add(cc_indent, "c-indent");
-       funmap_add(cc_lfindent, "c-indent-and-newline");
-       maps_add((KEYMAP *)&cmodemap, "c");
-}
-
-/*
- * Enable/toggle c-mode
- */
-int
-cmode(int f, int n)
-{
-       return(changemode(f, n, "c"));
-}
-
-/*
- * Handle special C character - selfinsert then indent.
- */
-int
-cc_char(int f, int n)
-{
-       if (n < 0)
-               return (FALSE);
-       if (selfinsert(FFRAND, n) == FALSE)
-               return (FALSE);
-       return (cc_indent(FFRAND, n));
-}
-
-/*
- * Handle special C character - selfinsert then indent.
- */
-int
-cc_brace(int f, int n)
-{
-       if (n < 0)
-               return (FALSE);
-       if (showmatch(FFRAND, 1) == FALSE)
-               return (FALSE);
-       return (cc_indent(FFRAND, n));
-}
-
-
-/*
- * If we are in the whitespace at the beginning of the line,
- * simply act as a regular tab. If we are not, indent
- * current line according to whitespace rules.
- */
-int
-cc_tab(int f, int n)
-{
-       int inwhitep = FALSE;   /* In leading whitespace? */
-       
-       inwhitep = in_whitespace(curwp->w_dotp, llength(curwp->w_dotp));
-
-       /* If empty line, or in whitespace */
-       if (llength(curwp->w_dotp) == 0 || inwhitep)
-               return (selfinsert(f, n));
-
-       return (cc_indent(FFRAND, 1));
-}
-
-/*
- * Attempt to indent current line according to KNF rules.
- */
-int
-cc_indent(int f, int n)
-{
-       int pi, mi;                     /* Previous indents */
-       int ci, dci;                    /* current indent, don't care */
-       struct line *lp;
-       int ret;
-       
-       if (n < 0)
-               return (FALSE);
-
-       undo_boundary_enable(FFRAND, 0);
-       if (cc_strip_trailp)
-               deltrailwhite(FFRAND, 1);
-
-       /*
-        * Search backwards for a non-blank, non-preprocessor,
-        * non-comment line
-        */
-
-       lp = findnonblank(curwp->w_dotp);
-
-       pi = getindent(lp, &mi);
-
-       /* Strip leading space on current line */
-       delleadwhite(FFRAND, 1);
-       /* current indent is computed only to current position */
-       dci = getindent(curwp->w_dotp, &ci);
-       
-       if (pi + ci < 0)
-               ret = indent(FFOTHARG, 0);
-       else
-               ret = indent(FFOTHARG, pi + ci);
-       
-       undo_boundary_enable(FFRAND, 1);
-       
-       return (ret);
-}
-
-/*
- * Indent-and-newline (technically, newline then indent)
- */
-int
-cc_lfindent(int f, int n)
-{
-       if (n < 0)
-               return (FALSE);
-       if (newline(FFRAND, 1) == FALSE)
-               return (FALSE);
-       return (cc_indent(FFRAND, n));
-}
-
-/*
- * Get the level of indention after line lp is processed
- * Note getindent has two returns:
- * curi = value if indenting current line.
- * return value = value affecting subsequent lines.
- */
-static int
-getindent(const struct line *lp, int *curi)
-{
-       int lo, co;             /* leading space,  current offset*/
-       int nicol = 0;          /* position count */
-       int ccol = 0;           /* current column */
-       int c = '\0';           /* current char */
-       int newind = 0;         /* new index value */
-       int stringp = FALSE;    /* in string? */
-       int escp = FALSE;       /* Escape char? */
-       int lastc = '\0';       /* Last matched string delimeter */
-       int nparen = 0;         /* paren count */
-       int obrace = 0;         /* open brace count */
-       int cbrace = 0;         /* close brace count */
-       int contp = FALSE;      /* Continue? */
-       int firstnwsp = FALSE;  /* First nonspace encountered? */
-       int colonp = FALSE;     /* Did we see a colon? */
-       int questionp = FALSE;  /* Did we see a question mark? */
-       int slashp = FALSE;     /* Slash? */
-       int astp = FALSE;       /* Asterisk? */
-       int cpos = -1;          /* comment position */
-       int cppp  = FALSE;      /* Preprocessor command? */
-       
-       *curi = 0;
-
-       /* Compute leading space */
-       for (lo = 0; lo < llength(lp); lo++) {
-               if (!isspace(c = lgetc(lp, lo)))
-                       break;
-               if (c == '\t'
-#ifdef NOTAB
-                   && !(curbp->b_flag & BFNOTAB)
-#endif /* NOTAB */
-                   ) {
-                       nicol |= 0x07;
-               }
-               nicol++;
-       }
-
-       /* If last line was blank, choose 0 */
-       if (lo == llength(lp))
-               nicol = 0;
-
-       newind = 0;
-       ccol = nicol;                   /* current column */
-       /* Compute modifiers */
-       for (co = lo; co < llength(lp); co++) {
-               c = lgetc(lp, co);
-               /* We have a non-whitespace char */
-               if (!firstnwsp && !isspace(c)) {
-                       contp = TRUE;
-                       if (c == '#')
-                               cppp = TRUE;
-                       firstnwsp = TRUE; 
-               }
-               if (c == '\\')
-                       escp = !escp;
-               else if (stringp) {
-                       if (!escp && (c == '"' || c == '\'')) {
-                               /* unescaped string char */
-                               if (getmatch(c, lastc))
-                                       stringp = FALSE;
-                       }
-               } else if (c == '"' || c == '\'') {
-                       stringp = TRUE;
-                       lastc = c;
-               } else if (c == '(') {
-                       nparen++;
-               } else if (c == ')') {
-                       nparen--;
-               } else if (c == '{') {
-                       obrace++;
-                       firstnwsp = FALSE;
-                       contp = FALSE;
-               } else if (c == '}') {
-                       cbrace++;
-               } else if (c == '?') {
-                       questionp = TRUE;
-               } else if (c == ':') {
-                       /* ignore (foo ? bar : baz) construct */
-                       if (!questionp)
-                               colonp = TRUE;
-               } else if (c == ';') {
-                       if (nparen > 0)
-                               contp = FALSE;
-               } else if (c == '/') {
-                       /* first nonwhitespace? -> indent */
-                       if (firstnwsp) {
-                               /* If previous char asterisk -> close */
-                               if (astp)
-                                       cpos = -1;
-                               else
-                                       slashp = TRUE;
-                       }
-               } else if (c == '*') {
-                       /* If previous char slash -> open */
-                       if (slashp)
-                               cpos = co;
-                       else
-                               astp = TRUE;
-               } else if (firstnwsp) {
-                       firstnwsp = FALSE;
-               }
-
-               /* Reset matches that apply to next character only */
-               if (c != '\\')
-                       escp = FALSE;
-               if (c != '*')
-                       astp = FALSE;
-               if (c != '/')
-                       slashp = FALSE;
-       }
-       /*
-        * If not terminated with a semicolon, and brace or paren open.
-        * we continue
-        */
-       if (colonp) {
-               *curi += cc_colon_indent;
-               newind -= cc_colon_indent;
-       }
-
-       *curi -= (cbrace) * cc_basic_indent;
-       newind += obrace * cc_basic_indent;
-
-       if (nparen < 0)
-               newind -= cc_cont_indent;
-       else if (nparen > 0)
-               newind += cc_cont_indent;
-
-       *curi += nicol;
-
-       /* Ignore preprocessor. Otherwise, add current column */
-       if (cppp) {
-               newind = nicol;
-               *curi = 0;
-       } else {
-               newind += nicol;
-       }
-
-       if (cpos != -1)
-               newind = findcolpos(curbp, lp, cpos);
-
-       return (newind);
-}
-
-/*
- * Given a delimeter and its purported mate, tell us if they
- * match.
- */
-static int
-getmatch(int c, int mc)
-{
-       int match = FALSE;
-
-       switch (c) {
-       case '"':
-               match = (mc == '"');
-               break;
-       case '\'':
-               match = (mc == '\'');
-               break;
-       case '(':
-               match = (mc == ')');
-               break;
-       case '[':
-               match = (mc == ']');
-               break;
-       case '{':
-               match = (mc == '}');
-               break;
-       }
-
-       return (match);
-}
-
-static int
-in_whitespace(struct line *lp, int len)
-{
-       int lo;
-       int inwhitep = FALSE;
-
-       for (lo = 0; lo < len; lo++) {
-               if (!isspace(lgetc(lp, lo)))
-                       break;
-               if (lo == len - 1)
-                       inwhitep = TRUE;
-       }
-
-       return (inwhitep);
-}
-
-
-/* convert a line/offset pair to a column position (for indenting) */
-static int
-findcolpos(const struct buffer *bp, const struct line *lp, int lo)
-{
-       int     col, i, c;
-       char tmp[5];
-
-       /* determine column */
-       col = 0;
-
-       for (i = 0; i < lo; ++i) {
-               c = lgetc(lp, i);
-               if (c == '\t'
-#ifdef NOTAB
-                   && !(bp->b_flag & BFNOTAB)
-#endif /* NOTAB */
-                       ) {
-                       col |= 0x07;
-                       col++;
-               } else if (ISCTRL(c) != FALSE)
-                       col += 2;
-               else if (isprint(c)) {
-                       col++;
-               } else {
-                       col += snprintf(tmp, sizeof(tmp), "\\%o", c);
-               }
-
-       }
-       return (col);
-}
-
-/*
- * Find a non-blank line, searching backwards from the supplied line pointer.
- * For C, nonblank is non-preprocessor, non C++, and accounts
- * for complete C-style comments.
- */
-static struct line *
-findnonblank(struct line *lp)
-{
-       int lo;
-       int nonblankp = FALSE;
-       int commentp = FALSE;
-       int slashp;
-       int astp;
-       int c;
-
-       while (lback(lp) != curbp->b_headp && (commentp || !nonblankp)) {
-               lp = lback(lp);
-               slashp = FALSE;
-               astp = FALSE;
-
-               /* Potential nonblank? */
-               nonblankp = isnonblank(lp, llength(lp));
-
-               /*
-                * Search from end, removing complete C-style
-                * comments. If one is found, ignore it and
-                * test for nonblankness from where it starts.
-                */
-               slashp = FALSE;
-               /* Scan backwards from end to find C-style comment */
-               for (lo = llength(lp) - 1; lo >= 0; lo--) {
-                       if (!isspace(c = lgetc(lp, lo))) {
-                               if (commentp) { /* find comment "open" */
-                                       if (c == '*')
-                                               astp = TRUE;
-                                       else if (astp && c == '/') {
-                                               commentp = FALSE;
-                                               /* whitespace to here? */
-                                               nonblankp = isnonblank(lp, lo);
-                                       }
-                               } else { /* find comment "close" */
-                                       if (c == '/')
-                                               slashp = TRUE;
-                                       else if (slashp && c == '*')
-                                               /* found a comment */
-                                               commentp = TRUE;
-                               }
-                       }
-               }
-       }
-
-       /* Rewound to start of file? */
-       if (lback(lp) == curbp->b_headp && !nonblankp)
-               return (curbp->b_headp);
-
-       return (lp);
-}
-
-/*
- * Given a line, scan forward to 'omax' and determine if we
- * are all C whitespace.
- * Note that preprocessor directives and C++-style comments
- * count as whitespace. C-style comments do not, and must
- * be handled elsewhere.
- */
-static int
-isnonblank(const struct line *lp, int omax)
-{
-       int nonblankp = FALSE;          /* Return value */
-       int slashp = FALSE;             /* Encountered slash */
-       int lo;                         /* Loop index */
-       int c;                          /* char being read */
-
-       /* Scan from front for preprocessor, C++ comments */
-       for (lo = 0; lo < omax; lo++) {
-               if (!isspace(c = lgetc(lp, lo))) {
-                       /* Possible nonblank line */
-                       nonblankp = TRUE;
-                       /* skip // and # starts */
-                       if (c == '#' || (slashp && c == '/')) {
-                               nonblankp = FALSE;
-                               break;
-                       } else if (!slashp && c == '/') {
-                               slashp = TRUE;
-                               continue;
-                       }
-               }
-               slashp = FALSE;
-       }
-       return (nonblankp);
-}