X-Git-Url: https://pd.if.org/git/?p=pd_readline;a=blobdiff_plain;f=mg%2Fcmode.c;fp=mg%2Fcmode.c;h=0000000000000000000000000000000000000000;hp=674d89d6e77ff79b680c2422eb0606208e987981;hb=4bb27266f935c9aafad6870ffc8847fc65c8120f;hpb=3f771e17236364ded86e96ee64f99344337991f8 diff --git a/mg/cmode.c b/mg/cmode.c deleted file mode 100644 index 674d89d..0000000 --- a/mg/cmode.c +++ /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 - */ - -/* - * Implement an non-irritating KNF-compliant mode for editing - * C code. - */ -#include - -#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); -}