/************************************************** -*- tab-width:4 -*- * * "Epsilon" is a registered trademark licensed to Lugaru Software, Ltd. * * "EEL" and "Lugaru" are trademarks of Lugaru Software, Ltd. * * * * Copyright (C) 1996, 2006 Lugaru Software Ltd. All rights reserved. * * * * Limited permission is hereby granted to reproduce and modify this * * copyrighted material provided that the resulting code is used only in * * conjunction with Lugaru products and that this notice is retained in * * any such reproduction or modification. * ************************************************************************/ // For certain XML files, display the value of the first attribute when // showing nesting. A modification by Mark Swann of a function in // html.e, based on Epsilon 13.00. #include "eel.h" #include "proc.h" #include "colcode.h" #include "c.h" #include "html.h" #include "indent.h" #include "vbasic.h" #include "perl.h" #include "python.h" #include "grep.h" #include "epsnet.h" user buffer short xml_show_1st_attr = 0; // Set tag to the first attribute of the tag whose < is at pos, // and return 1 if it's an opening tag, -1 if it's a closing tag, // or 0 if it's bad. // Will include the name of the xml tag when flags is set to multi-line, // I.E. (flags & 1) != zero. int html_get_1st_tag_attribute(int pos, char *tag, int flags) { save_var point = pos; int i = parse_string(1, "%<[ \t\n]*"), ret = 1; if (!i) return 0; point += i; if (curchar() == '/') { ret = -1; point++; } point += parse_string(1, "[ \t\n]"); i = parse_string(1, "[-_./A-Za-z0-9:]+", tag); if (!i) return 0; point += parse_string(1, "[ \t\n]"); if ( !parse_string(1, "([-_./A-Za-z0-9]+[ \t\n]*=[ \t\n]*\"([^\"]+)\")" ) ) { return ret; } if ( flags & 1 ) { strcat ( tag, " " ); grab(find_group(1, 1), find_group(1, 0), tag+i+1); } else { grab(find_group(2, 1), find_group(2, 0), tag); } return ret; } // List element context at point into buffer b. Flags: 1=multi-line // format, 2=give up on keypress and return 0. int do_list_element_nesting(int b, int flags) { char tag[FNAMELEN], depth[FNAMELEN]; save_var point, case_fold = (sublanguage_code != SUBLANG_XML); int open = html_in_tag() != -1; while (do_color_searching(REVERSE | REGEX, "[<]") == 1) { if ((flags & 2) && (char_avail() || is_key_repeating())) return 0; // Give up search now? set_buf_point(b, 0); int i = html_is_start_tag(point, 0); if (i == -1) { i = do_html_find_matching_tag(point, tag); if (i >= 0) { point = i; search(-1, "<"); // Get from element name to before its <. } else if (!(flags & 1)) buf_printf(b, "%s? ", tag); else if (i == -1) buf_printf(b, " unmatched at line %d, position %d.\n", tag, lines_between(0, point) + 1, point); else buf_printf(b, "Can't recognize tag at line %d, position %d.\n", lines_between(0, point) + 1, point); } else if (i == 1 || !i && open) { if ( xml_show_1st_attr ) { i = html_get_1st_tag_attribute(point, tag, flags); } else { i = html_get_tag_name(point, tag); } if ( i == 1 ) { char *bad = html_invalid_tag(point + 1) ? "?" : ""; if ((flags & 1) && *bad) buf_printf(b, "Unclosed <%s at line %d, position %d.\n", tag, lines_between(0, point) + 1, point); else { if ( xml_show_1st_attr ) { buf_printf(b, !(flags & 1) ? (open ? "/<%s%s" : "/%s%s") : (open ? "<%s%s\n" : "<%s%s>\n"), tag, bad ); } else { buf_printf(b, !(flags & 1) ? (open ? "<%s%s " : "%s%s ") : (open ? "<%s%s\n" : "<%s%s>\n"), tag, bad ); } } } } open = 0; } if (flags & 1) { save_var bufnum = b, point = 0; *depth = 0; while (re_search(1, "^[<]" HTML_NAME)) { set_character_color(matchstart + 1, matchend, color_class html_tag); point = matchstart; bprintf("%s", depth); strcat(depth, " "); to_end_line(); } } return 1; } command xml_mode() { html_like_mode(1); xml_show_1st_attr = 0; } suffix_xsl() // XML style sheet { xml_mode(); xml_show_1st_attr = 1; } suffix_xsd() // W3 Schema for XML { xml_mode(); xml_show_1st_attr = 1; }