📄 reference.java
字号:
/*
* MC2 -- j2me spreadsheet
*
* Copyright (c) 2004-2006 Michael Zemljanukha (mixaz@mail.ru)
*
* 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 com.wapindustrial.calc;
/* * Reference.java * * Created on February 26, 2004, 3:35 PM */public class Reference extends LispObject {
static final byte ABS_I1 = 0x01; static final byte ABS_J1 = 0x02; static final byte ABS_I2 = 0x04; static final byte ABS_J2 = 0x08; static final byte BAD_REF = 0x10; final short i1,j1,i2,j2; final byte absFlags; // absolute/relative flags /** Without normalization (used in (selection)) */ Reference( int _i1, int _j1, int _i2, int _j2 ) { i1 = (short)_i1; j1 = (short)_j1; i2 = (short)_i2; j2 = (short)_j2;
absFlags = 0; } Reference( int i1, int j1, int i2, int j2, int absFlags ) {
if (i1 > i2) {
int ii = i1;
i1 = i2;
i2 = ii;
absFlags = (byte) ((absFlags & ~(ABS_I1 | ABS_I2)) | (absFlags & ABS_I1 << 2) | (absFlags & ABS_I2 >> 2));
}
if (j1 > j2) {
int jj = j1;
j1 = j2;
j2 = jj;
absFlags = (byte) ((absFlags & ~(ABS_J1 | ABS_J2)) | (absFlags & ABS_J1 << 2) | (absFlags & ABS_J2 >> 2));
}
// if (i1 == i2) {
// absFlags = (byte) ((absFlags & ~ABS_I2) | ((absFlags & ABS_I1) << 2));
// }
// if (j1 == j2) {
// absFlags = (byte) ((absFlags & ~ABS_J2) | ((absFlags & ABS_J1) << 2));
// }
this.i1 = (byte)i1;
this.j1 = (byte)j1;
this.i2 = (byte)i2;
this.j2 = (byte)j2;
this.absFlags = (byte) absFlags;
} // not an atom! just a mix of functor/atom // this evaluation is implemented for experessions (ops and lisp as well) // functor going to manumulate with references must not evaluate them before ops public LispObject evaluateSExp() throws EvaluateException { // this for atoms & list, calculate functions for functors if( (absFlags&BAD_REF) != 0 ) return FormulaError.REF_ERROR;
//#ifndef NOGUI return CanvasHandler1.canvasHandler.getCellValue( i1, j1 );
//#else
//# return NIL;
//#endif } // public LispObject convertToType( int type ) throws EvaluateException {// if( (absFlags&BAD_REF) != 0 )// throw new EvaluateException( "bad cell reference" );// LispObject value = CanvasHandler1.canvasHandler.getCellValue( i1, j1 );// return value.convertToType( type );// } // public LispObject getReferredValue() {// return getReferredValue0().getReferredValue();// } /** Gets value of the first cell in the referred range * @return Cell.value or REF_ERROR */ public FunctorList toList() { return new FunctorListN(
Bfunc.BFUNC.table[Bfunc.INDEX_REF], new LispObject[] { new ShortAtom( i1 ), new ShortAtom( j1 ), new ShortAtom( i2 ), new ShortAtom( j2 ), new ShortAtom( absFlags ) } ); } /** Used to represent atoms (and lists) in worksheets formulas. * The representation must be supported by Operator.parseFormula(), * this is related interfaces. * To be overrided by implementations. * @param sb Buffer to write to. To get a string use toFormulaString() */ public void toFormulaBuffer( StringBuffer sb ) { sb.append( rangeAddress( i1,j1, i2, j2, absFlags ) ); }// public void toValueBuffer( StringBuffer sb, int format ) {// LispObject value = getReferredValue();// value.toValueBuffer( sb, format );// }// public int typeNumber() { return TYPE_REFERENCE; } public LispObject cloneReferences() { return new Reference( i1,j1,i2,j2,absFlags ); // for immutable items } /** * Description of the Method * *@param j Description of the Parameter *@return Description of the Return Value */ public static String columnName(int j) { StringBuffer name = new StringBuffer(2); final int nn = 'Z' - 'A' + 1; int n1 = j / nn; if (n1 > 0) { name.append((char) ('A' + n1 - 1)); } j %= nn; name.append((char) ('A' + j)); return name.toString(); } public static String cellAddress(int i, int j, int absolute) { StringBuffer sb = new StringBuffer(10); if ((absolute & ABS_J1) != 0) { sb.append('$'); } sb.append(columnName(j)); if ((absolute & ABS_I1) != 0) { sb.append('$'); } sb.append(String.valueOf(i + 1)); return sb.toString(); } public static String rangeAddress(int i1, int j1, int i2, int j2, int absolute) { StringBuffer sb = new StringBuffer(cellAddress(i1, j1, absolute)); if (i1 != i2 || j1 != j2 || (absolute&0x3) != (absolute>>2)) { sb.append(':'); sb.append(cellAddress(i2, j2, absolute >> 2)); } return sb.toString(); } public static Reference parseAddress(String ss) throws FormulaParseException { byte sss[] = ss.toUpperCase().getBytes(); int ii = 0; char cc; try { byte abs = 0; final int nn = 'Z' - 'A' + 1; int col = -1; int row = 0; // read column number if (sss[0] == '$') { ii = 1; abs = ABS_J1; } while (!(
//#ifdef ISDIGIT
//# isDigit(cc = (char) (sss[ii]))
//#else
Character.isDigit(cc = (char) (sss[ii]))
//#endif
|| cc == '$')) { if (cc < 'A' || cc > 'Z') { throw new Exception(); } ii++; int ncc = cc - 'A'; // second pass if( col != -1 ) { col = (col+1) * nn + ncc; } else { col = ncc; } if (col >= nn * (nn+1)) { // only 2 chars in column name allowed throw new Exception(); } // only 2 chars in column name are allowed } if( col < 0 ) { throw new Exception(); } // read row number if (cc == '$') { ii++; abs |= ABS_I1; } while (ii < sss.length &&
//#ifdef ISDIGIT
//# isDigit(cc = (char) (sss[ii]))
//#else
Character.isDigit(cc = (char) (sss[ii]))
//#endif
) { row *= 10; row += (short) (cc - '0'); ii++; } row--; if (row < 0) { throw new Exception(); } if (ii == sss.length) { return new Reference(row, col, row, col, abs|(abs<<2)); } if (cc == ':') { // ii++; if (ss.indexOf(':', ii + 1) != -1) { // more then 1 occurency of ':' throw new Exception(); } Reference rrr = parseAddress(ss.substring(ii + 1)); return new Reference(row,col,rrr.i1,rrr.j1,((rrr.absFlags << 2) | abs)); } // there are characters after digits if (ii != sss.length) { throw new Exception(); } } catch (Exception e) { debug( "exception catched:" ); debug( e.getMessage() ); } throw new FormulaParseException("illegal cell address [" + ss + "]"); } // returns true if changed public LispObject shiftReferences(int I1, int J1, int dI, int dJ) { boolean rr;// boolean rr1 = false;// boolean rr2 = false; boolean inter = false;// for (int i = 0; i < funcargs.length; i++) {//// rr = rr || funcargs[i].shiftReferences(I1, J1, dI, dJ); ! error !// rr1 = funcargs[i].shiftReferences(I1, J1, dI, dJ);// rr = rr || rr1; //!!! see below// }// int i1 = this.i1;
int j1 = this.j1;
int i2 = this.i2;
int j2 = this.j2;
if (dI < 0) { if (i1 >= I1 && i2 < I1 - dI) { // range within deleted area
return new Reference(i1,j1,i2,j2,absFlags|BAD_REF); } inter = Reference.intersect(i1, j1, i2, j2, I1, J1, (short) (I1 - dI), j2); // check _before_ deleting if (i1 >= I1 - dI) { i1 += dI; } else if (i1 > I1) { i1 = I1; } if (i2 >= I1 - dI) { i2 += dI; } else if (i2 > I1) { i2 = I1; } } else if (dI > 0) { if (i1 >= I1) { i1 += dI; } if (i2 >= I1) { i2 += dI; } inter = Reference.intersect(i1, j1, i2, j2, I1, J1, I1 + dI, j2); // check _after_ inserting } // dI = 0 if (dJ < 0) { if (j1 >= J1 && j2 < J1 - dJ) { return new Reference(i1,j1,i2,j2,absFlags|BAD_REF);
} inter = Reference.intersect(i1, j1, i2, j2, I1, J1, i2, J1 - dJ); // check _before_ deleting if (j1 >= J1 - dJ) { j1 += dJ; } else if (j1 > J1) { j1 = J1; } if (j2 >= J1 - dJ) { j2 += dJ; } else if (j2 > J1) { j2 = J1; } } else if (dJ > 0) { if (j1 >= J1) { j1 += dJ; } if (j2 >= J1) { j2 += dJ; } inter = Reference.intersect(i1, j1, i2, j2, I1, J1, i2, J1 + dJ); } // dJ = 0 rr = inter || i1 != this.i1 || j1 != this.j1 || i2 != this.i2 || j2 != this.j2; // formula has changed ?
if(rr)
return new Reference(i1,j1,i2,j2,absFlags);
// no changes return this; } /** * shifts references according to absolute flags (being used in copy/paste operations) * *@param di Description of the Parameter *@param dj Description of the Parameter *@return true if reference changed (not formula but refers to othe cell), needs value recalculation */ public LispObject moveReferences(int di, int dj) { boolean rr;
int i1 = this.i1; int j1 = this.j1;
int i2 = this.i2;
int j2 = this.j2;
if ((absFlags & ABS_I1) == 0) { i1 += di; } if ((absFlags & ABS_J1) == 0) { j1 += dj; } if ((absFlags & ABS_I2) == 0) { i2 += di; } if ((absFlags & ABS_J2) == 0) { j2 += dj; } rr = (absFlags & (ABS_I1 | ABS_J1 | ABS_I2 | ABS_J2)) != (ABS_I1 | ABS_J1 | ABS_I2 | ABS_J2);
// formula has changed ?
if(rr)
return new Reference(i1,j1,i2,j2,absFlags);
// no changes
return this;
}
public static final boolean intersect(
int x1, int y1, int x2, int y2,
int xx1, int yy1, int xx2, int yy2) {
int xxx1 = x1 > xx1 ? x1 : xx1;
int xxx2 = x2 < xx2 ? x2 : xx2;
int yyy1 = y1 > yy1 ? y1 : yy1;
int yyy2 = y2 < yy2 ? y2 : yy2;
return xxx1 < xxx2 && yyy1 < yyy2;
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -