App-SocialCalc-Multiplayer

 view release on metacpan or  search on metacpan

socialcalc/socialcalc-3.js  view on Meta::CPAN

   //    calccheckdone, calclist length [once per recalc]
   //    calcstep, {coord: coord, total: calclist length, count: count} [0 or more times per recalc]
   //    calcloading, {sheetname: name-of-sheet}
   //    calcserverfunc, {funcname: name-of-function, coord: coord, total: calclist length, count: count}
   //    calcfinished, time in milliseconds [once per recalc]
   //
   // During commands, data is SocialCalc.SheetCommandInfo.
   // These values for status and arg are:
   //
   //    cmdstart, cmdstr
   //    cmdend
   //

   this.statuscallback = null; // routine called with cmdstart, calcstart, etc., status and args:
                                // sheet.statuscallback(data, status, arg, params)
   this.statuscallbackparams = null; // parameters passed to that routine

   }

//
// SocialCalc.ResetSheet(sheet)
//
// Resets (and/or initializes) sheet data values.
// 

SocialCalc.ResetSheet = function(sheet, reload) {

   // properties:

   sheet.cells = {}; // at least one for each non-blank cell: coord: cell-object
   sheet.attribs = // sheet attributes
      {
         lastcol: 1,
         lastrow: 1,
         defaultlayout: 0
      };
   sheet.rowattribs =
      {
         hide: {}, // access by row number
         height: {}
      };
   sheet.colattribs =
      {
         width: {}, // access by col name
         hide: {}
      };
   sheet.names={}; // Each is: {desc: "optional description", definition: "B5, A1:B7, or =formula"}
   sheet.layouts=[];
   sheet.layouthash={};
   sheet.fonts=[];
   sheet.fonthash={};
   sheet.colors=[];
   sheet.colorhash={};
   sheet.borderstyles=[];
   sheet.borderstylehash={};
   sheet.cellformats=[];
   sheet.cellformathash={};
   sheet.valueformats=[];
   sheet.valueformathash={};

   sheet.copiedfrom = ""; // if a range, then this was loaded from a saved range as clipboard content

   sheet.changes = new SocialCalc.UndoStack();

   sheet.renderneeded = false;

   sheet.changedrendervalues = true; // if true, spans and/or fonts have changed (set by ExecuteSheetCommand & GetStyle)

   sheet.recalcchangedavalue = false; // true if a recalc resulted in a change to a cell's calculated value

   }

// Methods:

SocialCalc.Sheet.prototype.ResetSheet = function() {SocialCalc.ResetSheet(this);};
SocialCalc.Sheet.prototype.AddCell = function(newcell) {return this.cells[newcell.coord]=newcell;};
SocialCalc.Sheet.prototype.GetAssuredCell = function(coord) {
   return this.cells[coord] || this.AddCell(new SocialCalc.Cell(coord));
   };
SocialCalc.Sheet.prototype.ParseSheetSave = function(savedsheet) {SocialCalc.ParseSheetSave(savedsheet,this);};
SocialCalc.Sheet.prototype.CellFromStringParts = function(cell, parts, j) {return SocialCalc.CellFromStringParts(this, cell, parts, j);};
SocialCalc.Sheet.prototype.CreateSheetSave = function(range, canonicalize) {return SocialCalc.CreateSheetSave(this, range, canonicalize);};
SocialCalc.Sheet.prototype.CellToString = function(cell) {return SocialCalc.CellToString(this, cell);};
SocialCalc.Sheet.prototype.CanonicalizeSheet = function(full) {return SocialCalc.CanonicalizeSheet(this, full);};
SocialCalc.Sheet.prototype.EncodeCellAttributes = function(coord) {return SocialCalc.EncodeCellAttributes(this, coord);};
SocialCalc.Sheet.prototype.EncodeSheetAttributes = function() {return SocialCalc.EncodeSheetAttributes(this);};
SocialCalc.Sheet.prototype.DecodeCellAttributes = function(coord, attribs, range) {return SocialCalc.DecodeCellAttributes(this, coord, attribs, range);};
SocialCalc.Sheet.prototype.DecodeSheetAttributes = function(attribs) {return SocialCalc.DecodeSheetAttributes(this, attribs);};

SocialCalc.Sheet.prototype.ScheduleSheetCommands = function(cmd, saveundo, isRemote) {return SocialCalc.ScheduleSheetCommands(this, cmd, saveundo, isRemote);};
SocialCalc.Sheet.prototype.SheetUndo = function() {return SocialCalc.SheetUndo(this);};
SocialCalc.Sheet.prototype.SheetRedo = function() {return SocialCalc.SheetRedo(this);};
SocialCalc.Sheet.prototype.CreateAuditString = function() {return SocialCalc.CreateAuditString(this);};
SocialCalc.Sheet.prototype.GetStyleNum = function(atype, style) {return SocialCalc.GetStyleNum(this, atype, style);};
SocialCalc.Sheet.prototype.GetStyleString = function(atype, num) {return SocialCalc.GetStyleString(this, atype, num);};
SocialCalc.Sheet.prototype.RecalcSheet = function() {return SocialCalc.RecalcSheet(this);};

//
// Sheet save format:
//
// linetype:param1:param2:...
//
// Linetypes are:
//
//    version:versionname - version of this format. Currently 1.4.
//
//    cell:coord:type:value...:type:value... - Types are as follows:
//
//       v:value - straight numeric value
//       t:value - straight text/wiki-text in cell, encoded to handle \, :, newlines
//       vt:fulltype:value - value with value type/subtype
//       vtf:fulltype:value:formulatext - formula resulting in value with value type/subtype, value and text encoded
//       vtc:fulltype:value:valuetext - formatted text constant resulting in value with value type/subtype, value and text encoded
//       vf:fvalue:formulatext - formula resulting in value, value and text encoded (obsolete: only pre format version 1.1)
//          fvalue - first char is "N" for numeric value, "T" for text value, "H" for HTML value, rest is the value
//       e:errortext - Error text. Non-blank means formula parsing/calculation results in error.
//       b:topborder#:rightborder#:bottomborder#:leftborder# - border# in sheet border list or blank if none
//       l:layout# - number in cell layout list
//       f:font# - number in sheet fonts list
//       c:color# - sheet color list index for text
//       bg:color# - sheet color list index for background color
//       cf:format# - sheet cell format number for explicit format (align:left, etc.)
//       cvf:valueformat# - sheet cell value format number (obsolete: only pre format v1.2)
//       tvf:valueformat# - sheet cell text value format number
//       ntvf:valueformat# - sheet cell non-text value format number
//       colspan:numcols - number of columns spanned in merged cell
//       rowspan:numrows - number of rows spanned in merged cell
//       cssc:classname - name of CSS class to be used for cell when published instead of one calculated here
//       csss:styletext - explicit CSS style information, encoded to handle :, etc.
//       mod:allow - if "y" allow modification of cell for live "view" recalc
//       comment:value - encoded text of comment for this cell (added in v1.5)
//
//    col:
//       w:widthval - number, "auto" (no width in <col> tag), number%, or blank (use default)
//       hide: - yes/no, no is assumed if missing
//    row:
//       hide - yes/no, no is assumed if missing
//
//    sheet:
//       c:lastcol - number
//       r:lastrow - number
//       w:defaultcolwidth - number, "auto", number%, or blank (default->80)
//       h:defaultrowheight - not used
//       tf:format# - cell format number for sheet default for text values
//       ntf:format# - cell format number for sheet default for non-text values (i.e., numbers)
//       layout:layout# - default cell layout number in cell layout list
//       font:font# - default font number in sheet font list
//       vf:valueformat# - default number value format number in sheet valueformat list (obsolete: only pre format version 1.2)
//       ntvf:valueformat# - default non-text (number) value format number in sheet valueformat list
//       tvf:valueformat# - default text value format number in sheet valueformat list
//       color:color# - default number for text color in sheet color list
//       bgcolor:color# - default number for background color in sheet color list
//       circularreferencecell:coord - cell coord with a circular reference
//       recalc:value - on/off (on is default). If not "off", appropriate changes to the sheet cause a recalc
//       needsrecalc:value - yes/no (no is default). If "yes", formula values are not up to date
//
//    name:name:description:value - name definition, name in uppercase, with value being "B5", "A1:B7", or "=formula";
//                                  description and value are encoded.
//    font:fontnum:value - text of font definition (style weight size family) for font fontnum
//                         "*" for "style weight", size, or family, means use default (first look to sheet, then builtin)
//    color:colornum:rgbvalue - text of color definition (e.g., rgb(255,255,255)) for color colornum
//    border:bordernum:value - text of border definition (thickness style color) for border bordernum
//    layout:layoutnum:value - text of vertical alignment and padding style for cell layout layoutnum (* for default):
//                             vertical-alignment:vavalue;padding:topval rightval bottomval leftval;
//    cellformat:cformatnum:value - text of cell alignment (left/center/right) for cellformat cformatnum
//    valueformat:vformatnum:value - text of number format (see FormatValueForDisplay) for valueformat vformatnum (changed in v1.2)
//    clipboardrange:upperleftcoord:bottomrightcoord - ignored -- from wikiCalc
//    clipboard:coord:type:value:... - ignored -- from wikiCalc
//
// If this is clipboard contents, then there is also information to facilitate pasting:
//
//    copiedfrom:upperleftcoord:bottomrightcoord - range from which this was copied
//

// Functions:

SocialCalc.ParseSheetSave = function(savedsheet,sheetobj) {

   var lines=savedsheet.split(/\r\n|\n/);
   var parts=[];
   var line;
   var i, j, t, v, coord, cell, attribs, name;
   var scc = SocialCalc.Constants;

   for (i=0;i<lines.length;i++) {
      line=lines[i];
      parts = line.split(":");
      switch (parts[0]) {
         case "cell":
            cell=sheetobj.GetAssuredCell(parts[1]);
            j=2;
            sheetobj.CellFromStringParts(cell, parts, j);
            break;

         case "col":
            coord=parts[1];
            j=2;
            while (t=parts[j++]) {
               switch (t) {
                  case "w":
                     sheetobj.colattribs.width[coord]=parts[j++]; // must be text - could be auto or %, etc.
                     break;
                  case "hide":
                     sheetobj.colattribs.hide[coord]=parts[j++];
                     break;
                  default:
                     throw scc.s_pssUnknownColType+" '"+t+"'";
                     break;
                  }
               }
            break;

         case "row":
            coord=parts[1]-0;
            j=2;
            while (t=parts[j++]) {
               switch (t) {
                  case "h":
                     sheetobj.rowattribs.height[coord]=parts[j++]-0;
                     break;
                  case "hide":
                     sheetobj.rowattribs.hide[coord]=parts[j++];
                     break;
                  default:
                     throw scc.s_pssUnknownRowType+" '"+t+"'";
                     break;
                  }
               }
            break;

socialcalc/socialcalc-3.js  view on Meta::CPAN

                     break;
                  case "recalc":
                     attribs.recalc=parts[j++];
                     break;
                  case "needsrecalc":
                     attribs.needsrecalc=parts[j++];
                     break;
                  default:
                     j+=1;
                     break;
                  }
               }
            break;

         case "name":
            name = SocialCalc.decodeFromSave(parts[1]).toUpperCase();
            sheetobj.names[name] = {desc: SocialCalc.decodeFromSave(parts[2])};
            sheetobj.names[name].definition = SocialCalc.decodeFromSave(parts[3]);
            break;

         case "layout":
            parts=lines[i].match(/^layout\:(\d+)\:(.+)$/); // layouts can have ":" in them
            sheetobj.layouts[parts[1]-0]=parts[2];
            sheetobj.layouthash[parts[2]]=parts[1]-0;
            break;

         case "font":
            sheetobj.fonts[parts[1]-0]=parts[2];
            sheetobj.fonthash[parts[2]]=parts[1]-0;
            break;

         case "color":
            sheetobj.colors[parts[1]-0]=parts[2];
            sheetobj.colorhash[parts[2]]=parts[1]-0;
            break;

         case "border":
            sheetobj.borderstyles[parts[1]-0]=parts[2];
            sheetobj.borderstylehash[parts[2]]=parts[1]-0;
            break;

         case "cellformat":
            v=SocialCalc.decodeFromSave(parts[2]);
            sheetobj.cellformats[parts[1]-0]=v;
            sheetobj.cellformathash[v]=parts[1]-0;
            break;

         case "valueformat":
            v=SocialCalc.decodeFromSave(parts[2]);
            sheetobj.valueformats[parts[1]-0]=v;
            sheetobj.valueformathash[v]=parts[1]-0;
            break;

         case "version":
            break;

         case "copiedfrom":
            sheetobj.copiedfrom = parts[1]+":"+parts[2];
            break;

         case "clipboardrange": // in save versions up to 1.3. Ignored.
         case "clipboard":
            break;

         case "":
            break;

         default:
alert(scc.s_pssUnknownLineType+" '"+parts[0]+"'");
            throw scc.s_pssUnknownLineType+" '"+parts[0]+"'";
            break;
         }
      parts = null;
      }

   }

//
// SocialCalc.CellFromStringParts(sheet, cell, parts, j)
//
// Takes string that has been split by ":" in parts, starting at item j,
// and fills in cell assuming save format.
//

SocialCalc.CellFromStringParts = function(sheet, cell, parts, j) {

   var cell, t, v;

   while (t=parts[j++]) {
      switch (t) {
         case "v":
            cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
            cell.datatype="v";
            cell.valuetype="n";
            break;
         case "t":
            cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
            cell.datatype="t";
            cell.valuetype=SocialCalc.Constants.textdatadefaulttype; 
            break;
         case "vt":
            v=parts[j++];
            cell.valuetype=v;
            if (v.charAt(0)=="n") {
               cell.datatype="v";
               cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
               }
            else {
               cell.datatype="t";
               cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
               }
            break;
         case "vtf":
            v=parts[j++];
            cell.valuetype=v;
            if (v.charAt(0)=="n") {
               cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
               }
            else {
               cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
               }
            cell.formula=SocialCalc.decodeFromSave(parts[j++]);

socialcalc/socialcalc-3.js  view on Meta::CPAN

         case "f":
            cell.font=parts[j++]-0;
            break;
         case "c":
            cell.color=parts[j++]-0;
            break;
         case "bg":
            cell.bgcolor=parts[j++]-0;
            break;
         case "cf":
            cell.cellformat=parts[j++]-0;
            break;
         case "ntvf":
            cell.nontextvalueformat=parts[j++]-0;
            break;
         case "tvf":
            cell.textvalueformat=parts[j++]-0;
            break;
         case "colspan":
            cell.colspan=parts[j++]-0;
            break;
         case "rowspan":
            cell.rowspan=parts[j++]-0;
            break;
         case "cssc":
            cell.cssc=parts[j++];
            break;
         case "csss":
            cell.csss=SocialCalc.decodeFromSave(parts[j++]);
            break;
         case "mod":
            j+=1;
            break;
         case "comment":
            cell.comment=SocialCalc.decodeFromSave(parts[j++]);
            break;
         default:
            throw SocialCalc.Constants.s_cfspUnknownCellType+" '"+t+"'";
            break;
         }
      }

   }


SocialCalc.sheetfields = ["defaultrowheight", "defaultcolwidth", "circularreferencecell", "recalc", "needsrecalc"];
SocialCalc.sheetfieldsshort = ["h", "w", "circularreferencecell", "recalc", "needsrecalc"];

SocialCalc.sheetfieldsxlat = ["defaulttextformat", "defaultnontextformat",
                              "defaulttextvalueformat", "defaultnontextvalueformat",
                              "defaultcolor", "defaultbgcolor", "defaultfont", "defaultlayout"];
SocialCalc.sheetfieldsxlatshort = ["tf", "ntf", "tvf", "ntvf", "color", "bgcolor", "font", "layout"];
SocialCalc.sheetfieldsxlatxlt = ["cellformat", "cellformat", "valueformat", "valueformat",
                                  "color", "color", "font", "layout"];

//
// sheetstr = SocialCalc.CreateSheetSave(sheetobj, range, canonicalize)
//
// Creates a text representation of the sheetobj data.
// If the range is present then only those cells are saved
// (as clipboard data with "copiedfrom" set).
//

SocialCalc.CreateSheetSave = function(sheetobj, range, canonicalize) {

   var cell, cr1, cr2, row, col, coord, attrib, line, value, formula, i, t, r, b, l, name, blanklen;
   var result=[];

   var prange;

   sheetobj.CanonicalizeSheet(canonicalize || SocialCalc.Constants.doCanonicalizeSheet);
   var xlt = sheetobj.xlt;

   if (range) {
      prange = SocialCalc.ParseRange(range);
      }
   else {
      prange = {cr1: {row: 1, col:1},
                cr2: {row: xlt.maxrow, col: xlt.maxcol}};
      }
   cr1 = prange.cr1;
   cr2 = prange.cr2;

   result.push("version:1.5");

   for (row=cr1.row; row <= cr2.row; row++) {
      for (col=cr1.col; col <= cr2.col; col++) {
         coord = SocialCalc.crToCoord(col, row);
         cell=sheetobj.cells[coord];
         if (!cell) continue;
         line=sheetobj.CellToString(cell);
         if (line.length==0) continue; // ignore completely empty cells
         line="cell:"+coord+line;
         result.push(line);
         }
      }

   for (col=1; col <= xlt.maxcol; col++) {
      coord = SocialCalc.rcColname(col);
      if (sheetobj.colattribs.width[coord])
         result.push("col:"+coord+":w:"+sheetobj.colattribs.width[coord]);
      if (sheetobj.colattribs.hide[coord])
         result.push("col:"+coord+":hide:"+sheetobj.colattribs.hide[coord]);
      }

   for (row=1; row <= xlt.maxrow; row++) {
      if (sheetobj.rowattribs.height[row])
         result.push("row:"+row+":h:"+sheetobj.rowattribs.height[row]);
      if (sheetobj.rowattribs.hide[row])
         result.push("row:"+row+":hide:"+sheetobj.rowattribs.hide[row]);
      }

   line="sheet:c:"+xlt.maxcol+":r:"+xlt.maxrow;

   for (i=0; i<SocialCalc.sheetfields.length; i++) { // non-xlated values
      value = SocialCalc.encodeForSave(sheetobj.attribs[SocialCalc.sheetfields[i]]);
      if (value) line+=":"+SocialCalc.sheetfieldsshort[i]+":"+value;
      }
   for (i=0; i<SocialCalc.sheetfieldsxlat.length; i++) { // xlated values
      value = sheetobj.attribs[SocialCalc.sheetfieldsxlat[i]];
      if (value) line+=":"+SocialCalc.sheetfieldsxlatshort[i]+":"+xlt[SocialCalc.sheetfieldsxlatxlt[i]+"sxlat"][value];

socialcalc/socialcalc-3.js  view on Meta::CPAN

   sci.timerobj = null;

   while (!sci.parseobj.EOF()) { // go through all commands (separated by newlines)

      errortext = SocialCalc.ExecuteSheetCommand(sci.sheetobj, sci.parseobj, sci.saveundo);
      if (errortext) alert(errortext);

      sci.parseobj.NextLine();

      if (sci.cmdextensionbusy.length > 0) { // forced wait
         if (sci.sheetobj.statuscallback) { // notify others if requested
            sci.sheetobj.statuscallback(sci, "cmdextension", sci.cmdextensionbusy, sci.sheetobj.statuscallbackparams);
            }
         return;
         }

      if (((new Date()) - starttime) >= sci.maxtimeslice) { // if taking too long, give up CPU for a while
         sci.timerobj = window.setTimeout(SocialCalc.SheetCommandsTimerRoutine, sci.timerdelay);
         return;
         }
      }

   if (sci.sheetobj.statuscallback) { // notify others if requested
      sci.sheetobj.statuscallback(sci, "cmdend", "", sci.sheetobj.statuscallbackparams);
      }

   }

SocialCalc.ResumeFromCmdExtension = function() {

   var sci = SocialCalc.SheetCommandInfo;

   sci.cmdextensionbusy = "";

   SocialCalc.SheetCommandsTimerRoutine();

}

//
// errortext = SocialCalc.ExecuteSheetCommand(sheet, cmd, saveundo)
//
// cmd is a SocialCalc.Parse object.
//
// Executes commands that modify the sheet data.
// Sets sheet "needsrecalc" as needed.
// Sets sheet "changedrendervalues" as needed.
//
// The cmd string may be multiple commands, separated by newlines. In that case
// only one "step" is put on the undo stack representing all the commands.
// Note that because of this, in "set A1 text ..." and "set A1 comment ..." text is
// treated as encoded (newline => \n, \ => \b, : => \c).
//
// The commands are in the forms:
//
//    set sheet attributename value (plus lastcol and lastrow)
//    set 22 attributename value
//    set B attributename value
//    set A1 attributename value1 value2... (see each attribute in code for details)
//    set A1:B5 attributename value1 value2...
//    erase/copy/cut/paste/fillright/filldown A1:B5 all/formulas/format
//    loadclipboard save-encoded-clipboard-data
//    clearclipboard
//    merge C3:F3
//    unmerge C3
//    insertcol/insertrow C5
//    deletecol/deleterow C5:E7
//    movepaste/moveinsert A1:B5 A8 all/formulas/format (if insert, destination must be in same rows or columns or else paste done)
//    sort cr1:cr2 col1 up/down col2 up/down col3 up/down
//    name define NAME definition
//    name desc NAME description
//    name delete NAME
//    recalc
//    redisplay
//    changedrendervalues
//    startcmdextension extension rest-of-command
//
// If saveundo is true, then undo information is saved in sheet.changes.
//

SocialCalc.ExecuteSheetCommand = function(sheet, cmd, saveundo) {

   var cmdstr, cmd1, rest, what, attrib, num, pos, pos2, errortext, undostart, val;
   var cr1, cr2, col, row, cr, cell, newcell;
   var fillright, rowstart, colstart, crbase, rowoffset, coloffset, basecell;
   var clipsheet, cliprange, numcols, numrows, attribtable;
   var colend, rowend, newcolstart, newrowstart, newcolend, newrowend, rownext, colnext, colthis, cellnext;
   var lastrow, lastcol, rowbefore, colbefore, oldformula, oldcr;
   var cols, dirs, lastsortcol, i, sortlist, sortcells, sortvalues, sorttypes;
   var sortfunction, slen, valtype, originalrow, sortedcr;
   var name, v1, v2;
   var cmdextension;

   var attribs = sheet.attribs;
   var changes = sheet.changes;
   var cellProperties = SocialCalc.CellProperties;
   var scc = SocialCalc.Constants;

   var ParseRange =
      function() {
         var prange = SocialCalc.ParseRange(what);
         cr1 = prange.cr1;
         cr2 = prange.cr2;
         if (cr2.col > attribs.lastcol) attribs.lastcol = cr2.col;
         if (cr2.row > attribs.lastrow) attribs.lastrow = cr2.row;
         };

   errortext = "";

   cmdstr = cmd.RestOfStringNoMove();
   if (saveundo) {
      sheet.changes.AddDo(cmdstr);
      }

   cmd1 = cmd.NextToken();

   switch (cmd1) {

      case "set":
         what = cmd.NextToken();
         attrib = cmd.NextToken();
         rest = cmd.RestOfString();
         undostart = "set "+what+" "+attrib;

socialcalc/socialcalc-3.js  view on Meta::CPAN

                     cell.csss = rest;
                     }
                  else if (attrib=="mod") {
                     rest = rest.replace(/[^yY]/g, "").toLowerCase();
                     cell.mod = rest;
                     }
                  else if (attrib=="comment") {
                     cell.comment = SocialCalc.decodeFromSave(rest);
                     }
                  else {
                     errortext = scc.s_escUnknownSetCoordCmd+cmdstr;
                     }
                  }
               }

            }
         break;

      case "merge":
         sheet.renderneeded = true;
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         ParseRange();
         cell=sheet.GetAssuredCell(cr1.coord);
         if (saveundo) changes.AddUndo("unmerge "+cr1.coord);

         if (cr2.col > cr1.col) cell.colspan = cr2.col - cr1.col + 1;
         else delete cell.colspan;
         if (cr2.row > cr1.row) cell.rowspan = cr2.row - cr1.row + 1;
         else delete cell.rowspan;

         sheet.changedrendervalues = true;

         break;

      case "unmerge":
         sheet.renderneeded = true;
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         ParseRange();
         cell=sheet.GetAssuredCell(cr1.coord);
         if (saveundo) changes.AddUndo("merge "+cr1.coord+":"+SocialCalc.crToCoord(cr1.col+(cell.colspan||1)-1, cr1.row+(cell.rowspan||1)-1));

         delete cell.colspan;
         delete cell.rowspan;

         sheet.changedrendervalues = true;

         break;

      case "erase":
      case "cut":
         sheet.renderneeded = true;
         sheet.changedrendervalues = true;
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         ParseRange();

         if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
         if (cmd1=="cut") { // save copy of whole thing before erasing
            if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
            SocialCalc.Clipboard.clipboard = SocialCalc.CreateSheetSave(sheet, what);
            }

         for (row = cr1.row; row <= cr2.row; row++) {
            for (col = cr1.col; col <= cr2.col; col++) {
               cr = SocialCalc.crToCoord(col, row);
               cell=sheet.GetAssuredCell(cr);
               if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
               if (rest=="all") {
                  delete sheet.cells[cr];
                  }
               else if (rest == "formulas") {
                  cell.datavalue = "";
                  cell.datatype = null;
                  cell.formula = "";
                  cell.valuetype = "b";
                  delete cell.errors;
                  delete cell.displaystring;
                  delete cell.parseinfo;
                  if (cell.comment) { // comments are considered content for erasing
                     delete cell.comment;
                     }
                  }
               else if (rest == "formats") {
                  newcell = new SocialCalc.Cell(cr); // create a new cell without attributes
                  newcell.datavalue = cell.datavalue; // copy existing values
                  newcell.datatype = cell.datatype;
                  newcell.formula = cell.formula;
                  newcell.valuetype = cell.valuetype;
                  if (cell.comment) {
                     newcell.comment = cell.comment;
                     }
                  sheet.cells[cr] = newcell; // replace
                  }
               }
            }
         attribs.needsrecalc = "yes";
         break;

      case "fillright":
      case "filldown":
         sheet.renderneeded = true;
         sheet.changedrendervalues = true;
         if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         ParseRange();
         if (cmd1 == "fillright") {
            fillright = true;
            rowstart = cr1.row;
            colstart = cr1.col + 1;
            }
         else {
            fillright = false;
            rowstart = cr1.row + 1;
            colstart = cr1.col;
            }
         for (row = rowstart; row <= cr2.row; row++) {
            for (col = colstart; col <= cr2.col; col++) {
               cr = SocialCalc.crToCoord(col, row);
               cell=sheet.GetAssuredCell(cr);
               if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
               if (fillright) {
                  crbase = SocialCalc.crToCoord(cr1.col, row);
                  coloffset = col - colstart + 1;
                  rowoffset = 0;
                  }
               else {
                  crbase = SocialCalc.crToCoord(col, cr1.row);
                  coloffset = 0;
                  rowoffset = row - rowstart + 1;
                  }
               basecell = sheet.GetAssuredCell(crbase);
               if (rest == "all" || rest == "formats") {
                  for (attrib in cellProperties) {
                     if (cellProperties[attrib] == 1) continue; // copy only format attributes
                     if (typeof basecell[attrib] === undefined || cellProperties[attrib] == 3) {
                        delete cell[attrib];
                        }
                     else {
                        cell[attrib] = basecell[attrib];
                        }
                     }
                  }
               if (rest == "all" || rest == "formulas") {
                  cell.datavalue = basecell.datavalue;
                  cell.datatype = basecell.datatype;            
                  cell.valuetype = basecell.valuetype;
                  if (cell.datatype == "f") { // offset relative coords, even in sheet references
                     cell.formula = SocialCalc.OffsetFormulaCoords(basecell.formula, coloffset, rowoffset);
                     }
                  else {
                     cell.formula = basecell.formula;
                     }
                  delete cell.parseinfo;
                  cell.errors = basecell.errors;
                  }
               delete cell.displaystring;
               }
            }

         attribs.needsrecalc = "yes";
         break;

      case "copy":
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
         SocialCalc.Clipboard.clipboard = SocialCalc.CreateSheetSave(sheet, what);
         break;

      case "loadclipboard":
         rest = cmd.RestOfString();
         if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
         SocialCalc.Clipboard.clipboard = SocialCalc.decodeFromSave(rest);
         break;

      case "clearclipboard":
         if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
         SocialCalc.Clipboard.clipboard = "";
         break;

      case "paste":
         sheet.renderneeded = true;
         sheet.changedrendervalues = true;
         if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
         what = cmd.NextToken();
         rest = cmd.RestOfString();
         ParseRange();
         if (!SocialCalc.Clipboard.clipboard) {
            break;
            }
         clipsheet = new SocialCalc.Sheet(); // load clipboard contents as another sheet
         clipsheet.ParseSheetSave(SocialCalc.Clipboard.clipboard);
         cliprange = SocialCalc.ParseRange(clipsheet.copiedfrom);
         coloffset = cr1.col - cliprange.cr1.col; // get sizes, etc.
         rowoffset = cr1.row - cliprange.cr1.row;
         numcols = cliprange.cr2.col - cliprange.cr1.col + 1;
         numrows = cliprange.cr2.row - cliprange.cr1.row + 1;
         if (cr1.col+numcols-1 > attribs.lastcol) attribs.lastcol = cr1.col+numcols-1;
         if (cr1.row+numrows-1 > attribs.lastrow) attribs.lastrow = cr1.row+numrows-1;

         for (row = cr1.row; row < cr1.row+numrows; row++) {
            for (col = cr1.col; col < cr1.col+numcols; col++) {
               cr = SocialCalc.crToCoord(col, row);
               cell=sheet.GetAssuredCell(cr);
               if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
               crbase = SocialCalc.crToCoord(col-coloffset, row-rowoffset);
               basecell = clipsheet.GetAssuredCell(crbase);
               if (rest == "all" || rest == "formats") {
                  for (attrib in cellProperties) {
                     if (cellProperties[attrib] == 1) continue; // copy only format attributes
                     if (typeof basecell[attrib] === undefined || cellProperties[attrib] == 3) {
                        delete cell[attrib];
                        }
                     else {
                        attribtable = SocialCalc.CellPropertiesTable[attrib];
                        if (attribtable && basecell[attrib]) { // table indexes to expand to strings since other sheet may have diff indexes
                           cell[attrib] = sheet.GetStyleNum(attribtable, clipsheet.GetStyleString(attribtable, basecell[attrib]));
                           }
                        else { // these are not table indexes
                           cell[attrib] = basecell[attrib];
                           }
                        }
                     }
                  }
               if (rest == "all" || rest == "formulas") {
                  cell.datavalue = basecell.datavalue;
                  cell.datatype = basecell.datatype;            
                  cell.valuetype = basecell.valuetype;
                  if (cell.datatype == "f") { // offset relative coords, even in sheet references
                     cell.formula = SocialCalc.OffsetFormulaCoords(basecell.formula, coloffset, rowoffset);
                     }
                  else {
                     cell.formula = basecell.formula;
                     }
                  delete cell.parseinfo;
                  cell.errors = basecell.errors;
                  if (basecell.comment) { // comments are pasted as part of content, though not filled, etc.
                     cell.comment = basecell.comment;
                     }
                  else if (cell.comment) {
                     delete cell.comment;
                     }
                  }
               delete cell.displaystring;
               }
            }

         attribs.needsrecalc = "yes";
         break;

      case "sort": // sort cr1:cr2 col1 up/down col2 up/down col3 up/down
         sheet.renderneeded = true;

socialcalc/socialcalc-3.js  view on Meta::CPAN

      this.stack.pop();
      }
   this.stack.push({command: [], type: type, undo: []});
   if (this.maxRedo && this.stack.length > this.maxRedo) { // limit number kept as audit trail
      this.stack.shift(); // remove the extra one
      }
   if (this.maxUndo && this.stack.length > this.maxUndo) { // need to trim excess undo info
      this.stack[this.stack.length - this.maxUndo - 1].undo = []; // only need to remove one
      }
   this.tos = this.stack.length - 1;
   }

SocialCalc.UndoStack.prototype.AddDo = function() {
   var args = [];
   for (var i=0; i<arguments.length; i++) {
      if (arguments[i]!=null) args.push(arguments[i]); // ignore null or undefined
      }
   var cmd = args.join(" ");
   this.stack[this.stack.length-1].command.push(cmd);
   }

SocialCalc.UndoStack.prototype.AddUndo = function() {
   var args = [];
   for (var i=0; i<arguments.length; i++) {
      if (arguments[i]!=null) args.push(arguments[i]); // ignore null or undefined
      }
   var cmd = args.join(" ");
   this.stack[this.stack.length-1].undo.push(cmd);
   }

SocialCalc.UndoStack.prototype.TOS = function() {
   if (this.tos >= 0) return this.stack[this.tos];
   else return null;
   }

SocialCalc.UndoStack.prototype.Undo = function() {
   if (this.tos >= 0 && (!this.maxUndo || this.tos > this.stack.length - this.maxUndo - 1)) {
      this.tos -= 1;
      return true;
      }
   else {
      return false;
      }
   }

SocialCalc.UndoStack.prototype.Redo = function() {
   if (this.tos < this.stack.length-1) {
      this.tos += 1;
      return true;
      }
   else {
      return false;
      }
   }

// *************************************
//
// Clipboard Object:
//
// This is a single object.
// Stores the clipboard, which is shared by all active sheets.
// Like the undo stack, it does not persist from one editing session to another.
//
// *************************************

SocialCalc.Clipboard = {

   // properties:

   clipboard:  "" // empty or string in save format with "copiedfrom:" set to a range

   }


// *************************************
//
// RenderContext class:
//
// *************************************

SocialCalc.RenderContext = function(sheetobj) {

   var parts, num, s;
   var attribs = sheetobj.attribs;
   var scc = SocialCalc.Constants;

   // properties:

   this.sheetobj = sheetobj;
   this.hideRowsCols = false; // Rendering with panes only works with "false"
                              // !!!! Note: not implemented yet in rendering, just saved as an attribute
   this.showGrid = false;
   this.showRCHeaders = false;
   this.rownamewidth = scc.defaultRowNameWidth;
   this.pixelsPerRow = scc.defaultAssumedRowHeight;

   this.cellskip = {}; // if present, coord of cell covering this cell
   this.coordToCR = {}; // for cells starting spans, coordToCR[coord]={row:row, col:col}
   this.colwidth = []; // precomputed column widths, taking into account defaults
   this.totalwidth = 0; // precomputed total table width

   this.rowpanes = []; // for each pane, {first: firstrow, last: lastrow}
   this.colpanes = []; // for each pane, {first: firstrow, last: lastrow}
   this.maxcol=0; // max col and row to display, adding long spans, etc.
   this.maxrow=0;

   this.highlights = {}; // for each cell with special display: coord:highlightType (see this.highlightTypes)
   this.cursorsuffix = ""; // added to highlights[cr]=="cursor" to get type to lookup

   this.highlightTypes = // attributes to change when highlit
      {
         cursor: {style: scc.defaultHighlightTypeCursorStyle, className: scc.defaultHighlightTypeCursorClass},
         range: {style: scc.defaultHighlightTypeRangeStyle, className: scc.defaultHighlightTypeRangeClass},
         cursorinsertup: {style: "color:#FFF;backgroundColor:#A6A6A6;backgroundRepeat:repeat-x;backgroundPosition:top left;backgroundImage:url("+scc.defaultImagePrefix+"cursorinsertup.gif);", className: scc.defaultHighlightTypeCursorClass},
         cursorinsertleft: {style: "color:#FFF;backgroundColor:#A6A6A6;backgroundRepeat:repeat-y;backgroundPosition:top left;backgroundImage:url("+scc.defaultImagePrefix+"cursorinsertleft.gif);", className: scc.defaultHighlightTypeCursorClass},
         range2: {style: "color:#000;backgroundColor:#FFF;backgroundImage:url("+scc.defaultImagePrefix+"range2.gif);", className: ""}
      }

   this.cellIDprefix = scc.defaultCellIDPrefix; // if non-null, each cell will render with an ID

   this.defaultlinkstyle = null; // default linkstyle object (allows you to pass values to link renderer)
   this.defaultHTMLlinkstyle = {type: "html"}; // default linkstyle for standalone HTML

   // constants:

   this.defaultfontstyle = scc.defaultCellFontStyle;
   this.defaultfontsize = scc.defaultCellFontSize;
   this.defaultfontfamily = scc.defaultCellFontFamily;

   this.defaultlayout = scc.defaultCellLayout;



( run in 2.122 seconds using v1.01-cache-2.11-cpan-302cb4679cc )