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; } }
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; }