void OnDoOperationClicked(object o, EventArgs args) { if (dataBook.NPages == 0) { return; } DataView dv = ((DataViewDisplay)dataBook.CurrentPageWidget).View; // get the operands as a byte array byte[] byteArray = null; try { byteArray = ParseOperand(); } catch (FormatException e) { ErrorAlert ea = new ErrorAlert(Catalog.GetString("Error in Operand"), e.Message, null); ea.Run(); ea.Destroy(); return; } /// get the range to apply the operation to Util.Range range = dv.Selection; if (range.IsEmpty()) { Util.Range bbRange = dv.Buffer.Range; range.Start = dv.CursorOffset; range.End = range.Start + byteArray.Length - 1; range.Intersect(bbRange); } // don't allow buffer modification while the operation is perfoming dv.Buffer.ModifyAllowed = false; dv.Buffer.FileOperationsAllowed = false; BitwiseOperation bo = new BitwiseOperation(dv.Buffer, byteArray, range, (OperationType)OperationComboBox.Active, Services.UI.Progress.NewCallback(), BitwiseOperationAsyncCallback, true); // start operation thread Thread boThread = new Thread(bo.OperationThread); boThread.IsBackground = true; boThread.Start(); }
/// <summary> /// Adds pattern match highlights to an area group before it is rendered /// </summary> protected virtual void BeforeRender(AreaGroup ag) { if (!active) { return; } Util.Range sel = ag.Selection; if (sel.IsEmpty() || sel.Size > 512) { return; } int nrows; Util.Range view = ag.GetViewRange(out nrows); findStrategy.Buffer = ag.Buffer; findStrategy.Position = view.Start; findStrategy.Pattern = ag.Buffer.RangeToByteArray(sel); // Merge overlapping matches Util.Range match; Util.Range currentHighlight = new Util.Range(); while ((match = findStrategy.FindNext(view.End)) != null) { if (currentHighlight.End >= match.Start) { currentHighlight.End = match.End; } else { ag.AddHighlight(currentHighlight.Start, currentHighlight.End, Drawer.HighlightType.PatternMatch); currentHighlight = match; } } ag.AddHighlight(currentHighlight.Start, currentHighlight.End, Drawer.HighlightType.PatternMatch); }
protected override void DoOperation() { byteBuffer.BeginActionChaining(); if (range.IsEmpty()) { return; } // create the operand array // this is either the original byte array // or a new array containing multiple copies of the original byte[] operandArray; if (byteArray.Length > 0) { long numberOfRepetitions = range.Size / byteArray.Length; // too many repetitions... create new array if (numberOfRepetitions > 1024) { int len = ((4096 / byteArray.Length) + 1) * byteArray.Length; operandArray = new byte[len]; FillWithPattern(operandArray, byteArray); } else // use old array { operandArray = byteArray; } } else // we have no operand eg when the operation is a NOT { operandArray = new byte[4096]; } // the array to keep the results of the operation byte[] resultArray = new byte[operandArray.Length]; long left = range.Size; currentOffset = range.Start; while (left > 0 && !cancelled) { int min = (int)((left < resultArray.Length) ? left : resultArray.Length); // fill result array // ...more efficient way needed, perhaps implement bb.Read for (int i = 0; i < min; i++) { resultArray[i] = byteBuffer[currentOffset + i]; } // perform the operation on the data DoOperation(resultArray, operandArray, min); lock (byteBuffer.LockObj) { byteBuffer.ModifyAllowed = true; // write the changed data back byteBuffer.Replace(currentOffset, currentOffset + min - 1, resultArray, 0, min); byteBuffer.ModifyAllowed = false; } currentOffset += min; left -= min; } }