예제 #1
0
파일: tkTextMark.c 프로젝트: arazaq/ns2
static int
MarkFindPrev(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    const char *string)		/* The starting index or mark name */
{
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    register TkTextSegment *segPtr, *seg2Ptr, *prevPtr;
    int offset;

    if (!strcmp(string, "insert")) {
        segPtr = textPtr->insertMarkPtr;
        TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else if (!strcmp(string, "current")) {
        segPtr = textPtr->currentMarkPtr;
        TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else {
        hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);
        if (hPtr != NULL) {
            /*
             * If given a mark name, return the previous mark in the list of
             * segments, even if it happens to be at the same character
             * position.
             */

            segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
            TkTextMarkSegToIndex(textPtr, segPtr, &index);
        } else {
            /*
             * For non-mark name indices we do not return any marks that are
             * right at the index.
             */

            if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) {
                return TCL_ERROR;
            }
            for (offset = 0, segPtr = index.linePtr->segPtr;
                    segPtr != NULL && offset < index.byteIndex;
                    offset += segPtr->size, segPtr = segPtr->nextPtr) {
                /* Empty loop body */
            }
        }
    }

    while (1) {
        /*
         * segPtr points just past the first possible candidate, or at the
         * begining of the line.
         */

        for (prevPtr = NULL, seg2Ptr = index.linePtr->segPtr;
                seg2Ptr != NULL && seg2Ptr != segPtr;
                seg2Ptr = seg2Ptr->nextPtr) {
            if (seg2Ptr->typePtr == &tkTextRightMarkType ||
                    seg2Ptr->typePtr == &tkTextLeftMarkType) {
                prevPtr = seg2Ptr;
            }
        }
        if (prevPtr != NULL) {
            if (prevPtr == textPtr->currentMarkPtr) {
                Tcl_SetResult(interp, "current", TCL_STATIC);
            } else if (prevPtr == textPtr->insertMarkPtr) {
                Tcl_SetResult(interp, "insert", TCL_STATIC);
            } else if (prevPtr->body.mark.textPtr != textPtr) {
                /*
                 * Ignore widget-specific marks for the other widgets.
                 */

                continue;
            } else {
                Tcl_SetResult(interp,
                              Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
                                             prevPtr->body.mark.hPtr), TCL_STATIC);
            }
            return TCL_OK;
        }
        index.linePtr = TkBTreePreviousLine(textPtr, index.linePtr);
        if (index.linePtr == NULL) {
            return TCL_OK;
        }
        segPtr = NULL;
    }
}
예제 #2
0
int Sn_Syntax_Highlight(ClientData clientData, Tcl_Interp * interp, int argc, char **argv)
{
	register TkText *textPtr = NULL;
	Tcl_CmdInfo infoPtr;
	int result = TCL_OK;
	int del = 0;
	char *argv0 = argv[0];
	int wargc;
	char *wargv[10];
	char *language;
	char *idx1;
	char *idx2;
	char *text_widget;
	char endpos[TK_POS_CHARS];
	char begpos[TK_POS_CHARS];
	int val;
	int (*high_func) () = NULL;
	void (*flush_lex_scanner) () = NULL;
	void (*high_init_func) (int ms, int lineno, int charno, void (**func) (), void *idx1, void *idx2) = NULL;
	Tcl_CmdProc *text_proc;
	int update = 0;
	TkTextIndex lex_index1;
	TkTextIndex lex_index2;
	TkTextIndex lex_end_index;
	char prev_begpos[TK_POS_CHARS];
	int lex_buf_size = 0;

	eos_read = 0;

	while (argc > 1 && argv[1][0] == '-') {
		if(strncmp(argv[1], "-delete", 5) == 0) {
			del = 1;
			argc--;
			argv++;
		} else if(strncmp(argv[1], "-delall", 5) == 0) {
			del = -1;
			argc--;
			argv++;
		} else if(strncmp(argv[1], "-update", 4) == 0) {
			lex_buf_size = 256;	/* It is probably not necessary to fill */
			/* the complete lex buffer. */
			update = 1;
			argc--;
			argv++;
		} else
			break;
	}

	if(argc != 4 && argc != 5) {
		Tcl_AppendResult(interp, "wrong # args: should be \"", argv0, " ?-delete? ?-delall? language text_widget index1 ?index2?", NULL);

		return TCL_ERROR;
	}

	language = argv[1];
	text_widget = argv[2];
	idx1 = argv[3];
	idx2 = argc == 5 ? argv[4] : idx1;

	LOGGER((LOGFP, "highlight lang: <%s> text: <%s> idx1: <%s> idx2: <%s>\n", language, text_widget, idx1, idx2));
	if(strcmp(language, "tcl") == 0) {
		high_func = tcl_highlight_lex;
		high_init_func = tcl_highlight_init_func;
	} else if(strcmp(language, "c++") == 0) {
		high_func = c_highlight_lex;
		high_init_func = c_highlight_init_func;
	} else if(strcmp(language, "java") == 0) {
		high_func = java_highlight_lex;
		high_init_func = java_highlight_init_func;
	} else if(strcmp(language, "chill") == 0) {
		high_func = ch_highlight_lex;
		high_init_func = ch_highlight_init_func;
	} else if(strcmp(language, "verilog") == 0) {
		high_func = verilog_highlight_lex;
		high_init_func = verilog_highlight_init_func;
	} else if(strcmp(language, "python") == 0) {
		high_func = py_highlight_lex;
		high_init_func = py_highlight_init_func;
	}

	if(!high_func) {
		return TCL_OK;
	}

	if(!Tcl_GetCommandInfo(interp, text_widget, &infoPtr)) {
		Tcl_AppendResult(interp, "wrong # \"", text_widget, "\" does not exist", (char *) NULL);
		return TCL_ERROR;
	}

	textPtr = (TkText *) infoPtr.clientData;
	Tcl_Preserve((ClientData) textPtr);
	text_proc = (Tcl_CmdProc *) infoPtr.proc;

	if(del) {
		remove_tag(textPtr, interp, text_widget, del, idx1, idx2);
	}

	TkTextGetIndex(interp, textPtr, "end", &lex_end_index);

	if(TkTextGetIndex(interp, textPtr, idx1, &lex_index1) != TCL_OK || TkTextGetIndex(interp, textPtr, idx2, &lex_index2) != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	}
	if(TkTextIndexCmp(&lex_index1, &lex_index2) >= 0) {
		result = TCL_OK;
		goto done;
	}
	high_init_func(lex_buf_size, TkBTreeLineIndex(lex_index1.linePtr) + 1,
		       lex_index1.CHARINDEX, &flush_lex_scanner, (void *) &lex_index1, (void *) &lex_end_index);

	wargc = 0;
	wargv[wargc++] = text_widget;
	wargv[wargc++] = "tag";
	wargv[wargc++] = "add";
	wargv[wargc++] = NULL;
	wargv[wargc++] = begpos;
	wargv[wargc++] = endpos;

	strcpy(prev_begpos, idx1);
	while ((val = (*high_func) ()) != 0) {
		sprintf(begpos, "%d.%d", paf_high_pos.beg_lineno, paf_high_pos.beg_charno);
		sprintf(endpos, "%d.%d", paf_high_pos.end_lineno, paf_high_pos.end_charno);
		wargv[3] = high_tag_names[val];

		if(update) {
			int tag_argc = 0;
			char *tag_argv[10];
			char *p_end;
			int cou;
			int tag_off;

			tag_argv[tag_argc++] = text_widget;
			tag_argv[tag_argc++] = "tag";
			tag_argv[tag_argc++] = "prevrange";
			tag_off = tag_argc;
			tag_argv[tag_argc++] = NULL;
			tag_argv[tag_argc++] = endpos;
			for (cou = 1; cou <= PAF_HIGH_STRING; cou++) {
				tag_argv[tag_off] = high_tag_names[cou];
				Tcl_ResetResult(interp);
				TkTextTagCmd(textPtr, interp, tag_argc, tag_argv);

				p_end = strchr(interp->result, ' ');
				/* Check whether it is synchronized ! */
				if(p_end && strcmp(p_end + 1, endpos) == 0) {
					eos_read = 1;
					/* It will get flex recognized that no further
					 * input is available. */
					flush_lex_scanner();
					break;
				}
			}
			LOGGER((LOGFP, "Add %s %d %s %s\n", high_tag_names[val], val, begpos, endpos));
		}
		if(update) {
			int tag_argc = 0;
			char *tag_argv[10];
			int cou;
			int tag_off;

			tag_argv[tag_argc++] = text_widget;
			tag_argv[tag_argc++] = "tag";
			tag_argv[tag_argc++] = "remove";
			tag_off = tag_argc;
			tag_argv[tag_argc++] = NULL;
			tag_argv[tag_argc++] = prev_begpos;
			tag_argv[tag_argc++] = endpos;

			for (cou = 1; cou <= PAF_HIGH_STRING; cou++) {
				tag_argv[tag_off] = high_tag_names[cou];
				TkTextTagCmd(textPtr, interp, tag_argc, tag_argv);
			}
			strcpy(prev_begpos, endpos);
		}
		TkTextTagCmd(textPtr, interp, wargc, wargv);
	}
done:
	Tcl_Release((ClientData) textPtr);

	return result;
}