private int convertFromMaster(int value, boolean approximate, int index) {
      if (index < 0) {
        return convertRaw(true, value, approximate);
      }

      CorrectedChange change = myChanges.get(index);
      int shift = change.newLength - change.oldLength;

      if (value < change.startMaster) { // So' -> Sm', So' -> Su'
        // So' == So; Sm' == Sm; Su' == Su
        // value = So'
        return convertFromMaster(value, approximate, index - 1);
      }
      if (value >= change.startMaster + change.newLength) { // Eo' -> Em', Eo' -> Eu'
        // Eo' == Eo + shift; Em' == Em + shift; Eu' == Eu
        // value = Eo'
        int converted = convertFromMaster(value - shift, approximate, index - 1);
        return append(converted, change.synchronous ? shift : 0);
      }

      if (!change.synchronous) { // Mo' -> Mu'
        if (!approximate) return -1;
        // we can't convert Mo' into Mo. And thus get valid Mu/Mu'.
        // return: Au'
        return convertFromMaster(change.startMaster, approximate, index - 1);
      }
      else { // Mo' -> Mm'
        // Ao == Ao'; Am == Am'; Mo' - Ao' == Mm' - Am'
        // value = Mo'
        int convertedStart = convertFromMaster(change.startMaster, approximate, index - 1);
        return append(convertedStart, value - change.startMaster);
      }
    }
private int convertFromMaster(int value, boolean approximate, int index)