+ case LFUN_TAB_INSERT: {
+ bool const multi_par_selection = cur.selection() &&
+ cur.selBegin().pit() != cur.selEnd().pit();
+ if (multi_par_selection) {
+ // If there is a multi-paragraph selection, a tab is inserted
+ // at the beginning of each paragraph.
+ cur.recordUndoSelection();
+ pit_type const pit_end = cur.selEnd().pit();
+ for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+ pars_[pit].insertChar(0, '\t',
+ bv->buffer().params().trackChanges);
+ // Update the selection pos to make sure the selection does not
+ // change as the inserted tab will increase the logical pos.
+ if (cur.realAnchor().pit() == pit)
+ cur.realAnchor().forwardPos();
+ if (cur.pit() == pit)
+ cur.forwardPos();
+ }
+ cur.finishUndo();
+ } else {
+ // Maybe we shouldn't allow tabs within a line, because they
+ // are not (yet) aligned as one might do expect.
+ FuncRequest cmd(LFUN_SELF_INSERT, from_ascii("\t"));
+ dispatch(cur, cmd);
+ }
+ break;
+ }
+
+ case LFUN_TAB_DELETE: {
+ bool const tc = bv->buffer().params().trackChanges;
+ if (cur.selection()) {
+ // If there is a selection, a tab (if present) is removed from
+ // the beginning of each paragraph.
+ cur.recordUndoSelection();
+ pit_type const pit_end = cur.selEnd().pit();
+ for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+ Paragraph & par = paragraphs()[pit];
+ if (par.empty())
+ continue;
+ char_type const c = par.getChar(0);
+ if (c == '\t' || c == ' ') {
+ // remove either 1 tab or 4 spaces.
+ int const n = (c == ' ' ? 4 : 1);
+ for (int i = 0; i < n
+ && !par.empty() && par.getChar(0) == c; ++i) {
+ if (cur.pit() == pit)
+ cur.posBackward();
+ if (cur.realAnchor().pit() == pit
+ && cur.realAnchor().pos() > 0 )
+ cur.realAnchor().backwardPos();
+ par.eraseChar(0, tc);
+ }
+ }
+ }
+ cur.finishUndo();
+ } else {
+ // If there is no selection, try to remove a tab or some spaces
+ // before the position of the cursor.
+ Paragraph & par = paragraphs()[cur.pit()];
+ pos_type const pos = cur.pos();
+
+ if (pos == 0)
+ break;
+
+ char_type const c = par.getChar(pos - 1);
+ cur.recordUndo();
+ if (c == '\t') {
+ cur.posBackward();
+ par.eraseChar(cur.pos(), tc);
+ } else
+ for (int n_spaces = 0;
+ cur.pos() > 0
+ && par.getChar(cur.pos() - 1) == ' '
+ && n_spaces < 4;
+ ++n_spaces) {
+ cur.posBackward();
+ par.eraseChar(cur.pos(), tc);
+ }
+ cur.finishUndo();
+ }
+ break;
+ }
+