~ubuntu-branches/debian/squeeze/freeciv/squeeze

« back to all changes in this revision

Viewing changes to client/editor.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (1.2.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20100223220902-kiyrmr9i4152cka5
Tags: 2.2.0-1
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************** 
 
2
 Freeciv - Copyright (C) 2005 - The Freeciv Poject
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; either version 2, or (at your option)
 
6
   any later version.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
***********************************************************************/
 
13
 
 
14
#ifdef HAVE_CONFIG_H
 
15
#include <config.h>
 
16
#endif
 
17
 
 
18
#include <assert.h>
 
19
#include <stdarg.h>
 
20
#include <string.h>
 
21
 
 
22
/* utility */
 
23
#include "fcintl.h"
 
24
#include "hash.h"
 
25
#include "log.h"
 
26
#include "support.h"
 
27
 
 
28
/* common */
 
29
#include "map.h"
 
30
#include "movement.h"
 
31
#include "packets.h"
 
32
 
 
33
/* client */
 
34
#include "client_main.h"
 
35
#include "climap.h"
 
36
#include "control.h"
 
37
#include "editor.h"
 
38
#include "mapctrl_common.h"
 
39
#include "mapview_common.h"
 
40
#include "tilespec.h"
 
41
 
 
42
#include "editgui_g.h"
 
43
#include "mapview_g.h"
 
44
 
 
45
 
 
46
enum selection_modes {
 
47
  SELECTION_MODE_NEW = 0,
 
48
  SELECTION_MODE_ADD,
 
49
  SELECTION_MODE_REMOVE
 
50
};
 
51
 
 
52
enum editor_tool_flags {
 
53
  ETF_NO_FLAGS  = 0,
 
54
  ETF_HAS_VALUE = 1<<0,
 
55
  ETF_HAS_SIZE  = 1<<1,
 
56
  ETF_HAS_COUNT = 1<<2,
 
57
  ETF_HAS_APPLIED_PLAYER = 1<<3,
 
58
  ETF_HAS_VALUE_ERASE = 1<<4
 
59
};
 
60
 
 
61
struct edit_buffer {
 
62
  int type_flags;
 
63
  struct tile_list *vtiles;
 
64
  const struct tile *origin;
 
65
};
 
66
 
 
67
struct editor_tool {
 
68
  int flags;
 
69
  enum editor_tool_mode mode;
 
70
  int size;
 
71
  int count;
 
72
  int applied_player_no;
 
73
  const char *name;
 
74
  int value;
 
75
  const char *tooltip;
 
76
};
 
77
 
 
78
struct editor_state {
 
79
  enum editor_tool_type tool;
 
80
  struct editor_tool tools[NUM_EDITOR_TOOL_TYPES];
 
81
 
 
82
  const struct tile *current_tile;
 
83
  bool tool_active;
 
84
 
 
85
  bool selrect_active;
 
86
  int selrect_start_x;
 
87
  int selrect_start_y;
 
88
  int selrect_x;
 
89
  int selrect_y;
 
90
  int selrect_width;
 
91
  int selrect_height;
 
92
 
 
93
  enum selection_modes selection_mode;
 
94
 
 
95
  struct hash_table *selected_tile_table;
 
96
  struct edit_buffer *copybuf;
 
97
};
 
98
 
 
99
static struct editor_state *editor;
 
100
 
 
101
/****************************************************************************
 
102
  Initialize editor tool data.
 
103
****************************************************************************/
 
104
static void tool_init(enum editor_tool_type ett, const char *name,
 
105
                      int flags, const char *tooltip)
 
106
{
 
107
  struct editor_tool *tool;
 
108
 
 
109
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
110
    return;
 
111
  }
 
112
 
 
113
  tool = editor->tools + ett;
 
114
 
 
115
  if (ett == ETT_COPYPASTE) {
 
116
    tool->mode = ETM_COPY;
 
117
  } else {
 
118
    tool->mode = ETM_PAINT;
 
119
  }
 
120
  tool->name = name;
 
121
  tool->flags = flags;
 
122
  tool->tooltip = tooltip;
 
123
  tool->size = 1;
 
124
  tool->count = 1;
 
125
  tool->applied_player_no = 0;
 
126
}
 
127
 
 
128
/****************************************************************************
 
129
  Initialize the client's editor state information to some suitable default
 
130
  values. This only needs to be done once at client start.
 
131
****************************************************************************/
 
132
void editor_init(void)
 
133
{
 
134
  if (editor != NULL) {
 
135
    return;
 
136
  }
 
137
 
 
138
  editor = fc_calloc(1, sizeof(struct editor_state));
 
139
 
 
140
  tool_init(ETT_TERRAIN, _("Terrain"),
 
141
            ETF_HAS_VALUE | ETF_HAS_SIZE,
 
142
            _("Change tile terrain.\nShortcut: t\n"
 
143
              "Select terrain type: shift+t or right-click here."));
 
144
  tool_init(ETT_TERRAIN_RESOURCE, _("Terrain Resource"),
 
145
            ETF_HAS_VALUE | ETF_HAS_SIZE,
 
146
            _("Change tile terrain resources.\nShortcut: r\n"
 
147
              "Select resource type: shift+r or right-click here."));
 
148
  tool_init(ETT_TERRAIN_SPECIAL, _("Terrain Special"), ETF_HAS_VALUE
 
149
            | ETF_HAS_SIZE | ETF_HAS_VALUE_ERASE,
 
150
            _("Modify tile specials.\nShortcut: s\n"
 
151
              "Select special type: shift+s or right-click here."));
 
152
  tool_init(ETT_MILITARY_BASE, _("Military Base"), ETF_HAS_VALUE
 
153
            | ETF_HAS_SIZE | ETF_HAS_VALUE_ERASE,
 
154
            _("Create a military base.\nShortcut: m\n"
 
155
              "Select base type: shift+m or right-click here."));
 
156
  tool_init(ETT_UNIT, _("Unit"), ETF_HAS_VALUE | ETF_HAS_COUNT
 
157
            | ETF_HAS_APPLIED_PLAYER | ETF_HAS_VALUE_ERASE,
 
158
            _("Create unit.\nShortcut: u\nSelect unit "
 
159
              "type: shift+u or right-click here."));
 
160
  tool_init(ETT_CITY, _("City"), ETF_HAS_SIZE | ETF_HAS_APPLIED_PLAYER,
 
161
            _("Create city.\nShortcut: c"));
 
162
  tool_init(ETT_VISION, _("Vision"), ETF_HAS_SIZE,
 
163
            _("Modify player's tile knowledge.\nShortcut: v"));
 
164
  tool_init(ETT_STARTPOS, _("Start Position"), ETF_HAS_APPLIED_PLAYER,
 
165
            _("Place a player start position.\nShortcut: p"));
 
166
 
 
167
  tool_init(ETT_COPYPASTE, _("Copy/Paste"), ETF_HAS_SIZE,
 
168
            _("Copy and paste tiles.\n"
 
169
              "Shortcut for copy mode: shift-c\n"
 
170
              "Shoftcut for paste mode: shift-v"));
 
171
  editor->copybuf = edit_buffer_new(EBT_ALL);
 
172
 
 
173
  editor->selected_tile_table = hash_new(hash_fval_keyval,
 
174
                                         hash_fcmp_keyval);
 
175
  hash_set_no_shrink(editor->selected_tile_table, TRUE);
 
176
}
 
177
 
 
178
/****************************************************************************
 
179
  Set the current tool to be used by the editor.
 
180
****************************************************************************/
 
181
void editor_set_tool(enum editor_tool_type ett)
 
182
{
 
183
  if (editor == NULL) {
 
184
    return;
 
185
  }
 
186
 
 
187
  if (!(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
188
    return;
 
189
  }
 
190
 
 
191
  editor->tool = ett;
 
192
}
 
193
 
 
194
/****************************************************************************
 
195
  Get the current tool used by the editor.
 
196
****************************************************************************/
 
197
enum editor_tool_type editor_get_tool(void)
 
198
{
 
199
  if (editor == NULL) {
 
200
    return NUM_EDITOR_TOOL_TYPES;
 
201
  }
 
202
 
 
203
  return editor->tool;
 
204
}
 
205
 
 
206
/****************************************************************************
 
207
  Set the mode for the editor tool.
 
208
****************************************************************************/
 
209
void editor_tool_set_mode(enum editor_tool_type ett,
 
210
                          enum editor_tool_mode etm)
 
211
{
 
212
  if (editor == NULL || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)
 
213
      || !(0 <= etm && etm < NUM_EDITOR_TOOL_MODES)
 
214
      || !editor_tool_has_mode(ett, etm)) {
 
215
    return;
 
216
  }
 
217
 
 
218
  editor->tools[ett].mode = etm;
 
219
}
 
220
 
 
221
/****************************************************************************
 
222
  Return TRUE if the given tool supports the given mode.
 
223
****************************************************************************/
 
224
bool editor_tool_has_mode(enum editor_tool_type ett,
 
225
                          enum editor_tool_mode etm)
 
226
{
 
227
  if (editor == NULL || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)
 
228
      || !(0 <= etm && etm < NUM_EDITOR_TOOL_MODES)) {
 
229
    return FALSE;
 
230
  }
 
231
 
 
232
  if (etm == ETM_COPY || etm == ETM_PASTE) {
 
233
    return ett == ETT_COPYPASTE;
 
234
  }
 
235
 
 
236
  if (ett == ETT_COPYPASTE) {
 
237
    return etm == ETM_COPY || etm == ETM_PASTE;
 
238
  }
 
239
 
 
240
  return TRUE;
 
241
}
 
242
 
 
243
/****************************************************************************
 
244
  Get the mode for the tool.
 
245
****************************************************************************/
 
246
enum editor_tool_mode editor_tool_get_mode(enum editor_tool_type ett)
 
247
{
 
248
  if (editor == NULL || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
249
    return NUM_EDITOR_TOOL_MODES;
 
250
  }
 
251
  return editor->tools[ett].mode;
 
252
}
 
253
 
 
254
/****************************************************************************
 
255
  Returns TRUE if the *client* is in edit mode.
 
256
****************************************************************************/
 
257
bool editor_is_active(void)
 
258
{
 
259
  return can_conn_edit(&client.conn);
 
260
}
 
261
 
 
262
/****************************************************************************
 
263
  Returns TRUE if the given tool should be made availble to the user via
 
264
  the editor GUI. For example, this will return FALSE for ETT_MILITARY_BASE
 
265
  if there are no bases defined in the ruleset.
 
266
 
 
267
  NB: This depends on the ruleset information received from the server, so
 
268
  it will return FALSE if the client does not have it yet.
 
269
****************************************************************************/
 
270
bool editor_tool_is_usable(enum editor_tool_type ett)
 
271
{
 
272
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
273
    return FALSE;
 
274
  }
 
275
 
 
276
  switch (ett) {
 
277
  case ETT_MILITARY_BASE:
 
278
    return base_count() > 0;
 
279
    break;
 
280
  case ETT_TERRAIN_RESOURCE:
 
281
    return resource_count() > 0;
 
282
    break;
 
283
  case ETT_UNIT:
 
284
    return utype_count() > 0;
 
285
    break;
 
286
  default:
 
287
    break;
 
288
  }
 
289
  return TRUE;
 
290
}
 
291
 
 
292
/****************************************************************************
 
293
  Returns TRUE if the given tool type has sub-values (e.g. the terrain
 
294
  tool has values corresponding to the terrain types).
 
295
****************************************************************************/
 
296
bool editor_tool_has_value(enum editor_tool_type ett)
 
297
{
 
298
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
299
    return FALSE;
 
300
  }
 
301
  return editor->tools[ett].flags & ETF_HAS_VALUE;
 
302
}
 
303
 
 
304
/****************************************************************************
 
305
  Set the value ID for the given tool. How the value is interpreted depends
 
306
  on the tool type.
 
307
****************************************************************************/
 
308
void editor_tool_set_value(enum editor_tool_type ett, int value)
 
309
{
 
310
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)
 
311
      || !editor_tool_has_value(ett)) {
 
312
    return;
 
313
  }
 
314
  editor->tools[ett].value = value;
 
315
}
 
316
 
 
317
/****************************************************************************
 
318
  Get the current tool sub-value.
 
319
****************************************************************************/
 
320
int editor_tool_get_value(enum editor_tool_type ett)
 
321
{
 
322
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)
 
323
      || !editor_tool_has_value(ett)) {
 
324
    return 0;
 
325
  }
 
326
  
 
327
  return editor->tools[ett].value;
 
328
}
 
329
 
 
330
/****************************************************************************
 
331
  Record the start of the selection rectangle.
 
332
****************************************************************************/
 
333
static void editor_start_selection_rectangle(int canvas_x, int canvas_y)
 
334
{
 
335
  if (!editor) {
 
336
    return;
 
337
  }
 
338
 
 
339
  if (editor->selection_mode == SELECTION_MODE_NEW
 
340
      && editor_selection_count() > 0) {
 
341
    editor_selection_clear();
 
342
    update_map_canvas_visible();
 
343
  }
 
344
 
 
345
  editor->selrect_start_x = canvas_x;
 
346
  editor->selrect_start_y = canvas_y;
 
347
  editor->selrect_width = 0;
 
348
  editor->selrect_height = 0;
 
349
  editor->selrect_active = TRUE;
 
350
}
 
351
 
 
352
/****************************************************************************
 
353
  Temporary convenience function to work-around the fact that certain
 
354
  special values (S_RESOURCE_VALID) do not in fact
 
355
  correspond to drawable special types.
 
356
****************************************************************************/
 
357
static inline bool tile_really_has_any_specials(const struct tile *ptile)
 
358
{
 
359
  bv_special specials;
 
360
 
 
361
  if (!ptile) {
 
362
    return FALSE;
 
363
  }
 
364
 
 
365
  specials = tile_specials(ptile);
 
366
 
 
367
  BV_CLR(specials, S_RESOURCE_VALID);
 
368
 
 
369
  return BV_ISSET_ANY(specials);
 
370
}
 
371
 
 
372
/****************************************************************************
 
373
  Set the editor's current applied player number according to what exists
 
374
  on the given tile.
 
375
****************************************************************************/
 
376
static void editor_grab_applied_player(const struct tile *ptile)
 
377
{
 
378
  int apno = -1;
 
379
 
 
380
  if (!editor || !ptile) {
 
381
    return;
 
382
  }
 
383
 
 
384
  if (client_has_player()
 
385
      && tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
 
386
    return;
 
387
  }
 
388
 
 
389
  if (tile_city(ptile) != NULL) {
 
390
    apno = player_number(city_owner(tile_city(ptile)));
 
391
  } else if (unit_list_size(ptile->units) > 0) {
 
392
    struct unit *punit = unit_list_get(ptile->units, 0);
 
393
    apno = player_number(unit_owner(punit));
 
394
  } else if (tile_owner(ptile) != NULL) {
 
395
    apno = player_number(tile_owner(ptile));
 
396
  }
 
397
  
 
398
  if (valid_player_by_number(apno) != NULL) {
 
399
    editor_tool_set_applied_player(editor_get_tool(), apno);
 
400
    editgui_refresh();
 
401
  }
 
402
}
 
403
 
 
404
/****************************************************************************
 
405
  Set the editor's current tool according to what exists at the given tile.
 
406
****************************************************************************/
 
407
static void editor_grab_tool(const struct tile *ptile)
 
408
{
 
409
  int ett = -1, value = 0;
 
410
  struct base_type *first_base = NULL;
 
411
 
 
412
  if (!editor) {
 
413
    return;
 
414
  }
 
415
 
 
416
  if (!ptile) {
 
417
    return;
 
418
  }
 
419
 
 
420
  base_type_iterate(pbase) {
 
421
    if (tile_has_base(ptile, pbase)) {
 
422
      first_base = pbase;
 
423
      break;
 
424
    }
 
425
  } base_type_iterate_end;
 
426
 
 
427
  if (client_has_player()
 
428
      && tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
 
429
    ett = ETT_VISION;
 
430
 
 
431
  } else if (tile_city(ptile)) {
 
432
    ett = ETT_CITY;
 
433
 
 
434
  } else if (unit_list_size(ptile->units) > 0) {
 
435
    int max_score = 0, score;
 
436
    struct unit *grabbed_punit = NULL;
 
437
    unit_list_iterate(ptile->units, punit) {
 
438
      score = 0;
 
439
      if (uclass_has_flag(unit_class(punit), UCF_UNREACHABLE)) {
 
440
        score = 5;
 
441
      } else if (is_ground_unit(punit)) {
 
442
        score = 4;
 
443
      } else if (is_sailing_unit(punit)) {
 
444
        score = 3;
 
445
      } else {
 
446
        score = 2;
 
447
      }
 
448
      if (punit->transported_by > 0) {
 
449
        score = 1;
 
450
      }
 
451
 
 
452
      if (score > max_score) {
 
453
        max_score = score;
 
454
        grabbed_punit = punit;
 
455
      }
 
456
    } unit_list_iterate_end;
 
457
 
 
458
    if (grabbed_punit) {
 
459
      ett = ETT_UNIT;
 
460
      value = utype_number(unit_type(grabbed_punit));
 
461
    }
 
462
  } else if (first_base != NULL) {
 
463
    ett = ETT_MILITARY_BASE;
 
464
    value = base_number(first_base);
 
465
 
 
466
  } else if (tile_really_has_any_specials(ptile)) {
 
467
    int specials_array[S_LAST];
 
468
    int count = 0, i, special = -1;
 
469
 
 
470
    tile_special_type_iterate(s) {
 
471
      specials_array[count++] = s;
 
472
    } tile_special_type_iterate_end;
 
473
 
 
474
    /* Grab specials in reverse order of enum tile_special_type. */
 
475
 
 
476
    for (i = count - 1; i >= 0; i--) {
 
477
      if (tile_has_special(ptile, specials_array[i])) {
 
478
        special = specials_array[i];
 
479
        break;
 
480
      }
 
481
    }
 
482
 
 
483
    if (special >= 0) {
 
484
      ett = ETT_TERRAIN_SPECIAL;
 
485
      value = special;
 
486
    }
 
487
  } else if (tile_resource(ptile) != NULL) {
 
488
    ett = ETT_TERRAIN_RESOURCE;
 
489
    value = resource_number(tile_resource(ptile));
 
490
 
 
491
  } else if (tile_terrain(ptile) != NULL) {
 
492
    ett = ETT_TERRAIN;
 
493
    value = terrain_number(tile_terrain(ptile));
 
494
  }
 
495
 
 
496
  if (ett < 0) {
 
497
    return;
 
498
  }
 
499
 
 
500
  editor_set_tool(ett);
 
501
  if (editor_tool_has_value(ett)) {
 
502
    editor_tool_set_value(ett, value);
 
503
  }
 
504
  editgui_refresh();
 
505
}
 
506
 
 
507
/****************************************************************************
 
508
  Returns TRUE if the given tile has some objects with editable properties.
 
509
****************************************************************************/
 
510
static inline bool can_edit_tile_properties(struct tile *ptile)
 
511
{
 
512
  return ptile != NULL;
 
513
}
 
514
 
 
515
/****************************************************************************
 
516
  Handle a request to edit the properties for the given tile. If the tile
 
517
  is part of a selection, then all selected tiles are passed to the
 
518
  property editor.
 
519
****************************************************************************/
 
520
static void popup_properties(struct tile *ptile)
 
521
{
 
522
  struct tile_list *tiles;
 
523
 
 
524
  if (!ptile) {
 
525
    return;
 
526
  }
 
527
 
 
528
  tiles = tile_list_new();
 
529
 
 
530
  if (editor_tile_is_selected(ptile)) {
 
531
    hash_keys_iterate(editor->selected_tile_table, sel_tile) {
 
532
      if (can_edit_tile_properties(sel_tile)) {
 
533
        tile_list_append(tiles, sel_tile);
 
534
      }
 
535
    } hash_keys_iterate_end;
 
536
  } else {
 
537
    if (can_edit_tile_properties(ptile)) {
 
538
      tile_list_append(tiles, ptile);
 
539
    }
 
540
  }
 
541
 
 
542
  editgui_popup_properties(tiles, NUM_OBJTYPES);
 
543
 
 
544
  tile_list_free(tiles);
 
545
}
 
546
 
 
547
/****************************************************************************
 
548
  Handle a user's mouse button press at the given point on the map canvas.
 
549
****************************************************************************/
 
550
void editor_mouse_button_press(int canvas_x, int canvas_y,
 
551
                               int button, int modifiers)
 
552
{
 
553
  struct tile *ptile;
 
554
 
 
555
  if (editor == NULL) {
 
556
    return;
 
557
  }
 
558
 
 
559
  ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
560
  if (ptile == NULL) {
 
561
    return;
 
562
  }
 
563
 
 
564
  switch (button) {
 
565
 
 
566
  case MOUSE_BUTTON_LEFT:
 
567
    if (modifiers == EKM_SHIFT) {
 
568
      editor_grab_tool(ptile);
 
569
    } else if (modifiers == EKM_CTRL) {
 
570
      editor_grab_applied_player(ptile);
 
571
    } else if (modifiers == EKM_NONE) {
 
572
      editor->tool_active = TRUE;
 
573
      editor_apply_tool(ptile, FALSE);
 
574
      editor_notify_edit_finished();
 
575
      editor_set_current_tile(ptile);
 
576
    }
 
577
    break;
 
578
 
 
579
  case MOUSE_BUTTON_RIGHT:
 
580
    if (modifiers == (EKM_ALT | EKM_CTRL)) {
 
581
      popup_properties(ptile);
 
582
      break;
 
583
    }
 
584
    
 
585
    if (modifiers == EKM_SHIFT) {
 
586
      editor->selection_mode = SELECTION_MODE_ADD;
 
587
    } else if (modifiers == EKM_ALT) {
 
588
      editor->selection_mode = SELECTION_MODE_REMOVE;
 
589
    } else if (modifiers == EKM_NONE) {
 
590
      editor->selection_mode = SELECTION_MODE_NEW;
 
591
    } else {
 
592
      break;
 
593
    }
 
594
    editor_start_selection_rectangle(canvas_x, canvas_y);
 
595
    break;
 
596
 
 
597
  case MOUSE_BUTTON_MIDDLE:
 
598
    if (modifiers == EKM_NONE) {
 
599
      popup_properties(ptile);
 
600
    }
 
601
    break;
 
602
 
 
603
  default:
 
604
    break;
 
605
  }
 
606
}
 
607
 
 
608
/****************************************************************************
 
609
  Record and handle the end of the selection rectangle.
 
610
****************************************************************************/
 
611
static void editor_end_selection_rectangle(int canvas_x, int canvas_y)
 
612
{
 
613
  int w, h;
 
614
 
 
615
  if (!editor) {
 
616
    return;
 
617
  }
 
618
 
 
619
  editor->selrect_active = FALSE;
 
620
 
 
621
  if (editor->selrect_width <= 0 || editor->selrect_height <= 0) {
 
622
    struct tile *ptile;
 
623
    
 
624
    ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
625
    if (ptile && editor->selection_mode == SELECTION_MODE_ADD) {
 
626
      editor_selection_add(ptile);
 
627
    } else if (ptile && editor->selection_mode == SELECTION_MODE_REMOVE) {
 
628
      editor_selection_remove(ptile);
 
629
    } else {
 
630
      recenter_button_pressed(canvas_x, canvas_y);
 
631
      return;
 
632
    }
 
633
 
 
634
    if (ptile) {
 
635
      refresh_tile_mapcanvas(ptile, TRUE, TRUE);
 
636
    }
 
637
 
 
638
    return;
 
639
  }
 
640
 
 
641
  gui_rect_iterate(mapview.gui_x0 + editor->selrect_x,
 
642
                   mapview.gui_y0 + editor->selrect_y,
 
643
                   editor->selrect_width, editor->selrect_height,
 
644
                   ptile, pedge, pcorner, gui_x, gui_y) {
 
645
    if (ptile == NULL) {
 
646
      continue;
 
647
    }
 
648
    if (editor->selection_mode == SELECTION_MODE_NEW
 
649
        || editor->selection_mode == SELECTION_MODE_ADD) {
 
650
      editor_selection_add(ptile);
 
651
    } else if (editor->selection_mode == SELECTION_MODE_REMOVE) {
 
652
      editor_selection_remove(ptile);
 
653
    }
 
654
  } gui_rect_iterate_end;
 
655
 
 
656
  w = tileset_tile_width(tileset);
 
657
  h = tileset_tile_height(tileset);
 
658
 
 
659
  update_map_canvas(editor->selrect_x - w,
 
660
                    editor->selrect_y - h,
 
661
                    editor->selrect_width + 2 * w,
 
662
                    editor->selrect_height + 2 * h);
 
663
  flush_dirty();
 
664
}
 
665
 
 
666
/****************************************************************************
 
667
  Draws the editor selection rectangle using draw_selection_rectangle().
 
668
****************************************************************************/
 
669
static void editor_draw_selrect(void)
 
670
{
 
671
  if (!editor) {
 
672
    return;
 
673
  }
 
674
 
 
675
  if (editor->selrect_active && editor->selrect_width > 0
 
676
      && editor->selrect_height > 0) {
 
677
    draw_selection_rectangle(editor->selrect_x,
 
678
                             editor->selrect_y,
 
679
                             editor->selrect_width,
 
680
                             editor->selrect_height);
 
681
  }
 
682
}
 
683
 
 
684
/****************************************************************************
 
685
  Handle the release of a mouse button click.
 
686
****************************************************************************/
 
687
void editor_mouse_button_release(int canvas_x, int canvas_y,
 
688
                                 int button, int modifiers)
 
689
{
 
690
  switch (button) {
 
691
 
 
692
  case MOUSE_BUTTON_LEFT:
 
693
    editor_set_current_tile(NULL);
 
694
    editor->tool_active = FALSE;
 
695
    break;
 
696
 
 
697
  case MOUSE_BUTTON_RIGHT:
 
698
    if (editor->selrect_active) {
 
699
      editor_end_selection_rectangle(canvas_x, canvas_y);
 
700
    }
 
701
    break;
 
702
 
 
703
  case MOUSE_BUTTON_MIDDLE:
 
704
    break;
 
705
 
 
706
  default:
 
707
    break;
 
708
  }
 
709
}
 
710
 
 
711
/****************************************************************************
 
712
  Handle a change in the size of the selection rectangle. The given point
 
713
  is the new extremity of the rectangle.
 
714
****************************************************************************/
 
715
static void editor_resize_selection_rectangle(int canvas_x, int canvas_y)
 
716
{
 
717
  int x1, y1, x2, y2;
 
718
 
 
719
  if (editor->selrect_start_x <= canvas_x) {
 
720
    x1 = editor->selrect_start_x;
 
721
    x2 = canvas_x;
 
722
  } else {
 
723
    x1 = canvas_x;
 
724
    x2 = editor->selrect_start_x;
 
725
  }
 
726
 
 
727
  if (editor->selrect_start_y <= canvas_y) {
 
728
    y1 = editor->selrect_start_y;
 
729
    y2 = canvas_y;
 
730
  } else {
 
731
    y1 = canvas_y;
 
732
    y2 = editor->selrect_start_y;
 
733
  }
 
734
 
 
735
  /* Erase the previously drawn rectangle. */
 
736
  editor_draw_selrect();
 
737
 
 
738
  if (x1 == x2 || y1 == y2) {
 
739
    editor->selrect_width = 0;
 
740
    editor->selrect_height = 0;
 
741
    return;
 
742
  }
 
743
 
 
744
  editor->selrect_x = x1;
 
745
  editor->selrect_y = y1;
 
746
  editor->selrect_width = x2 - x1;
 
747
  editor->selrect_height = y2 - y1;
 
748
 
 
749
  editor_draw_selrect();
 
750
}
 
751
 
 
752
/****************************************************************************
 
753
  Handle the mouse moving over the map canvas.
 
754
****************************************************************************/
 
755
void editor_mouse_move(int canvas_x, int canvas_y, int modifiers)
 
756
{
 
757
  const struct tile *ptile, *old;
 
758
 
 
759
  if (!editor) {
 
760
    return;
 
761
  }
 
762
 
 
763
  old = editor_get_current_tile();
 
764
  ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
765
 
 
766
  if (!ptile) {
 
767
    return;
 
768
  }
 
769
 
 
770
  if (editor->tool_active && old != NULL && old != ptile) {
 
771
    editor_apply_tool(ptile, FALSE);
 
772
    editor_notify_edit_finished();
 
773
    editor_set_current_tile(ptile);
 
774
  }
 
775
 
 
776
  if (editor->selrect_active) {
 
777
    editor_resize_selection_rectangle(canvas_x, canvas_y);
 
778
  }
 
779
}
 
780
 
 
781
/****************************************************************************
 
782
  Notify the server that a batch of edits has completed. This is used as
 
783
  a hint for the server to now do any checks it has saved while the batch
 
784
  was being processed.
 
785
****************************************************************************/
 
786
void editor_notify_edit_finished(void)
 
787
{
 
788
  send_packet_edit_check_tiles(&client.conn);
 
789
}
 
790
 
 
791
/****************************************************************************
 
792
  Apply the current editor tool to the given tile. This function is
 
793
  suitable to called over multiple tiles at once. Once the batch of
 
794
  operations is finished you should call editor_notify_edit_finished.
 
795
  The 'part_of_selection' parameter should be TRUE if the tool is
 
796
  being applied to a tile from a selection.
 
797
****************************************************************************/
 
798
void editor_apply_tool(const struct tile *ptile,
 
799
                       bool part_of_selection)
 
800
{
 
801
  enum editor_tool_type ett;
 
802
  enum editor_tool_mode etm;
 
803
  int value, size, count, apno, x, y, id;
 
804
  bool erase;
 
805
  struct connection *my_conn = &client.conn;
 
806
 
 
807
  if (editor == NULL || ptile == NULL) {
 
808
    return;
 
809
  }
 
810
 
 
811
  ett = editor_get_tool();
 
812
  etm = editor_tool_get_mode(ett);
 
813
  size = editor_tool_get_size(ett);
 
814
  count = editor_tool_get_count(ett);
 
815
  value = editor_tool_get_value(ett);
 
816
  apno = editor_tool_get_applied_player(ett);
 
817
 
 
818
  if (ett != ETT_VISION && !client_is_global_observer()
 
819
      && client_has_player()
 
820
      && tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
 
821
    return;
 
822
  }
 
823
 
 
824
  if (editor_tool_has_applied_player(ett)
 
825
      && valid_player_by_number(apno) == NULL) {
 
826
    return;
 
827
  }
 
828
 
 
829
  if (ett == ETT_COPYPASTE) {
 
830
    struct edit_buffer *ebuf;
 
831
    ebuf = editor_get_copy_buffer();
 
832
    if (etm == ETM_COPY) {
 
833
      if (part_of_selection) {
 
834
        edit_buffer_copy(ebuf, ptile);
 
835
      } else {
 
836
        edit_buffer_clear(ebuf);
 
837
        edit_buffer_copy_square(ebuf, ptile, size);
 
838
        editgui_refresh();
 
839
      }
 
840
    } else if (etm == ETM_PAINT || etm == ETM_PASTE) {
 
841
      edit_buffer_paste(ebuf, ptile);
 
842
    }
 
843
    return;
 
844
  }
 
845
 
 
846
  if (part_of_selection && ett != ETT_CITY) {
 
847
    size = 1;
 
848
  }
 
849
 
 
850
  erase = (etm == ETM_ERASE);
 
851
  x = ptile->x;
 
852
  y = ptile->y;
 
853
 
 
854
  switch (ett) {
 
855
 
 
856
  case ETT_TERRAIN:
 
857
    dsend_packet_edit_tile_terrain(my_conn, x, y, erase ? 0 : value, size);
 
858
    break;
 
859
 
 
860
  case ETT_TERRAIN_RESOURCE:
 
861
    dsend_packet_edit_tile_resource(my_conn, x, y, erase ? -1 : value,
 
862
                                    size);
 
863
    break;
 
864
 
 
865
  case ETT_TERRAIN_SPECIAL:
 
866
    dsend_packet_edit_tile_special(my_conn, x, y, value, erase, size);
 
867
    break;
 
868
 
 
869
  case ETT_MILITARY_BASE:
 
870
    dsend_packet_edit_tile_base(my_conn, x, y, value, erase, size);
 
871
    break;
 
872
 
 
873
  case ETT_UNIT:
 
874
    if (erase) {
 
875
      dsend_packet_edit_unit_remove(my_conn, apno, x, y, value, count);
 
876
    } else {
 
877
      dsend_packet_edit_unit_create(my_conn, apno, x, y, value, count, 0);
 
878
    }
 
879
    break;
 
880
 
 
881
  case ETT_CITY:
 
882
    if (erase) {
 
883
      struct city *pcity = tile_city(ptile);
 
884
      if (pcity != NULL) {
 
885
        id = pcity->id;
 
886
        dsend_packet_edit_city_remove(my_conn, id);
 
887
      }
 
888
    } else {
 
889
      dsend_packet_edit_city_create(my_conn, apno, x, y, size, 0);
 
890
    }
 
891
    break;
 
892
 
 
893
  case ETT_VISION:
 
894
    if (client_has_player()) {
 
895
      id = client_player_number();
 
896
      dsend_packet_edit_player_vision(my_conn, id, x, y, !erase, size);
 
897
    }
 
898
    break;
 
899
 
 
900
  case ETT_STARTPOS:
 
901
    dsend_packet_edit_startpos(my_conn, x, y,
 
902
                               erase ? NATION_NONE :
 
903
                               nation_number(player_by_number(apno)->nation));
 
904
    break;
 
905
 
 
906
  default:
 
907
    break;
 
908
  }
 
909
}
 
910
 
 
911
/****************************************************************************
 
912
  Sets the tile currently assumed to be under the user's mouse pointer.
 
913
****************************************************************************/
 
914
void editor_set_current_tile(const struct tile *ptile)
 
915
{
 
916
  if (editor == NULL) {
 
917
    return;
 
918
  }
 
919
  
 
920
  editor->current_tile = ptile;
 
921
}
 
922
 
 
923
/****************************************************************************
 
924
  Get the tile that the user's mouse pointer is currently over.
 
925
****************************************************************************/
 
926
const struct tile *editor_get_current_tile(void)
 
927
{
 
928
  if (editor == NULL) {
 
929
    return NULL;
 
930
  }
 
931
  
 
932
  return editor->current_tile;
 
933
}
 
934
 
 
935
/****************************************************************************
 
936
  Toggle the current tool mode between the given mode and ETM_PAINT (or
 
937
  ETM_COPY for the copy & paste tool).
 
938
****************************************************************************/
 
939
void editor_tool_toggle_mode(enum editor_tool_type ett,
 
940
                             enum editor_tool_mode etm)
 
941
{
 
942
  if (!editor_tool_has_mode(ett, etm)) {
 
943
    return;
 
944
  }
 
945
  if (editor_tool_get_mode(ett) == etm) {
 
946
    editor_tool_set_mode(ett, ett == ETT_COPYPASTE
 
947
                         ? ETM_COPY : ETM_PAINT);
 
948
  } else {
 
949
    editor_tool_set_mode(ett, etm);
 
950
  }
 
951
}
 
952
 
 
953
/****************************************************************************
 
954
  Set the editor tool mode to the next available mode.
 
955
****************************************************************************/
 
956
void editor_tool_cycle_mode(enum editor_tool_type ett)
 
957
{
 
958
  int mode, count;
 
959
  bool found = FALSE;
 
960
 
 
961
  mode = editor_tool_get_mode(ett);
 
962
  if (!(0 <= mode && mode < NUM_EDITOR_TOOL_MODES)) {
 
963
    return;
 
964
  }
 
965
 
 
966
  for (count = 0; count < NUM_EDITOR_TOOL_MODES; count++) {
 
967
    mode = (mode + 1) % NUM_EDITOR_TOOL_MODES;
 
968
    if (editor_tool_has_mode(ett, mode)) {
 
969
      found = TRUE;
 
970
      break;
 
971
    }
 
972
  }
 
973
 
 
974
  if (found) {
 
975
    editor_tool_set_mode(ett, mode);
 
976
  }
 
977
}
 
978
 
 
979
/****************************************************************************
 
980
  Unselect all selected tiles.
 
981
****************************************************************************/
 
982
void editor_selection_clear(void)
 
983
{
 
984
  if (!editor) {
 
985
    return;
 
986
  }
 
987
  hash_delete_all_entries(editor->selected_tile_table);
 
988
}
 
989
 
 
990
/****************************************************************************
 
991
  Add the given tile to the current selection.
 
992
****************************************************************************/
 
993
void editor_selection_add(const struct tile *ptile)
 
994
{
 
995
  if (!editor || !ptile) {
 
996
    return;
 
997
  }
 
998
  hash_insert(editor->selected_tile_table, ptile, NULL);
 
999
}
 
1000
 
 
1001
/****************************************************************************
 
1002
  Remove the given tile from the current selection.
 
1003
****************************************************************************/
 
1004
void editor_selection_remove(const struct tile *ptile)
 
1005
{
 
1006
  if (!editor || !ptile) {
 
1007
    return;
 
1008
  }
 
1009
  hash_delete_entry(editor->selected_tile_table, ptile);
 
1010
}
 
1011
 
 
1012
/****************************************************************************
 
1013
  Returns TRUE if the given tile is selected.
 
1014
****************************************************************************/
 
1015
bool editor_tile_is_selected(const struct tile *ptile)
 
1016
{
 
1017
  if (!editor || !ptile) {
 
1018
    return FALSE;
 
1019
  }
 
1020
  return hash_key_exists(editor->selected_tile_table, ptile);
 
1021
}
 
1022
 
 
1023
/****************************************************************************
 
1024
  Apply the current editor tool to all tiles in the current selection.
 
1025
****************************************************************************/
 
1026
void editor_apply_tool_to_selection(void)
 
1027
{
 
1028
  enum editor_tool_type ett;
 
1029
 
 
1030
  if (!editor || editor_selection_count() <= 0) {
 
1031
    return;
 
1032
  }
 
1033
 
 
1034
  ett = editor_get_tool();
 
1035
  if (editor_tool_get_mode(ett) == ETM_COPY) {
 
1036
    struct edit_buffer *ebuf;
 
1037
    ebuf = editor_get_copy_buffer();
 
1038
    edit_buffer_clear(ebuf);
 
1039
    edit_buffer_set_origin(ebuf, editor_get_selection_center());
 
1040
  }
 
1041
 
 
1042
  connection_do_buffer(&client.conn);
 
1043
  hash_keys_iterate(editor->selected_tile_table, ptile) {
 
1044
    editor_apply_tool(ptile, TRUE);
 
1045
  } hash_keys_iterate_end;
 
1046
  editor_notify_edit_finished();
 
1047
  connection_do_unbuffer(&client.conn);
 
1048
 
 
1049
  if (editor_tool_get_mode(ett) == ETM_COPY) {
 
1050
    editgui_refresh();
 
1051
  }
 
1052
}
 
1053
 
 
1054
/****************************************************************************
 
1055
  Get the translated name of the given tool type.
 
1056
****************************************************************************/
 
1057
const char *editor_tool_get_name(enum editor_tool_type ett)
 
1058
{
 
1059
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1060
    return "";
 
1061
  }
 
1062
 
 
1063
  return editor->tools[ett].name;
 
1064
}
 
1065
 
 
1066
/****************************************************************************
 
1067
  Get the translated name of the given tool value. If no such name exists,
 
1068
  returns an empty string.
 
1069
****************************************************************************/
 
1070
const char *editor_tool_get_value_name(enum editor_tool_type emt, int value)
 
1071
{
 
1072
  struct terrain *pterrain;
 
1073
  struct resource *presource;
 
1074
  struct unit_type *putype;
 
1075
  struct base_type *pbase;
 
1076
 
 
1077
  if (!editor) {
 
1078
    return "";
 
1079
  }
 
1080
 
 
1081
  switch (emt) {
 
1082
  case ETT_TERRAIN:
 
1083
    pterrain = terrain_by_number(value);
 
1084
    return pterrain ? terrain_name_translation(pterrain) : "";
 
1085
    break;
 
1086
  case ETT_TERRAIN_RESOURCE:
 
1087
    presource = resource_by_number(value);
 
1088
    return presource ? resource_name_translation(presource) : "";
 
1089
    break;
 
1090
  case ETT_TERRAIN_SPECIAL:
 
1091
    if (!(0 <= value && value < S_LAST)) {
 
1092
      return "";
 
1093
    }
 
1094
    return special_name_translation(value);
 
1095
    break;
 
1096
  case ETT_MILITARY_BASE:
 
1097
    pbase = base_by_number(value);
 
1098
    return pbase != NULL ? base_name_translation(pbase) : "";
 
1099
    break;
 
1100
  case ETT_UNIT:
 
1101
    putype = utype_by_number(value);
 
1102
    return putype ? utype_name_translation(putype) : "";
 
1103
    break;
 
1104
  default:
 
1105
    break;
 
1106
  }
 
1107
  return "";
 
1108
}
 
1109
 
 
1110
/****************************************************************************
 
1111
  Return TRUE if the given editor tool uses the 'size' parameter.
 
1112
****************************************************************************/
 
1113
bool editor_tool_has_size(enum editor_tool_type ett)
 
1114
{
 
1115
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1116
    return FALSE;
 
1117
  }
 
1118
  return editor->tools[ett].flags & ETF_HAS_SIZE;
 
1119
}
 
1120
 
 
1121
/****************************************************************************
 
1122
  Returns the current size parameter for the given editor tools.
 
1123
****************************************************************************/
 
1124
int editor_tool_get_size(enum editor_tool_type ett)
 
1125
{
 
1126
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1127
    return 1;
 
1128
  }
 
1129
  return editor->tools[ett].size;
 
1130
}
 
1131
 
 
1132
/****************************************************************************
 
1133
  Sets the size parameter for the given tool.
 
1134
****************************************************************************/
 
1135
void editor_tool_set_size(enum editor_tool_type ett, int size)
 
1136
{
 
1137
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1138
    return;
 
1139
  }
 
1140
  editor->tools[ett].size = MAX(1, size);
 
1141
}
 
1142
 
 
1143
/****************************************************************************
 
1144
  Return TRUE if it is meaningful for the given tool to use the 'count'
 
1145
  parameter.
 
1146
****************************************************************************/
 
1147
bool editor_tool_has_count(enum editor_tool_type ett)
 
1148
{
 
1149
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1150
    return FALSE;
 
1151
  }
 
1152
  return editor->tools[ett].flags & ETF_HAS_COUNT;
 
1153
}
 
1154
 
 
1155
/****************************************************************************
 
1156
  Returns the 'count' parameter for the editor tool.
 
1157
****************************************************************************/
 
1158
int editor_tool_get_count(enum editor_tool_type ett)
 
1159
{
 
1160
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1161
    return 1;
 
1162
  }
 
1163
  return editor->tools[ett].count;
 
1164
}
 
1165
 
 
1166
/****************************************************************************
 
1167
  Sets the 'count' parameter of the tool to the given value.
 
1168
****************************************************************************/
 
1169
void editor_tool_set_count(enum editor_tool_type ett, int count)
 
1170
{
 
1171
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1172
    return;
 
1173
  }
 
1174
  editor->tools[ett].count = MAX(1, count);
 
1175
}
 
1176
 
 
1177
/****************************************************************************
 
1178
  Returns a sprite containing an icon for the given tool type. Returns
 
1179
  NULL if no such sprite exists.
 
1180
****************************************************************************/
 
1181
struct sprite *editor_tool_get_sprite(enum editor_tool_type ett)
 
1182
{
 
1183
  const struct editor_sprites *sprites;
 
1184
 
 
1185
  if (!tileset || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1186
    return NULL;
 
1187
  }
 
1188
 
 
1189
  sprites = get_editor_sprites(tileset);
 
1190
  if (!sprites) {
 
1191
    return NULL;
 
1192
  }
 
1193
 
 
1194
  switch (ett) {
 
1195
  case ETT_COPYPASTE:
 
1196
    return sprites->copypaste;
 
1197
    break;
 
1198
  case ETT_TERRAIN:
 
1199
    return sprites->terrain;
 
1200
    break;
 
1201
  case ETT_TERRAIN_RESOURCE:
 
1202
    return sprites->terrain_resource;
 
1203
    break;
 
1204
  case ETT_TERRAIN_SPECIAL:
 
1205
    return sprites->terrain_special;
 
1206
    break;
 
1207
  case ETT_MILITARY_BASE:
 
1208
    return sprites->military_base;
 
1209
    break;
 
1210
  case ETT_UNIT:
 
1211
    return sprites->unit;
 
1212
    break;
 
1213
  case ETT_CITY:
 
1214
    return sprites->city;
 
1215
    break;
 
1216
  case ETT_VISION:
 
1217
    return sprites->vision;
 
1218
    break;
 
1219
  case ETT_STARTPOS:
 
1220
    return sprites->startpos;
 
1221
    break;
 
1222
  default:
 
1223
    break;
 
1224
  }
 
1225
 
 
1226
  return NULL;
 
1227
}
 
1228
 
 
1229
/****************************************************************************
 
1230
  Returns a translated "tooltip" description for the given tool type.
 
1231
****************************************************************************/
 
1232
const char *editor_tool_get_tooltip(enum editor_tool_type ett)
 
1233
{
 
1234
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)
 
1235
      || !editor->tools[ett].tooltip) {
 
1236
    return "";
 
1237
  }
 
1238
  return editor->tools[ett].tooltip;
 
1239
}
 
1240
 
 
1241
/****************************************************************************
 
1242
  Returns the current applied player number for the editor tool.
 
1243
 
 
1244
  May return a player number for which valid_player_by_number returns NULL.
 
1245
****************************************************************************/
 
1246
int editor_tool_get_applied_player(enum editor_tool_type ett)
 
1247
{
 
1248
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1249
    return -1;
 
1250
  }
 
1251
  return editor->tools[ett].applied_player_no;
 
1252
}
 
1253
 
 
1254
/****************************************************************************
 
1255
  Sets the editor tool's applied player number to the given value.
 
1256
****************************************************************************/
 
1257
void editor_tool_set_applied_player(enum editor_tool_type ett,
 
1258
                                    int player_no)
 
1259
{
 
1260
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1261
    return;
 
1262
  }
 
1263
  editor->tools[ett].applied_player_no = player_no;
 
1264
}
 
1265
 
 
1266
/****************************************************************************
 
1267
  Returns TRUE if the given tool makes use of the editor's applied player
 
1268
  number.
 
1269
****************************************************************************/
 
1270
bool editor_tool_has_applied_player(enum editor_tool_type ett)
 
1271
{
 
1272
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1273
    return FALSE;
 
1274
  }
 
1275
  return editor->tools[ett].flags & ETF_HAS_APPLIED_PLAYER;
 
1276
}
 
1277
 
 
1278
/****************************************************************************
 
1279
  Returns TRUE if erase mode for the given tool erases by sub-value instead
 
1280
  of any object corresponding to the tool type.
 
1281
****************************************************************************/
 
1282
bool editor_tool_has_value_erase(enum editor_tool_type ett)
 
1283
{
 
1284
  if (!editor || !(0 <= ett && ett < NUM_EDITOR_TOOL_TYPES)) {
 
1285
    return FALSE;
 
1286
  }
 
1287
  return editor->tools[ett].flags & ETF_HAS_VALUE_ERASE;
 
1288
}
 
1289
 
 
1290
/****************************************************************************
 
1291
  Returns the number of currently selected tiles.
 
1292
****************************************************************************/
 
1293
int editor_selection_count(void)
 
1294
{
 
1295
  if (!editor) {
 
1296
    return 0;
 
1297
  }
 
1298
  return hash_num_entries(editor->selected_tile_table);
 
1299
}
 
1300
 
 
1301
/****************************************************************************
 
1302
  Creates a virtual unit (like create_unit_virtual) based on the current
 
1303
  editor state. You should free() the unit when it is no longer needed.
 
1304
  If creation is not possible, then NULL is returned.
 
1305
 
 
1306
  The virtual unit has no homecity or tile. It is owned by the player
 
1307
  corresponding to the current 'applied player' parameter and has unit type
 
1308
  given by the sub-value of the unit tool (ETT_UNIT).
 
1309
****************************************************************************/
 
1310
struct unit *editor_create_unit_virtual(void)
 
1311
{
 
1312
  struct unit *vunit;
 
1313
  struct player *pplayer;
 
1314
  struct unit_type *putype;
 
1315
  int apno, value;
 
1316
 
 
1317
  value = editor_tool_get_value(ETT_UNIT);
 
1318
  putype = utype_by_number(value);
 
1319
 
 
1320
  if (!putype) {
 
1321
    return NULL;
 
1322
  }
 
1323
 
 
1324
  apno = editor_tool_get_applied_player(ETT_UNIT);
 
1325
  pplayer = valid_player_by_number(apno);
 
1326
  if (!pplayer) {
 
1327
    return NULL;
 
1328
  }
 
1329
 
 
1330
  vunit = create_unit_virtual(pplayer, NULL, putype, 0);
 
1331
 
 
1332
  return vunit;
 
1333
}
 
1334
 
 
1335
/****************************************************************************
 
1336
  Create a new edit buffer corresponding to all types set in 'type_flags'.
 
1337
****************************************************************************/
 
1338
struct edit_buffer *edit_buffer_new(int type_flags)
 
1339
{
 
1340
  struct edit_buffer *ebuf;
 
1341
 
 
1342
  if (!(0 <= type_flags && type_flags <= EBT_ALL)) {
 
1343
    return NULL;
 
1344
  }
 
1345
 
 
1346
  ebuf = fc_calloc(1, sizeof(*ebuf));
 
1347
  ebuf->type_flags = type_flags;
 
1348
  ebuf->vtiles = tile_list_new();
 
1349
 
 
1350
  return ebuf;
 
1351
}
 
1352
 
 
1353
/****************************************************************************
 
1354
  Free all memory allocated for the edit buffer.
 
1355
****************************************************************************/
 
1356
void edit_buffer_free(struct edit_buffer *ebuf)
 
1357
{
 
1358
  if (!ebuf) {
 
1359
    return;
 
1360
  }
 
1361
 
 
1362
  if (ebuf->vtiles) {
 
1363
    tile_list_iterate(ebuf->vtiles, vtile) {
 
1364
      destroy_tile_virtual(vtile);
 
1365
    } tile_list_iterate_end;
 
1366
    tile_list_free(ebuf->vtiles);
 
1367
    ebuf->vtiles = NULL;
 
1368
  }
 
1369
  free(ebuf);
 
1370
}
 
1371
 
 
1372
/****************************************************************************
 
1373
  Remove all copy data stored in the edit buffer.
 
1374
****************************************************************************/
 
1375
void edit_buffer_clear(struct edit_buffer *ebuf)
 
1376
{
 
1377
  if (!ebuf || !ebuf->vtiles) {
 
1378
    return;
 
1379
  }
 
1380
 
 
1381
  tile_list_iterate(ebuf->vtiles, vtile) {
 
1382
    destroy_tile_virtual(vtile);
 
1383
  } tile_list_iterate_end;
 
1384
  tile_list_clear(ebuf->vtiles);
 
1385
 
 
1386
  edit_buffer_set_origin(ebuf, NULL);
 
1387
}
 
1388
 
 
1389
/****************************************************************************
 
1390
  Copy from a square region of half-width 'radius' centered around 'center'
 
1391
  into the buffer.
 
1392
****************************************************************************/
 
1393
void edit_buffer_copy_square(struct edit_buffer *ebuf,
 
1394
                             const struct tile *center,
 
1395
                             int radius)
 
1396
{
 
1397
  if (!ebuf || !center || radius < 1) {
 
1398
    return;
 
1399
  }
 
1400
 
 
1401
  edit_buffer_set_origin(ebuf, center);
 
1402
  square_iterate(center, radius - 1, ptile) {
 
1403
    edit_buffer_copy(ebuf, ptile);
 
1404
  } square_iterate_end;
 
1405
}
 
1406
 
 
1407
/****************************************************************************
 
1408
  Append a single tile to the copy buffer.
 
1409
****************************************************************************/
 
1410
void edit_buffer_copy(struct edit_buffer *ebuf, const struct tile *ptile)
 
1411
{
 
1412
  struct tile *vtile;
 
1413
  struct unit *vunit;
 
1414
  const struct tile *origin;
 
1415
  int dx, dy;
 
1416
  bool copied = FALSE;
 
1417
 
 
1418
  if (!ebuf || !ptile) {
 
1419
    return;
 
1420
  }
 
1421
 
 
1422
  origin = edit_buffer_get_origin(ebuf);
 
1423
  if (origin) {
 
1424
    map_distance_vector(&dx, &dy, origin, ptile);
 
1425
  } else {
 
1426
    dx = 0;
 
1427
    dy = 0;
 
1428
  }
 
1429
  vtile = create_tile_virtual();
 
1430
  vtile->x = dx;
 
1431
  vtile->y = dy;
 
1432
 
 
1433
  edit_buffer_type_iterate(ebuf, type) {
 
1434
    switch (type) {
 
1435
    case EBT_TERRAIN:
 
1436
      if (tile_terrain(ptile)) {
 
1437
        tile_set_terrain(vtile, tile_terrain(ptile));
 
1438
        copied = TRUE;
 
1439
      }
 
1440
      break;
 
1441
    case EBT_RESOURCE:
 
1442
      if (tile_resource(ptile)) {
 
1443
        tile_set_resource(vtile, tile_resource(ptile));
 
1444
        copied = TRUE;
 
1445
      }
 
1446
      break;
 
1447
    case EBT_SPECIAL:
 
1448
      if (tile_has_any_specials(ptile)) {
 
1449
        tile_set_specials(vtile, tile_specials(ptile));
 
1450
        copied = TRUE;
 
1451
      }
 
1452
      break;
 
1453
    case EBT_BASE:
 
1454
      if (tile_has_any_bases(ptile)) {
 
1455
        tile_set_bases(vtile, tile_bases(ptile));
 
1456
        copied = TRUE;
 
1457
      }
 
1458
      break;
 
1459
    case EBT_UNIT:
 
1460
      unit_list_iterate(ptile->units, punit) {
 
1461
        if (!punit) {
 
1462
          continue;
 
1463
        }
 
1464
        vunit = create_unit_virtual(unit_owner(punit), NULL,
 
1465
                                    unit_type(punit), punit->veteran);
 
1466
        vunit->homecity = punit->homecity;
 
1467
        vunit->hp = punit->hp;
 
1468
        unit_list_append(vtile->units, vunit);
 
1469
        copied = TRUE;
 
1470
      } unit_list_iterate_end;
 
1471
      break;
 
1472
    case EBT_CITY:
 
1473
      if (tile_city(ptile)) {
 
1474
        struct city *pcity, *vcity;
 
1475
        char name[MAX_LEN_NAME];
 
1476
 
 
1477
        pcity = tile_city(ptile);
 
1478
        my_snprintf(name, sizeof(name), "Copy of %s",
 
1479
                    city_name(pcity));
 
1480
        vcity = create_city_virtual(city_owner(pcity), NULL, name);
 
1481
        vcity->size = pcity->size;
 
1482
        improvement_iterate(pimprove) {
 
1483
          if (!is_improvement(pimprove)
 
1484
              || !city_has_building(pcity, pimprove)) {
 
1485
            continue;
 
1486
          }
 
1487
          city_add_improvement(vcity, pimprove);
 
1488
        } improvement_iterate_end;
 
1489
        tile_set_worked(vtile, vcity);
 
1490
        copied = TRUE;
 
1491
      }
 
1492
      break;
 
1493
    default:
 
1494
      break;
 
1495
    }
 
1496
  } edit_buffer_type_iterate_end;
 
1497
 
 
1498
  if (copied) {
 
1499
    tile_list_append(ebuf->vtiles, vtile);
 
1500
  } else {
 
1501
    destroy_tile_virtual(vtile);
 
1502
  }
 
1503
}
 
1504
 
 
1505
/****************************************************************************
 
1506
  Helper function to fill in an edit packet with the tile's current values.
 
1507
****************************************************************************/
 
1508
static void fill_tile_edit_packet(struct packet_edit_tile *packet,
 
1509
                                  const struct tile *ptile)
 
1510
{
 
1511
  const struct resource *presource;
 
1512
  const struct terrain *pterrain;
 
1513
  const struct nation_type *pnation;
 
1514
 
 
1515
  if (!packet || !ptile) {
 
1516
    return;
 
1517
  }
 
1518
  packet->id = tile_index(ptile);
 
1519
  packet->specials = tile_specials(ptile);
 
1520
  packet->bases = tile_bases(ptile);
 
1521
 
 
1522
  presource = tile_resource(ptile);
 
1523
  packet->resource = presource ? resource_number(presource) : -1;
 
1524
 
 
1525
  pterrain = tile_terrain(ptile);
 
1526
  packet->terrain = pterrain ? terrain_number(pterrain) : -1;
 
1527
 
 
1528
  pnation = map_get_startpos(ptile);
 
1529
  packet->startpos_nation = pnation ? nation_number(pnation) : -1;
 
1530
}
 
1531
 
 
1532
/****************************************************************************
 
1533
  Helper function for edit_buffer_paste(). Do a single paste of the stuff set
 
1534
  in the buffer on the virtual tile to the destination tile 'ptile_dest'.
 
1535
****************************************************************************/
 
1536
static void paste_tile(struct edit_buffer *ebuf,
 
1537
                       const struct tile *vtile,
 
1538
                       const struct tile *ptile_dest)
 
1539
{
 
1540
  struct connection *my_conn = &client.conn;
 
1541
  struct packet_edit_tile tile_packet;
 
1542
  struct city *vcity;
 
1543
  int value, owner, x, y;
 
1544
  bool send_edit_tile = FALSE;
 
1545
 
 
1546
  if (!ebuf || !vtile || !ptile_dest) {
 
1547
    return;
 
1548
  }
 
1549
 
 
1550
  x = ptile_dest->x;
 
1551
  y = ptile_dest->y;
 
1552
 
 
1553
  fill_tile_edit_packet(&tile_packet, ptile_dest);
 
1554
 
 
1555
  edit_buffer_type_iterate(ebuf, type) {
 
1556
    switch (type) {
 
1557
    case EBT_TERRAIN:
 
1558
      if (!tile_terrain(vtile)) {
 
1559
        continue;
 
1560
      }
 
1561
      value = terrain_number(tile_terrain(vtile));
 
1562
      dsend_packet_edit_tile_terrain(my_conn, x, y, value, 1);
 
1563
      break;
 
1564
    case EBT_RESOURCE:
 
1565
      if (!tile_resource(vtile)) {
 
1566
        continue;
 
1567
      }
 
1568
      value = resource_number(tile_resource(vtile));
 
1569
      dsend_packet_edit_tile_resource(my_conn, x, y, value, 1);
 
1570
      break;
 
1571
    case EBT_SPECIAL:
 
1572
      tile_packet.specials = tile_specials(vtile);
 
1573
      send_edit_tile = TRUE;
 
1574
      break;
 
1575
    case EBT_BASE:
 
1576
      tile_packet.bases = tile_bases(vtile);
 
1577
      send_edit_tile = TRUE;
 
1578
      break;
 
1579
    case EBT_UNIT:
 
1580
      unit_list_iterate(vtile->units, vunit) {
 
1581
        value = utype_number(unit_type(vunit));
 
1582
        owner = player_number(unit_owner(vunit));
 
1583
        dsend_packet_edit_unit_create(my_conn, owner, x, y, value, 1, 0);
 
1584
      } unit_list_iterate_end;
 
1585
      break;
 
1586
    case EBT_CITY:
 
1587
      vcity = tile_city(vtile);
 
1588
      if (!vcity) {
 
1589
        continue;
 
1590
      }
 
1591
      owner = player_number(city_owner(vcity));
 
1592
      value = vcity->size;
 
1593
      dsend_packet_edit_city_create(my_conn, owner, x, y, value, 0);
 
1594
      break;
 
1595
    default:
 
1596
      break;
 
1597
    }
 
1598
  } edit_buffer_type_iterate_end;
 
1599
 
 
1600
  if (send_edit_tile) {
 
1601
    send_packet_edit_tile(my_conn, &tile_packet);
 
1602
  }
 
1603
}
 
1604
 
 
1605
/****************************************************************************
 
1606
  Paste the entire contents of the edit buffer using 'dest' as the origin.
 
1607
****************************************************************************/
 
1608
void edit_buffer_paste(struct edit_buffer *ebuf, const struct tile *dest)
 
1609
{
 
1610
  struct connection *my_conn = &client.conn;
 
1611
  const struct tile *ptile;
 
1612
 
 
1613
  if (!ebuf || !dest) {
 
1614
    return;
 
1615
  }
 
1616
 
 
1617
  connection_do_buffer(my_conn);
 
1618
  tile_list_iterate(ebuf->vtiles, vtile) {
 
1619
    ptile = map_pos_to_tile(dest->x + vtile->x, dest->y + vtile->y);
 
1620
    if (!ptile) {
 
1621
      continue;
 
1622
    }
 
1623
    paste_tile(ebuf, vtile, ptile);
 
1624
  } tile_list_iterate_end;
 
1625
  connection_do_unbuffer(my_conn);
 
1626
}
 
1627
 
 
1628
/****************************************************************************
 
1629
  Returns the copy buffer for the given tool.
 
1630
****************************************************************************/
 
1631
struct edit_buffer *editor_get_copy_buffer(void)
 
1632
{
 
1633
  if (!editor) {
 
1634
    return NULL;
 
1635
  }
 
1636
  return editor->copybuf;
 
1637
}
 
1638
 
 
1639
/****************************************************************************
 
1640
  Returns the translated string name for the given mode.
 
1641
****************************************************************************/
 
1642
const char *editor_tool_get_mode_name(enum editor_tool_type ett,
 
1643
                                      enum editor_tool_mode etm)
 
1644
{
 
1645
  bool value_erase;
 
1646
 
 
1647
  value_erase = editor_tool_has_value_erase(ett);
 
1648
 
 
1649
  switch (etm) {
 
1650
  case ETM_PAINT:
 
1651
    return _("Paint");
 
1652
    break;
 
1653
  case ETM_ERASE:
 
1654
    if (value_erase) {
 
1655
      return _("Erase Value");
 
1656
    } else {
 
1657
      return _("Erase");
 
1658
    }
 
1659
    break;
 
1660
  case ETM_COPY:
 
1661
    return _("Copy");
 
1662
    break;
 
1663
  case ETM_PASTE:
 
1664
    return _("Paste");
 
1665
    break;
 
1666
  default:
 
1667
    freelog(LOG_ERROR, "Unrecognized editor tool mode %d "
 
1668
            "in editor_tool_get_mode_name().", etm);
 
1669
    break;
 
1670
  }
 
1671
 
 
1672
  return "";
 
1673
}
 
1674
 
 
1675
/****************************************************************************
 
1676
  Returns a translated tooltip string assumed to be used for the toggle
 
1677
  button for this tool mode in the editor gui.
 
1678
****************************************************************************/
 
1679
const char *editor_get_mode_tooltip(enum editor_tool_mode etm)
 
1680
{
 
1681
  switch (etm) {
 
1682
  case ETM_ERASE:
 
1683
    return _("Toggle erase mode.\nShortcut: shift-d");
 
1684
    break;
 
1685
  case ETM_COPY:
 
1686
    return _("Toggle copy mode.\nShortcut: shift-c");
 
1687
    break;
 
1688
  case ETM_PASTE:
 
1689
    return _("Toggle paste mode.\nShortcut: shift-v");
 
1690
    break;
 
1691
  default:
 
1692
    break;
 
1693
  }
 
1694
 
 
1695
  return NULL;
 
1696
}
 
1697
 
 
1698
/****************************************************************************
 
1699
  Returns the editor sprite corresponding to the tool mode.
 
1700
****************************************************************************/
 
1701
struct sprite *editor_get_mode_sprite(enum editor_tool_mode etm)
 
1702
{
 
1703
  const struct editor_sprites *sprites;
 
1704
 
 
1705
  sprites = get_editor_sprites(tileset);
 
1706
  if (!sprites) {
 
1707
    return NULL;
 
1708
  }
 
1709
 
 
1710
  switch (etm) {
 
1711
  case ETM_PAINT:
 
1712
    return sprites->brush;
 
1713
    break;
 
1714
  case ETM_ERASE:
 
1715
    return sprites->erase;
 
1716
    break;
 
1717
  case ETM_COPY:
 
1718
    return sprites->copy;
 
1719
    break;
 
1720
  case ETM_PASTE:
 
1721
    return sprites->paste;
 
1722
    break;
 
1723
  default:
 
1724
    break;
 
1725
  }
 
1726
 
 
1727
  return NULL;
 
1728
}
 
1729
 
 
1730
/****************************************************************************
 
1731
  Fill the supplied buffer with a translated string describing the edit
 
1732
  buffer's current state. Returns the number of bytes used.
 
1733
****************************************************************************/
 
1734
int edit_buffer_get_status_string(const struct edit_buffer *ebuf,
 
1735
                                  char *buf, int buflen)
 
1736
{
 
1737
  int ret, total;
 
1738
  const char *fmt;
 
1739
 
 
1740
  if (!buf || buflen < 1) {
 
1741
    return 0;
 
1742
  }
 
1743
 
 
1744
  ret = mystrlcpy(buf, _("Buffer empty."), buflen);
 
1745
  if (!ebuf || !ebuf->vtiles) {
 
1746
    return ret;
 
1747
  }
 
1748
 
 
1749
  total = tile_list_size(ebuf->vtiles);
 
1750
  if (total > 0) {
 
1751
    fmt = PL_("%d tile copied.", "%d tiles copied.", total);
 
1752
    ret = my_snprintf(buf, buflen, fmt, total);
 
1753
  }
 
1754
 
 
1755
  return ret;
 
1756
}
 
1757
 
 
1758
/****************************************************************************
 
1759
  Set the "origin" for subsequent copy operations. This controls the x and
 
1760
  y offset of newly created virtual tiles in the buffer.
 
1761
****************************************************************************/
 
1762
void edit_buffer_set_origin(struct edit_buffer *ebuf,
 
1763
                            const struct tile *ptile)
 
1764
{
 
1765
  if (!ebuf) {
 
1766
    return;
 
1767
  }
 
1768
  ebuf->origin = ptile;
 
1769
}
 
1770
 
 
1771
/****************************************************************************
 
1772
  Return the previously set origin, or NULL if none.
 
1773
****************************************************************************/
 
1774
const struct tile *edit_buffer_get_origin(const struct edit_buffer *ebuf)
 
1775
{
 
1776
  if (!ebuf) {
 
1777
    return NULL;
 
1778
  }
 
1779
  return ebuf->origin;
 
1780
}
 
1781
 
 
1782
/****************************************************************************
 
1783
  Returns TRUE if the edit buffer was created with the given type flag.
 
1784
****************************************************************************/
 
1785
bool edit_buffer_has_type(const struct edit_buffer *ebuf, int type)
 
1786
{
 
1787
  if (!ebuf) {
 
1788
    return FALSE;
 
1789
  }
 
1790
  return ebuf->type_flags & type;
 
1791
}
 
1792
 
 
1793
/****************************************************************************
 
1794
  Returns the "center" tile of a group of selected tiles, or NULL.
 
1795
  The center is calculated as the vector sum divided by the number of tiles,
 
1796
  i.e. the average of the map distance vectors of the selected tiles.
 
1797
****************************************************************************/
 
1798
const struct tile *editor_get_selection_center(void)
 
1799
{
 
1800
  int count;
 
1801
  const struct tile *origin, *center;
 
1802
  int dx, dy, cx, cy;
 
1803
  int xsum = 0, ysum = 0;
 
1804
 
 
1805
  if (!editor || !editor->selected_tile_table) {
 
1806
    return NULL;
 
1807
  }
 
1808
 
 
1809
  count = hash_num_entries(editor->selected_tile_table);
 
1810
  if (count < 1) {
 
1811
    return NULL;
 
1812
  }
 
1813
 
 
1814
  origin = map_pos_to_tile(0, 0);
 
1815
  hash_keys_iterate(editor->selected_tile_table, ptile) {
 
1816
    map_distance_vector(&dx, &dy, origin, ptile);
 
1817
    xsum += dx;
 
1818
    ysum += dy;
 
1819
  } hash_keys_iterate_end;
 
1820
 
 
1821
  cx = xsum / count;
 
1822
  cy = ysum / count;
 
1823
  center = map_pos_to_tile(cx, cy);
 
1824
 
 
1825
  return center;
 
1826
}