Routine Debugging

Hi all,
Would be grateful to you if you could guide me about the basics to write and debug update routine/start routine.
Thanks in advance.
Arun

Hi
Follow the below steps.
1) Write "Break-Point" in your start routine and field routine where you want to trace the code.
2) Activate it and load the data via PSA.
3) After the load is done, goto monitor screen ---> Details tab ---> Processing
4) Right-click and select "Simulate Update"
5) Select the data package and press enter.
6) Press F7 twice. It will take you to the Break-Point stmt in the Start routine.
7) From there you can continue the debugging.
Open the transformation where you have written the start routine and from there, go to the menu option Extras -> Display Generated Program. It will contain the start routine you have written. Place a break point there in the code and come to the DTP Execute tab.
Here you can debug the custom --
Select Processing mode as "Serially in the dialog process (for debugging) and then click on execute button. You will now be able to debug the code you have written.
Debugging data upload in BW
Go through the below link
Tracing data transformation in SAP BW without debugging
Debugging data upload in BW
Hope this helps
regards
gaurav

Similar Messages

  • Infostructure update routine : debug problem

    Hi All,
    We have created three update routines for three corresponding infostructures. But I am not able to debug this routine. I tried to put a hard breakpoint also, but it was of no use. The Infostructure logs the changes in the sales order.
    How can I get the list of objects that are accessible in these routines?
    How can I view the values of MCVBAP and MCVBAK(communication structures) that are used in the update routines?
    How can I debug such routines?
    From where does these structures, MCVBAK and MCVBAP, get value? Are these runtime values? How much time does it take normally take for the infostructure to be updated? or is it updated immediately when the sales Order is saved?
    Thanks,
    Jiten

    Hello,
    some hopefully helpful answers:
    - the MCVBAK / MCVBAP are structures, that are built from the orderdata in the function MCV_STATISTICS_ORDER. There are two exits EXIT_SAPLMCS1_001 (header Data) and EXIT_SAPLMCS1_002 (position data) where you could fill additional user fields in these structures. Additional fields you could define in the structures MCVBAKUSR or MCVABPUSR.
    - the time that it takes to get an infostructure updates depends on it's customizing of updating (transaction OM01). the possibilities are: no update, update in V1-posting, update in V2-posting, update in batch.
    - Helpful are folling transactions: MC30 ( shows the update logs, you have to set the parameter MCL = 'X' in your userdate, see OSS - Note 77427) , MCVR (simulation of update).
    Regards Wolfgang

  • IPC Pricing routine for Product Family Margin in Quotation is not working

    Hi,
    I am working on the IPC Pricing Routine to calculate Item's Product Family Margin in the Quotation. 
    Process followed:
    Step 1:  Created a Group condition ZPFM for Product Family Margin and assigned to the pricing procedure. 
    Step 2:  Created a Value Routine to determine ZPFM's Condition Rate and Condition Value.
    Logic: 
              1.  Collect (Sum Of)  the Cost (ZSVC) and the Subtotal 3 of the items which are in same Material Group.
               2.  Assign the ZPFM Condition Value = Sum of Subtotal 3 - Cost.
    Issue:  The condition value for ZPFM is calculating correct for all line items except the last item.  I am getting some junk value always to the last item. If I delete the last time, again next last item is giving wrong value.  The calculation value in the routine debugging log (SM53) is showing correct value.  However, assigning the wrong value.  No other routines have been assigned to this condition type in the pricing procedure. 
    Routine Code:
    package stanley.pricing.userexits.val;
    import java.math.BigDecimal;
    import com.sap.spe.pricing.customizing.PricingCustomizingConstants;
    import com.sap.spe.pricing.transactiondata.PricingTransactiondataConstants;
    import com.sap.spe.pricing.transactiondata.userexit.IPricingConditionUserExit;
    import com.sap.spe.pricing.transactiondata.userexit.IPricingItemUserExit;
    import com.sap.spe.base.logging.UserexitLogger;
    import com.sap.spe.pricing.transactiondata.userexit.ValueFormulaAdapter;
    //import com.sap.spe.pricing.transactiondata.userexit.IPricingCondition;
    public class Z_CondValueRoutine730 extends  ValueFormulaAdapter{
       private static UserexitLogger uelogger =
              new UserexitLogger(Z_CondValueRoutine730.class);
      public BigDecimal overwriteConditionValue(IPricingItemUserExit pricingItem,
             IPricingConditionUserExit pricingCondition) {
      // Variable Declarations.
      BigDecimal conditionValueZCVC=PricingTransactiondataConstants.ZERO;
      BigDecimal conditionValueZCVCAccrual=PricingTransactiondataConstants.ZERO;
      BigDecimal subTotal3=PricingTransactiondataConstants.ZERO;
      BigDecimal subTotal3Accrual=PricingTransactiondataConstants.ZERO;
      if(pricingCondition.getConditionTypeName().equalsIgnoreCase("ZPFM")){
                IPricingItemUserExit[] prItems;
                prItems = pricingItem.getUserExitDocument().getUserExitItems();
                String materialGroup = pricingItem.getAttributeValue("MATL_GRP");
                uelogger.writeLogDebug("  Material Group  :"+materialGroup);
                for (int i=0;i<prItems.length;i++){
                     String materialGroup1 = prItems[i].getAttributeValue("MATL_GRP");
                     if (materialGroup1.equalsIgnoreCase(materialGroup)){
                          subTotal3 = prItems[i].getSubtotal(PricingCustomizingConstants.ConditionSubtotal.SUBTOTAL_3).getValue();
                          subTotal3Accrual = subTotal3Accrual.add(subTotal3);
                          IPricingConditionUserExit[] conditionsForCumulation = prItems[i].getUserExitConditions();
                          for (int j = 0; j < conditionsForCumulation.length; j++) {
                               if(conditionsForCumulation[j].getConditionTypeName()==null) {
                                   continue;
                               else if ( conditionsForCumulation[j].getConditionTypeName().equalsIgnoreCase("ZCVC")){
                                    conditionValueZCVC = conditionsForCumulation[j].getConditionValue().getValue();
                                    conditionValueZCVCAccrual = conditionValueZCVCAccrual.add(conditionValueZCVC);
                BigDecimal conditionValueZPFM=PricingTransactiondataConstants.ZERO;
                conditionValueZPFM = subTotal3Accrual.subtract(conditionValueZCVCAccrual);
               BigDecimal conditionRateZPFM=PricingTransactiondataConstants.ZERO;
               conditionRateZPFM = conditionValueZPFM.multiply(new BigDecimal ("100"));
              conditionRateZPFM = conditionRateZPFM.divide(subTotal3Accrual,7,BigDecimal.ROUND_FLOOR);
             uelogger.writeLogDebug(subTotal3Accrual+"-"+conditionValueZCVCAccrual+" = "+conditionValueZPFM);
             uelogger.writeLogDebug("Condition Rate  :"+conditionRateZPFM);
           pricingCondition.setConditionRateValue(conditionRateZPFM.setScale(2,BigDecimal.ROUND_HALF_UP));
           pricingCondition.setConditionValue(conditionValueZPFM.setScale(2,BigDecimal.ROUND_HALF_UP));
              return null;
           return null;

    Hi,
    I think you should change xkwert variable instead of komv-kwert.
    Standard routines does the same.
    Aslo check in SPRO settings that routine is attached and
    getting triggered by putting break-point.
    Regards,
    Vishal

  • How to debugg and put a break-point in End Routine

    Hi all,
    Can anybody suggest how to put a break point in Endroutine in BI.7
    Thanks
    DB

    Hi Bhanu,
    Please go through these links:
    How to debug abap code in update rules...routine?
    debug abap routine in infopackage
    Debugging of global transfer and update routine
    Debugging Start/Transfer routine
    And have a look at this demo video to know how to set up break points and how to debug an ABAP program in NW2004s:
    https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/9cbb7716-0a01-0010-58b1-a2ddd8361ac0?prtmode=navigate
    Hope it helps..
    Cheers,
    Habeeb

  • How to put a break point while creating a travel request in ess

    Hi to all experts,
    My requirement is to put a break point in the badi while creating a travel request in Ess.
    The badi name is TRIP_WEB_CHECK
    i tried both external and session bps
    i also tried this.
    break uname
    break-point
    and it is i check whether is triggering by throwing dump like ( divide by zero) it is triggering
    how to stop it while triggering

    Hi Bhanu,
    Please go through these links:
    How to debug abap code in update rules...routine?
    debug abap routine in infopackage
    Debugging of global transfer and update routine
    Debugging Start/Transfer routine
    And have a look at this demo video to know how to set up break points and how to debug an ABAP program in NW2004s:
    https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/9cbb7716-0a01-0010-58b1-a2ddd8361ac0?prtmode=navigate
    Hope it helps..
    Cheers,
    Habeeb

  • Perpetual BSOD on Windows 7 Enterprise machine

    Hello guys, I have a Dell Optiplex 780 with Windows 7 Enterprise which makes me hard days trying to get it healthy. There is a BSOD once in a while, well basically weekly if not daily and I could't get rid of it.
    The Log is:
    Microsoft (R) Windows Debugger Version 6.2.9200.16384 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    Loading Dump File [\\EB-OR1019945\c$\Windows\Minidump\011515-11310-01.dmp]
    Mini Kernel Dump File: Only registers and stack trace are available
    Symbol search path is: srv*;c:\symbols
    Executable search path is: srv*
    Windows 7 Kernel Version 7601 (Service Pack 1) MP (2 procs) Free x64
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 7601.18409.amd64fre.win7sp1_gdr.140303-2144
    Machine Name:
    Kernel base = 0xfffff800`03010000 PsLoadedModuleList = 0xfffff800`03253890
    Debug session time: Thu Jan 15 09:47:28.179 2015 (UTC + 2:00)
    System Uptime: 0 days 10:53:13.263
    Loading Kernel Symbols
    Loading User Symbols
    Loading unloaded module list
    *                        Bugcheck Analysis                                   
    Use !analyze -v to get detailed debugging information.
    BugCheck 1, {77a1132a, 0, ffff, fffff88009921c60}
    Probably caused by : ntkrnlmp.exe ( nt!KiSystemServiceExit+245 )
    Followup: MachineOwner
    0: kd> !analyze -v
    *                        Bugcheck Analysis                                   
    APC_INDEX_MISMATCH (1)
    This is a kernel internal error. The most common reason to see this
    bugcheck is when a filesystem or a driver has a mismatched number of
    calls to disable and re-enable APCs. The key data item is the
    Thread->CombinedApcDisable field. This consists of two separate 16-bit
    fields, the SpecialApcDisable and the KernelApcDisable. A negative value
    of either indicates that a driver has disabled special or normal APCs
    (respectively) without re-enabling them; a positive value indicates that
    a driver has enabled special or normal APCs (respectively) too many times.
    Arguments:
    Arg1: 0000000077a1132a, Address of system call function or worker routine
    Arg2: 0000000000000000, Thread->ApcStateIndex
    Arg3: 000000000000ffff, (Thread->SpecialApcDisable << 16) | Thread->KernelApcDisable
    Arg4: fffff88009921c60, Call type (0 - system call, 1 - worker routine)
    Debugging Details:
    FAULTING_IP:
    +0
    00000000`77a1132a ??              ???
    CUSTOMER_CRASH_COUNT:  1
    DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT
    BUGCHECK_STR:  0x1
    PROCESS_NAME:  svchost.exe
    CURRENT_IRQL:  0
    LAST_CONTROL_TRANSFER:  from fffff80003085169 to fffff80003085bc0
    STACK_TEXT:  
    fffff880`09921a28 fffff800`03085169 : 00000000`00000001 00000000`77a1132a 00000000`00000000 00000000`0000ffff : nt!KeBugCheckEx
    fffff880`09921a30 fffff800`030850a0 : 00000000`00000000 0000007f`ffffffff 00000000`00000000 00000980`00000000 : nt!KiBugCheckDispatch+0x69
    fffff880`09921b70 00000000`77a1132a : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceExit+0x245
    00000000`00fbe318 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x77a1132a
    STACK_COMMAND:  kb
    FOLLOWUP_IP:
    nt!KiSystemServiceExit+245
    fffff800`030850a0 4883ec50        sub     rsp,50h
    SYMBOL_STACK_INDEX:  2
    SYMBOL_NAME:  nt!KiSystemServiceExit+245
    FOLLOWUP_NAME:  MachineOwner
    MODULE_NAME: nt
    IMAGE_NAME:  ntkrnlmp.exe
    DEBUG_FLR_IMAGE_TIMESTAMP:  531590fb
    FAILURE_BUCKET_ID:  X64_0x1_SysCallNum_4_nt!KiSystemServiceExit+245
    BUCKET_ID:  X64_0x1_SysCallNum_4_nt!KiSystemServiceExit+245
    Followup: MachineOwner
    I made a BIOS update, Video Card, Chipset, all windows updates ar done, antivirus also. I ran a check disk and a SFC Scan, non solved the problem yet..
    Any help is much appreciated!

    CV
    Only one of the DMP files contained information.  It was memory related and pointed to McAfee (yours is 3+ years old)> I would remove it and use MSE in its place and if you continue to crash I would run driver verifier
    McAffe often contributes to BSOD'S
    I would remove and replace it with Microsoft Security Essentials
    http://download.mcafee.com/products/licensed/cust_support_patches/MCPR.exe
    http://www.microsoft.com/security_essentials/
    These crashes were related to memory corruption (probably caused by a driver). 
    Please run these two tests to verify your memory and find which driver is causing the problem.  Please run verifier  first
    If you are over-clocking anything reset to default before running these tests.
    In other words STOP!!!  
    If you do not know what this means you probably are not
    1-Driver verifier (for complete directions see our wiki here)
    2-Memtest. (You can read more about running memtest here)
    Wanikiya and Dyami--Team Zigzag

  • Photoshop Cs 4 Image Processor

    Unable to use image processor feature in CS 4. Error message indicates "Cannot find javascript plug-in. This feature was working just fine until a few weeks ago. Nothing unusual has changed. Thanks

    the folder must have moved or something...
    here it is for now copy it to ... applications/adobe photoshop cs4/presets/scripts : and it will be a good time to see if that folder is even there.
    Regards
    G
    // (c) Copyright 2006-2007.  Adobe Systems, Incorporated.  All rights reserved.
    // Photomerge in ExtendScript.
    // Translated from the original C++ automation & filter plugins
    // John Peterson, Adobe Systems, 2006
    // Adobe Patent or Adobe Patent Pending Invention Included Within this File
    @@@BUILDINFO@@@ Photomerge.jsx 3.0.0.1
    // BEGIN__HARVEST_EXCEPTION_ZSTRING
    <javascriptresource>
    <name>$$$/JavaScripts/Photomerge/Menu=Photomerge...</name>
    <about>$$$/JavaScripts/Photomerge/About=Photomerge^r^rCopyright 2006-2008 Adobe Systems Incorporated. All rights reserved.^r^rCombines several photographs into one continuous image.</about>
    <menu>automate</menu>
    </javascriptresource>
    // END__HARVEST_EXCEPTION_ZSTRING
    // on localized builds we pull the $$$/Strings from a .dat file
    $.localize = true;
    // Put header files in a "Stack Scripts Only" folder.  The "...Only" tells
    // PS not to place it in the menu.  For that reason, we do -not- localize that
    // portion of the folder name.
    var g_StackScriptFolderPath = app.path + "/"+ localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts") + "/"
                                            + localize("$$$/Private/Exposuremerge/StackScriptOnly=Stack Scripts Only/");
    $.evalFile(g_StackScriptFolderPath + "LatteUI.jsx");
    $.evalFile(g_StackScriptFolderPath + "StackSupport.jsx");
    $.evalFile(g_StackScriptFolderPath + "CreateImageStack.jsx");
    $.evalFile(g_StackScriptFolderPath + "Geometry.jsx");
    $.evalFile(g_StackScriptFolderPath + "PolyClip.jsx");
    // debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
    // Must leave at zero, otherwise trapping gFileFromBridge fails on QA's debug builds.
    $.level = 0; // (Window.version.search("d") != -1) ? 1 : 0;
    // debugger; // launch debugger on next line
    if (typeof(PMDebug) == 'undefined')
        var PMDebug = false;
    // photomerge routines
    // Debug - write the trapezoid in Matlab format
    function dumpTrap( name, corners )
        var i;
        if (! PMDebug) return;
        $.write( name + "= [" );
        for (i in corners)
            $.write( ((i > 0) ? "; " : "" ) + corners[i].fX + " " + corners[i].fY );
        $.writeln( "];");
    StackElement.prototype.dumpMLCorners = function()
        // Weed out file suffix (chokes matlab)
        dumpTrap( this.fName.match(/([^.]+)/)[1], this.fCorners );
    // Set the fCorners of the layer to the bounds of the Photoshop layer.
    StackElement.prototype.setCornersToLayerBounds = function( stackDoc )
        if (typeof(stackDoc) == "undefined")
            stackDoc = app.activeDocument;
        var bounds = stackDoc.layers[this.fName].bounds;
        this.fCorners = new Array();
        this.fCorners[0] = new TPoint( bounds[0].as("px"), bounds[1].as("px") );
        this.fCorners[2] = new TPoint( bounds[2].as("px"), bounds[3].as("px") );
        this.fCorners[1] = new TPoint( this.fCorners[2].fX, this.fCorners[0].fY );
        this.fCorners[3] = new TPoint( this.fCorners[0].fX, this.fCorners[2].fY );
    // Add the corner data to the string of per-stackElement information
    // that gets passed to the filter plugin
    StackElement.prototype.addPieceData = function()
        if (typeof(this.fCorners) != "undefined")
            // Add corners in place of trailing '\n'
            this.fString = this.fString.slice(0,-1) + "fCorners=";
            for (j = 0; j < 4; j++)
                this.fString += " " + this.fCorners[j].fX.toString() + " " + this.fCorners[j].fY.toString();
            this.fString += "\t";
            if (typeof(this.fScale) != "undefined")
                this.fString += ("fScale=" + this.fScale.toString() + "\t");
            if ((typeof(this.fConnectedTo) != "undefined") && this.fConnectedTo)
                this.fString += "fConnectedTo=" + this.fConnectedTo.fLayerID + "\t";
            if (typeof(this.fLayerID) != "undefined")
                this.fString += "fLayerID=" + this.fLayerID.toString() + "\t";
            this.fString += "\n";
        else
            debugger;    // Corner data missing!
    StackElement.prototype.overlapArea = function( other )
        if (other == this)
            return TPoint.polygonArea( this.fCorners );
        var overlapBounds = TRect.intersection( this.fBoundsCache, other.fBoundsCache );
        if (overlapBounds.isEmpty())
            return 0.0;
        var clipPoly = TPoint.intersectConvexPolygons( this.fCorners, other.fCorners );
        if (! clipPoly)
            return 0.0;
        else return TPoint.polygonArea( clipPoly );
    // Find the points where the two quadrilaterals intersect (yes, eight is a theoretical max)
    // Note situations where one piece intersects the same edge twice - special
    // case handled by SoftEdgeBlend
    StackElement.prototype.findQuadIntersections = function( other, intersections )
        var i, j;
        var curIntersections, numIntersections = 0;
        var innerEdgeIntersections = [ 0, 0, 0, 0 ];
        var outerEdgeIntersections = [ 0, 0, 0, 0 ];
        var thisEdge = false;
        var otherEdge = false;
        for (i = 0; i < 4; i++)
            var eb0 = other.fCorners[i];
            var eb1 = other.fCorners[(i + 1) > 3 ? 0 : i + 1];
            curIntersections = numIntersections;
            for (j = 0; j < 4; j++)
                var ed0 = this.fCorners[j];
                var ed1 = this.fCorners[(j + 1) > 3 ? 0 : j + 1];
                var cross = TPoint.lineSegmentIntersect( eb0, eb1, ed0, ed1 );
                if (cross != TPoint.kInfinite)
                    intersections[numIntersections++] = cross;
                    innerEdgeIntersections[j]++;
            outerEdgeIntersections[i] = numIntersections - curIntersections;
        if (numIntersections == 2)
            for (i = 0; i < 4; i++)
                if (innerEdgeIntersections[i] == 2) thisEdge = true;
                if (outerEdgeIntersections[i] == 2) otherEdge = true;
        return {"numIntersections":numIntersections, "thisEdge":thisEdge, "otherEdge":otherEdge};
    // Look for a point of this that's inside the corners of other.
    StackElement.prototype.findSingleInsidePoint = function( other )
        var i;
        var result = new Object();
        result.numFound = 0;
        for (i = 0; i < 4; i++)
            if (this.fCorners[i].pointInQuad( other.fCorners ))
                result.numFound++;
                result.insidePt = this.fCorners[i];
        return result;
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Because we're dealing with quads, we can't use the simple scheme
    // to generate blend rects that the rectangles use - black stuff
    // from the rects will seep in. So instead, we use various heuristics to
    // figure out how the quads themselves intersect.  This isn't too hard
    // when there's just two intersection points (usual case), but there are
    // some pathological cases where there are many more intersections (the octogon
    // from one square 45 deg. off from another is the classic example).          
    StackElement.prototype.softEdgeBlend = function( other, blendRad )
        var i, j;
        var intersections = new Array();    // Worst case is a square inside a 45 degree rot square
        // If there's no distortion, do the blend strictly on the rectangles
    /*    if ((!IsQuadMapped() && !other->IsQuadMapped())
            || (IsRectilinear() && other->IsRectilinear()))
            Assert_( other->fWarpedRaster );
            fWarpedRaster->SoftEdgeBlendRasters( *(other->fWarpedRaster), blendRad );
            return;
        var bounds = this.getBounds();
        // Find the points where the two quadrilaterals intersect
        var intResult = this.findQuadIntersections( other, intersections );
        var numIntersections = intResult.numIntersections;
        var thisEdgeTwice = intResult.thisEdge;
        var otherEdgeTwice = intResult.otherEdge;
        var thisInsidePt = this.findSingleInsidePoint( other );
        var otherInsidePt = other.findSingleInsidePoint( this );
        // If quads don't overlap, just bail
        if (numIntersections == 0)
            return;
        // Handle cases where just one point overlaps the other piece
        var insidePoint;
        if (otherEdgeTwice || ((numIntersections == 2) && (thisInsidePt.numFound == 1)))
            insidePoint = thisInsidePt.insidePt;
            this.makeBlendTrapezoid( intersections[0], intersections[1], insidePoint, blendRad, false );
            return;
        if (thisEdgeTwice /*|| ((numIntersections == 2) && (otherInsidePt.numFound == 1))*/)
            insidePoint = otherInsidePt.insidePt;
            this.makeBlendTrapezoid( intersections[0], intersections[1], insidePoint, blendRad, false );
            return;
        // ...More than two corners overlap, apply heuristics to find reasonable blending
        $.bp( numIntersections > 8 );
        // If we got more than two points, pick the two furthest apart
        if (numIntersections > 2)
            var max0, max1;
            var maxDist = -1.0;
            for (i = 0; i < numIntersections - 1; i++)
                for (j = i + 1; j < numIntersections; j++)
                    var dist = (intersections[i] - intersections[j]).vectorLength();
                    if (dist > maxDist)
                        max0 = intersections[i];
                        max1 = intersections[j];
                        maxDist = dist;
            $.bp( maxDist <= -1.0 );
            intersections[0] = max0;
            intersections[1] = max1;
            numIntersections = 2;
        TPoint.clipLineToRect( bounds, intersections[0], intersections[1] );
        // The point furthest away from the cut line on the "other" image
        // is the one that we blend toward (the "dark" corner).
        var maxPoint = 0, maxDist = -1;
        for (i = 0; i < 4; i++)
            var dist = Math.abs( other.fCorners[i].distanceToLine( intersections[0], intersections[1] ) );
            if (dist > maxDist)
                maxDist = dist;
                maxPoint = i;
        this.makeBlendTrapezoid( intersections[0], intersections[1], other.fCorners[maxPoint], blendRad, true );
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Create a layer mask that fades out from the edge0,edge1 cutline towards "insidePt"
    // If two points are inside, construct the mask fade from the edge of the image.
    //                       insidePt
    //             |            *           |
    //             |           / \          |
    //             |          /   \         |
    // insetLine-> |       +-/-----\-+      |  --
    //             |       |/       \|      |   | radius
    // baseLine->  +-------*---------*------+  --
    //                    /edge0      \edge1
    StackElement.prototype.makeBlendTrapezoid = function( edge0, edge1, insidePt, radius, useCorners )
        function sgn(x) { if (x < 0) return -1; if (x > 0) return 1; return 0; }
        function wrap4(i, next)
            i += next;
            if (i > 3) return i % 4;
            if (i < 0) return 3;
            return i;
        // Create a layer mask
        selectOneLayer( app.activeDocument, this.fName );
    //    app.activeDocument.activeLayer = app.activeDocument.layers[this.fName];    // Broken if multiple layers selected.
        createLayerMask();    // Does nothing if the layer already has a mask
        // Create vector perpendicular to edge towards insidePt
        var edgeDir = edge1 - edge0;
        var blendDir = new TPoint( -edgeDir.fY, edgeDir.fX );
        blendDir /= blendDir.vectorLength();    // Make unit length
        // Make a polygonal selection covering the area
        var dist = insidePt.distanceToLine( edge0, edge1 );
        var blendOffset = blendDir * dist;
        var blendBox;
        if (! useCorners)
            blendBox = [edge0, edge0+blendOffset, edge1+blendOffset, edge1, edge0];
        else
            // If the cutline slices across the image (two points on each side), then
            //        - Look for the edge edge0 is on
            //        - Figure out which corner is on the same side as "insdePt"
            //        - Construct the blendBox from that.
            var i, nextPtInd;
            for (i = 0; i < 4; i++)
                if (edge0.distanceToLine( this.fCorners[i], this.fCorners[wrap4(i,1)] ) < 0.0001 )
                    if (this.fCorners[i].sideOf( edge0, edge1 ) == sgn( dist ))
                        nextPtInd = -1;
                    else
                        nextPtInd = 1;
                    blendBox = new Array();
                    blendBox[0] = edge0;
                    blendBox[1] = (nextPtInd < 0) ? this.fCorners[i] : this.fCorners[i+1];
                    blendBox[2] = (nextPtInd < 0) ? this.fCorners[wrap4(i, -1)] : this.fCorners[wrap4(i, 2)];
                    blendBox[3] = edge1;
                    break;
            $.bp( i == 4 );    // Never found edge0?
        createPolygonSelection( blendBox );
        // Fill it.
        var midPoint = (edge0 + edge1) * 0.5;
        gradientFillLayerMask( midPoint, midPoint + blendDir * radius * sgn(dist) );
        app.activeDocument.selection.deselect();
    // Photomerge base class
    const kPhotomergeAdvancedBlendingFlag = app.stringIDToTypeID( "PhotomergeAdvancedBlendingFlag" );  
    photomerge = new ImageStackCreator( localize("$$$/AdobePlugin/Shared/Photomerge/Process/Name=Photomerge"),
                                              localize('$$$/AdobePlugin/Shared/Photomerge/Auto/untitled=Untitled_Panorama' ), null );
    // For now, alignment is turned OFF, because we want to
    // invoke it independantly.             
    photomerge.useAlignment            = false;    // We do the alignment, not PS
    photomerge.hideAlignment        = true;
    photomerge.mustBeSameSize        = false;
    photomerge.mustBeUnmodifiedRaw = false;
    photomerge.mustNotBe32Bit        = ! app.featureEnabled(localize("$$$/private/32BitLayersFeature=32-Bit Layers"));
    photomerge.radioButtons = ["_LOauto", "_LOperspective", "_LOcylindrical", "_LOspherical", "_LOcollage", "_LOnormal", "_LOinteractive"];
    photomerge.interactiveFlag        = false;
    photomerge.alignmentKey            = "Auto";    // Defaults to perspective
    photomerge.compositionFile        = null;
    photomerge.advancedBlending        = true;
    photomerge.lensCorrection        = false;
    photomerge.removeVignette        = false;
    try {
    // We want to steer people to the advanced blending option,
    // so have it be on by default, rather than sticky.
    //    var desc = app.getCustomOptions("PhotomergeFlags001");
    //    photomerge.advancedBlending = desc.getBoolean( kPhotomergeAdvancedBlendingFlag );
    catch (e)
    // Get the bounds of all of the stackElements.
    photomerge.getBounds = function()
        var i;
        for (i in this.stackElements)
            if (i == 0)
                this.fBounds = this.stackElements[i].getBounds();
            else
                this.fBounds.extendTo( this.stackElements[i].getBounds() );
        return this.fBounds;
    // Align selected layers by content (uses SIFT registration in Photoshop core)
    // This just returns the alignment data, it does not actually transform the layers
    // unless doTransform is true
    photomerge.getAlignmentInfo = function( stackDoc, doTransform )
        selectAllLayers(stackDoc, 1);
        const kMargin = 10;
        function offsetGroup( delta, group )
            group.bounds.offset( delta );
            var k;
            for (k = 0; k < group.layers.length; ++k)
                group.layers[k].offset( delta );
                if (doTransform)
                    selectOneLayer( stackDoc, group.layers[k].fName );
                    // Translate gets broken when document DPI isn't 72 DPI...(PR 1417264)
    //                activeDocument.activeLayer.translate( UnitValue( delta.fX, "px" ), UnitValue( delta.fY, "px" ) );   
                    translateActiveLayer( delta.fX, delta.fY );
        var i, j, alignInfo;
        var alignmentFlags = [];
        if (this.lensCorrection) alignmentFlags.push(kradialDistortStr);
        if (this.removeVignette) alignmentFlags.push(kvignetteStr);
        alignInfo = getActiveDocAlignmentInfo( this.alignmentKey, doTransform, alignmentFlags );
        // If the alignment fails completely, fake up a plan B...
        // For now, just set the images side by side.
        if (! alignInfo)
            alert(localize("$$$/AdobePlugin/Shared/Photomerge/alignbad=Some images could not be automatically aligned"));
            var xpos = 0;
            for (i in this.stackElements)
                this.stackElements[i].setCornersToSize();
                this.stackElements[i].offset( new TPoint( xpos, 0 ) );
                xpos += this.stackElements[i].getBounds().getWidth() + kMargin;
            this.fGroups = null;
        else
            var layerList = alignInfo.layerInfo;
            this.fGroups = new Array();
            for (i = 0; i < layerList.length; ++i)
                // Note we depend on stackElement's order matching
                // the document's sheet list!
                var curGroup = layerList[i].groupNum;
                if (!doTransform && (layerList[i].corners.length > 0))
                    this.stackElements[i].fCorners = layerList[i].corners;
                else
                    this.stackElements[i].setCornersToLayerBounds( stackDoc );
                this.stackElements[i].fAlignGroup = curGroup;
                this.stackElements[i].fBaseFlag = layerList[i].baseFlag;
                if (typeof(this.fGroups[curGroup]) == "undefined")
                    this.fGroups[curGroup] = new Object();
                    this.fGroups[curGroup].hasCorners = layerList[i].corners.length > 0;
                    this.fGroups[curGroup].bounds = this.stackElements[i].getBounds();
                    this.fGroups[curGroup].layers = new Array();
                    this.fGroups[curGroup].xformType = layerList[i].xformType;
                else
                    this.fGroups[curGroup].bounds.extendTo( this.stackElements[i].getBounds() );
                this.fGroups[curGroup].layers.push( this.stackElements[i] );
            // Now move the groups into  place
            // Note carefully: if the corners were given, then the group is already
            // transformed into the proper spot, and we just need to move the corners to
            // match.  So shut off moving the layer pixels around from here on out.
            offsetGroup( -this.fGroups[0].bounds.getTopLeft(), this.fGroups[0] );
            for (i = 1; i < alignInfo.numGroups; ++i)
                var spacing = Math.round(this.fGroups[i-1].bounds.getHeight() / 10.0);
                offsetGroup( -this.fGroups[i].bounds.getTopLeft() + new TPoint(0, spacing + Math.round(this.fGroups[i-1].bounds.fBottom)),
                               this.fGroups[i] );
        this.getBounds();
    // The original Photomerge plugin needs to have the "connectivity" of the
    // pieces when in perspective mode, i.e., a pieces distortion is based
    // on the distortion of the one it overlaps most.  This takes the
    // "base" piece information from the PS core and uses overlap area to
    // determine this.
    photomerge.setupConnectivity = function()
        var i;
        // See if stackElem is connected to the "base".  If "without"
        // is given, then the path to the base must not use "without"
        function isConnectedToBase( stackElem, without, dbg_count )
            if (typeof(dbg_count) == "undefined")
                dbg_count = 0;
            if (typeof(without) == "undefined")
                without = null;
            $.bp( dbg_count > 150 );    // oops, got stuck in a loop...
            if (stackElem == null)
                return false;
            if (stackElem == without)
                return false;
            if (stackElem.fConnectedTo == stackElem)
                return true;        // Already at base
            return isConnectedToBase( stackElem.fConnectedTo, without, dbg_count + 1 );
        // Initialize
        for (i in this.stackElements)
            this.stackElements[i].fBoundsCache = this.stackElements[i].getBounds();
            this.stackElements[i].fLayerID = i;
            // Bases connect to themselves.
            this.stackElements[i].fConnectedTo = this.stackElements[i].fBaseFlag ? this.stackElements[i] : null;
            this.stackElements[i].fNeighborOverlap = 0;
        // Create a connection table based on the overlap of the pieces
        var g, i, j, baseInd = -1;
        if (this.fGroups)
            for (g in this.fGroups)
                var group = this.fGroups[g];
                var connections = new Array();
                var numLayers = group.layers.length;
                // Ignore orphan images
                if (numLayers < 2)
                    group.layers[0].fBaseFlag = false;
                    group.layers[0].fConnectedTo = null;
                    continue;
                // If there's no perspective, there's no connections ("0" is kProjective in UAlignment.h)
                if (group.xformType != 0)
                    for (i = 0; i < numLayers; ++i)
                        group.layers[i].fBaseFlag = false;
                        group.layers[i].fConnectedTo = group.layers[i];
                    continue;
                for (i = 0; i < numLayers; ++i)
                    if (group.layers[i].fBaseFlag)
                        baseInd = i;
                    connections[i] = new Array();
                    group.layers[i].fGroupIndex = i;
                    if (i > 0)
                        for (j = 0; j < i; ++j)
                            connections[i][j] = group.layers[i].overlapArea( group.layers[j] );
                            connections[j][i] = connections[i][j];    // table is symentric
                $.bp( baseInd == -1 );    // Never found the base?
                // Debug - dump the connection table
        /*        for (i = 0; i < numLayers; ++i)
                    var s = "";
                    for (j = 0; j < numLayers; ++j)
                        s += ", " + Math.floor(connections[i][j]);
                    $.writeln(s);
                // Connect everything to the base that's connected.
                for (i = 0; i < numLayers; ++i)
                    if ((i != baseInd) && (connections[baseInd][i] > 0))
                        group.layers[i].fConnectedTo = group.layers[baseInd];
                        group.layers[i].fNeighborOverlap = connections[baseInd][i];
                // Walk the cconnectivity table and make sure everything is
                // "optimally" connected.
                var changes = false;
                do {
                    changes = false;
                    for (i = 0; i < numLayers; ++i)
                        if (i != baseInd)
                            var curLayer = group.layers[i];
                            for (j = 0; j < numLayers; ++j)
                                if (((j != baseInd) && (j != i))
                                    && (((connections[i][j] > curLayer.fNeighborOverlap)
                                            && isConnectedToBase( group.layers[j], curLayer ))))
                                    curLayer.fConnectedTo = group.layers[j];
                                    curLayer.fNeighborOverlap = connections[i][j];
                                    changes = true;
                } while (changes);
        //        for (i = 0; i < numLayers; ++i)
        //            $.writeln( group.layers[i].fName + " is connected to " + (group.layers[i].fConnectedTo ? group.layers[i].fConnectedTo.fName : "??") );
    photomerge.offsetStack = function( delta )
        for (i in this.stackElements)
            this.stackElements[i].offset( delta );
        this.fBounds.offset( delta );
    photomerge.scaleStack = function( s )
        for (i in this.stackElements)
            this.stackElements[i].scale( s );
        this.getBounds();
    // This gets executed before a filter plugin is invoked.  "desc"
    // allows passing parameters to the filter.
    photomerge.customPluginArguments = function( desc )
        var f = new File(this.stackElements[0].fFullName);
        var path = File.encode( f.parent.fsName ) + (File.fs == "Windows" ? "\\" : "/");
        desc.putString( app.charIDToTypeID('PMfp'), path );
        if (this.compositionFile)
            desc.putString( app.charIDToTypeID('PMrf'), this.compositionFile.fsName );
            desc.putString( app.charIDToTypeID('PMcf'), File.encode( this.compositionFile.fsName ) );
    photomerge.callInteractivePlugin = function( stackDoc )
        // Scale the results to fit the screen
    /*        var scaleFactor = 1.0, screenSize = primaryScreenDimensions() * 0.75;
        if (this.fBounds.getHeight() > this.fBounds.getWidth())
            if (this.fBounds.getHeight() > screenSize.fY)
                scaleFactor = screenSize.fY / this.fBounds.getHeight();
        else
            if (this.fBounds.getWidth() > screenSize.fX)
                scaleFactor = screenSize.fX / this.fBounds.getWidth();
        const kMaxPieceSize = 1024;        // Must match value in PhotomergeUI.cpp
        var i;
        // The old plugin insists on eight bit data.
        if (stackDoc.bitsPerChannel != BitsPerChannelType.EIGHT)
            stackDoc.bitsPerChannel = BitsPerChannelType.EIGHT;
            this.stackDepthChanged = true;
        if (this.compositionFile == null)
            // Make sure the quad coordinates coorespond to the scale used by the UI plugin
            var maxPieceSize = 0;
            for (i in this.stackElements)
                maxPieceSize = Math.max( Math.max( this.stackElements[i].fWidth, this.stackElements[i].fHeight ), maxPieceSize );
            var mipLevel = 0;
            while (maxPieceSize >> mipLevel > kMaxPieceSize)
                mipLevel++;
            var imageReduction = 1.0 / (1 << mipLevel);
            this.offsetStack( -this.fBounds.getCenter() );
            this.scaleStack( imageReduction );
            this.offsetStack( -this.fBounds.getTopLeft() );
            this.setupConnectivity();
            // Add the additional per-piece metadata to pass to the filter plugin
            for (i in this.stackElements)
                this.stackElements[i].addPieceData();
        // Make the result layer active
        app.activeDocument.activeLayer = app.activeDocument.layers[app.activeDocument.layers.length -1];
        // Note: we need an "unmodified" flag, so if no
        // changes are made we skip the data recovery step...
        var result, err;
        try {
            result = this.invokeFilterPlugin( "AdobePhotomergeUI4SCRIPT", DialogModes.ALL );
        catch (err)
            result = null;
        if (result == null)        // Cancelled / bombed out
            stackDoc.close(SaveOptions.DONOTSAVECHANGES);
            return null;
        // Extract the data from the plugin
        var modifiedPieceInfo = result.getString( app.charIDToTypeID('PSpc') ).split('\n');
        for (i in modifiedPieceInfo)
            // If we loaded a composition (.pmg) file, we won't have corners yet.
            if (typeof(this.stackElements[i].fCorners) == "undefined")
                this.stackElements[i].fCorners = new Array();
            var j, pieceData = modifiedPieceInfo[i].split('\t');
            for (j in pieceData)
                var k, pair = pieceData[j].split('=');
                if (pair[0] == 'fUsed')
                    this.stackElements[i].fUsed = eval(pair[1]);
                if (pair[0] == 'fCorners')
                    var coords = pair[1].split(/\s+/).slice(1);
                    for (k = 0; k < 4; k++)
                        this.stackElements[i].fCorners[k] = new TPoint( Number(coords[k*2]), Number(coords[k*2+1]) );
        // Remove unused photos
        for (i = 0; i < this.stackElements.length; ++i)
            if (! this.stackElements[i].fUsed)
                stackDoc.layers[(this.stackElements.length-1)-i].remove();
                this.stackElements.splice(i,1);
                i--;
        // Hey...it could happen.
        if (this.stackElements.length < 2)
            return null;
        // If we run the UI, we're restricted to an eight bit stack.
        // If the source images were higher, we need to reload the image stack.
        if (this.stackDepthChanged)
            stackDoc.close(SaveOptions.DONOTSAVECHANGES);
            stackDoc = this.loadStackLayers();
        this.getBounds();        // Update w/new corner data
        return stackDoc;
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Use the geometry of the overlapping pieces to create
    // simple rectangular blend masks.
    photomerge.quickBlend = function()
        var i, j;
        var blendRadius = Math.round(Math.min(this.stackElements[0].fWidth, this.stackElements[0].fHeight) / 10.0);
        if (PMDebug)
            for (i in this.stackElements)
                this.stackElements[i].dumpMLCorners();
        // Set up progress bar for blending
        // The progress bar doesn't work - there's know way in ScriptUI to force it to update.
    /*    var progressWindow = latteUI( g_StackScriptFolderPath + "PMBlendingProgress.exv" );
        var num = this.stackElements.length;
        var progressBar = progressWindow.findControl('_progress');
        progressBar.maxvalue = (num * (num + 1)) / 2;
        num = 0;
        progressWindow.center();
        progressWindow.show();
        // Blend the i'th piece against the 0..i-1 pieces below it
        for (i = this.stackElements.length-1; i > 0; --i)
            for (j = i-1; j >= 0; j--)
    //            num++;
    //            progressBar.value = num; // ScriptUI bug - there's no way to force this to update.
                this.stackElements[i].softEdgeBlend( this.stackElements[j], blendRadius );
    //    progressWindow.close();
    // Wrap the advancedBlend in a try/catch so errors (i.e., user cancel)
    // just stop the blend process.
    photomerge.advancedBlend = function( stackDoc )
        try {
            selectAllLayers(stackDoc, 1);
            advancedMergeLayers();
        catch (err)
    // With the stack elements specified, this
    // portion actually creates the Panorama.
    // Returns boolean indicating success/failure
    photomerge.doPanorama = function()
        var i, stackDoc = null;
        function primaryScreenDimensions()
            var i;
            for (i in $.screens)
                if ($.screens[i].primary)
                    return new TPoint( $.screens[i].right - $.screens[i].left,
                                          $.screens[i].bottom - $.screens[i].top );
        function resizeCanvasToFitPano()
            // Extend the canvas to hold the panorama
            var w = UnitValue( photomerge.getBounds().getWidth(), "px" );
            var h = UnitValue( photomerge.getBounds().getHeight(), "px" );
            app.activeDocument.resizeCanvas( w, h, AnchorPosition.TOPLEFT );
        if (this.interactiveFlag)
            // Filter must have eight bit depth and RGB color space
            stackDoc = this.loadStackLayers( BitsPerChannelType.EIGHT );
            stackDoc.changeMode(ChangeMode.RGB);
        else
            stackDoc = this.loadStackLayers();
        if (! stackDoc)
            return false;
        // Remove spurious last layer (not needed by Photomerge)
        if (app.activeDocument.layers[app.activeDocument.layers.length-1].name == this.pluginName)
            app.activeDocument.layers[app.activeDocument.layers.length-1].remove();
        // The UI needs everything in the top left corner
        if (this.interactiveFlag)
            for (i = 0; i < stackDoc.layers.length; ++i)
                var xoff = stackDoc.layers[i].bounds[0].as("px");
                var yoff = stackDoc.layers[i].bounds[1].as("px");
                if ((xoff != 0) || (yoff != 0))
                    stackDoc.layers[i].translate( UnitValue( -xoff, "px" ), UnitValue( -yoff, "px" ) );
        // Sort out exactly what operations we want to do.
        if (! this.interactiveFlag)
            selectAllLayers(stackDoc, 1);
            this.getAlignmentInfo( stackDoc, true );
            resizeCanvasToFitPano();
            if (this.advancedBlending)
                stackDoc.changeMode( ChangeMode.RGB );    // Auto-blend requires  RGB
                this.advancedBlend( stackDoc );
    // The Advanced blending works so well that there's little point
    // in having the rectangular gradient blends anymore.  Uncomment the
    // following two lines if you still want them (see similar code below
    // for the interactive case).
    //        else
    //            this.quickBlend();
            purgeHistoryStates();
            return true;
        // Interactive happens here
        if (this.compositionFile == null)
            this.getAlignmentInfo( stackDoc, false );   
            // With the corners computed by getAlignmentInfo,
            // find the bounds and use that to slide the images
            // over so their bounds has origin 0,0 (top left)
            this.offsetStack( -this.fBounds.getTopLeft() );
        if (this.interactiveFlag)
            stackDoc = this.callInteractivePlugin( stackDoc );
        if (stackDoc == null)
            return false;
        resizeCanvasToFitPano();
        // Now apply the transformation to the pieces
        for (i in this.stackElements)
            this.stackElements[i].transform();
        if (this.advancedBlending)
            selectAllLayers( stackDoc, 1 );
            stackDoc.changeMode( ChangeMode.RGB );    // Auto-blend requires  RGB
            advancedMergeLayers();
    // The new "advanced blending" works well enough that there's
    // little point in invoking the rectangular gradient blends anymore.
    // If you really want them, you can uncomment the two lines below.
    //    else
    //        this.quickBlend();
        purgeHistoryStates();
        return true;
    // Extra group breaks the main dialog's radio buttons,
    // so we manually implement it here (ScriptUI lossage)
    // NOTE: When called, this is a member function of radioControl,
    // -not- photomerge.  JavaScript voodoo.
    photomerge.radioClick = function()
        var w = this.window;
        var i;
        // Some of the transforms don't allow lens correction...
        var allowLensCor = ((this.button_id != '_LOnormal')
                            && (this.button_id != '_LOcollage')
                            && (this.button_id != '_LOinteractive'));
        w.findControl('_useLensCorrection').enabled = allowLensCor;
        w.findControl('_removeVignette').enabled = allowLensCor;
        // Be aggressive about it...
        if (! allowLensCor)
            w.findControl('_useLensCorrection').value = false;
            w.findControl('_removeVignette').value = false;
        for (i in photomerge.radioButtons)
            var b = w.findControl(photomerge.radioButtons[i]);
            if (b != this)
                b.value = false;
    // Callback when "Load Composition" is clicked.
    // NOTE: When called, this is a member function of buttonControl,
    // -not- photomerge.  JavaScript voodoo.
    photomerge.loadCompositionClick = function()
        function MacPMGType( f )
            if (f.type == 'PhMg')
                return true;
            var match = f.name.match(/.*[.](.+)$/);
            var suffix = match != null ? match[1].toLowerCase() : "";
            if (suffix == "pmg")
                return true;
            if (f instanceof Folder)
                // If the item is an app or a bundle it will be an
                // instance of folder. If we return true it will
                // appear as an enabled item. While the OS will not
                // let the user navigate into it, it is better to
                // have it appear as disabled.
                if (suffix.match(/app|bundle/i) != null)
                    // Do not navigate folders that end in .app or .bundle
                    return false;
                // navigate any other folder
                return true;
            // some unknown file type/suffix
            return false;
        var fileType = File.fs == "Windows" ? localize("$$$/AdobePlugin/Shared/Photomerge/Auto/Win=Photomerge Compositions:*.pmg")
                                        : MacPMGType;
        photomerge.compositionFile = File.openDialog( localize("$$$/AdobePlugin/Photomerge/LoadComp=Load Photomerge Composition"), fileType );
        if (photomerge.compositionFile == null || !photomerge.compositionFile.open("r"))
            return;
        var line = photomerge.compositionFile.readln();
        if (! line.match(/^VIS/))
            alert( this.pluginName + localize("$$$/AdobePlugin/Photomerge/BadComp=The Composition file is corrupt"), this.pluginName, true );
            return;
        // Read through the composition file and extract the file paths in it.
        var mergeFiles = new Array();
        while (! photomerge.compositionFile.eof)
            line = photomerge.compositionFile.readln();
            var f = line.match(/^\s*PATH\s+<([^>]+)/);
            if (f)
                // If no file path delimiters, image paths are assumed relative to the composition file
                var relPath = (f[1].indexOf( (File.fs == "Windows") ? "\\" : "/" ) < 0);
                f = (relPath ? photomerge.compositionFile.path + "/" : "") + f[1];
                mergeFiles.push( new StackElement( new File(f) ) );
        if (mergeFiles.length < 2)
            alert( this.pluginName + localize("$$$/AdobePlugin/Photomerge/BadComp=The Composition file is corrupt"), this.pluginName, true );
            return;
        photomerge.stackElements = mergeFiles;
        photomerge.interactiveFlag = true;
        this.window.close(kFilesFromPMLoad);
    // Set up the radio buttons
    photomerge.customDialogSetup = function( w )
        var i, button;
        for (i in this.radioButtons)
            button = w.findControl(this.radioButtons[i]);
            button.onClick = this.radioClick;
            // Flag with name so we can identify it in radioClick
            button.button_id = this.radioButtons[i];
        // Missing feature: We should query the selected file's metadata and
        // automatically turn on the '_useLensCorrection' checkbox if the
        // file has the proper support for it.
        w.findControl("_loadcomp").onClick = this.loadCompositionClick;
        // Julie didn't like the intro line; nuke it here because stackDialog looks for it.
        w.findControl("_intro").parent.remove(['_intro']);
        var size = w.findControl("_fileList").size;
        size[1] += 20;
        w.findControl("_LOauto").value = true;        // Set default
        w.findControl("_advancedBlend").value = this.advancedBlending;
        // If the PhotomergeUI or ADM plugins aren't there, don't display the option for it.
        if ((app.systemInformation.search(/PhotomergeUI/) < 0) || (app.systemInformation.search(/ADM /) < 0))
           w.findControl("_PMInteractive").hide();
           w.findControl("_loadcomp").hide();
    // Called by the dialog on closing to collect the results
    photomerge.customDialogFunction = function( w )
        if (w.findControl("_LOinteractive").value)
            this.interactiveFlag = true;
            this.alignmentKey = 'interactive';
        else
            var i, d = [{k:"_LOauto",v:"Auto"},{k:"_LOnormal",v:"translation"},{k:"_LOperspective",v:"Prsp"},{k: "_LOcylindrical",v:"cylindrical"},{k:"_LOspherical",v:"spherical"},{k:"_LOcollage",v:"scen eCollage"}];
            for (i in d)
                if (w.findControl(d[i].k).value)
                    this.alignmentKey = d[i].v;
                    break;
        this.advancedBlending = w.findControl("_advancedBlend").value;
        this.lensCorrection = w.findControl("_useLensCorrection").value;
        this.removeVignette = w.findControl("_removeVignette").value;
    // "Main" execution of Photomerge from the menu
    photomerge.doInteractivePano = function ()
        // Because of the ",true", the dialog is pre-loaded with any bridge files.
        this.getFilesFromBridgeOrDialog( localize("$$$/Private/Photomerge/PMDialogexv=PMDialog.exv"), true );
        try {
            if (this.stackElements && this.doPanorama())
                fitViewOnScreen();
                var flagDesc = new ActionDescriptor();
                flagDesc.putBoolean( kPhotomergeAdvancedBlendingFlag, photomerge.advancedBlending );
                app.putCustomOptions( "PhotomergeFlags001", flagDesc, true );
        catch (err)
            if (this.stackDoc)
                this.stackDoc.close(SaveOptions.DONOTSAVECHANGES)
    // Use this version to call Photomerge from a script.
    photomerge.createPanorama = function(filelist, displayDialog)
        this.interactiveFlag = (typeof(displayDialog) == 'boolean') ? displayDialog : false;
        if (filelist.length < 2)
            alert(localize("$$$/AdobePlugin/Shared/Photomerge/AtLeast2=Photomerge needs at least two files selected."), this.pluginName, true );
            return;
        var j;
        this.stackElements = new Array();
        for (j in filelist)
            var f = filelist[j];
            this.stackElements.push( new StackElement( (typeof(f) == 'string') ? File(f) : f ) );
        if (this.stackElements.length > 1)
            this.doPanorama();
    if ((typeof(runphotomergeFromScript) == 'undefined')
        || (runphotomergeFromScript==false))
        photomerge.doInteractivePano();

  • Firefox can't open normally without going through the "this is embarrassing" routine; nor does it close down properly; it also sticks frequently, i.e. screen freezes for a minute or more; should I uninstall and re-install to try and debug?

    Firefox can't open normally without going through the "this is embarrassing" routine; nor does it close down properly; I get the "end program" message and have to say "end now"it also sticks frequently, i.e. screen freezes for a minute or more; should I uninstall and re-install to try and debug?
    - I've used Firefox exclusively for around 2 years.
    - My outlook express has no problems
    - other programs seem unaffected; it seems peculiar to Firefox.
    - my main use is surfing the net, primarily entering competitions on line via specialist competition sites.
    - every day at some stage(s) I have to switch computer off as Firefox has got very slow/sticky/freezes.
    I'm not techy by any means, but I can only thing of un- and re-installing to hopefully start with a clean slate.

    Sounds like something is keeping Firefox from closing properly. See this: <br />
    https://support.mozilla.com/en-US/kb/Firefox+hangs#Hang_at_exit

  • How can I debug a routine created in Deletion of similar requests?

    Hello Experts,
    I need some help from you. I need to delete overlapping requests and the common
    settings you can set are not suitable, so I decided to write my own ABAP routine.
    But how can I debug a routine, which is implemented in the deletion of similar requests?
    Hope you can help me.
    Cheers
    Daniel Weilbacher

    Please go to the routine code..
    In the menu options..u will find an option for breakpoint--set..
    The line where breakpoint is set will get highlighted and u will also see a STOP symbol..
    then come out of routine..and then run the data load..
    this ABAP routine for overlapping request deletion runs before the scheduled data load..
    the run shud stop at the set breakpoint and show the routine code..in debugger mode..
    cheers,
    Vishvesh

  • How to debug start routines of update rules from ODS to InfoCube

    Dear gurus,
      I have an update rule from ODS to InfoCube. I wrote a start routine in the update rule. Now I want to debug it. I went to monitor and simulate update the data package and only got the prompt "No data exists in the corresponding PSA table". So how can I debug this start routine?
      Thanks in advance.
    Jin Ming

    Jin,
    In order to use PSA between ODS and InfoCube, you may have to use an exclusive InfoPackage and load separately. In that InfoPackage, choose the radio button to use a PSA.
    I think you are currently updating the InfoCube directly without using a separate InfoPackage.
    Look for an InfoSource under DataMarts (search for 8<ODS Technical name>) and create your InfoPackage there.
    Good luck.

  • (BI 7.0) Debugging Routines in Transformation

    Dear All,
    I would like to debug my own ABAP routine in the transformation for BI 7.0, anyone know how to set a break-point somewhere for popping up the debugging window? thanks
    B.R
    Charlie

    1. find the program behind your transformation (from the Transformation Display screen go to menu Extras > Display Generated Program)
    2. put a break-point where you need it
    3. create a DTP with Processing Mode (Execute tab) "Serially in the Dialog Process (for Debugging)"
    4. launch the DTP

  • Process for Debugging BW Start Routines

    I need a detailed process for how to debug the ABAP code of a start routine, particuarly when one ODS is being loaded into another.  I know that there is a way to do this with the ABAP debugger but cannot figure it out.
    Are there any documents out there that can assist me?  I did a search, but all of the examples were too specific to be useful for just general debugging.
    Thanks!

    Hi,
    It is not possible to debug in start routine through conventional way upto 3.5 version.
    You need to put an endless loop in the start routine.
    The program will keep running in the endless loop.
    It can achieved by the following code.
      data: true,
            false.
      true = 'X'.
      do.
        if true = false.
          exit.
        endif.
      enddo.
    And in transaction SM50, the endless loop program will visible.
    select the program by clicking the check box on the left hand side,
    then on the menu,
    Program/Mode -> Program -> Debugging.
    I hope this helps.
    Thanks.

  • How to Debug routine in Infopackge

    Hi All,
      I have an ABAP routine in the Infopackage. How can I debug the code.
    Thanks.
    Regards,
    bw_newbie

    Hi,
    See here:
    debug abap routine in infopackage
    debug the code at infopackage level
    Hope this helps...

  • How to debug a ABAP Routine which is in Infopackage Data selection Tab

    Hi ,
       Please let me know How to debug a ABAP Routine which is in Infopackage Data selection Tab.

    Hi,
    You can try to create infinite loop:
    DATA: STOP.
    WHILE STOP IS INITIAL. ENDWHILE.
    Start InfoPackage and then go to SM50 and swich on debugging for your process. Then in debugger you can change value of STOP variable to skip the loop.
    Krzys

  • How debug a routine created in InfoPackage for Data selection ?

    Hi everybody,
    I decide to debug a routine create in InfoPackage.
    Here, the name of my ABAP routine:
    program conversion_routine
    form compute_TREATMENT_DATE
    When i execute the "/h" command to launch debugger, i don't see this routine in Call Stack...
    How i can debbug ?
    Any suggestions ?
    Thanks in advance,
    Best regards,
    Rodolphe.

    Debug ABAP Routine in InfoPackage:  
    Put a loop on the routine,
    data : debug(1).
    do.
    if debug = 'X'.
    exit.
    endif.
    enddo.
    And when run infopackage, go to sm50.
    On that process, menu program->debug program.
    In debug screen, type in debug, and fill with X and click 'edit'-pencil icon.
    F5 to next step.
    hope this helps...

Maybe you are looking for

  • HOW CAN I USE TIME MACHINE TO BACKUP ONLY PART OF MY FILES ON EXTERNAL D?

    Hi, I am using time machine to back up all my files at the moment. but I want to get rid of video and photo material from my laptop and keep it on the external hard drive to which the time machine backs up my stuff. how can i do this without losing t

  • Wi-Fi won't work after upgrading to iPod Touch ver 3.1.3

    That is what i've notice after upgarding to iPod touch (ver. 3.1.3) and iTunes (ver. 9.0.3). I lost my WIFI connection, i used to connect to free WiFi hotspots, but now can't do, previously i have the (ver. 3.1.2) and run pretty good. What happen to

  • Make item read-only after Approved using SPD Workflow

    Hi All - Is it possible to create a workflow in SPD 2013 which can make approved items readonly for the creator of the item.  Regards, Khushi Khushi

  • Incompletion log in delivery for foreign trade data

    Hi all, I am doing export delivery and i want to put foreign trade date as in incompletion log. This log i want to do only for export document types (zex) which i have created separately. Delivery header > foreign trade / custom >geography > 1. Expor

  • Connections refused after editing master.cf file

    Hi: I just got done editing (successfully, I thought) the master.cf file using TextEdit in order to add Port 587 to the list of smtp ports available for users to send. I tried both ways suggested by various posters, including uncommenting the submiss