/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2005 Ben Fry and Casey Reas Copyright (c) 2003 Martin Gomez, Ateneo de Manila University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.tools; import processing.app.*; //import processing.core.*; import java.io.*; import java.util.StringTokenizer; /** * Alternate handler for dealing with auto format, * contributed by Martin Gomez. */ public class AutoFormat { Editor editor; public AutoFormat(Editor editor) { this.editor = editor; } /* public void show() { String prog = editor.textarea.getText(); // TODO re-enable history //history.record(prog, SketchHistory.BEAUTIFY); //int tabSize = Preferences.getInteger("editor.tabs.size"); char program[] = prog.toCharArray(); StringBuffer buffer = new StringBuffer(); boolean gotBlankLine = false; int index = 0; int level = 0; while (index != program.length) { int begin = index; while ((program[index] != '\n') && (program[index] != '\r')) { index++; if (program.length == index) break; } int end = index; if (index != program.length) { if ((index+1 != program.length) && // treat \r\n from windows as one line (program[index] == '\r') && (program[index+1] == '\n')) { index += 2; } else { index++; } } // otherwise don't increment String line = new String(program, begin, end-begin); line = line.trim(); if (line.length() == 0) { if (!gotBlankLine) { // let first blank line through buffer.append('\n'); gotBlankLine = true; } } else { //System.out.println(level); int idx = -1; String myline = line.substring(0); while (myline.lastIndexOf('}') != idx) { idx = myline.indexOf('}'); myline = myline.substring(idx+1); level--; } //for (int i = 0; i < level*2; i++) { // TODO i've since forgotten how i made this work (maybe it's even // a bug) but for now, level is incrementing/decrementing in // steps of two. in the interest of getting a release out, // i'm just gonna roll with that since this function will prolly // be replaced entirely and there are other things to worry about. for (int i = 0; i < tabSize * level / 2; i++) { buffer.append(' '); } buffer.append(line); buffer.append('\n'); //if (line.charAt(0) == '{') { //level++; //} idx = -1; myline = line.substring(0); while (myline.lastIndexOf('{') != idx) { idx = myline.indexOf('{'); myline = myline.substring(idx+1); level++; } gotBlankLine = false; } } // save current (rough) selection point int selectionEnd = editor.textarea.getSelectionEnd(); // replace with new bootiful text editor.setText(buffer.toString(), false); // make sure the caret would be past the end of the text if (buffer.length() < selectionEnd - 1) { selectionEnd = buffer.length() - 1; } // at least in the neighborhood editor.textarea.select(selectionEnd, selectionEnd); editor.sketch.setModified(); //buttons.clear(); } */ StringBuffer strOut; String formattedText; int indentValue; String indentChar; String uhOh = null; String theStuff; int EOF; BufferedInputStream bin = null; int nBytesRead, indexBlock, lineLength, lineNumber; byte bArray[]; String strBlock; int s_level[]; int c_level; int sp_flg[][]; int s_ind[][]; int s_if_lev[]; int s_if_flg[]; int if_lev, if_flg, level; int ind[]; int e_flg, paren; static int p_flg[]; char l_char, p_char; int a_flg, q_flg, ct; int s_tabs[][]; String w_if_, w_else, w_for, w_ds, w_case, w_cpp_comment, w_jdoc; int jdoc, j; int BLOCK_MAXLEN; char string[]; byte bstring[]; byte bblank; char cc; int s_flg, b_flg; int peek; char peekc; int tabs; char next_char, last_char; char lastc0, lastc1; char c, c0; char w_kptr; String line_feed; static int outfil; // temporary public void comment() { int save_s_flg; save_s_flg = s_flg; int done = 0; c = string[j++] = getchr(); // extra char while (done == 0) { c = string[j++] = getchr(); while(c != '/') { if(c == '\n' || c == '\r') { lineNumber++; putcoms(); s_flg = 1; } c = string[j++] = getchr(); } String tmpstr = new String(string); if (j>1 && string[j-2] == '*') { done = 1; jdoc = 0; } } putcoms(); s_flg = save_s_flg; jdoc = 0; return; } public char get_string() { char ch; ch = '*'; while (true) { switch (ch) { default: ch = string[j++] = getchr(); if (ch == '\\') { string[j++] = getchr(); break; } if (ch == '\'' || ch == '"') { cc = string[j++] = getchr(); while (cc != ch) { if (cc == '\\') string[j++] = getchr(); cc = string[j++] = getchr(); } break; } if (ch == '\n' || ch == '\r') { indent_puts(); a_flg = 1; break; } else { return(ch); } } } } public void indent_puts() { string[j] = '\0'; if (j > 0) { if (s_flg != 0) { if((tabs > 0) && (string[0] != '{') && (a_flg == 1)) { tabs++; } p_tabs(); s_flg = 0; if ((tabs > 0) && (string[0] != '{') && (a_flg == 1)) { tabs--; } a_flg = 0; } String j_string = new String(string); strOut.append(j_string.substring(0,j)); for (int i=0; i 0)string[j++] = c; indent_puts(); s_flg = 0; break; } if(s_flg == 0 || j > 0)string[j++] = c; break; case '\r': /* for MS Windows 95 */ case '\n': lineNumber++; if (EOF==1) { break; } String j_string = new String(string); e_flg = lookup(w_else); if(e_flg == 1) gotelse(); if (lookup_com(w_cpp_comment) == 1) { if (string[j] == '\n') { string[j] = '\0'; j--; } } indent_puts(); fprintf(outfil, line_feed); s_flg = 1; if(e_flg == 1) { p_flg[level]++; tabs++; } else if(p_char == l_char) { a_flg = 1; } break; case '{': if(lookup(w_else) == 1)gotelse(); s_if_lev[c_level] = if_lev; s_if_flg[c_level] = if_flg; if_lev = if_flg = 0; c_level++; if(s_flg == 1 && p_flg[level] != 0) { p_flg[level]--; tabs--; } string[j++] = c; indent_puts(); getnl() ; indent_puts(); fprintf(outfil,"\n"); tabs++; s_flg = 1; if(p_flg[level] > 0) { ind[level] = 1; level++; s_level[level] = c_level; } break; case '}': c_level--; if (c_level < 0) { EOF = 1; string[j++] = c; indent_puts(); break; } if((if_lev = s_if_lev[c_level]-1) < 0)if_lev = 0; if_flg = s_if_flg[c_level]; indent_puts(); tabs--; p_tabs(); peekc = getchr(); if( peekc == ';') { onechar = new StringBuffer(); onechar.append(c); /* } */ onechar.append(';'); fprintf(outfil, onechar.toString()); peek = -1; peekc = '`'; } else { onechar = new StringBuffer(); onechar.append(c); fprintf(outfil, onechar.toString()); peek = 1; } getnl(); indent_puts(); fprintf(outfil,"\n"); s_flg = 1; if(c_level < s_level[level]) if(level > 0) level--; if(ind[level] != 0) { tabs -= p_flg[level]; p_flg[level] = 0; ind[level] = 0; } break; case '"': case '\'': string[j++] = c; cc = getchr(); while(cc != c) { // max. length of line should be 256 string[j++] = cc; if(cc == '\\') { cc = string[j++] = getchr(); } if(cc == '\n') { lineNumber++; indent_puts(); s_flg = 1; } cc = getchr(); } string[j++] = cc; if(getnl() == 1) { l_char = cc; peek = 1; peekc = '\n'; } break; case ';': string[j++] = c; indent_puts(); if(p_flg[level] > 0 && ind[level] == 0) { tabs -= p_flg[level]; p_flg[level] = 0; } getnl(); indent_puts(); fprintf(outfil,"\n"); s_flg = 1; if(if_lev > 0) if(if_flg == 1) { if_lev--; if_flg = 0; } else if_lev = 0; break; case '\\': string[j++] = c; string[j++] = getchr(); break; case '?': q_flg = 1; string[j++] = c; break; case ':': string[j++] = c; peekc = getchr(); if(peekc == ':') { indent_puts(); fprintf (outfil,":"); peek = -1; peekc = '`'; break; } else { int double_colon = 0; peek = 1; } if(q_flg == 1) { q_flg = 0; break; } if(lookup(w_ds) == 0 && lookup(w_case) == 0) { s_flg = 0; indent_puts(); } else { tabs--; indent_puts(); tabs++; } peekc = getchr(); if(peekc == ';') { fprintf(outfil,";"); peek = -1; peekc = '`'; } else { peek = 1; } getnl(); indent_puts(); fprintf(outfil,"\n"); s_flg = 1; break; case '/': c0 = string[j]; string[j++] = c; peekc = getchr(); if(peekc == '/') { string[j++] = peekc; peekc = '`'; peek = -1; cpp_comment(); fprintf(outfil,"\n"); break; } else { peek = 1; } if(peekc != '*') { break; } else { if (j > 0) string[j--] = '\0'; if (j > 0) indent_puts(); string[j++] = '/'; string[j++] = '*'; peek = -1; peekc = '`'; comment(); break; } case '#': string[j++] = c; cc = getchr(); while(cc != '\n') { string[j++] = cc; cc = getchr(); } string[j++] = cc; s_flg = 0; indent_puts(); s_flg = 1; break; case ')': paren--; if (paren < 0) { EOF = 1; } string[j++] = c; indent_puts(); if(getnl() == 1) { peekc = '\n'; peek = 1; if(paren != 0) { a_flg = 1; } else if(tabs > 0) { p_flg[level]++; tabs++; ind[level] = 0; } } break; case '(': string[j++] = c; paren++; if ((lookup(w_for) == 1)) { c = get_string(); while(c != ';') c = get_string(); ct=0; int for_done = 0; while (for_done==0) { c = get_string(); while(c != ')') { if(c == '(') ct++; c = get_string(); } if(ct != 0) { ct--; } else for_done = 1; } /* endwhile for_done */ paren--; if (paren < 0) { EOF = 1; } indent_puts(); if(getnl() == 1) { peekc = '\n'; peek = 1; p_flg[level]++; tabs++; ind[level] = 0; } break; } if(lookup(w_if_) == 1) { indent_puts(); s_tabs[c_level][if_lev] = tabs; sp_flg[c_level][if_lev] = p_flg[level]; s_ind[c_level][if_lev] = ind[level]; if_lev++; if_flg = 1; } } /* end switch */ String j_string = new String(string); } // end while not EOF //formattedText = strOut.toString(); // save current (rough) selection point int selectionEnd = editor.textarea.getSelectionEnd(); // make sure the caret would be past the end of the text if (strOut.length() < selectionEnd - 1) { selectionEnd = strOut.length() - 1; } // replace with new bootiful text // selectionEnd hopefully at least in the neighborhood editor.setText(strOut.toString(), selectionEnd, selectionEnd); editor.sketch.setModified(); bin.close(); // close buff } catch (IOException ioe) { editor.error(ioe); //ioe.printStackTrace(); } // () {} check String ck_paren = new String("left"); if (paren < 0) ck_paren = "right"; if (paren != 0) { setUhOh("Uh oh... too many " + ck_paren + " parentheses."); } else { // check braces only if parens are ok ck_paren = "left"; if (c_level < 0) { ck_paren = "right"; } else if (c_level != 0) { setUhOh("Uh oh... too many " + ck_paren + " curled braces."); } } } /* throw back the stuff to the editor */ public String getFormattedText() { return formattedText; } /* special edition of put string for comment processing */ public void putcoms() { int i = 0; int sav_s_flg = s_flg; if(j > 0) { if(s_flg != 0) { p_tabs(); s_flg = 0; } string[j] = '\0'; i = 0; while (string[i] == ' ') i++; if (lookup_com(w_jdoc) == 1) jdoc = 1; String strBuffer = new String(string,0,j); if (string[i] == '/' && string[i+1]=='*') { if ((last_char != ';') && (sav_s_flg==1) ) { fprintf(outfil, strBuffer.substring(i,j)); } else { fprintf(outfil, strBuffer); } } else { if (string[i]=='*' || jdoc == 0) fprintf (outfil, " "+strBuffer.substring(i,j)); else fprintf (outfil, " * "+strBuffer.substring(i,j)); } j = 0; string[0] = '\0'; } } public void cpp_comment() { c = getchr(); while(c != '\n' && c != '\r' && j<133) { string[j++] = c; c = getchr(); } lineNumber++; indent_puts(); s_flg = 1; } /* expand indentValue into tabs and spaces */ public void p_tabs() { int i,k; if (tabs<0) tabs = 0; if (tabs==0) return; i = tabs * indentValue; // calc number of spaces //j = i/8; /* calc number of tab chars */ for (k=0; k < i; k++) { strOut.append(indentChar); } } public char getchr() { if((peek < 0) && (last_char != ' ') && (last_char != '\t')) { if((last_char != '\n') && (last_char != '\r')) p_char = last_char; } if(peek > 0) /* char was read previously */ { last_char = peekc; peek = -1; } else /* read next char in string */ { indexBlock++; if (indexBlock >= lineLength) { for (int ib=0; ib 0) { nBytesRead = bin.read(bArray); lineLength = nBytesRead; strBlock = new String(bArray); indexBlock = 0; last_char = strBlock.charAt(indexBlock); peek = -1; peekc = '`'; } else { EOF = 1; peekc = '\0'; } } catch(IOException ioe) { System.out.println(ioe.toString()); } } else { last_char = strBlock.charAt(indexBlock); } } peek = -1; if (last_char == '\r') { last_char = getchr(); } return last_char; } /* else processing */ public void gotelse() { tabs = s_tabs[c_level][if_lev]; p_flg[level] = sp_flg[c_level][if_lev]; ind[level] = s_ind[c_level][if_lev]; if_flg = 1; } /* read to new_line */ public int getnl() { int save_s_flg; save_s_flg = tabs; peekc = getchr(); while(peekc == '\t' || peekc == ' ') { string[j++] = peekc; peek = -1; peekc = '`'; peekc = getchr(); peek = 1; } peek = 1; if (peekc == '/') { peek = -1; peekc = '`'; peekc = getchr(); if (peekc == '*') { string[j++] = '/'; string[j++] = '*'; peek = -1; peekc = '`'; comment(); } else if (peekc == '/') { string[j++] = '/'; string[j++] = '/'; peek = -1; peekc = '`'; cpp_comment(); return (1); } else { string[j++] = '/'; peek = 1; } } peekc = getchr(); if(peekc == '\n') { lineNumber++; peek = -1; peekc = '`'; tabs = save_s_flg; return(1); } else { peek = 1; } return 0; } public int lookup (String keyword) { char r; int l,kk,k,i; String j_string = new String(string); if (j<1) return (0); kk=0; while(string[kk] == ' ')kk++; l=0; l = j_string.indexOf(keyword); if (l<0 || l!=kk) { return 0; } r = string[kk+keyword.length()]; if(r >= 'a' && r <= 'z') return(0); if(r >= 'A' && r <= 'Z') return(0); if(r >= '0' && r <= '9') return(0); if(r == '_' || r == '&') return(0); return (1); } public int lookup_com (String keyword) { char r; int l,kk,k,i; String j_string = new String(string); if (j<1) return (0); kk=0; while(string[kk] == ' ')kk++; l=0; l = j_string.indexOf(keyword); if (l<0 || l!=kk) { return 0; } return (1); } }