- function ready_handler(){
- get_elem('content').focus();
- // handle_null();
- }
- // ==========================================================
- // Some utils
- function get_elem(x){
- return document.getElementById(x);
- }
- function insert_elem_at_caret(elem){
- window.getSelection().getRangeAt(0).insertNode(elem);
- }
- function move_beyond(){
- var sel = window.getSelection();
- var ran = sel.getRangeAt(0);
- ran.collapse(true);
- if(ran.startContainer.nodeType != 3) ran.setStart(ran.startContainer, ran.startOffset + 1);
- else ran.setStart(ran.startContainer.nextSibling.nextSibling, 0);
- sel.removeAllRanges();
- sel.addRange(ran);
- }
- function keydown_handler(e){
- e.stopPropagation();
- if(e.which == '13'){
- e.preventDefault();
- var x = document.createTextNode('\n');
- insert_elem_at_caret(x);
- move_beyond();
- }
- if(e.which == '9'){
- e.preventDefault();
- var x = document.createTextNode('\t');
- insert_elem_at_caret(x);
- move_beyond();
- }
- window.setTimeout('sub()', 0);
- }
- function keypress_handler(e){
- }
- function block_match(string){
- return string
- .replace(func.patt_reg, func.patt_repl)
- .replace(func.post_reg, func.post_repl)
- .replace(func.post_reg2, func.post_repl);
- }
- function global_key_match(string){
- return string
- .replace(key.regex, key.style)
- .replace(type.regex, type.style)
- .replace(post.regex_global, post.style);
- }
- function local_key_match(string){
- return string
- .replace(key.regex, key.style)
- .replace(type.regex, type.style)
- .replace(post.regex_local, post.style);
- }
- // This portion should be placed in another file and dynamically loaded in the future.
- var func = { patt_reg: /((?:[a-zA-Z_][a-zA-Z_0-9]*\s+){1,3})([a-z_][a-z_A-Z0-9]+\s*)(\([^\)]*\)\s*)(\{[^\{\}]*\}\s*)/g,
- patt_repl: "<func>$1$2$3$4</func>",
- post_reg: /((?:<\/func>)|^)([^<]+)(?=<func>)/g,
- post_reg2: /(^)([^<>]+)/g,
- post_repl: "$1<nofunc>$2</nofunc>"
- };
- var key = { regex: /(\W|^)(if|switch|for|while|break|case|continue|default|do|else|enum|goto|return|sizeof|struct|typedef|union)(\W|$)/g,
- style:"$1<key>$2</key>$3"
- };
- var type = { regex: /((?:const|volatile|static|extern)\s+)?((?:short|long|(?:un)?signed)\s+)?((?:int|float|double|char|void|enum)\s+)/g,
- style: "<type>$1$2$3</type>"
- };
- var post = { regex_global: /((?:func>)|(?:\/[^>]+>))([^<]+)/g,
- regex_local: /(^|(?:\/[^>]+>))([^<]+)/g,
- style: "$1<flat>$2</flat>"
- }
- function get_outer_offset(elem){
- var curr = window.getSelection().getRangeAt(0);
- curr.setStart(elem, 0);
- return curr.toString().length;
- }
- // Here I use some weird walk around.
- // the regex (<[^>]*>)+ is supposed to match all countinuous HTML tag,
- // but the opening tag of each element appears in the result.
- // So I have to use match instead, however, for each match, there will
- // be two extra bracket. Since we just want the length, simply subtract
- // them in the following calculation
- function get_pos(elem, elem_offset){
- var content = elem.innerHTML.match(/>([^<]+)</g);
- if(content){
- var len = content.length,
- accum = 0;
- for(i = 0; i < len; i++){
- accum += content[i].length -2;
- if(accum >= elem_offset) break;
- }
- var off = elem_offset - (accum - (content[i].length - 2));
- return {ith: i,
- offset: off
- }
- }
- }
- function set_pos(elem, offset){
- var ran = document.createRange(),
- sel = window.getSelection();
- // get_elem('container2').textContent = get_elem('content').innerHTML;
- // get_elem('container3').textContent = pos.offset;
- ran.collapse(false);
- ran.setStart(elem, offset);
- sel.removeAllRanges();
- sel.addRange(ran);
- }
- // determine whether a global match is needed by checking the number of blocks
- // in the whole content.
- function block_number_check(con){
- return con.children.length == block_match(con.innerHTML).match(/\/(no)?func>/g).length;
- }
- function sub(){
- var con = get_elem('content'),
- con2 = get_elem('container2'),
- con3 = get_elem('container3'),
- con_original = con.textContent;
- con_blockized = block_match(con.textContent);
- if(!con.children.length){ // Handles the first character
- // alert("hey!");
- con.innerHTML = "<nofunc><flat>"+ con.textContent +"\n</flat></nofunc>";
- set_pos(con.firstChild.firstChild, 1);
- con2.textContent = con.innerHTML;
- }else if(con.children.length == con_blockized.match(/\/(no)?func>/g).length){
- // Handles the block-inside matching
- //1. get the block-inside offset
- var caret = window.getSelection().getRangeAt(0);
- var block = caret.startContainer;
- con2.textContent = block.parentNode;
- while(block.tagName != 'FUNC' && block.tagName != 'NOFUNC')
- block = block.parentNode;
- caret.setStart(block, 0);
- var len = caret.toString().length;
- //2. then apply the new style
- block.innerHTML = local_key_match(block.textContent);
- con2.textContent = con.innerHTML;
- var pos = get_pos(block, len);
- //3. Plug the caret back to the original place
- set_pos(block.children[pos.ith].firstChild, pos.offset);
- }else{
- // Oops ... we have to match the whole content
- //1. Get the global ofset
- var caret = window.getSelection().getRangeAt(0);
- var block = caret.startContainer;
- while(block.tagName != 'DIV')
- block = block.parentNode;
- caret.setStart(block, 0);
- var len = caret.toString().length;
- con3.textContent = len;
- //2. Get the block index
- block.innerHTML = block_match(block.textContent);
- var block_pos = get_pos(block, len);
- //3. Get the inside-block tag index
- block.innerHTML = global_key_match(block.innerHTML);
- var inner_pos = get_pos(block.children[block_pos.ith], block_pos.offset);
- set_pos(block.children[block_pos.ith].children[inner_pos.ith].firstChild, inner_pos.offset);
- }
- }