コード例 #1
0
void win_textgrid_setfocus(window_t *win, int turnon)
{
  window_textgrid_t *cutwin = win->data; 
  if (turnon) {
    if (!cutwin->isactive) {
      cutwin->isactive = TRUE;
      flip_selection(cutwin, &cutwin->dot);
    }
  }
  else {
    if (cutwin->isactive) {
      flip_selection(cutwin, &cutwin->dot);
      cutwin->isactive = FALSE;
    }
  }
}
コード例 #2
0
ファイル: editor_c.cpp プロジェクト: twelvedogs/Lix
void Editor::calc_self()
{
    // Aendert die Mauskoordinaten ggf., also frueh aufrufen!
    map.calc_scrolling();

    // Wo ist die Maus auf dem Land?
    mx = map.get_mouse_x();
    my = map.get_mouse_y();

    const bool mouse_on_panel = hardware.get_my() > map.get_screen_yl();

    const int grid    = get_grid();
    const int mx_grid = (mx + grid/2) - Help::mod(mx, grid);
    const int my_grid = (my + grid/2) - Help::mod(my, grid);

    // Maus wird erst beim Zeichnen positioniert, damit auch die Unterfenster
    // davon profitieren, denn bei ihnen wird dieser main_loop uebersprungen.
    mouse_cursor.set_x_frame(0);
    mouse_cursor.set_y_frame(0);
    if (map.get_scrollable()
     && ((useR->scroll_right  && hardware.get_mrh())
      || (useR->scroll_middle && hardware.get_mmh())))
     mouse_cursor.set_x_frame(3);

    hover.clear();












    // Hotkey ohne Button: Cycle around all the buttons, and every button off
    if (hardware.key_once(useR->key_ed_grid)) {
        if (!panel[GRID_2 ].get_on()
         && !panel[GRID_CUSTOM].get_on()
         && !panel[GRID_16].get_on()) panel[GRID_2].set_on();
        else if (panel[GRID_2].get_on()) {
            panel[GRID_2 ].set_off();
            panel[GRID_CUSTOM].set_on();
        }
        else if (panel[GRID_CUSTOM].get_on()) {
            panel[GRID_CUSTOM].set_off();
            panel[GRID_16].set_on();
        }
        else panel[GRID_16].set_off();
    }

    // Moving objects with the arrow keys. This doesn't have an OSD button.
    // Testing for key_hold is good for this: If the drawing of the level is
    // slow, lots of keypresses get stuck in the buffer and the object(s) will
    // move on despite you've let got. Only moving the object(s) when you
    // first press the key (one could write a new function in Hardware for
    // this, of course) is also bad if the drawing is quick, because
    // you'd have to repeatedly tap the key to move it a distance.
    if (hardware.key_once(useR->key_ed_up)
     && hardware.key_hold(useR->key_ed_up)) {
        for (SelIt i = selection.begin(); i != selection.end(); ++i)
         i->o->set_y(i->o->get_y() - grid);
        if (!selection.empty()) draw_required = true;
    }
    else if (hardware.key_once(useR->key_ed_right)
     &&      hardware.key_hold(useR->key_ed_right)) {
        for (SelIt i = selection.begin(); i != selection.end(); ++i)
         i->o->set_x(i->o->get_x() + grid);
        if (!selection.empty()) draw_required = true;
    }
    else if (hardware.key_once(useR->key_ed_down)
     &&      hardware.key_hold(useR->key_ed_down)) {
        for (SelIt i = selection.begin(); i != selection.end(); ++i)
         i->o->set_y(i->o->get_y() + grid);
        if (!selection.empty()) draw_required = true;
    }
    else if (hardware.key_once(useR->key_ed_left)
     &&      hardware.key_hold(useR->key_ed_left)) {
        for (SelIt i = selection.begin(); i != selection.end(); ++i)
         i->o->set_x(i->o->get_x() - grid);
        if (!selection.empty()) draw_required = true;
    }

    // Buttons mit Hotkeys, die aber nicht auf normale Weise damit
    // assoziiert sind, werden jetzt speziell behandelt.
    // Es gibt bloede Ueberschneidungen mit dem Druecken und Loslassen von
    // Shift waehrend einer Mauszieh-Aktion, daher beheben wir das hier
    // von vornherein und nicht unten im Maus-Code.
    if (hardware.key_hold(useR->key_ed_sel_frame) && ! hardware.get_mlh())
     panel[SELECT_FRAME].set_on();
    if (hardware.key_release(useR->key_ed_sel_frame) && ! hardware.get_mlh())
     panel[SELECT_FRAME].set_off();

    if (hardware.key_hold(useR->key_ed_sel_add))
     panel[SELECT_ADD].set_on();
    if (hardware.key_release(useR->key_ed_sel_add))
     panel[SELECT_ADD].set_off();

    // Das Eindruecken von Buttons sperren, solange etwas umhergezogen wird:
    // Ansonsten wird die For-Schleife durchlaufen.
    if ((!hardware.get_mlh() && !hardware.get_mlr())
     || !mouse_hold_started_outside_panel || !mouse_on_panel)
     // Steuerleisten-Buttons abfragen
     for (unsigned int i = 0; i < panel.size(); ++i) {
        Api::BitmapButton& b = panel[i];
        if (b.get_clicked()) switch (i) {
        case FILE_NEW:
        case FILE_EXIT:
            save_lists();
            if (Level(useR->single_last_level) != level) {
                box_unsaved_data = new_box_unsaved_data(level);
                Api::Manager::add_focus(box_unsaved_data);
                b.set_on();
            }
            else if (i == FILE_NEW) delete_everything();
            else                    exit = true;
            break;

        case FILE_SAVE:
            if (useR->single_last_level.get_file().empty()) {
                // same as FILE_SAVE_AS
                b.set_on();
                browser_save = new Api::SaveBrowser(gloB->dir_levels,
                               gloB->ext_level,
                               useR->single_last_level,
                               Api::SaveBrowser::search_criterion_level,
                               Api::SaveBrowser::new_box_overwrite_level);
                browser_save->set_info_level_name(level.get_name());
                browser_save->set_info_filename(useR->single_last_level);
                Api::Manager::add_focus(browser_save);
            }
            else save_lists_and_level();
            break;

        case FILE_SAVE_AS:
            b.set_on();
            browser_save = new Api::SaveBrowser(gloB->dir_levels,
                               gloB->ext_level,
                               useR->single_last_level,
                               Api::SaveBrowser::search_criterion_level,
                               Api::SaveBrowser::new_box_overwrite_level);
            browser_save->set_info_level_name(level.get_name());
            browser_save->set_info_filename(useR->single_last_level);
            Api::Manager::add_focus(browser_save);
            break;

        case GRID_2:
        case GRID_CUSTOM:
        case GRID_16:
            {
                bool was_on = b.get_on();
                panel[GRID_2 ].set_off();
                panel[GRID_CUSTOM].set_off();
                panel[GRID_16].set_off();
                panel[i].set_on(!was_on);
            }
            break;

        case SELECT_ALL:
            selection.clear();
            for  (int type = Object::TERRAIN; type != Object::MAX; ++type)
             for (GraIt i = object[type].begin(); i != object[type].end(); ++i)
             selection.push_back(Selection(&object[type], i));
            break;

        case SELECT_FRAME:
        case SELECT_ADD:
            b.set_on(!b.get_on()); // Der Maus-Code kontrolliert, ob diese
            break;                 // Buttons eingeschaltet sind

        case SELECT_COPY:
            for (SelIt i = selection.begin(); i != selection.end(); ++i) {
                int offset = grid;
                while (offset < 8) offset *= 2;
                i->l->push_back(*i->o); // An einem Listenende anhaengen
                i->o = --i->l->end();   // Neue Position fuer den Auswahliter.
                i->o->set_x(i->o->get_x() + offset);
                i->o->set_y(i->o->get_y() + offset);
            }
            if (!selection.empty()) draw_required = true;
            break;

        case SELECT_DELETE:
            for (SelIt i = selection.begin(); i != selection.end(); ++i) {
                i->l->erase(i->o);
            }
            if (!selection.empty()) draw_required = true;
            selection.clear();
            break;

        case SELECT_MINUS: selection_fore_background(true,  false); break;
        case SELECT_PLUS:  selection_fore_background(false, false); break;
        case SELECT_BACK:  selection_fore_background(true,  true ); break;
        case SELECT_FRONT: selection_fore_background(false, true ); break;

        case SELECT_FLIP:
            flip_selection();
            if (!selection.empty()) draw_required = true;
            break;

        case SELECT_ROTATE:
            rotate_selection();
            if (!selection.empty()) draw_required = true;
            break;

        case SELECT_DARK:
            for (SelIt i = selection.begin(); i != selection.end(); ++i)
             if (i->l == &object[Object::TERRAIN])
             i->o->set_mode(i->o->get_mode() == Cutbit::DARK_EDITOR
              ? Cutbit::NORMAL : Cutbit::DARK_EDITOR);
            if (!selection.empty()) draw_required = true;
            break;

        case SELECT_NOOW:
            for (SelIt i = selection.begin(); i != selection.end(); ++i)
             if (i->l == &object[Object::TERRAIN])
             i->o->set_mode(i->o->get_mode() == Cutbit::NOOW_EDITOR
              ? Cutbit::NORMAL : Cutbit::NOOW_EDITOR);
            if (!selection.empty()) draw_required = true;
            break;

        case VIEW_ZOOM:
            b.set_on(!b.get_on());
            map.set_zoom(b.get_on());
            break;

        case MENU_SIZE:
            b.set_on();
            window_size     = new Api::WindowSize(level, map);
            Api::Manager::add_focus(window_size);
            break;

        case MENU_SCROLL:
            b.set_on();
            window_scroll   = new Api::WindowScroll(level, map);
            Api::Manager::add_focus(window_scroll);
            break;

        case MENU_VARS:
            b.set_on();
            window_variable = new Api::WindowVariables(level);
            Api::Manager::add_focus(window_variable);
            break;

        case MENU_SKILL:
            b.set_on();
            window_skill    = new Api::WindowSkill(level);
            Api::Manager::add_focus(window_skill);
            break;

        case HELP:
            b.set_on(!b.get_on());
            break;

        case ADD_TERRAIN:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_terrain,
                             useR->editor_last_dir_terrain,
                             Language::add_terrain,
                             browser_terrain_last_page);
            Api::Manager::add_focus(browser_bitmap);
            break;

        case ADD_STEEL:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_steel,
                             useR->editor_last_dir_steel,
                             Language::add_steel);
            Api::Manager::add_focus(browser_bitmap);
            break;

        case ADD_HATCH:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_hatch,
                             useR->editor_last_dir_hatch,
                             Language::add_hatch);
            Api::Manager::add_focus(browser_bitmap);
            break;

        case ADD_GOAL:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_goal,
                             useR->editor_last_dir_goal,
                             Language::add_goal);
            Api::Manager::add_focus(browser_bitmap);
            break;

        case ADD_DECO:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_deco,
                             useR->editor_last_dir_deco,
                             Language::add_deco);
            Api::Manager::add_focus(browser_bitmap);
            break;

        case ADD_HAZARD:
            b.set_on();
            browser_bitmap = new Api::BitmapBrowser(
                             search_criterion_hazard,
                             useR->editor_last_dir_hazard,
                             Language::add_hazard);
            Api::Manager::add_focus(browser_bitmap);
            break;

        default:
            break;
        }
    }













    // Dies verhindert Umherziehen und dergleichen, wenn das Maushalten
    // nicht im Spielfeld mit Objektwahl o. Ae. begann
    if (hardware.get_ml() && mouse_on_panel) {
        mouse_hold_started_outside_panel = false;
    }

    // Determine hover objects.
    // (Allerdings Hoverobjekt nicht beim Umherziehen waehlen.)
    // If no hover object found, then ignore transparency and go just by
    // the objects' selection boxes' sizes.
    if (! mouse_on_panel && hardware.get_mlh() < 2
     && ! panel[SELECT_FRAME].get_on()) {
        Selection s = find_under_mouse_cursor(FIND_BY_TRANSP);
        if (! s.is_valid()) s = find_under_mouse_cursor(FIND_BY_SELBOX);
        if (s.is_valid()) hover.push_back(s);
    }

    // Vielleicht doch klicken und Rahmen ziehen? Wenn man ins Nirvana
    // klickt, dann noch schnell den Button aktivieren
    if (!mouse_on_panel && !panel[SELECT_FRAME].get_on()
     && hardware.get_ml() && hover.empty()) {
        panel[SELECT_FRAME].set_on();
    }

    // Mehrere grosse Moeglichkeiten zur Auswahl
    // Moeglichkeit: Rahmen ziehen
    if (panel[SELECT_FRAME].get_on()) {
        // Rahmenziehen beginnt
        if (hardware.get_ml() && !mouse_on_panel) {
            mouse_hold_started_outside_panel = true;
            frame_start_x  = mx;
            frame_start_y  = my;
        }
        // Beim Rahmenziehen Objekte markieren, auch beim Loslassen diesen
        // Code nutzen, denn beim Loslassen wird einfach alles aus der
        // Hover-Liste in die Auswahl uebernommen!
        if ((hardware.get_mlh() || hardware.get_mlr())
         && mouse_hold_started_outside_panel) {
            int x1 = (frame_start_x < mx) ? frame_start_x : mx;
            int y1 = (frame_start_y < my) ? frame_start_y : my;
            int x2 = (frame_start_x > mx) ? frame_start_x : mx;
            int y2 = (frame_start_y > my) ? frame_start_y : my;
//            // Rahmen ueber dem Panel lassen, gaebe beim Torus sonst Kaese
//            if (hardware.is_mouse_over_panel()) {
//                y1 = frame_start_y;
//                y2 = map.get_screen_y()
//                   + (map.get_zoom() ? Level::min_y*3/4 : Level::min_y) - 2;
//                if (level.torus_y) y2 = Help::mod(y2, map.get_yl());
//                if (y1 < y2) std::swap(y1, y2);
//            }
            // Bei Toruskarten sollte der Rahmen so gezogen werden, dass er
            // nur im sichtbaren Bereich verlaeuft. Dieser Test funktioniert
            // auch, wenn der Zoom an ist!
            if (level.torus_x && x1 < map.get_screen_x()
                              && x2 > map.get_screen_x()) frame_torus_x=true;
            else                                           frame_torus_x=false;
            if (level.torus_y && y1 < map.get_screen_y()
                              && y2 > map.get_screen_y()) frame_torus_y=true;
            else                                           frame_torus_y=false;
            // Stopfe Gefundenes in die Hoverliste
            for (int type = Object::TERRAIN; type != Object::MAX; ++type)
             find_check_frame(object[Object::perm(type)], x1, y1, x2, y2);
            frame_draw_x1 = x1;
            frame_draw_y1 = y1;
            frame_draw_x2 = x2;
            frame_draw_y2 = y2;
            // Beim Loslassen alles aus der Hover-Liste in die Auswahl setzen
            if (hardware.get_mlr()) {
                if (!hardware.get_shift()) panel[SELECT_FRAME].set_off();
                // Kein CTRL gedrueckt - genau alles im Hover wird zur Auswahl
                if (!panel[SELECT_ADD].get_on()) selection.clear();
                for (SelIt i = hover.begin(); i != hover.end(); ++i) {
                    selection.push_back(*i);
                }
                // Radikal auf Dubletten ueberpruefen - zuvor hatte ich hier
                // etwas schlankeren Code stehen fuer CTRL-Auswahl, mit Ein-
                // fuehrung der Toruskarten kommen wir glaube ich nicht mehr
                // unter der O(n^2)-Loesung weg.
                // Kommen wir doch, die CTRL-Loesung von damals sollte reichen.
                // Mache ich aber (noch) nicht, kostet bisher noch nix.
                delete_dublicates_from_selection();
            }
            // Fertig mit dem Uebertragen in die Auswahl
        }
        // Rahmen fertig gezogen
    }



    // Weitere grosse Moeglichkeit:
    // Keinen Rahmen ziehen
    else {
        // Neuauswahl der Grafikobjekte
        if (hardware.get_ml() && !mouse_on_panel) {
            mouse_hold_started_outside_panel = true;
            // Wir haben hier garantiert etwas angeklickt, denn sonst
            // haette eine Abfrage oben bereits den SELECT_FRAME-Button
            // aktiviert.
            // Soll zur Auswahl hinzugefuegt werden (CTRL/entspr. Button)?
            // Falls das Element bereits in der Auswahl ist, wird es
            // wieder hieraus entfernt.
            if (panel[SELECT_ADD].get_on()) {
                bool is_already_in_selection = false;
                for (SelIt i = selection.begin(); i!=selection.end(); ++i){
                    if (*i == *hover.begin()) {
                        selection.erase(i);
                        is_already_in_selection = true;
                        hover.clear(); // Verhindert dunklen Rahmen, weil im
                                       // naechsten Tick umhergezogen wird
                        break;
                    }
                }
                if (!is_already_in_selection) {
                    selection.push_back(*hover.begin());
                }
            }
            // Nicht CTRL gedrueckt:
            // - Wenn in eine Auswahl geklickt, passiert nichts, denn man
            //   will ja moeglicherweise umherziehen
            // - Wenn noch nicht ausgewaehlt, dies als neue Auswahl nehmen
            else {
                bool is_already_in_selection = false;
                for (SelIt i = selection.begin(); i!=selection.end(); ++i){
                    if (*i == *hover.begin()) {
                        is_already_in_selection = true;
                        break;
                    }
                }
                if (!is_already_in_selection) {
                    selection.clear();
                    selection.push_back(*hover.begin());
                }
            }
            // Andere Dinge bei Mausklick
            mx_grid_last = mx_grid;
            my_grid_last = my_grid;
        }







        // Umherziehen von Objekten mit der Maus
        else if (hardware.get_mlh() && mouse_hold_started_outside_panel) {
            if (mx_grid != mx_grid_last || my_grid != my_grid_last) {
                for (SelIt i = selection.begin(); i != selection.end(); ++i) {
                    const int iox = i->o->get_x() + grid/2;
                    const int ioy = i->o->get_y() + grid/2;
                    i->o->set_x(
                        iox - Help::mod(iox, grid) - mx_grid_last + mx_grid
                    );
                    i->o->set_y(
                        ioy - Help::mod(ioy, grid) - my_grid_last + my_grid
                    );
                }
                if (!selection.empty()) draw_required = true;
            }
            mx_grid_last = mx_grid;
            my_grid_last = my_grid;

            if (selection.size() > 0 && mouse_on_panel) {
                mouse_cursor.set_y_frame(2);
            }
        }

        // Loslassen von umhergezogenen Objekten - nur wichtig fuer's
        // Wegschmeissen in das ewige Nirwana am unteren Bildschirmrand :-D
        else if (hardware.get_mlr() && mouse_hold_started_outside_panel) {
            if (mouse_on_panel) {
                // Komplette Auswahl loeschen
                for (SelIt i = selection.begin(); i != selection.end(); ++i) {
                    i->l->erase(i->o);
                }
                if (!selection.empty()) draw_required = true;
                selection.clear();
            }
        }
        // Ende Loslassen

    }
    // Ende der grossen Moeglichkeit fuer "Keinen Rahmen ziehen"


}
コード例 #3
0
static void win_textgrid_layout(window_textgrid_t *cutwin, int drawall)
{
  int ix, ix2, jx, sx;
  int startln, endln, startchar, endchar;
  sattr_t *attr;
  
  int charwidth = cutwin->font.gc[0].spacewidth;
  int charheight = cutwin->font.lineheight;
  fontref_t *gclist = cutwin->font.gc;

  if (drawall) {
    startln = 0;
    endln = cutwin->height;
  }
  else {
    if (cutwin->dirtybeg < 0 || cutwin->dirtyend < 0) {
      startln = 0;
      endln = 0;
    }
    else {
      startln = cutwin->dirtybeg;
      endln = cutwin->dirtyend;
      if (endln > cutwin->height)
	endln = cutwin->height;
    }
  }
  
  if (startln >= endln) {
    /* no text changes */
    if (cutwin->lastdot.begline != cutwin->dot.begline
      || cutwin->lastdot.begchar != cutwin->dot.begchar
      || cutwin->lastdot.endline != cutwin->dot.endline
      || cutwin->lastdot.endchar != cutwin->dot.endchar) {
      refiddle_selection(cutwin, &cutwin->lastdot, &cutwin->dot);
      cutwin->lastdot = cutwin->dot;
    }
    return;
  }
  
  /* flip dot off */
  flip_selection(cutwin, &cutwin->lastdot);
  cutwin->lastdot = cutwin->dot;
  
  for (jx = startln; jx < endln; jx++) {
    sline_t *ln = &(cutwin->linelist[jx]);
    
    if (drawall) {
      startchar = 0;
      endchar = cutwin->width;
    }
    else {
      if (ln->dirtybeg < 0 || ln->dirtyend < 0)
	continue;
      startchar = ln->dirtybeg;
      endchar = ln->dirtyend;
      if (endchar > cutwin->width)
	endchar = cutwin->width;
    }
    
    ix = startchar;
    sx = find_style_at(ln, ix, 0);
    while (ix < endchar) {
      if (sx >= 0 && sx < ln->numattr) {
	attr = &(ln->attr[sx]);
	ix2 = attr->end;
      }
      else { 
	attr = NULL;
	ix2 = cutwin->width;
      }
      if (ix2 > endchar)
	ix2 = endchar;
      
      if (!attr || attr->blank) {
	/* ### This may screw up styled whitespace (bkcolors) ### */
	xglk_clearfor_string(&(cutwin->font.backcolor),
	  cutwin->cbox.x+ix*charwidth, 
	  cutwin->cbox.y+jx*charheight, 
	  (ix2-ix)*charwidth, charheight);
      }
      else {
	xglk_clearfor_string(&(gclist[attr->style].backcolor),
	  cutwin->cbox.x+ix*charwidth,
          cutwin->cbox.y+jx*charheight,
          (ix2-ix)*charwidth, charheight);
	xglk_draw_string(&(gclist[attr->style]),
	  (attr->linkid != 0), (ix2-ix)*charwidth,
	  cutwin->cbox.x+ix*charwidth,
          cutwin->cbox.y+jx*charheight+cutwin->font.lineoff,
          ln->text+ix, (ix2-ix));
      }
      
      ix = ix2;
      sx++;
    }
    
    ln->dirtybeg = -1;
    ln->dirtyend = -1;
  }
  
  cutwin->dirtybeg = -1;
  cutwin->dirtyend = -1;

  /* flip dot back on */
  flip_selection(cutwin, &cutwin->lastdot);
}
コード例 #4
0
static void refiddle_selection(window_textgrid_t *cutwin, 
  sdot_t *olddot, sdot_t *newdot)
{
  sdot_t tmpdot;
  int ix;
  
  if (DOT_LENGTH_ZERO(olddot) || DOT_LENGTH_ZERO(newdot) 
    || olddot->begline < 0 || newdot->begline < 0) {
    flip_selection(cutwin, olddot);
    flip_selection(cutwin, newdot);
    return;
  }

  if (olddot->begline == newdot->begline && olddot->begchar == newdot->begchar) {
    /* start at same place */
    
    if (olddot->endline == newdot->endline && olddot->endchar == newdot->endchar) {
      /* identical! */
      return;
    }
    
    ix = compare_pos_to_dot(cutwin, olddot, newdot->endchar, newdot->endline);
    if (ix == 3) {
      tmpdot.begline = olddot->endline;
      tmpdot.begchar = olddot->endchar;
      tmpdot.endline = newdot->endline;
      tmpdot.endchar = newdot->endchar;
    }
    else {
      tmpdot.begline = newdot->endline;
      tmpdot.begchar = newdot->endchar;
      tmpdot.endline = olddot->endline;
      tmpdot.endchar = olddot->endchar;
    }
    flip_selection(cutwin, &tmpdot);
    return;
  }
  
  if (olddot->endline == newdot->endline && olddot->endchar == newdot->endchar) {
    /* end at same place */
    
    ix = compare_pos_to_dot(cutwin, olddot, newdot->begchar, newdot->begline);
    if (ix == 0) {
      tmpdot.begline = newdot->begline;
      tmpdot.begchar = newdot->begchar;
      tmpdot.endline = olddot->begline;
      tmpdot.endchar = olddot->begchar;
    }
    else {
      tmpdot.begline = olddot->begline;
      tmpdot.begchar = olddot->begchar;
      tmpdot.endline = newdot->begline;
      tmpdot.endchar = newdot->begchar;
    }
    flip_selection(cutwin, &tmpdot);
    return;
  }

  flip_selection(cutwin, olddot);
  flip_selection(cutwin, newdot);
}