⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartindent.c

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
# $1 to a maximum of $2.\n\# if $3 is non-zero, newlines are considered blank space as well.  Return -1\n\# if the maximum position ($2) is hit mid-comment or mid-directive\n\#\n\define cSkipBlankSpace {\n\    \n\    for (i=$1; i<$2; i++) {\n\	c = get_character(i)\n\	if (c == \"/\") {\n\	    if (i+1 >= $2)\n\		return i\n\	    if (get_character(i+1) == \"*\") {\n\		for (i=i+1; ; i++) {\n\		    if (i+1 >= $2)\n\			return -1\n\		    if (get_character(i) == \"*\" && get_character(i+1) == \"/\") {\n\			i++\n\			break\n\		    }\n\		}\n\	    } else if (get_character(i+1) == \"/\") {\n\		for (i=i+1; i<$2; i++) {\n\		    if (get_character(i) == \"\\n\") {\n\			if (!$3)\n\			    return i\n\			break\n\		    }\n\		}\n\	    }\n\	} else if (c == \"#\" && $3) {\n\	    for (i=i+1; ; i++) {\n\		if (i >= $2) {\n\		    if (get_character(i-1) == \"\\\\\")\n\			return -1\n\		    else\n\			break\n\		}\n\		if (get_character(i) == \"\\n\" && get_character(i-1) != \"\\\\\")\n\		    break\n\	    }\n\	} else if (!(c == \" \" || c == \"\\t\" || ($3 && c==\"\\n\")))\n\	    return i\n\    }\n\    return $2\n\}\n\\n\#\n\# Search backward for an anchor point: a line ending brace, or semicolon\n\# or case statement, followed (ignoring blank lines and comments) by what we\n\# assume is a properly indented line, a brace on a line by itself, or a case\n\# statement.  Returns the position of the first non-white, non comment\n\# character on the line.  returns -1 if an anchor position can't be found\n\# before $cMaxSearchBackLines.\n\#\n\define cFindIndentAnchorPoint {\n\\n\    nLines = 0\n\    anchorPos = $1\n\    for (i=$1-1; i>0; i--) {\n\	c = get_character(i)\n\	if (c == \";\" || c == \"{\" || c == \"}\" || c == \":\") {\n\\n\	    # Verify that it's line ending\n\	    lineEnd = cSkipBlankSpace(i+1, $1, 0)\n\	    if (lineEnd == -1 || \\\n\	    	    (lineEnd != $text_length && get_character(lineEnd) != \"\\n\"))\n\   		continue\n\\n\	    # if it's a colon, it's only meaningful if \"case\" begins the line\n\	    if (c == \":\") {\n\	    	lineStart = startOfLine(i)\n\		caseStart = cSkipBlankSpace(lineStart, lineEnd, 0)\n\		if (get_range(caseStart, caseStart+4) != \"case\")\n\		    continue\n\		delim = get_character(caseStart+4)\n\		if (delim!=\" \" && delim!=\"\\t\" && delim!=\"(\" && delim!=\":\")\n\		    continue\n\		isCase = 1\n\	    } else\n\	    	isCase = 0\n\\n\	    # Move forward past blank lines and comment lines to find\n\	    #    non-blank, non-comment line-start\n\	    anchorPos = cSkipBlankSpace(lineEnd, $1, 1)\n\\n\	    # Accept if it's before the requested position, otherwise\n\	    #    continue further back in the file and try again\n\	    if (anchorPos != -1 && anchorPos < $1)\n\		break\n\\n\	    # A case statement by itself is an acceptable anchor\n\	    if (isCase)\n\	    	return caseStart\n\\n\	    # A brace on a line by itself is an acceptable anchor, even\n\	    #    if it doesn't follow a semicolon or another brace\n\	    if (c == \"{\" || c == \"}\") {\n\		for (j = i-1; ; j--) {\n\		    if (j == 0)\n\			return i\n\		    ch = get_character(j)\n\		    if (ch == \"\\n\")\n\		       return i\n\		    if (ch != \"\\t\" && ch != \" \")\n\		       break\n\		}\n\	    }\n\\n\	} else if (c == \"\\n\")\n\	    if (++nLines > $cMaxSearchBackLines)\n\		return -1\n\    }\n\    if (i <= 0)\n\	return -1\n\    return anchorPos\n\}\n\\n\#\n\# adjust the indent on a line about to recive either a right or left brace\n\# or pound (#) character ($2) following position $1\n\#\n\define cBraceOrPound {\n\\n\    # Find start of the line, and make sure there's nothing but white-space\n\    #   before the character.  If there's anything before it, do nothing\n\    for (i=$1-1; ; i--) {\n\	if (i < 0) {\n\	    lineStart = 0\n\	    break\n\	}\n\	c = get_character(i)\n\	if (c == \"\\n\") {\n\	    lineStart = i + 1\n\	    break\n\	}\n\	if (c != \" \" && c != \"\\t\")\n\	    return\n\    }\n\\n\    # If the character was a pound, drag it all the way to the left margin\n\    if ($2 == \"#\") {\n\	replace_range(lineStart, $1, \"\")\n\	return\n\    }\n\\n\    # Find the position on which to base the indent\n\    indent = cFindSmartIndentDist($1 - 1, \"noContinue\")\n\    if (indent == -1)\n\	return\n\    \n\    # Adjust the indent if it's a right brace (left needs no adjustment)\n\    if ($2 == \"}\") {\n\	indent -= defaultIndent($cIndentDist)\n\        if (indent < 0)\n\	    indent = 0\n\    }\n\\n\    # Replace the current indent with the new indent string\n\    insertStr = makeIndentString(indent)\n\    replace_range(lineStart, $1, insertStr)\n\}\n\\n\#\n\# Find Smart Indent Distance for a newline character inserted at $1,\n\# or return -1 to give up.  Adding the optional argument \"noContinue\"\n\# will stop the routine from inserting line continuation indents\n\#\n\define cFindSmartIndentDist {\n\\n\    # Find a known good indent to base the new indent upon\n\    anchorPos = cFindIndentAnchorPoint($1)\n\    if (anchorPos == -1)\n\	return -1\n\\n\    # Find the indentation of that line\n\    anchorIndent = measureIndent(anchorPos)\n\\n\    # Look for special keywords which affect indent (for, if, else while, do)\n\    #    and modify the continuation indent distance to the normal indent\n\    #    distance when a completed statement of this type occupies the line.\n\    if ($n_args >= 2 && $2 == \"noContinue\") {\n\	continueIndent = 0\n\	$allowSemi = 0\n\    } else\n\	continueIndent = cCalcContinueIndent(anchorPos, $1)\n\\n\    # Move forward from anchor point, ignoring comments and blank lines,\n\    #   remembering the last non-white, non-comment character.  If $1 is\n\    #   in the middle of a comment, give up\n\    lastChar = get_character(anchorPos)\n\    if (anchorPos < $1) {\n\	for (i=anchorPos;;) {\n\   	    i = cSkipBlankSpace(i, $1, 1)\n\	    if (i == -1)\n\		return -1\n\ 	    if (i >= $1)\n\ 		break\n\ 	    lastChar = get_character(i++)\n\	}\n\    }\n\\n\    # Return the new indent based on the type of the last character.\n\    #   In a for stmt, however, last character may be a semicolon and not\n\    #   signal the end of the statement\n\    if (lastChar == \"{\")\n\	return anchorIndent + defaultIndent($cIndentDist)\n\    else if (lastChar == \"}\")\n\	return anchorIndent\n\    else if (lastChar == \";\") {\n\	if ($allowSemi)\n\	    return anchorIndent + continueIndent\n\	else\n\	    return anchorIndent\n\    } else if (lastChar == \":\" && get_range(anchorPos, anchorPos+4) == \"case\")\n\    	return anchorIndent + defaultIndent($cIndentDist)\n\    return anchorIndent + continueIndent\n\}\n\\n\#\n\# Calculate the continuation indent distance for statements not ending in\n\# semicolons or braces.  This is not necessarily $continueIndent.  It may\n\# be adjusted if the statement contains if, while, for, or else.\n\#\n\# As a side effect, also return $allowSemi to help distinguish statements\n\# which might contain an embedded semicolon, which should not be interpreted\n\# as an end of statement character.\n\#\n\define cCalcContinueIndent {\n\\n\    anchorPos = $1\n\    maxPos = $2\n\\n\    # Figure out if the anchor is on a keyword which changes indent.  A special\n\    #   case is made for elses nested in after braces\n\    anchorIsFor = 0\n\    $allowSemi = 0\n\    if (get_character(anchorPos) == \"}\") {\n\	for (i=anchorPos+1; i<maxPos; i++) {\n\	    c = get_character(i)\n\	    if (c != \" \" && c != \"\\t\")\n\		break\n\	}\n\	if (get_range(i, i+4) == \"else\") {\n\	    keywordEnd = i + 4\n\	    needsBalancedParens = 0\n\	} else\n\	    return defaultContIndent($cContinuationIndent)\n\    } else if (get_range(anchorPos, anchorPos + 4) == \"else\") {\n\	keywordEnd = anchorPos + 4\n\	needsBalancedParens = 0\n\    } else if (get_range(anchorPos, anchorPos + 2) == \"do\") {\n\	keywordEnd = anchorPos + 2\n\	needsBalancedParens = 0\n\    } else if (get_range(anchorPos, anchorPos + 3) == \"for\") {\n\	keywordEnd = anchorPos + 3\n\	anchorIsFor = 1\n\	needsBalancedParens = 1\n\    } else if (get_range(anchorPos, anchorPos + 2) == \"if\") {\n\	keywordEnd = anchorPos + 2\n\	needsBalancedParens = 1\n\    } else if (get_range(anchorPos, anchorPos + 5) == \"while\") {\n\	keywordEnd = anchorPos + 5\n\	needsBalancedParens = 1\n\    } else\n\	return defaultContIndent($cContinuationIndent)\n\\n\    # If the keyword must be followed balanced parenthesis, find the end of\n\    # the statement by following balanced parens.  If the parens aren't\n\    # balanced by maxPos, continue the condition.  In the special case of\n\    # the for keyword, a semicolon can end the line and the caller should be\n\    # signaled to allow that\n\    if (needsBalancedParens) {\n\	stmtEnd = findBalancingParen(keywordEnd, maxPos)\n\	if (stmtEnd == -1) {\n\	    $allowSemi = anchorIsFor\n\	    return defaultContIndent($cContinuationIndent)\n\	}\n\    } else\n\	stmtEnd = keywordEnd\n\\n\    # check if the statement ends the line\n\    lineEnd = cSkipBlankSpace(stmtEnd, maxPos, 0)\n\    if (lineEnd == -1)		    	    # ends in comment or preproc\n\	return -1\n\    if (lineEnd == maxPos)  	    	    # maxPos happens at stmt end\n\	return defaultIndent($cIndentDist)\n\    c = get_character(lineEnd)\n\    if (c != \"\\n\")   		    	    # something past last paren on line,\n\	return defaultIndent($cIndentDist)  #   probably quoted or extra braces\n\\n\    # stmt contintinues beyond matching paren && newline, we're in\n\    #   the conditional part, calculate the continue indent distance\n\    #   recursively, based on the anchor point of the new line\n\    newAnchor = cSkipBlankSpace(lineEnd+1, maxPos, 1)\n\    if (newAnchor == -1)\n\	return -1\n\    if (newAnchor == maxPos)\n\	return defaultIndent($cIndentDist)\n\    return cCalcContinueIndent(newAnchor, maxPos) + defaultIndent($cIndentDist)\n\}\n\";/*** Turn on smart-indent (well almost).  Unfortunately, this doesn't do** everything.  It requires that the smart indent callback (SmartIndentCB)** is already attached to all of the text widgets in the window, and that the** smartIndent resource must be turned on in the widget.  These are done** separately, because they are required per-text widget, and therefore must** be repeated whenever a new text widget is created within this window** (a split-window command).*/void BeginSmartIndent(WindowInfo *window, int warn){    windowSmartIndentData *winData;    smartIndentRec *indentMacros;    char *modeName, *stoppedAt, *errMsg;    static int initialized;    /* Find the window's language mode.  If none is set, warn the user */    modeName = LanguageModeName(window->languageMode);    if (modeName == NULL)    {        if (warn)        {            DialogF(DF_WARN, window->shell, 1, "Smart Indent",                    "No language-specific mode has been set for this file.\n\n"                    "To use smart indent in this window, please select a\n"                    "language from the Preferences -> Language Modes menu.",                    "Dismiss");        }        return;    }        /* Look up the appropriate smart-indent macros for the language */    indentMacros = findIndentSpec(modeName);    if (indentMacros == NULL)    {        if (warn)        {            DialogF(DF_WARN, window->shell, 1, "Smart Indent",                    "Smart indent is not available in languagemode\n%s.\n\n"                    "You can create new smart indent macros in the\n"                    "Preferences -> Default Settings -> Smart Indent\n"                    "dialog, or choose a different language mode from:\n"                    "Preferences -> Language Mode.", "Dismiss", modeName);        }        return;    }        /* Make sure that the initial macro file is loaded before we execute        any of the smart-indent macros. Smart-indent macros may reference       routines defined in that file. */    ReadMacroInitFile(window);           /* Compile and run the common and language-specific initialization macros       (Note that when these return, the immediate commands in the file have not       necessarily been executed yet.  They are only SCHEDULED for execution) */    if (!initialized) {    	if (!ReadMacroString(window, CommonMacros,	    	"smart indent common initialization macros"))    	    return;	initialized = True;    }    if (indentMacros->initMacro != NULL) {	if (!ReadMacroString(window, indentMacros->initMacro,    	    	"smart indent initialization macro"))    	    return;    }        /* Compile the newline and modify macros and attach them to the window */    winData = (windowSmartIndentData *)XtMalloc(sizeof(windowSmartIndentData));    winData->inNewLineMacro = 0;    winData->inModMacro = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -