| 392 | } |
| 393 | |
| 394 | void |
| 395 | selection_floodfill( |
| 396 | struct selectionvar *ov, |
| 397 | coordxy x, coordxy y, |
| 398 | boolean diagonals) |
| 399 | { |
| 400 | struct selectionvar *tmp = selection_new(); |
| 401 | #define SEL_FLOOD_STACK (COLNO * ROWNO) |
| 402 | #define SEL_FLOOD(nx, ny) \ |
| 403 | do { \ |
| 404 | if (idx < SEL_FLOOD_STACK) { \ |
| 405 | dx[idx] = (nx); \ |
| 406 | dy[idx] = (ny); \ |
| 407 | idx++; \ |
| 408 | } else \ |
| 409 | panic(floodfill_stack_overrun); \ |
| 410 | } while (0) |
| 411 | #define SEL_FLOOD_CHKDIR(mx, my, sel) \ |
| 412 | do { \ |
| 413 | if (isok((mx), (my)) \ |
| 414 | && (*selection_flood_check_func)((mx), (my)) \ |
| 415 | && !selection_getpoint((mx), (my), (sel)) \ |
| 416 | && !sel_flood_havepoint((mx), (my), dx, dy, idx)) \ |
| 417 | SEL_FLOOD((mx), (my)); \ |
| 418 | } while (0) |
| 419 | static const char floodfill_stack_overrun[] = "floodfill stack overrun"; |
| 420 | int idx = 0; |
| 421 | coordxy dx[SEL_FLOOD_STACK]; |
| 422 | coordxy dy[SEL_FLOOD_STACK]; |
| 423 | |
| 424 | if (selection_flood_check_func == (int (*)(coordxy, coordxy)) 0) { |
| 425 | selection_free(tmp, TRUE); |
| 426 | return; |
| 427 | } |
| 428 | SEL_FLOOD(x, y); |
| 429 | do { |
| 430 | idx--; |
| 431 | x = dx[idx]; |
| 432 | y = dy[idx]; |
| 433 | if (isok(x, y)) { |
| 434 | selection_setpoint(x, y, ov, 1); |
| 435 | selection_setpoint(x, y, tmp, 1); |
| 436 | } |
| 437 | SEL_FLOOD_CHKDIR((x + 1), y, tmp); |
| 438 | SEL_FLOOD_CHKDIR((x - 1), y, tmp); |
| 439 | SEL_FLOOD_CHKDIR(x, (y + 1), tmp); |
| 440 | SEL_FLOOD_CHKDIR(x, (y - 1), tmp); |
| 441 | if (diagonals) { |
| 442 | SEL_FLOOD_CHKDIR((x + 1), (y + 1), tmp); |
| 443 | SEL_FLOOD_CHKDIR((x - 1), (y - 1), tmp); |
| 444 | SEL_FLOOD_CHKDIR((x - 1), (y + 1), tmp); |
| 445 | SEL_FLOOD_CHKDIR((x + 1), (y - 1), tmp); |
| 446 | } |
| 447 | } while (idx > 0); |
| 448 | #undef SEL_FLOOD |
| 449 | #undef SEL_FLOOD_STACK |
| 450 | #undef SEL_FLOOD_CHKDIR |
| 451 | selection_free(tmp, TRUE); |
no test coverage detected