<URL: http://bugs.freeciv.org/Ticket/Display.html?id=39811 >

Some months ago, I began a project to review iterators, and covered
most of the major ones.  Here are those remaining, infrequently used,
mostly only in one or two files.  Where they have the lack of name
qualification nesting problems, they were able to work around by
careful selection of leading "__", "___", etc. -- and in one case, by
naming variables with leading "GRI_"!  (Not good practice.)

Another technique seems to be copying the parameters into some local
variables, just in case the parameters are overwritten.  While not
inherently evil, it does violate the principle of least astonishment.
These are insufficiently used to worry much about efficiency, so I left
them in place for future review.  However, I reorganized some conditional
blocks to be more efficient, and eliminated some variables or duplicate
function calls entirely.

In one case, the function documentation block is completely wrong.
Presumably, the iterator having been converted from indexes to pointers
sometime in the distant past.  Some of these haven't been reviewed in a
long time....

server/generator/utilities.h
   axis_iterate (was iterate_axe)
   whole_map_iterate_filtered

common/terrain.c
   variable_adjc_iterate

common/unitlist.h
   unit_list_iterate_safe

ai/aiunit.h
   simple_ai_unit_type_iterate

ai/aicity.c
   city_range_iterate

client/agents/cma_core.c
   my_city_map_iterate

client/citydlg_common.c
   citydlg_iterate

client/mapview_common.h
   gui_rect_iterate

This last looks like a big change, but should have no real change at all.
Please devote some eyeballs to it to catch any mistakes -- and the
unit_list_iterate_safe, too.

Index: server/generator/utilities.h
===================================================================
--- server/generator/utilities.h        (revision 13898)
+++ server/generator/utilities.h        (working copy)
@@ -33,44 +33,47 @@
 }
 
 /***************************************************************************
- iterate axe iterate on selected axe ( x if Xaxe is TRUE) over a intervale
- of -dist to dist arround the tile indexed by index0
- this iterator create 2 vars:
- index : the map index of the iterate pointed tile
- i : the position in the intervale of iteration (from -dist to dist)
- index0, dist, Xaxe are side effect safe.
+ iterate on selected axe (x if X_axis is TRUE) over a interval of -dist
+ to dist around the center_tile
+ _index : the position in the interval of iteration (from -dist to dist)
+ _tile : the tile pointer
  ***************************************************************************/
-#define iterate_axe(iter_tile, i, center_tile, dist, Xaxe)             \
-  {                                                                    \
-    const int ___dist = (dist);                                                
\
-    const struct tile *_center_tile = (center_tile);                   \
-    const bool ___Xaxe = (Xaxe);                                       \
-    int i, ___x, ___y;                                                 \
-    struct tile *iter_tile;                                            \
+#define axis_iterate(center_tile, _tile, _index, dist, X_axis)         \
+{                                                                      \
+  int _index##_x, _index##_y;                                          \
+  struct tile *_tile;                                                  \
+  const struct tile *_tile##_center = (center_tile);                   \
+  const bool _index##_axis = (X_axis);                                 \
+  const int _index##_d = (dist);                                       \
+  int _index = -(_index##_d);                                          \
                                                                        \
-    for (i = -___dist; i <= ___dist; i++) {                            \
-      ___x = _center_tile->nat_x + (___Xaxe ? i : 0);                  \
-      ___y = _center_tile->nat_y + (___Xaxe ? 0 : i);                  \
-      iter_tile = native_pos_to_tile(___x, ___y);                      \
-      if (!iter_tile) {                                                        
\
-       continue;                                                       \
-      }
+  for (; _index <= _index##_d; _index++) {                             \
+    _index##_x = _tile##_center->nat_x + (_index##_axis ? _index : 0); \
+    _index##_y = _tile##_center->nat_y + (_index##_axis ? 0 : _index); \
+    _tile = native_pos_to_tile(_index##_x, _index##_y);                        
\
+    if (NULL != _tile) {
 
-#define iterate_axe_end \
-    } \
+#define axis_iterate_end                                               \
+    }                                                                  \
+  }                                                                    \
 } 
-#define whole_map_iterate_filtered(ptile, pdata, pfilter)                   \
-{                                                                          \
-  bool (*_filter)(const struct tile *ptile, const void *data) = (pfilter);  \
-  const void *_data = (pdata);                                             \
-                                                                           \
-  whole_map_iterate(ptile) {                                                \
-    if (_filter && !(_filter)(ptile, _data)) {                             \
-      continue;                                                             \
-    }
 
-#define whole_map_iterate_filtered_end                                     \
-  } whole_map_iterate_end                                                  \
+/***************************************************************************
+ ...
+***************************************************************************/
+#define whole_map_iterate_filtered(ptile, pdata, pfilter)              \
+{                                                                      \
+  if (NULL != pfilter) {                                               \
+    bool (*ptile##_filter)(const struct tile *ptile, const void *data) = 
(pfilter);\
+    const void *ptile##_data = (pdata);                                        
\
+                                                                       \
+    whole_map_iterate(ptile) {                                         \
+      if ((ptile##_filter)(ptile, ptile##_data)) {                     \
+
+#define whole_map_iterate_filtered_end                                 \
+      }                                                                        
\
+    } whole_map_iterate_end;                                           \
+  }                                                                    \
 }
 
 bool is_normal_nat_pos(int x, int y);
Index: server/generator/utilities.c
===================================================================
--- server/generator/utilities.c        (revision 13898)
+++ server/generator/utilities.c        (working copy)
@@ -184,10 +184,10 @@
     whole_map_iterate(ptile) {
       int  N = 0, D = 0;
 
-      iterate_axe(tile1, i, ptile, 2, axe) {
+      axis_iterate(ptile, pnear, i, 2, axe) {
        D += weight[i + 2];
-       N += weight[i + 2] * source_map[tile1->index];
-      } iterate_axe_end;
+       N += weight[i + 2] * source_map[pnear->index];
+      } axis_iterate_end;
       if(zeroes_at_edges) {
        D = total_weight;
       }
Index: common/terrain.c
===================================================================
--- common/terrain.c    (revision 13898)
+++ common/terrain.c    (working copy)
@@ -394,23 +394,23 @@
   This iterator behaves like adjc_iterate or cardinal_adjc_iterate depending
   on the value of card_only.
 ****************************************************************************/
-#define variable_adjc_iterate(center_tile, itr_tile, card_only)                
    \
-{                                                                          \
-  enum direction8 *_dirlist;                                               \
-  int _total;                                                              \
-                                                                           \
-  if (card_only) {                                                         \
-    _dirlist = map.cardinal_dirs;                                          \
-    _total = map.num_cardinal_dirs;                                        \
-  } else {                                                                 \
-    _dirlist = map.valid_dirs;                                             \
-    _total = map.num_valid_dirs;                                           \
-  }                                                                        \
-                                                                           \
-  adjc_dirlist_iterate(center_tile, itr_tile, _dir, _dirlist, _total) {
+#define variable_adjc_iterate(center_tile, _tile, card_only)           \
+{                                                                      \
+  enum direction8 *_tile##_list;                                       \
+  int _tile##_count;                                                   \
+                                                                       \
+  if (card_only) {                                                     \
+    _tile##_list = map.cardinal_dirs;                                  \
+    _tile##_count = map.num_cardinal_dirs;                             \
+  } else {                                                             \
+    _tile##_list = map.valid_dirs;                                     \
+    _tile##_count = map.num_valid_dirs;                                        
\
+  }                                                                    \
+  adjc_dirlist_iterate(center_tile, _tile, _tile##_dir,                        
\
+                      _tile##_list, _tile##_count) {
 
-#define variable_adjc_iterate_end                                          \
-  } adjc_dirlist_iterate_end;                                              \
+#define variable_adjc_iterate_end                                      \
+  } adjc_dirlist_iterate_end;                                          \
 }
 
 
Index: common/unitlist.h
===================================================================
--- common/unitlist.h   (revision 13898)
+++ common/unitlist.h   (working copy)
@@ -27,25 +27,30 @@
     TYPED_LIST_ITERATE(struct unit, unitlist, punit)
 #define unit_list_iterate_end  LIST_ITERATE_END
 
-#define unit_list_iterate_safe(unitlist, punit)                                
    \
-{                                                                          \
-  int _size = unit_list_size(unitlist);                                        
    \
-                                                                           \
-  if (_size > 0) {                                                         \
-    int _ids[_size], _i = 0;                                               \
-                                                                           \
-    unit_list_iterate(unitlist, punit) {                                   \
-      _ids[_i++] = punit->id;                                              \
-    } unit_list_iterate_end;                                               \
-    for (_i = 0; _i < _size; _i++) {                                       \
-      struct unit *punit = game_find_unit_by_number(_ids[_i]);             \
-                                                                           \
-      if (punit) {
+#define unit_list_iterate_safe(unitlist, _unit)                                
\
+{                                                                      \
+  int _unit##_size = unit_list_size(unitlist);                         \
+                                                                       \
+  if (_unit##_size > 0) {                                              \
+    int _unit##_numbers[_unit##_size];                                 \
+    int _unit##_index = 0;                                             \
+                                                                       \
+    unit_list_iterate(unitlist, _unit) {                               \
+      _unit##_numbers[_unit##_index++] = _unit->id;                    \
+    } unit_list_iterate_end;                                           \
+                                                                       \
+    for (_unit##_index = 0;                                            \
+         _unit##_index < _unit##_size;                                 \
+         _unit##_index++) {                                            \
+      struct unit *_unit =                                             \
+        game_find_unit_by_number(_unit##_numbers[_unit##_index]);      \
+                                                                       \
+      if (NULL != _unit) {
 
-#define unit_list_iterate_safe_end                                         \
-      }                                                                        
    \
-    }                                                                      \
-  }                                                                        \
+#define unit_list_iterate_safe_end                                     \
+      }                                                                        
\
+    }                                                                  \
+  }                                                                    \
 }
 
 struct unit *unit_list_find(const struct unit_list *punitlist, int unit_id);
Index: ai/aiunit.h
===================================================================
--- ai/aiunit.h (revision 13898)
+++ ai/aiunit.h (working copy)
@@ -98,18 +98,14 @@
 /* Call this after rulesets are loaded */
 void unit_class_ai_init(void);
 
-#define simple_ai_unit_type_iterate(m_i)                                    \
-{                                                                           \
-  int m_c;                                                                  \
-  for (m_c = 0;; m_c++) {                                                   \
-    struct unit_type * m_i = simple_ai_types[m_c];                         \
-                                                                           \
-    if (!m_i) {                                                                
    \
-      break;                                                                \
-    }
+#define simple_ai_unit_type_iterate(_ut)                               \
+{                                                                      \
+  struct unit_type *_ut;                                               \
+  int _ut##_i = 0;                                                     \
+  while (NULL != (_ut = simple_ai_types[_ut##_i++])) {
 
-#define simple_ai_unit_type_iterate_end                                     \
- }                                                                          \
+#define simple_ai_unit_type_iterate_end                                        
\
+  }                                                                    \
 }
 
 #endif  /* FC__AIUNIT_H */
Index: ai/aicity.c
===================================================================
--- ai/aicity.c (revision 13898)
+++ ai/aicity.c (working copy)
@@ -69,18 +69,21 @@
 
 /* Iterate over cities within a certain range around a given city
  * (city_here) that exist within a given city list. */
-#define city_range_iterate(city_here, list, range, city)            \
-{                                                                   \
-  Continent_id continent = tile_get_continent(city_here->tile);            \
-  city_list_iterate(list, city) {                                   \
-    if ((range == REQ_RANGE_CITY && city == city_here)              \
-        || (range == REQ_RANGE_LOCAL && city == city_here)          \
-        || (range == REQ_RANGE_CONTINENT                            \
-            && tile_get_continent(city->tile) == continent)        \
-        || (range == REQ_RANGE_PLAYER)) {
-#define city_range_iterate_end \
-  } } city_list_iterate_end; }
+#define city_range_iterate(city_here, list, range, city)               \
+{                                                                      \
+  city_list_iterate(list, city) {                                      \
+    if (range == REQ_RANGE_PLAYER                                      \
+     || ((range == REQ_RANGE_CITY || range == REQ_RANGE_LOCAL)         \
+      && city == city_here)                                            \
+     || (range == REQ_RANGE_CONTINENT                                  \
+      && tile_get_continent(city->tile) ==                             \
+        tile_get_continent(city_here->tile))) {
 
+#define city_range_iterate_end                                         \
+    }                                                                  \
+  } city_list_iterate_end;                                             \
+}
+
 #define CITY_EMERGENCY(pcity)                        \
  (pcity->surplus[O_SHIELD] < 0 || city_unhappy(pcity)   \
   || pcity->food_stock + pcity->surplus[O_FOOD] < 0)
Index: client/agents/cma_core.c
===================================================================
--- client/agents/cma_core.c    (revision 13898)
+++ client/agents/cma_core.c    (working copy)
@@ -78,13 +78,13 @@
   int apply_result_ignored, apply_result_applied, refresh_forced;
 } stats;
 
-#define my_city_map_iterate(pcity, cx, cy) {                           \
-  city_map_checked_iterate(pcity->tile, cx, cy, _ptile) { \
+#define my_city_map_iterate(pcity, cx, cy) {                           \
+  city_map_checked_iterate(pcity->tile, cx, cy, cx##cy##_ptile) {      \
     if (!is_free_worked_tile(cx, cy)) {
 
-#define my_city_map_iterate_end \
-    }                                \
-  } city_map_checked_iterate_end;    \
+#define my_city_map_iterate_end                                                
\
+    }                                                                  \
+  } city_map_checked_iterate_end;                                      \
 }
 
 
Index: client/citydlg_common.c
===================================================================
--- client/citydlg_common.c     (revision 13898)
+++ client/citydlg_common.c     (working copy)
@@ -142,29 +142,28 @@
 
 /* Iterate over all known tiles in the city.  This iteration follows the
  * painter's algorithm and can be used for drawing. */
-#define citydlg_iterate(pcity, ptile, pedge, pcorner, canvas_x, canvas_y)   \
-{                                                                          \
-  int _my_gui_x0, _my_gui_y0;                                              \
-  struct city *_pcity = (pcity);                                           \
-  const int _my_width = get_citydlg_canvas_width();                        \
-  const int _my_height = get_citydlg_canvas_height();                      \
-                                                                           \
-  map_to_gui_vector(tileset, &_my_gui_x0, &_my_gui_y0,                     \
-                   _pcity->tile->x, _pcity->tile->y);                      \
-  _my_gui_x0 -= (_my_width - tileset_tile_width(tileset)) / 2;             \
-  _my_gui_y0 -= (_my_height - tileset_tile_height(tileset)) / 2;           \
-  freelog(LOG_DEBUG, "citydlg: %d,%d + %dx%d",                             \
-         _my_gui_x0, _my_gui_y0, _my_width, _my_height);                   \
-                                                                           \
-  gui_rect_iterate(_my_gui_x0, _my_gui_y0, _my_width, _my_height,          \
-                  ptile, pedge, pcorner, _gui_x, _gui_y) {                 \
-    const int canvas_x = _gui_x - _my_gui_x0;                              \
-    const int canvas_y = _gui_y - _my_gui_y0;                              \
+#define citydlg_iterate(pcity, ptile, pedge, pcorner, _x, _y)          \
+{                                                                      \
+  int _x##_0, _y##_0;                                                  \
+  const int _x##_w = get_citydlg_canvas_width();                       \
+  const int _y##_h = get_citydlg_canvas_height();                      \
+                                                                       \
+  map_to_gui_vector(tileset, &_x##_0, &_y##_0,                         \
+                   (pcity)->tile->x, (pcity)->tile->y);                \
+  _x##_0 -= (_x##_w - tileset_tile_width(tileset)) / 2;                        
\
+  _y##_0 -= (_y##_h - tileset_tile_height(tileset)) / 2;               \
+  freelog(LOG_DEBUG, "citydlg: %d,%d + %dx%d",                         \
+         _x##_0, _y##_0, _x##_w, _y##_h);                              \
+                                                                       \
+  gui_rect_iterate(_x##_0, _y##_0, _x##_w, _y##_h,                     \
+                  ptile, pedge, pcorner, _x##_, _y##_) {               \
+    const int _x = _x##_ - _x##_0;                                     \
+    const int _y = _y##_ - _y##_0;                                     \
     {
 
-#define citydlg_iterate_end                                                \
-    }                                                                       \
-  } gui_rect_iterate_end;                                                  \
+#define citydlg_iterate_end                                            \
+    }                                                                  \
+  } gui_rect_iterate_end;                                              \
 }
 
 /****************************************************************************
Index: client/mapview_common.h
===================================================================
--- client/mapview_common.h     (revision 13898)
+++ client/mapview_common.h     (working copy)
@@ -58,157 +58,158 @@
  * The order of iteration is guaranteed to satisfy the painter's algorithm.
  * The iteration covers not only tiles but tile edges and corners.
  *
- * gui_x0, gui_y0: gives the GUI origin of the rectangle.
- * width, height: gives the GUI width and height of the rectangle.  These
- * values may be negative.
+ * GRI_x0, GRI_y0: gives the GUI origin of the rectangle.
  *
- * ptile, pedge, pcorner: gives the tile, edge, or corner that is being
- * iterated over.  These are declared inside the macro.  Usually only
- * one of them will be non-NULL at a time.  These values may be passed in
- * directly to fill_sprite_array.
+ * GRI_width, GRI_height: gives the GUI width and height of the rectangle.
+ * These values may be negative.
  *
- * canvas_x, canvas_y: the canvas position of the current element.  Each
- * element is assumed to be tileset_tile_width(tileset) * 
tileset_tile_height(tileset) in
- * size.  If an element is larger the caller needs to use a larger rectangle
- * of iteration.
+ * _t, _e, _c: the tile, edge, or corner that is being iterated, declared
+ * inside the macro.  Usually, only one of them will be non-NULL at a time.
+ * These values may be passed directly to fill_sprite_array().
  *
+ * _x, _y: the canvas position of the current element, declared inside
+ * the macro.  Each element is assumed to be tileset_tile_width(tileset) *
+ * tileset_tile_height(tileset) in size.  If an element is larger, the 
+ * caller needs to use a larger rectangle of iteration.
+ *
  * The grid of iteration is rather complicated.  For a picture of it see
  * http://bugs.freeciv.org/Ticket/Attachment/89565/56824/newgrid.png
  * or the other text in PR#12085.
  */
-#define gui_rect_iterate(GRI_gui_x0, GRI_gui_y0, width, height,                
    \
-                        ptile, pedge, pcorner, gui_x, gui_y)               \
-{                                                                          \
-  int _gui_x0 = (GRI_gui_x0), _gui_y0 = (GRI_gui_y0);                      \
-  int _width = (width), _height = (height);                                \
-                                                                           \
-  if (_width < 0) {                                                        \
-    _gui_x0 += _width;                                                     \
-    _width = -_width;                                                      \
-  }                                                                        \
-  if (_height < 0) {                                                       \
-    _gui_y0 += _height;                                                        
    \
-    _height = -_height;                                                        
    \
-  }                                                                        \
-  if (_width > 0 && _height > 0) {                                         \
-    const int _ratio = (tileset_is_isometric(tileset) ? 2 : 1);                
    \
-    const int _r = _ratio * 2;                                             \
-    const int _Wr = tileset_tile_width(tileset);                               
            \
-    const int _Hr = tileset_tile_height(tileset);                              
            \
-    /* Don't divide by _r yet, to avoid integer rounding errors. */        \
-    const int GRI_x0 = DIVIDE(_gui_x0 * _r, _Wr) - _ratio / 2;         \
-    const int GRI_y0 = DIVIDE(_gui_y0 * _r, _Hr) - _ratio / 2;         \
-    const int GRI_x1 = DIVIDE((_gui_x0 + _width) * _r + _Wr - 1,           \
-                             _Wr) + _ratio;                                \
-    const int GRI_y1 = DIVIDE((_gui_y0 + _height) * _r + _Hr - 1,          \
-                             _Hr) + _ratio;                                \
-    const int _count = (GRI_x1 - GRI_x0) * (GRI_y1 - GRI_y0);              \
-    int GRI_itr, GRI_x_itr, GRI_y_itr, GRI_sum, GRI_diff;                  \
-                                                                           \
-    freelog(LOG_DEBUG, "Iterating over %d-%d x %d-%d rectangle.",          \
-           GRI_x1, GRI_x0, GRI_y1, GRI_y0);                                \
-    for (GRI_itr = 0; GRI_itr < _count; GRI_itr++) {                       \
-      struct tile *ptile = NULL;                                           \
-      struct tile_edge *pedge = NULL;                                      \
-      struct tile_corner *pcorner = NULL;                                  \
-      struct tile_edge GRI_edge;                                           \
-      struct tile_corner GRI_corner;                                       \
-      int gui_x, gui_y;                                                        
    \
-                                                                           \
-      GRI_x_itr = GRI_x0 + (GRI_itr % (GRI_x1 - GRI_x0));                  \
-      GRI_y_itr = GRI_y0 + (GRI_itr / (GRI_x1 - GRI_x0));                  \
-      GRI_sum = GRI_x_itr + GRI_y_itr;                                     \
-      GRI_diff = GRI_y_itr - GRI_x_itr;                                        
    \
-      if (tileset_is_isometric(tileset)) {                                 \
-       if ((GRI_x_itr + GRI_y_itr) % 2 != 0) {                             \
-         continue;                                                         \
-       }                                                                   \
-       if (GRI_x_itr % 2 == 0 && GRI_y_itr % 2 == 0) {                     \
-         if ((GRI_x_itr + GRI_y_itr) % 4 == 0) {                           \
-           /* Tile */                                                      \
-           ptile = map_pos_to_tile(GRI_sum / 4 - 1, GRI_diff / 4);         \
-         } else {                                                          \
-           /* Corner */                                                    \
-           pcorner = &GRI_corner;                                          \
-           pcorner->tile[0] = map_pos_to_tile((GRI_sum - 6) / 4,           \
-                                              (GRI_diff - 2) / 4);         \
-           pcorner->tile[1] = map_pos_to_tile((GRI_sum - 2) / 4,           \
-                                              (GRI_diff - 2) / 4);         \
-           pcorner->tile[2] = map_pos_to_tile((GRI_sum - 2) / 4,           \
-                                              (GRI_diff + 2) / 4);         \
-           pcorner->tile[3] = map_pos_to_tile((GRI_sum - 6) / 4,           \
-                                              (GRI_diff + 2) / 4);         \
-           if (tileset_hex_width(tileset) > 0) {                           \
-             pedge = &GRI_edge;                                            \
-             pedge->type = EDGE_UD;                                        \
-             pedge->tile[0] = pcorner->tile[0];                            \
-             pedge->tile[1] = pcorner->tile[2];                            \
-           } else if (tileset_hex_height(tileset) > 0) {                   \
-             pedge = &GRI_edge;                                            \
-             pedge->type = EDGE_LR;                                        \
-             pedge->tile[0] = pcorner->tile[1];                            \
-             pedge->tile[1] = pcorner->tile[3];                            \
-           }                                                               \
-         }                                                                 \
-       } else {                                                            \
-         /* Edge. */                                                       \
-         pedge = &GRI_edge;                                                \
-         if (GRI_sum % 4 == 0) {                                           \
-           pedge->type = EDGE_NS;                                          \
-           pedge->tile[0] = map_pos_to_tile((GRI_sum - 4) / 4, /* N */     \
-                                            (GRI_diff - 2) / 4);           \
-           pedge->tile[1] = map_pos_to_tile((GRI_sum - 4) / 4, /* S */     \
-                                            (GRI_diff + 2) / 4);           \
-         } else {                                                          \
-           pedge->type = EDGE_WE;                                          \
-           pedge->tile[0] = map_pos_to_tile((GRI_sum - 6) / 4,             \
-                                            GRI_diff / 4); /* W */         \
-           pedge->tile[1] = map_pos_to_tile((GRI_sum - 2) / 4,             \
-                                            GRI_diff / 4); /* E */         \
-         }                                                                 \
-       }                                                                   \
-      } else {                                                             \
-       if (GRI_sum % 2 == 0) {                                             \
-         if (GRI_x_itr % 2 == 0) {                                         \
-           /* Corner. */                                                   \
-           pcorner = &GRI_corner;                                          \
-           pcorner->tile[0] = map_pos_to_tile(GRI_x_itr / 2 - 1,           \
-                                              GRI_y_itr / 2 - 1); /* NW */ \
-           pcorner->tile[1] = map_pos_to_tile(GRI_x_itr / 2,               \
-                                              GRI_y_itr / 2 - 1); /* NE */ \
-           pcorner->tile[2] = map_pos_to_tile(GRI_x_itr / 2,               \
-                                              GRI_y_itr / 2); /* SE */     \
-           pcorner->tile[3] = map_pos_to_tile(GRI_x_itr / 2 - 1,           \
-                                              GRI_y_itr / 2); /* SW */     \
-         } else {                                                          \
-           /* Tile. */                                                     \
-           ptile = map_pos_to_tile((GRI_x_itr - 1) / 2,                    \
-                                   (GRI_y_itr - 1) / 2);                   \
-         }                                                                 \
-       } else {                                                            \
-         /* Edge. */                                                       \
-         pedge = &GRI_edge;                                                \
-         if (GRI_y_itr % 2 == 0) {                                         \
-           pedge->type = EDGE_NS;                                          \
-           pedge->tile[0] = map_pos_to_tile((GRI_x_itr - 1) / 2, /* N */   \
-                                            GRI_y_itr / 2 - 1);            \
-           pedge->tile[1] = map_pos_to_tile((GRI_x_itr - 1) / 2, /* S */   \
-                                            GRI_y_itr / 2);                \
-         } else {                                                          \
-           pedge->type = EDGE_WE;                                          \
-           pedge->tile[0] = map_pos_to_tile(GRI_x_itr / 2 - 1, /* W */     \
-                                            (GRI_y_itr - 1) / 2);          \
-           pedge->tile[1] = map_pos_to_tile(GRI_x_itr / 2, /* E */         \
-                                            (GRI_y_itr - 1) / 2);          \
-         }                                                                 \
-       }                                                                   \
-      }                                                                        
    \
-      gui_x = GRI_x_itr * _Wr / _r - tileset_tile_width(tileset) / 2;          
    \
-      gui_y = GRI_y_itr * _Hr / _r - tileset_tile_height(tileset) / 2;
+#define gui_rect_iterate(GRI_x0, GRI_y0, GRI_width, GRI_height,        \
+                        _t, _e, _c, _x, _y)                            \
+{                                                                      \
+  int _x##_0 = (GRI_x0), _y##_0 = (GRI_y0);                    \
+  int _x##_w = (GRI_width), _y##_h = (GRI_height);                     \
+                                                                       \
+  if (_x##_w < 0) {                                                    \
+    _x##_0 += _x##_w;                                                  \
+    _x##_w = -_x##_w;                                                  \
+  }                                                                    \
+  if (_y##_h < 0) {                                                    \
+    _y##_0 += _y##_h;                                                  \
+    _y##_h = -_y##_h;                                                  \
+  }                                                                    \
+  if (_x##_w > 0 && _y##_h > 0) {                                      \
+    struct tile_edge _t##_e;                                           \
+    struct tile_corner _t##_c;                                         \
+    int _t##_xi, _t##_yi, _t##_si, _t##_di;                            \
+    int _x, _y;                                                                
\
+    const int _t##_r1 = (tileset_is_isometric(tileset) ? 2 : 1);       \
+    const int _t##_r2 = _t##_r1 * 2; /* double the ratio */            \
+    const int _t##_w = tileset_tile_width(tileset);                    \
+    const int _t##_h = tileset_tile_height(tileset);                   \
+    /* Don't divide by _r2 yet, to avoid integer rounding errors. */   \
+    const int _t##_x0 = DIVIDE(_x##_0 * _t##_r2, _t##_w) - _t##_r1 / 2;        
\
+    const int _t##_y0 = DIVIDE(_y##_0 * _t##_r2, _t##_h) - _t##_r1 / 2;        
\
+    const int _t##_x1 = DIVIDE((_x##_0 + _x##_w) * _t##_r2 + _t##_w - 1,\
+                              _t##_w) + _t##_r1;                       \
+    const int _t##_y1 = DIVIDE((_y##_0 + _y##_h) * _t##_r2 + _t##_h - 1,\
+                              _t##_h) + _t##_r1;                       \
+    const int _t##_count = (_t##_x1 - _t##_x0) * (_t##_y1 - _t##_y0);  \
+    int _t##_index = 0;                                                        
\
+                                                                       \
+    freelog(LOG_DEBUG, "Iterating over %d-%d x %d-%d rectangle.",      \
+           _t##_x1, _t##_x0, _t##_y1, _t##_y0);                        \
+    for (; _t##_index < _t##_count; _t##_index++) {                    \
+      struct tile *_t = NULL;                                          \
+      struct tile_edge *_e = NULL;                                     \
+      struct tile_corner *_c = NULL;                                   \
+                                                                       \
+      _t##_xi = _t##_x0 + (_t##_index % (_t##_x1 - _t##_x0));          \
+      _t##_yi = _t##_y0 + (_t##_index / (_t##_x1 - _t##_x0));          \
+      _t##_si = _t##_xi + _t##_yi;                                     \
+      _t##_di = _t##_yi - _t##_xi;                                     \
+      if (2 == _t##_r1 /*tileset_is_isometric(tileset)*/) {            \
+       if ((_t##_xi + _t##_yi) % 2 != 0) {                             \
+         continue;                                                     \
+       }                                                               \
+       if (_t##_xi % 2 == 0 && _t##_yi % 2 == 0) {                     \
+         if ((_t##_xi + _t##_yi) % 4 == 0) {                           \
+           /* Tile */                                                  \
+           _t = map_pos_to_tile(_t##_si / 4 - 1, _t##_di / 4);         \
+         } else {                                                      \
+           /* Corner */                                                \
+           _c = &_t##_c;                                               \
+           _c->tile[0] = map_pos_to_tile((_t##_si - 6) / 4,            \
+                                         (_t##_di - 2) / 4);           \
+           _c->tile[1] = map_pos_to_tile((_t##_si - 2) / 4,            \
+                                         (_t##_di - 2) / 4);           \
+           _c->tile[2] = map_pos_to_tile((_t##_si - 2) / 4,            \
+                                         (_t##_di + 2) / 4);           \
+           _c->tile[3] = map_pos_to_tile((_t##_si - 6) / 4,            \
+                                         (_t##_di + 2) / 4);           \
+           if (tileset_hex_width(tileset) > 0) {                       \
+             _e = &_t##_e;                                             \
+             _e->type = EDGE_UD;                                       \
+             _e->tile[0] = _c->tile[0];                                \
+             _e->tile[1] = _c->tile[2];                                \
+           } else if (tileset_hex_height(tileset) > 0) {               \
+             _e = &_t##_e;                                             \
+             _e->type = EDGE_LR;                                       \
+             _e->tile[0] = _c->tile[1];                                \
+             _e->tile[1] = _c->tile[3];                                \
+           }                                                           \
+         }                                                             \
+       } else {                                                        \
+         /* Edge. */                                                   \
+         _e = &_t##_e;                                                 \
+         if (_t##_si % 4 == 0) {                                       \
+           _e->type = EDGE_NS;                                         \
+           _e->tile[0] = map_pos_to_tile((_t##_si - 4) / 4,            \
+                                         (_t##_di - 2) / 4);   /*N*/   \
+           _e->tile[1] = map_pos_to_tile((_t##_si - 4) / 4,            \
+                                         (_t##_di + 2) / 4);   /*S*/   \
+         } else {                                                      \
+           _e->type = EDGE_WE;                                         \
+           _e->tile[0] = map_pos_to_tile((_t##_si - 6) / 4,            \
+                                         _t##_di / 4);         /*W*/   \
+           _e->tile[1] = map_pos_to_tile((_t##_si - 2) / 4,            \
+                                         _t##_di / 4);         /*E*/   \
+         }                                                             \
+       }                                                               \
+      } else {                                                         \
+       if (_t##_si % 2 == 0) {                                         \
+         if (_t##_xi % 2 == 0) {                                       \
+           /* Corner. */                                               \
+           _c = &_t##_c;                                               \
+           _c->tile[0] = map_pos_to_tile(_t##_xi / 2 - 1,              \
+                                         _t##_yi / 2 - 1);     /*NW*/  \
+           _c->tile[1] = map_pos_to_tile(_t##_xi / 2,                  \
+                                         _t##_yi / 2 - 1);     /*NE*/  \
+           _c->tile[2] = map_pos_to_tile(_t##_xi / 2,                  \
+                                         _t##_yi / 2);         /*SE*/  \
+           _c->tile[3] = map_pos_to_tile(_t##_xi / 2 - 1,              \
+                                         _t##_yi / 2);         /*SW*/  \
+         } else {                                                      \
+           /* Tile. */                                                 \
+           _t = map_pos_to_tile((_t##_xi - 1) / 2,                     \
+                                (_t##_yi - 1) / 2);                    \
+         }                                                             \
+       } else {                                                        \
+         /* Edge. */                                                   \
+         _e = &_t##_e;                                                 \
+         if (_t##_yi % 2 == 0) {                                       \
+           _e->type = EDGE_NS;                                         \
+           _e->tile[0] = map_pos_to_tile((_t##_xi - 1) / 2,            \
+                                         _t##_yi / 2 - 1);     /*N*/   \
+           _e->tile[1] = map_pos_to_tile((_t##_xi - 1) / 2,            \
+                                         _t##_yi / 2);         /*S*/   \
+         } else {                                                      \
+           _e->type = EDGE_WE;                                         \
+           _e->tile[0] = map_pos_to_tile(_t##_xi / 2 - 1,              \
+                                         (_t##_yi - 1) / 2);   /*W*/   \
+           _e->tile[1] = map_pos_to_tile(_t##_xi / 2,                  \
+                                         (_t##_yi - 1) / 2);   /*E*/   \
+         }                                                             \
+       }                                                               \
+      }                                                                        
\
+      _x = _t##_xi * _t##_w / _t##_r2 - _t##_w / 2;                    \
+      _y = _t##_yi * _t##_h / _t##_r2 - _t##_h / 2;
 
-#define gui_rect_iterate_end                                               \
-    }                                                                      \
-  }                                                                        \
+#define gui_rect_iterate_end                                           \
+    }                                                                  \
+  }                                                                    \
 }
 
 void refresh_tile_mapcanvas(struct tile *ptile,
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to