private void update() {
   if (syncText != null) {
     this.syncText.setPermissions(permissions);
     if ((permissions & PermissionManager.FLAG_WRITE) == PermissionManager.FLAG_WRITE) {
       editText.setVisibility(VISIBLE);
       overlay.setVisibility(GONE);
       editText.setInputType(inputType);
       editText.setEnabled(true);
       syncText.acceptSuggestions();
     } else if ((permissions & PermissionManager.FLAG_SUGGEST) == PermissionManager.FLAG_SUGGEST) {
       editText.setVisibility(VISIBLE);
       overlay.setVisibility(GONE);
       editText.setInputType(inputType);
       editText.setEnabled(true);
     } else if ((permissions & PermissionManager.FLAG_READ) == PermissionManager.FLAG_READ) {
       editText.setVisibility(VISIBLE);
       overlay.setVisibility(GONE);
       syncText.rejectSuggestions();
       editText.setInputType(EditorInfo.TYPE_NULL);
       editText.setEnabled(false);
     } else {
       editText.setVisibility(GONE);
       overlay.setVisibility(VISIBLE);
       syncText.rejectSuggestions();
       editText.setInputType(EditorInfo.TYPE_NULL);
       editText.setEnabled(false);
     }
   }
   if (!editable) {
     editText.disable();
   } else {
     editText.enable();
   }
 }
 public List<SyncTextDiff> getSuggestions() {
   List<SyncTextDiff> result = new LinkedList<>();
   for (SyncTextDiff diff : syncText.getDiffs()) {
     if (diff.operation != SyncTextDiff.EQUAL
         && diff.permission == PermissionManager.FLAG_SUGGEST) {
       result.add(diff);
     }
   }
   return result;
 }
 private SyncTextDiff getDiffAt(int index) {
   int count = 0;
   if (syncText != null) {
     for (SyncTextDiff diff : syncText.getDiffs()) {
       count += diff.length();
       if (index < count) {
         return diff;
       }
     }
   }
   return null;
 }
  public void setSyncText(SyncText sync) {
    this.syncText = sync;

    syncText.setOnTextChangeListener(
        new SyncText.OnTextChangeListener() {
          @Override
          public void onTextChange(
              final String currentText, final LinkedList<SyncTextDiff> diffs, int ver) {
            if (ver >= version) {
              updateText(diffs);
            }
          }
        });

    editText.addTextChangedListener(watcher);
  }
 public void unlink() {
   if (syncText != null) {
     syncText.unlink();
   }
 }
 public void rejectSuggestions(String src) {
   syncText.rejectSuggestions(src);
 }
 public void acceptSuggestions(String src) {
   syncText.acceptSuggestions(src);
 }
 @Override
 public void onTextChanged(CharSequence s, int start, int before, int count) {
   version = Math.max(version, syncText.update(s.toString()));
 }